# Functional macro expansion revised for pack pac-1.6.0

EDIT 2021-08-28T15:00:00Z (Signature Added for kind rules (pac-1.6.2) )

example signature for set operations

Note that closures are allowed for semantics of signature symbols.

:- bekind(set, [nonvar, stop]).
sgn(emptyset, 0, []).
sgn([], 0,	[]).
sgn([X|Y], 0, [X|Y]).
sgn(+, 2,	union).
sgn(plus, 2, pred([X, Y, Z]:-union(X, Y, Z))).
sgn(yaplus, 2, fun([X, Y]>> :union(X, Y))).
sgn(yayaplus, 2, fun([X, Y]>> :union@X@Y)).
sgn(&, 2,	intersection).
sgn(\, 2,	subtract).
sgn(pow, 1, powerset).
sgn(++, 2,	direct_sum).
sgn(*, 2,	cartesian).
sgn(#, 2,	scramble_cons).
singleton(A) = xargs([X] -> [X])@ A.
:- ekind.

expanded clauses for the set signature
% ?- listing(set).
%@ set(A, []) :-
%@     var(A),
%@     !,
%@     false.
%@ set(emptyset, []) :-
%@     !.
%@ set([], []) :-
%@     !.
%@ set([A|B], [A|B]) :-
%@     !.
%@ set(A+B, C) :-
%@     !,
%@     set(A, D),
%@     set(B, E),
%@     union(D, E, C).
%@ set(plus(A, B), C) :-
%@     !,
%@     set(A, D),
%@     set(B, E),
%@     'pac#4'(D, E, C).
%@ set(yaplus(A, B), C) :-
%@     !,
%@     set(A, D),
%@     set(B, E),
%@     'pac#5'(D, E, C).
%@ set(yayaplus(A, B), C) :-
%@     !,
%@     set(A, D),
%@     set(B, E),
%@     'pac#6'(D, E, C).
%@ set(&(A, B), C) :-
%@     !,
%@     set(A, D),
%@     set(B, E),
%@     intersection(D, E, C).
%@ set(\(A, B), C) :-
%@     !,
%@     set(A, D),
%@     set(B, E),
%@     subtract(D, E, C).
%@ set(pow(A), B) :-
%@     !,
%@     set(A, C),
%@     powerset(C, B).
%@ set(++(A, B), C) :-
%@     !,
%@     set(A, D),
%@     set(B, E),
%@     direct_sum(D, E, C).
%@ set(A*B, C) :-
%@     !,
%@     set(A, D),
%@     set(B, E),
%@     cartesian(D, E, C).
%@ set(#(A, B), C) :-
%@     !,
%@     set(A, D),
%@     set(B, E),
%@     scramble_cons(D, E, C).
%@ set(singleton(A), [B]) :-
%@     !,
%@     set(A, B).
%@ set(A, A) :-
%@     !.
%@
%@ true.

old style example for kind rules
% :- bekind(yaset, [nonvar, stop, flip([2,1])]).
:- bekind(yaset, [nonvar, stop]).
emptyset = [].
X = X :- is_list(X), !.
singleton(A) = xargs([X] -> [X])@ A.
+(A, B)	= :union@A@B.
&(A, B) = :intersection @ A @ B.
\(A, B) = :subtract@ A @ B.
pow(A)	= :powerset@ A.
++(A, B) = :direct_sum @ A @ B.
*(A, B) = :cartesian @ A @ B.
#(A, B) = :scramble_cons @ A@ B.
:- ekind.

expanded clauses for the old style kind rules
% ?- listing(yaset).
%@ yaset(A, []) :-
%@     var(A),
%@     !,
%@     false.
%@ yaset(emptyset, []) :-
%@     !.
%@ yaset(A, A) :-
%@     is_list(A),
%@     !.
%@ yaset(singleton(A), [B]) :-
%@     !,
%@     yaset(A, B).
%@ yaset(A+B, C) :-
%@     !,
%@     yaset(A, D),
%@     yaset(B, E),
%@     union(D, E, C).
%@ yaset(&(A, B), C) :-
%@     !,
%@     yaset(A, D),
%@     yaset(B, E),
%@     intersection(D, E, C).
%@ yaset(\(A, B), C) :-
%@     !,
%@     yaset(A, D),
%@     yaset(B, E),
%@     subtract(D, E, C).
%@ yaset(pow(A), B) :-
%@     !,
%@     yaset(A, C),
%@     powerset(C, B).
%@ yaset(++(A, B), C) :-
%@     !,
%@     yaset(A, D),
%@     yaset(B, E),
%@     direct_sum(D, E, C).
%@ yaset(A*B, C) :-
%@     !,
%@     yaset(A, D),
%@     yaset(B, E),
%@     cartesian(D, E, C).
%@ yaset(#(A, B), C) :-
%@     !,
%@     yaset(A, D),
%@     yaset(B, E),
%@     scramble_cons(D, E, C).
%@ yaset(A, A) :-
%@     !.
%@
%@ true.


EDIT 2021.8.28

I have updated pac-1.6.0 to pac-1.6.1, to which I have added a minor simplification on expand_exp/8
in library(pac(prolog/pac/expand-pac.pl), which seems more close to the policy along the semantic equation below. I will edit document on functional macros of the pac later.

% ?- eval( (X\X)@ (Y\Y)@ (Z\Z), V).
%@ V = pac:'pac#3'(pac:'pac#1', pac:'pac#2').

% ?- eval( :((X\X)@ (Y\Y)), V).
%@ V = pac:'pac#7'.


Expanded codes are displayed with show_exp/1 like this.

% ?- show_exp((X\X)@ (Y\Y)@ (Z\Z)).
%@ pac#14(pac#12,pac#13), where
%@ pac#12(A,A):-true
%@ pac#13(A,A):-true
%@ pac#14(A,A):-true
%@ true .


EDIT END.

As I found my package pac-1.5.7 broken after some recent swipl-devel git, fixing a bug in pac-1.5.7, on this occasion I have reviewed codes on functional macros expansion mainly in expand-exp.pl and updated to pac-1.6.0. The trouble was caused by a bad use of b_setval, which is related, I guess, to what Jan warned. While reviewing, I kept in in mind that behavior of functional macros, that is, eval/2, eval/3should follow a simple semantic equation as possible as I could, though there must be much room to be revised further.

\def\sem#1{[\![#1]\!]}
\sem{ e_0@e_1@e_2@\cdots@e_n}=\sem{e_0}(\sem{e_1}, \sem{e_2}, \ldots, \sem{e_n})

A few of sample queries on eval follows.

%   swipl
?- pack_install(pac).
% Contacting server at https://www.swi-prolog.org/pack/query ... ok
% Pack pac' is already installed @1.6.0
true.

?- use_module(library(pac)).
true.

?- module(pac).
true.

?- eval(append, V).
V = append.

?- eval(append@[a,b], V).
V = append([a, b]).

?- eval(append@[a,b]@[c,d], V).
V = append([a, b], [c, d]).

?- eval(append@[a,b]@[c,d]@U, V).
V = append([a, b], [c, d], U).

?- eval(:append@[a,b]@[c,d], V).
V = [a, b, c, d].

?- eval(:append@ (:append@[a,b]@[c,d]) @ (:append@([e,f])@[g,h]) , V).
V = [a, b, c, d, e, f, g, h].

?- eval(:fun([F,X,Y]-> (:F)@X@Y) @ append @ [1,2,3] @ [a, b, c], V).
V = [1, 2, 3, a, b, c].
`

Kuniaki Mukai