Syntax sugar aka sort-of-"macro"

Normally you would do

foo(..., RV), bar(..,RV,..)

is it possible to create :

$(Term) :- ....

such that writing this :

$foo(...) translates to foo(...,FOO)

so that it becomes from :

$foo(...), bar(..,FOO,..)

to this :sever


foo(..., FOO), bar(..,FOO,..)


?- write_canonical($foo()).
$(foo())
true.

?- write_canonical($foo(abc)).
$(foo(abc))
true.

now that i red the answers … i should not have called for FUNCTION…

what i want is literally what i wrote i.e. create a clause on the fly with a FOO var.

from what i saw…the examples are a way to chain functions…like linux pipe … i want that but i also want to use the VAR across the body i.e. this

foo(…, FOO), bar(…,FOO,…)

but also this :

foo(…, FOO), …more,stuff,in,between,… bar(…,FOO,…)

seems more like a macro to be done at compile time…!! rather than a function

IBM Prolog did something very similar (I think it used ?; I don’t remember if it also needed a declaration that a predicate could be used as a function). I suppose the transformation would require wrapping the call with once/1 unless the predicate is known to be deterministic.

I suppose it wouldn’t be difficult to support, given that “.” is already expanded out in a similar way. And, it would allow writing, e.g.:

length([_|Xs], $succ(Len0)) :-
    length(Xs, Len0).

But this wouldn’t work well with is/2, although it would be easy to define expr(Expr,Number):-Number is Expr, allowing:

length(List, Len) :- length(List, 0, Len).
length([], Len, Len).
length([_|Xs], LenSoFar, Len) :-
    length(Xs, $expr(LenSoFar+1), Len).

This would be a nice complement to “lambda” (library(yall)).

1 Like

i’m ok if it does backtracking i.e it is not pure function…in fact i prefer it

1 Like

If the function appears in the head, the expansion is a bit trickier than for expanding “.” for dicts. If I take my example …

length([_|Xs], $succ(Len0)) :-
    length(Xs, Len0).

the expansion should be this if Len is instantiated:

length([_|Xs], Len) :-
    succ(Len0, Len),
    length(Xs, Len0).

but this, if Len isn’t instantiated:

length([_|Xs], Len) :-
    length(Xs, Len0),
    succ(Len0, Len).

I could see this causing some confusion, although listing/1 would should the expansion.

I wrote a tiny module ten years ago, lifter.pl, that you can try using its test module.

From packages you can download func or function_expansion, by M.Hendricks, or fnotation.

2 Likes

Note that from my experience with ‘.’, reliable handling of functional notation given meta-predicates is nearly impossible. I guess that might be a reason why most of this stuff is in peoples personal libraries or local to specific projects and never got mainstream.

In the end you get used to the extra line :slight_smile: I think it mostly results from people coming to Prolog and wanting to pursue what they were used to. Prolog has disadvantages and advantages :slight_smile: