Nope because the ! also cuts possible other clauses, so we need to really do a cut.
My personal preference for it over
comes from writing or
statements using ;
but then when running the code it would leave choice-points and the easiest way to fix that was to add the cut (!
).
However when designing code and I am not sure if I will have to add something for both outcomes of the conditional I will use the conditional with one of the branches being true
.
It is a bit misleading to talk about âor statementsâ in Prolog, I think. It is not an âor statementâ because it is not a statement and it isnât an âorâ in the widely accepted use of both these terms/concepts in programming.
Just repeating @jan now (nothing of substance coming from me).
This construct:
( condition
-> then
; else
)
is about as close as you can get to an âif-then-elseâ using conventional Prolog.
This is another way to write the same, wrapping it in a predicate:
foo :-
condition,
!,
then.
foo :-
else.
It starts getting confusing really fast though.
condition
on its own, outside of those constructs, might leave choice points (and maybe succeed multiple times), and there is no obvious analogy to those in a programming language like C or Java.
condition
might also have a side effect. In C at least there are idioms where the condition has a side effect, on purpose, like the good old
while ((c = getchar()) != EOF)
⌠but with Prolog, having a condition with a side effect is a code smell?
PS: the reason why I used to think of this construct as a âguardâ:
foo :- guard_a, !, a.
foo :- guard_b, !, b.
...
foo :- default.
is that I had recently read in a hurry some stuff about Erlang. There is something very similar in Erlang and there are guards. However! if memory serves correctly, you cannot use just anything as a guard in Erlang. Translating this to Prolog, it can only be side-effect free, and not instantiate its arguments any further! While in Prolog, you can have anything you want in the condition
part, with varying levels of surprise as a result.
Good point.
That should be re-worded but I will leave for now as it was not meant to be a technical description but something that gets the thought across as why I use one style versus the other.
Yes, I think I understood what you meant, I was only pointing out that it might be adding confusion. But then again my comments are also adding confusion and so onâŚ
Thank you for the link. A very precursory text search of the 27-page document (Ctrl + F in my browserâs PDF viewer) shows that the word âstatementâ is not used even once; âexpressionâ is used 7 times (outside of the TOC and the page headers); the only occurrence of âorâ outside of normal sentence structure is in the snippet you show.
In the dead-tree books that I can easily access, âstatementâ is not indexed in âThe Art of Prologâ, and is indexed in âThe Craft of Prologâ as the DCG rule statement//1
, in the context of writing a parser for an âextensible programming languageâ.
In the paper âCoding guidelines for Prologâ, as found here:
http://www.covingtoninnovations.com/mc/plcoding.pdf
⌠a full text search for âstatementâ also finds nothing.
I am sharing this because I got worried that am I spreading misinformation.
That entire post would make for a Nice to know
FYI
Pack transpiler by Anderson Green
AFAIK Anderson is not here but he frequents StackOverflow.
StackOverlfow user Anderson Green
Pack pfd_meta by Nicos Angelopoulos
NB true/0 is valid for calling in a meta interpreter but has the property foreign
true/0 is one of the control predicates.
Details
?- predicate_property(true,P).
P = visible ;
P = built_in ;
P = foreign ;
P = static ;
P = imported_from(system) ;
P = nodebug ;
P = iso ;
P = defined ;
P = size(144) ;
false.
EDIT
Oddly false
is not foreign
?- predicate_property(false,P).
P = interpreted ;
P = visible ;
P = built_in ;
P = static ;
P = imported_from(system) ;
P = file('c:/program files/swipl/boot/init.pl') ;
P = line_count(473) ;
P = nodebug ;
P = number_of_clauses(1) ;
P = number_of_rules(1) ;
P = last_modified_generation(92) ;
P = iso ;
P = defined ;
P = size(240) ;
false.
Very useful, thanks!
As we have fail
, false is easily defined as false :- fail
. Without some bootstrapping it becomes ugly. Not defining raise an error. Using dynamic or multifile allows the user to define it (also as something not failing). So, we are left with stuff such as fail :- 1 \== 2
. That would work, but isnât particularly neat in my view.
Note that fail/0 is old. The false/0 variant is more recent. I like it for the toplevel, but rarely use it in code. These predicates are mostly used in a procedural context where fail/0 is quite adequate.
One use of meta-interpreters is for partial evaluation. This can be used for program optimization, type inferencing, custom debuggers, alternative evaluation strategies (e.g., breadth-first), and probably other things.
If your meta-interpreter needs to be aware of modules then it gets more complex. See this post by Jan W.