Unsigned integer subtraction

Problem

You want to perform subtraction where the result is unsigned and never negative.

Solution

When a subtraction result would be negative, the answer should be zero. The following query creates a UDF that performs the calculation:

try
{
    Value result = await client.Query(
        CreateFunction(
            Obj(
                "name", "subtract_unsigned",
                "body", Query(
                    Lambda(
                        Arr("a", "b"),
                        Let(
                            "diff", Subtract(Var("a"), Var("b")),
                            "negative", Not(
                                EqualsFn(Var("diff"), Abs(Var("diff")))
                            )
                        ).In(
                            If(Var("negative"), 0, Var("diff"))
                        )
                    )
                )
            )
        )
    );
    Console.WriteLine(result);
}
catch (Exception e)
{
    Console.WriteLine($"ERROR: {e.Message}");
}
result, err := client.Query(
	f.CreateFunction(
		f.Obj{
			"name": "subtract_unsigned",
			"body": f.Query(
				f.Lambda(
					f.Arr{"a", "b"},
					f.Let().Bind(
						"diff", f.Subtract(f.Var("a"), f.Var("b")),
					).Bind(
						"negative", f.Not(
							f.Equals(f.Var("diff"), f.Abs(f.Var("diff"))),
						),
					).In(
						f.If(f.Var("negative"), 0, f.Var("diff")),
					),
				),
			),
		},
	))

if err != nil {
	fmt.Fprintln(os.Stderr, err)
} else {
	fmt.Println(result)
}
System.out.println(
    client.query(
        CreateFunction(
            Obj(
                "name", Value("subtract_unsigned"),
                "body", Query(
                    Lambda(
                        Arr(Value("a"), Value("b")),
                        Let(
                            "diff", Subtract(Var("a"), Var("b")),
                            "negative", Not(
                                Equals(Var("diff"), Abs(Var("diff")))
                            )
                        ).in(
                            If(Var("negative"), Value(0), Var("diff"))
                        )
                    )
                )
            )
        )
    ).get());
client.query(
  q.CreateFunction({
    name: 'subtract_unsigned',
    body: q.Query(
      q.Lambda(
        ['a', 'b'],
        q.Let(
          {
            diff: q.Subtract(q.Var('a'), q.Var('b')),
            negative: q.Not(q.Equals(q.Var('diff'), q.Abs(q.Var('diff')))),
          },
          q.If(q.Var('negative'), 0, q.Var('diff'))
        )
      )
    ),
  })
)
.then((ret) => console.log(ret))
.catch((err) => console.error('Error: %s', err))
result = client.query(
  q.create_function({
    "name": "subtract_unsigned",
    "body": q.query(
      q.lambda_(
        ["a", "b"],
        q.let(
          {
            "diff": q.subtract(q.var("a"), q.var("b")),
            "negative": q.not_(q.equals(q.var("diff"), q.abs(q.var("diff"))))
          },
          q.if_(q.var("negative"), 0, q.var("diff"))
        )
      )
    )
  })
)
print(result)
try {
  println(Await.result(
    client.query(
      CreateFunction(
        Obj(
          "name" -> "subtract_unsigned",
          "body" -> Query(
            Lambda(
              Arr("a", "b"),
              Let(
                Seq(
                  "diff" -> Subtract(Var("a"), Var("b")),
                  "negative" -> Not(Equals(Var("diff"), Abs(Var("diff"))))
                ),
                If(Var("negative"), 0, Var("diff"))
              )
            )
          )
        )
      )
    ),
    5.seconds
  ))
} catch {
  case unknown: Throwable => println("Error: " + unknown.getMessage())
}
CreateFunction({
  name: "subtract_unsigned",
  body: Query(
    Lambda(
      ["a", "b"],
      Let(
        {
          diff: Subtract(Var("a"), Var("b")),
          negative: Not(Equals(Var("diff"), Abs(Var("diff"))))
        },
        If(Var("negative"), 0, Var("diff"))
      )
    )
  )
})

The following query calls the UDF with parameters that return a positive result:

try
{
    Value result = await client.Query(
        Call("subtract_unsigned", 123, 45)
    );
    Console.WriteLine(result);
}
catch (Exception e)
{
    Console.WriteLine($"ERROR: {e.Message}");
}
LongV(78)
result, err := client.Query(
	f.Call("subtract_unsigned", 123, 45))

if err != nil {
	fmt.Fprintln(os.Stderr, err)
} else {
	fmt.Println(result)
}
78
System.out.println(
    client.query(
        Call(Value("subtract_unsigned"), Value(123), Value(45))
    ).get());
78
client.query(
  q.Call('subtract_unsigned', 123, 45)
)
.then((ret) => console.log(ret))
.catch((err) => console.error('Error: %s', err))
78
result = client.query(
  q.call("subtract_unsigned", 123, 45)
)
print(result)
78
try {
  println(Await.result(
    client.query(
      Call("subtract_unsigned", 123, 45)
    ),
    5.seconds
  ))
} catch {
  case unknown: Throwable => println("Error: " + unknown.getMessage())
}
78
Call("subtract_unsigned", 123, 45)
78

The following query calls the UDF with parameters that return what would have been a negative result:

try
{
    Value result = await client.Query(
        Call("subtract_unsigned", 45, 123)
    );
    Console.WriteLine(result);
}
catch (Exception e)
{
    Console.WriteLine($"ERROR: {e.Message}");
}
LongV(0)
result, err := client.Query(
	f.Call("subtract_unsigned", 45, 123))

if err != nil {
	fmt.Fprintln(os.Stderr, err)
} else {
	fmt.Println(result)
}
0
System.out.println(
    client.query(
        Call(Value("subtract_unsigned"), Value(45), Value(123))
    ).get());
0
client.query(
  q.Call('subtract_unsigned', 45, 123)
)
.then((ret) => console.log(ret))
.catch((err) => console.error('Error: %s', err))
0
result = client.query(
  q.call("subtract_unsigned", 45, 123)
)
print(result)
0
try {
  println(Await.result(
    client.query(
      Call("subtract_unsigned", 45, 123)
    ),
    5.seconds
  ))
} catch {
  case unknown: Throwable => println("Error: " + unknown.getMessage())
}
0
Call("subtract_unsigned", 45, 123)
0

More information

Was this article helpful?

We're sorry to hear that.
Tell us how we can improve!
Visit Fauna's Discourse forums or email docs@fauna.com

Thank you for your feedback!