Wiki Discussion: Meta interpreter

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… :wink:

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!

1 Like

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.

1 Like

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.

1 Like