# Set a default value for a variable if it is not provided by user

**URL:** <https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760>\
**Category:** Predicate\
**Tags:** how-to\
**Created:** [September 3, 2024, 8:48pm UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760 "2024-09-03T20:48:17Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![konokaiden](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/konokaiden/32/6708_2.png) [@konokaiden](https://swi-prolog.discourse.group/u/konokaiden)\
**Post date:** [September 3, 2024, 8:48pm UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/1 "2024-09-03T20:48:17Z")

</div>

I want to make a rule where I have three variables, Input, Compare, Output.  
If the user supplies the Compare value, I want it to be run with that. If the user does  
not supply a Compare, I want to set it. Does SWI-Prolog have a way to set a variable to  
a default value without overriding what the user inputs?

Something like if(x = null) {do y}, else {do z}.

To be more specific, I am trying to create an odd/3 rule so that we can test if a number is odd (without using mod/2), or if we know a number was odd, we can find what that number was (run it in reverse).

I have a functional odd/2 rule that goes like:  
odd(Input, Output):-  
Input #\> 0,  
integer(Input),  
Input\>\>1 =:= (Input-1)/2.

The last line gets rid of the final binary 1, so if the user supplied the fact that a number was odd, and perhaps the value of Compare = (Input-1)/2, then the rule could solve for the Input.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [September 3, 2024, 11:11pm UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/2 "2024-09-03T23:11:48Z")

</div>

Your code for `odd/2` doesn’t do anything with ‘Output’ and I also got a syntax error with it – which library are you using (for `#>`)?

Are you trying to write a predicate that can do this?

```prolog
?- odd(2).
false.
?- odd(3).
true.
?- odd(X).
X = 1 ;
X = 3 ;
X = 5 ;
   ...

```

---

<div class="post-metadata">

**Author:** ![brebs](https://avatars.discourse-cdn.com/v4/letter/b/e9c0ed/32.png) [@brebs](https://swi-prolog.discourse.group/u/brebs)\
**Post date:** [September 3, 2024, 11:22pm UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/3 "2024-09-03T23:22:40Z")

</div>

> [@konokaiden](#):
>
> if(x = null) {do y}, else {do z}

-\>/2 performs that if… then… else.

---

<div class="post-metadata">

**Author:** ![konokaiden](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/konokaiden/32/6708_2.png) [@konokaiden](https://swi-prolog.discourse.group/u/konokaiden)\
**Post date:** [September 4, 2024, 5:20am UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/4 "2024-09-04T05:20:24Z")

</div>

Sorry, I was messing with it before posting this, so it looks like I hadn’t gotten it back to the way it was originally.

It should be an odd/1 function, as far as what works currently:

odd(Input) :-  
Input #\> 0,  
integer(Input),  
Input\>\>1 =:= (Input-1)/2.

The library is clp(fd). I have a couple of other flags set normally, so if you continue to get errors, please let me know, and we can track those down. I think this should be enough though.

But the idea was to make a relation \<odd(In, Compare, Out)\> so that a rule involving odd-checking could work in reverse. This requires that I modify the odd/1 rule into something like an odd/3, which if I knew the answer (True / False being “Out” and what number the bit movement was compared to), I could generate the thing that was tested (In).

It may not be possible, but I figured I’d ask here since I’m relatively inexperienced with Prolog.

---

<div class="post-metadata">

**Author:** ![konokaiden](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/konokaiden/32/6708_2.png) [@konokaiden](https://swi-prolog.discourse.group/u/konokaiden)\
**Post date:** [September 4, 2024, 5:32am UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/5 "2024-09-04T05:32:02Z")

</div>

As far as I know, → cannot be used in reverse cases. So like, in the case of a statement like

X + 2 #= 3 → Z #= 5; Z#= 3

you can’t supply Z to find X, precisely because you dont know what X might be if the relation doesnt hold.

In my case, I want to perform different operations based on a truth statement, so I’m unsure if an if statement can be used backwards, since the means of determining the input will be set. Something more like:

X #\> 5,  
integer(X),  
even(X) → (Bool = true, Y #= X + 3); (Bool = false, Y #= X - 4).

In this case, X must be \> 5 and a whole number. If X is an even number, then it is Y - 3 (I could supply Y and the Bool), and if it is odd, X is known to be Y + 4.

Logically I know how to work this in reverse because the conditions are precise enough to force an answer to be available either way. But I dont know how to assign boolean values and I dont know if this last statement is capable of being run in reverse given Bool and Y.

That’s why I’m looking for another clever way to accomplish the same thing.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [September 4, 2024, 5:37am UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/6 "2024-09-04T05:37:12Z")

</div>

Maybe this will do what you want:

```prolog
odd(Input):-
    Input #> 0,
    freeze(Input, (integer(Input),
                   Input>>1 =:= (Input-1)/2)).

```

```prolog
?- odd(X), between(1, 5, X).
X = 1 ;
X = 3 ;
X = 5.

```

---

<div class="post-metadata">

**Author:** ![brebs](https://avatars.discourse-cdn.com/v4/letter/b/e9c0ed/32.png) [@brebs](https://swi-prolog.discourse.group/u/brebs)\
**Post date:** [September 4, 2024, 5:58am UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/7 "2024-09-04T05:58:07Z")

</div>

> [@konokaiden](#):
>
> Input #\> 0,  
> integer(Input),  
> Input\>\>1 =:= (Input-1)/2.

That’s a strange mix of clpfd and non-clpfd.

Could use e.g.:

```prolog
?- freeze(X, integer(X)), X mod 2 #= 1, X = 5.
X = 5.

?- freeze(X, integer(X)), X mod 2 #= 1, X = 4.
false.

?- freeze(X, integer(X)), X mod 2 #= 1, X = z.
false.

```

---

<div class="post-metadata">

**Author:** ![konokaiden](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/konokaiden/32/6708_2.png) [@konokaiden](https://swi-prolog.discourse.group/u/konokaiden)\
**Post date:** [September 4, 2024, 1:48pm UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/8 "2024-09-04T13:48:57Z")

</div>

It took a little bit of struggling, but freeze does work. I forgot that #= subsumes both is/2 and =:=/2. Can I ask you two to check my rule for good/ideal syntax?

```prolog
odd(Input, Compare, Output) :-
	freeze(Input, (Input #> 0, integer(Input), Compare #= (Input-1) rdiv 2, Input>>1 #= Compare -> Output #= 1; Output #= 0)),
	freeze(Output, is(Output, 1) -> Input #= (Compare * 2) + 1; Input #= 2 * Compare).

```

If you set Input as 7, you do get true (Output has to be 1 or 0, because I’m getting a “Arithmetic: true/0 is not a function” error).

Also, for some reason, I can’t say that `Compare #= (Input-1)/2`, I have to say `Compare is (Input-1)/2`. It seems to be the division symbol throwing things off, but for now I am going with #= … div.

Is there a meaningful difference in using “#= div”, “#= rdiv”, or “is /” in terms of the number of calculations being done? The documentation says that div includes a modulo, but I don’t know how rdiv is different from div. I do know that by default, / is exact and does not prefer rationals.

---

<div class="post-metadata">

**Author:** ![brebs](https://avatars.discourse-cdn.com/v4/letter/b/e9c0ed/32.png) [@brebs](https://swi-prolog.discourse.group/u/brebs)\
**Post date:** [September 4, 2024, 6:22pm UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/9 "2024-09-04T18:22:45Z")

</div>

> [@konokaiden](#):
>
> Can I ask you two to check my rule for good/ideal syntax?

I’m too confused. What are you trying to achieve?

> [@konokaiden](#):
>
> if we know a number was odd, we can find what that number was (run it in reverse).

What does this mean? It’s trivially easy to count up from 1, incrementing by 2 each time, into infinity. Or use clpfd:

```prolog
?- I #> 0, I mod 2 #= 1.
I in 1..sup,
I mod 2#=1.

```

Or use clpBNR:

```prolog
?- [I, _I1, _I2]::integer(1, _), {_I1 == I + 1, _I2 == _I1 / 2}.
I::integer(1, 72057594037927933),
_I1::integer(2, 72057594037927934),
_I2::integer(1, 36028797018963967).

```

---

<div class="post-metadata">

**Author:** ![konokaiden](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/konokaiden/32/6708_2.png) [@konokaiden](https://swi-prolog.discourse.group/u/konokaiden)\
**Post date:** [September 4, 2024, 7:02pm UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/10 "2024-09-04T19:02:32Z")

</div>

> [@konokaiden](#):
>
> But the idea was to make a relation \<odd(In, Compare, Out)\> so that a rule involving odd-checking could work in reverse. This requires that I modify the odd/1 rule into something like an odd/3, which if I knew the answer (True / False being “Out” and what number the bit movement was compared to), I could generate the thing that was tested (In).

The two freeze statements allow me to either execute the forward direction (when Input is bound) or the reverse direction (when Output is bound). It is currently working, now I’m curious if this is a fairly good syntax, or if it would be better if it were rearranged / defined differently.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [September 4, 2024, 10:03pm UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/11 "2024-09-04T22:03:26Z")

</div>

For this situation, you could use var/1 or nonvar/1 instead of freeze/2, even though var/1 and nonvar/1 are “impure” and must be used carefully.  
Something like this (untested):

```prolog
odd(Input, Compare, Output) :-
	( nonvar(Input),
    -> Input #> 0, integer(Input), Compare #= (Input-1) rdiv 2, Input>>1 #= Compare -> Output #= 1; Output #= 0),
	; nonvar(Output)
    -> is(Output, 1) -> Input #= (Compare * 2) + 1; Input #= 2 * Compare
    ; throw(error(...)).

```

This is a fairly standard way of handling “bidrectional” predicates, if you don’t mind a bit more restrictions in the order that you call things (e.g., in this case, you can’t have both `Input` and `Output` unbound, then bind one of them after the call to `odd/3`).

---

<div class="post-metadata">

**Author:** ![brebs](https://avatars.discourse-cdn.com/v4/letter/b/e9c0ed/32.png) [@brebs](https://swi-prolog.discourse.group/u/brebs)\
**Post date:** [September 4, 2024, 11:59pm UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/12 "2024-09-04T23:59:25Z")

</div>

> [@konokaiden](#):
>
> `Input #> 0, integer(Input)`

The integer/1 there is pointless - clpfd ensures integers.

```prolog
?- X = 1.5, X #> 0.
ERROR: Domain error: `clpfd_expression' expected, found `1.5'

```

Perhaps put the integer check first, if you want simple failure rather than an error.

---

<div class="post-metadata">

**Author:** ![kwon-young](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/kwon-young/32/4841_2.png) [@kwon-young](https://swi-prolog.discourse.group/u/kwon-young)\
**Post date:** [September 6, 2024, 1:00pm UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/13 "2024-09-06T13:00:10Z")

</div>

After reading the whole topic, I believe there is an implicit subject that was not touched on in this thread.

From your initial formulation:

> I want to make a rule where I have three variables, Input, Compare, Output.  
> If the user supplies the Compare value, I want it to be run with that. If the user does  
> not supply a Compare, I want to set it.

Essentially, your `Compare` variable represent the _ **mode** _ of the predicate.  
Or in your own words, whether the predicate is running in forward or reverse mode.  
Usually, in prolog, we qualify the mode of variables. [In the documentation](https://www.swi-prolog.org/pldoc/man?section=modes), you will see variables annotated with either `+`, `-` or `?` that respectively means input, output or both.

So to go back to your problem, you actually don’t need that third variable `Compare` to specify the mode of your predicate.  
You can use different instantiation pattern of your predicate to evaluate either in forward or backward mode:

```prolog
?- odd(3, IsOdd). % call the predicate in forward mode, meaning: Is 3 odd ?
?- odd(X, 1). % call the predicate in backward mode, meaning: X is an odd number

```

Usually, forward mode is, well, straightforward to reason about and implement but you also need to ask yourself what it means to run in backward mode.  
In your example, calling `odd(X, 1)` means `X is an odd number`. However, since there is an infinity of odd numbers, what would you like prolog to return here ?

Usually, prolog provides two type of solutions:

1. iterate one solution at a time using backtracking. So calling `odd(X, 1)` would bind X to values like `1` then `3` then `5` and so on infinitely on backtracking (although this limits the solution to positive integers only…)
2. delay the goal until X is ground. This is what you do when using clpfd or clpBNR or freeze.

PS: here is another lengthy reply of mine about the `even/1` predicate : [Fully understanding the "intricacies" of the Prolog code design process - #40 by kwon-young](https://swi-prolog.discourse.group/t/fully-understanding-the-intricacies-of-the-prolog-code-design-process/7552/40)

---

<div class="post-metadata">

**Author:** ![konokaiden](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/konokaiden/32/6708_2.png) [@konokaiden](https://swi-prolog.discourse.group/u/konokaiden)\
**Post date:** [September 6, 2024, 6:47pm UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/14 "2024-09-06T18:47:03Z")

</div>

I absolutely love this, my only comment is that Compare would tell the odd function what it should output in the reverse direction.

This is because Compare stores the odd number when its bits were moved to the right. Moving those bits to the left then results by default in an even number which is always 1 less than the odd it came from, if it was originally odd, or the same number if it was originally even.

Thus knowing if it was odd allows you to decide whether or not to add a 1 to get the regenerated number.

---

<div class="post-metadata">

**Author:** ![kwon-young](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/kwon-young/32/4841_2.png) [@kwon-young](https://swi-prolog.discourse.group/u/kwon-young)\
**Post date:** [September 6, 2024, 8:12pm UTC](https://swi-prolog.discourse.group/t/set-a-default-value-for-a-variable-if-it-is-not-provided-by-user/7760/15 "2024-09-06T20:12:40Z")

</div>

Ha, I did not catch what you wanted to do with `Compare`.

> [@konokaiden](#):
>
> This is because Compare stores the odd number when its bits were moved to the right.

Well, based on this, `Compare` actually becomes an additional variables that can have different modes.  
This complicates the instantiation patterns even further. This is where constraints shines most, since you can just states your constraints and the prolog engine does the rests.  
You can actually simplify your implementations with the following two statements:

```prolog
odd(Input, Compare, Output) :-
    Output in 0..1,
    Input #= Compare * 2 + Output.

```

So, here:

1. `Input` can be any number
2. `Compare` is `Input // 2`
3. `Output` is 0 or 1, representing the oddity of `Input` and luckily it exactly correspond to the rest of `Input` divided by 2 🙂

Try to call the predicate in any way, with any instantiation patterns and you will see that it will work both in forward or reverse mode, although with 3 variables, it starts to become foggy what input/output, forward/backward even is…
