1:- module(meta,
    2	  [foldr/4, iterate/3,
    3	   for/3, foldnum/4,
    4	   fold/3, fold/4, fold/5,
    5	   do/3,
    6	   mapterm_rec/3,
    7	   maplist_opp/3,
    8	   repeat/2, monad/3, time/3,
    9	   until/4, while/4,
   10	  iff/2, cputime/1, cputime/0,
   11	  pred_eval/2, pred_eval/3
   12	  ]
   13	 ).   14
   15
   16:- use_module(pac(basic)).   17:- use_module(pac(op)).
 do(+F, +A, -B) is det
Similar to meta predicate phrase/2,3, but works not only for list processing. F must not contain ! (cut), mainly simplicity for interpretation.
   24:- meta_predicate do(:, ?, ?).   25
   26% ?- do((append([a,b]), append([c,d])), [x,y], R).
   27
   28do(M:X, A, B):- once(do(X, A, B, M)).
   29%
   30do(M:X, A, B, _)	:-!, do(X, A, B, M).
   31do((X,Y), A, B, M)	:-!, do(X, A, C, M), do(Y, C, B, M).
   32do((X;Y), A, B, M)	:-!, ( do(X, A, B, M);  do(Y, A, B, M)).
   33do((X->Y), A, B, M)	:-!, ( do(X, A, C, M) ->  do(Y, C, B, M)).
   34do({G}, A, A, M)	:-!, call(M:G).
   35do(X, A, B, M)		:- call(M:X, A, B).
   36
   37% Experimental [2023/10/30]
   38% ?-  maplist(=([_,_]), [[a,b],[a,c]]).			% false
   39% ?-  maplist(local(=([_,_])), [[a,b],[a,c]]).	% true
   40% ?-  maplist(pred([[_,_]]), [[a,b],[a,c]]).	% true
   41% ?-  maplist(local(pred([[_,_]])), [[a,b],[a,c]]).	% true
   42% ?-  maplist(local(local(pred([[_,_]])), [[a,b],[a,c]])).	% true
   43user:local(X):- copy_term(X, Y), call(Y).
   44user:local(X,A):- copy_term(X, Y), call(Y,A).
   45user:local(X,A,B):- copy_term(X, Y), call(Y,A,B).
   46user:local(X,A,B,C):- copy_term(X, Y), call(Y,A,B,C).
   47user:local(X,A,B,C,D):- copy_term(X, Y), call(Y,A,B,C,D).
   48user:local(X,A,B,C,D,E):- copy_term(X, Y), call(Y,A,B,C,D,E).
   49
   50% if-and-only-if condition test.
   51% ?- meta:iff(true, member(X, [1,2])).
   52iff(C0, C1) :- \+( (C0,\+C1) ; (C1, \+C0)).
   53
   54% ?- flip_call([2,1], 1+2 is X).
   55% ?- flip_call([1,2], 1+2 is X, A is B).
   56% ?- flip_call([1, 3, 2], between(4, X, 6)).
   57% ?- flip_call(1+2 is X).
   58% ?- flip_call([3,2,1], append(A, [1,2], [3,4])).
   59
   60:- meta_predicate user:flip_arg(2, ?, ?).   61user:flip_arg(F, X, Y):- call(F, Y, X).
   62
   63% ?- listing(flip).
   64user:flip_call(G) :- flip_call([2,1], G).  % Binary is default.
   65%
   66user:flip_call(Is, G):- flip_call(Is, G, G0), call(G0).
   67
   68
   69
   70%
   71flip_call(Is, M:X, M:Y):-!, flip_call(Is, X, Y).
   72flip_call(Is, X, Y):- length(Is, N),
   73	functor(X, F, N),
   74	functor(Y, F, N),
   75	flip_call(Is, 1, X, Y).
   76
   77%
   78flip_call([], _, _, _).
   79flip_call([I|Is], J, X, Y):-
   80	arg(J, X, A),
   81	arg(I, Y, A),
   82	!,
   83	J0 is J + 1,
   84	flip_call(Is, J0, X, Y).
   85
   86:- meta_predicate foldr(3, ?, ?, ?).   87foldr(_, [], X, X):-!.
   88foldr(F, [A|L], X, Y):- call(F, A, Y, Y0), foldr(F, L, X, Y0).
   89
   90% ?- foldl(cons, [a,b,c,d], [], R).
   91% ?- foldl(pred([X, Y, [X|Y]]), [1,2,3,4], [], R).
   92% ?- foldr(pred([X, [X|Y], Y]), [1,2,3,4], R, []).
   93% ?- foldr(flip([1,3,2], pred([X, [X|Y], Y])), [1,2,3,4], [], R).
   94% ?- foldl(flip([1,3,2], pred([X, Y, [X|Y]])), [1,2,3,4], R, []).
   95% ?- foldr(pred([X, Y, [X|Y]]), [1,2,3,4], [], R).
   96% ?- fold_paths_of_term(pred([A,[A|B], B]), f(1,2), X, []).
   97fold_paths_of_term(G, T, X, Y):- fold_paths_of_term([[T]], [], X, Y, G).
   98%
   99fold_paths_of_term([], _, X, X, _):-!.
  100fold_paths_of_term([Ts|L], P, X, Y, G):-
  101	(	Ts==[]
  102	->	fold_paths_of_term(L, P, X, Y, G)
  103	;	Ts=[T|Rs],
  104		fold_paths_of_term(T, [Rs|L], P,  X, Y, G)
  105	).
  106%
  107fold_paths_of_term(T, Ls, P, X, Y, G):- atomic(T), !,
  108	call(G, [T|P], X, Xtp),
  109	fold_paths_of_term(Ls, P, Xtp, Y, G).
  110fold_paths_of_term(T, Ls, P, X, Y, G):- T=..[F,A|As],
  111	fold_paths_of_term(A, [As|Ls], [F|P], X, Y, G).
  112
  113% ?- fold_args(plus, f(1,2,3,4), 0, S).
  114% ?- fold_args(pred([X, Y, Z]:- Z is X + Y), f(1,2,3,4), 0, S).
  115fold_args(F, V, A, B):-
  116	fold_args(1, F, V, A, B).
  117%
  118fold_args(I, F, V, A, B):-	arg(I, V, Vi), !,
  119	call(F, Vi, A, Ai),
  120	I1 is I+1,
  121	fold_args(I1, F, V, Ai, B).
  122fold_args(_I, _F, _V, _A, _B).
  123
  124% ?- mapargs(pred([A, [A, A]]), (a,b), Out).
  125% ?- mapterm(pred([A, [A, A]]), (a,b), Out).
  126% ?- mapsubterms(pred([A, [A, A]]), (a,b), Out).
  127% ?- mapsubterms(pred([A, [A, A]]), f(h(a),g(b)), Out).
  128%@ Out = [f(h(a), g(b)), f(h(a), g(b))].
  129
  130
  131% mapterm(F, A, B):-
  132% 	functor(A, Fa, Na),
  133% 	functor(B, Fa, Na),
  134% 	mapterm(1, F, A, B).
  135% %
  136% mapterm(I, F, A, B):- arg(I, A, Ai), !,
  137% 	call(F, Ai, Bi),
  138% 	arg(I, B, Bi),
  139% 	J is I+1,
  140% 	mapterm(J, F, A, B).
  141% mapterm(_, _, _, _).
  142
  143
  144% ?- callargs(write, (a,b)).
  145callargs(F, A):- callargs(1, F, A).
  146%
  147
  148callargs(I, F, A):- arg(I, A, Ai), !,
  149	call(F, Ai),
  150	J is I+1,
  151	callargs(J, F, A).
  152callargs(_, _, _).
  153
  154
  155% ?- Y = f(1, 2), trace, nopac((meta:mapargs(=, count(2, 1, 1), f(a,b), Y))).
  156%@    Call: (11) meta:mapargs(=, count(2, 1, 1), f(a, b), f(1, 2)) ? no debug
  157%@ Y = f(a, b).
  158
  159% ?- Y = f(1, 2), meta:mapargs(=, count(1, 2, 2), f(a,b), Y).
  160% ?- Y = g(1, 2), mapargs(=, count(1, 1, 2), f(a,b), Y).
  161% mapargs(F, count(N, I, J), A, B):- mapargs(N, I, J, F, A, B).
  162% %
  163% mapargs(0, _, _, _, _, _):-!.
  164% mapargs(N, I, J, F, A, B):- arg(I, A, Ai),
  165% 	call(F, Ai, Bj),
  166% 	setarg(J, B, Bj),
  167% 	N1 is N-1,
  168% 	I1 is I+1,
  169% 	J1 is J+1,
  170% 	mapargs(N1, I1, J1, F, A, B).
  171
  172% ?- help(mapterm).
  173
  174
  175% ?- meta:scanargs(pred([I, X, I-X]), f(a,b), Z).
  176scanargs(F, A, B):- ( var(A)
  177					->	functor(B, C, N),
  178						functor(A, C, N)
  179					;	functor(A, C, N),
  180						functor(B, C, N)
  181					),
  182	scanargs(1, N, F, A, B).
  183%
  184scanargs(I, N, _, _, _):- I > N, !.
  185scanargs(I, N, F, A, B):- arg(I, A, Ai),
  186	arg(I, B, Bi),
  187	call(F, I, Ai, Bi),
  188	J is I +1,
  189	scanargs(J, N, F, A, B).
  190
  191% ?- meta:scanargs(pred([I, I]), f(A, B)).
  192scanargs(F, A):- functor(A, _,  N),
  193	scanargs_(1, N, F, A).
  194%
  195scanargs_(I, N, _, _):- I > N, !.
  196scanargs_(I, N, F, A):- arg(I, A, Ai),
  197	call(F, I, Ai),
  198	J is I + 1,
  199	scanargs_(J, N, F, A).
  200
  201
  202% ?- Z = g(x,y), meta:setargs(pred([I, J, I-J]), f(a,b), Z).
  203setargs(F, A, B):-  functor(A, C, N),
  204		( var(B)
  205		->	functor(B, C, N)
  206		;	true
  207		),
  208		setargs(1, N, F, A, B).
  209%
  210setargs(I, N, _, _, _):- I > N, !.
  211setargs(I, N, F, A, B):- arg(I, A, Ai),
  212	call(F, I, Ai, Bi),
  213	setarg(I, B, Bi),
  214	J is I + 1,
  215	setargs(J, N, F, A, B).
  216
  217% ?- A = f(a,b), meta:setargs(pred([I, X, I-X]), A).
  218setargs(F, A):- functor(A, _,  N),
  219	setargs_(1, N, F, A).
  220%
  221setargs_(I, N, _, _):- I > N, !.
  222setargs_(I, N, F, A):- arg(I, A, Ai),
  223	call(F, I, Ai, Bi),
  224	setarg(I, A, Bi),
  225	J is I + 1,
  226	setargs_(J, N, F, A).
  227
  228% ?-  maprows(zdd:inner_prod(f(1,2)), m(f(1,2), f(3,4)), B).
  229%@ B = f(7, 10).
  230% ?-  maprows(zdd:inner_prod(f(1,2)), m(f(1,2,3), f(3,4,5)), B).
  231%@ B = f(7, 10, 13).
  232maprows(_, A, A):- atom(A), !.
  233maprows(F, A, B):- arg(1, A, A1),
  234	functor(A1, Fa, Na),
  235	functor(B, Fa, Na),
  236	maprows(Na, F, A, B).
  237%
  238maprows(0, _, _, _):-!.
  239maprows(I, F, A, B):- arg(I, B, Bi),
  240	call(F, I, A, Bi),
  241	J is I - 1,
  242	maprows(J, F, A, B).
  243
  244%
  245until(F, S, X, Y):- call(S, X, X0),
  246	(	call(F, X0) -> Y = X0
  247	;   until(F, S, X0, Y)
  248	).
  249%
  250iterate(_, stop(X), X):-!.
  251iterate(S, X, Y):-	call(S, X, X0),
  252	iterate(S, X0, Y).
  253
  254while(F, S, X, Y):-
  255	(	call(F, X) ->
  256		call(S, X, X0),
  257		while(F, S, X0, Y)
  258	;   Y = X
  259	).
  260
  261%	process(+Delta/2, +Final/1, ?S:state, ?S0:state) is semidet.
  262%	Starting with initial state S, repeat applying Delta
  263%	to the successive states until the state
  264%	satisfies the condition Final/1, with which S0 is unified.
  265
  266% :- meta_predicate process(1, 2, +, -).
  267% process(Final, _, S, S):- call(Final, S).
  268% process(Final, Delta, S, S0):-
  269% 		call(Delta, S, S1),
  270% 		process(Final, Delta, S1, S0).
  271
  272:- meta_predicate for(?, 1).  273for(I..J, F):-!, for(I, J, F).
  274for(I-J, F):-for(I, J, F).
  275
  276%
  277for(I, J, _):- I>J, !.
  278for(I, J, F):- call(F, I), !,
  279		I0 is I + 1,
  280		for(I0, J, F).
  281
  282% ?- F = plus, meta:foldnum(F, 1-2, 0, R).
  283% ?- foldnum(pred([X,Y,Z]:-plus(X, Y, Z)), 1-2, 0, R).
  284% ?- foldnum(plus, 1-2, 0, R).
  285% ?- let(X, pred([I,[I|U], U])), foldnum(X, 1-10, R, []).
  286
  287:- meta_predicate foldnum(3, ?, ?, ?).  288foldnum(F, I-J, U, V):-!, foldnum(I, J, U, V, F).
  289foldnum(F, I..J, U, V):- foldnum(I, J, U, V, F).
  290%
  291foldnum(I, J, U, U, _):- I>J, !.
  292foldnum(I, J, U, V, F):- call(F, I, U, U0),
  293	K is I + 1,
  294	foldnum(K, J, U0, V, F).
  295
  296% REMARK. ":- meta_predicate maplist_opp(:, ?, ?)" NOT work.
  297maplist_opp([F|Fs], X, [FX|Y]):- call(F, X, FX), !,
  298	maplist_opp(Fs, X, Y).
  299maplist_opp([], _, []).
  300
  301%
  302:- meta_predicate map(2, ?, ?).  303map(P) --> maplist(phrase(P)).
  304%
  305:- meta_predicate phrase_list(2, ?, ?).  306phrase_list(P) --> maplist(phrase(P)).
  307
  308% ?- repeat(_, write(.)).
  309% ?- repeat(10, write(.)).
  310% ?- repeat(between(1, 20, I), writeln(I)).
  311:- meta_predicate repeat(?, 0).  312repeat(1, G):-!, call(G).
  313repeat(N, G):- simple_int_exp(N), !,
  314			   N0 is N,
  315			   (between(1, N0, _), call(G), fail; true).
  316repeat(P, G):- (call(P), call(G), fail) ; true.
  317%
  318repeat_cond(N, between(1, N0, _)):- simple_int_exp(N), !,  N0 is N.
  319repeat_cond(X, X).
  320%
  321simple_int_exp(N):- integer(N).
  322simple_int_exp(E):- ground(E),
  323	functor(E, F, _),
  324	memberchk(F, [+,-,^,mod, //]).
  325
  326%%% for statistics
  327% ?- time(repeat(10^8, X is 1 + 2), Time).
  328%@ Time = 9.844715.
  329% ?- N is 10^8, time(repeat(between(1, N,_), X is 1 + 2), Time).
  330%@ N = 100000000,
  331%@ Time = 9.896004999999999.
  332
  333
  334:- meta_predicate time(0, ?).  335time(G, T):-  time(G, T0, T1), T is T1-T0.
  336%
  337time(G, T, T0):-  statistics(cputime, T),
  338	call(G),
  339	statistics(cputime, T0).
  340
  341% ?- apropos(variables).
  342% ?- cputime, A=(X=1), cputime(100, A, T), cputime(Total).
  343% ?- cputime, A=(X=1), cputime(10000000, A, T), cputime(Total).
  344% ?- cputime, cputime(10000000, X=1, T), cputime(Total).
  345% ?- cputime, cputime(10000000, (b_setval(x,1), b_getval(x, Y)), T), cputime(Total).
  346% ?- cputime, cputime(10000000, (X=1, Y=X), T), cputime(Total).
  347% ?- cputime, cputime(1000000, X=1, T), cputime(Total).
  348:- meta_predicate cputime(?, 0, ?).  349%
  350cputime(N, G, T):- writeln("Running pac runtime library cputime/3...  "),
  351				   cputime(N, G, 0.00, T).
  352%
  353cputime(0, _G,  T, T).
  354cputime(N, G, T, T0):-  succ(N0, N),
  355						cputime_for_step(G, S),
  356						T1 is T + S,
  357						cputime(N0, G, T1, T0).
  358%
  359cputime_for_step(G, T):-
  360	statistics(cputime, T0),
  361	call(G),
  362	statistics(cputime, T1),
  363	T is T1-T0.
  364%
  365cputime:- statistics(cputime, T), b_setval(cputime, T).
  366cputime(T):- statistics(cputime, Stop), b_getval(cputime, Start), T is Stop - Start.
  367
  368% ?- cputime(10000000, true, T).
  369% ?- meta:cputime(1000, (A=a, B=A), T).
  370% ?- meta:cputime(1000, (b_setval(a, b), b_getval(a, B)), T).
  371
  372% monad/3
  373:- meta_predicate monad(:, ?, ?).  374monad(G, X, Y):- once(ml:bind_context(G, (X, []), (Y, _))).
  375
  376% ?- trace.
  377% ?- pred_eval(=, f(a, b), V).
  378% ?- pred_eval(append(union([a],[b]), union([c],[d])), R).
  379%@ R = [a, b, c, d].
  380
  381pred_eval(X, Y):- pred_eval(call, X, Y).
  382
  383:- meta_predicate pred_eval(2, ?, ?).  384pred_eval(_, X, X):- ( var(X); number(X); string(X); is_list(X)), !.
  385pred_eval(P, X, V):- atom(X), !, call(P, X, V).
  386pred_eval(P, X, V):- functor(X, F, N),
  387	functor(Y, F, N),
  388	pred_eval_args(1, P, X, Y),
  389	call(P, Y, V).
  390%
  391pred_eval_args(I, P, X, Y):- arg(I, X, A), !,
  392	arg(I, Y, B),
  393	pred_eval(P, A, B),
  394	J is I + 1,
  395	pred_eval_args(J, P, X, Y).
  396pred_eval_args(_, _, _, _).
  397
  398
  399% recursive mapterm.
  400:- meta_predicate mapterm_rec(2, ?, ?).  401
  402% ?- mapterm_rec(=, f(g(a, b), h(c)), X).
  403
  404mapterm_rec(_, A, B):- var(A), !, B = A.
  405mapterm_rec(F, A, B):- atomic(A), !, call(F, A, B).
  406mapterm_rec(F, A, B):- functor(A, Fa, Na),
  407	functor(B, Fa, Na),
  408	mapterm_rec(F, 1, A, B).
  409%
  410mapterm_rec(F, I, A, B):- arg(I, A, Ai), !,
  411	arg(I, B, Bi),
  412	mapterm_rec(F, Ai, Bi),
  413	J is I + 1,
  414	mapterm_rec(F, J, A, B).
  415mapterm_rec(_, _, _, _):-!.
  416
  417% recursive maplist.
  418:- meta_predicate maplist_rec(2, ?, ?).  419maplist_rec(_, [], []):-!.
  420maplist_rec(F, [X|Xs], [Y|Ys]):-
  421	(	X = [_|_]
  422	->  maplist_rec(F, X, Y)
  423	;	call(F, X, Y)
  424	),
  425	maplist_rec(F, Xs, Ys).
  426
  427% ?- fold(M, member(M, [1,2,3]), cons, [], X).
  428%@ X = [3, 2, 1].
  429
  430:- meta_predicate fold(?, :, :, ?, ?).  431fold(V, G, A, X, Y):-	Acc = '$ACC'(X),
  432	(	call(G),
  433		arg(1, Acc, U),
  434		call(A, V, U, W),
  435		nb_setarg(1, Acc, W),
  436		fail
  437	;	arg(1, Acc, Y)
  438	).
  439
  440% ?- Sum = acc(0), fold(J,
  441%	between(1, 3, J), test_add_to_acc, Sum).
  442test_add_to_acc(X, Acc):- arg(1, Acc, V),
  443	V0 is X + V,
  444	nb_setarg(1, Acc, V0).
  445
  446:- meta_predicate fold(?, :, :, ?).  447fold(V, G, Fun, X):-
  448		(	call(G),
  449			call(Fun, V, X),
  450			fail
  451		;	true
  452		).
  453
  454% ?- fold(I, between(1, 3, I), writeln).
  455% ?- fold(I, between(1, 3, I), X^(Y is X*X, writeln(Y))).
  456:- meta_predicate fold(?, :, ?).  457fold(V, G, V^Act):-!,
  458	(	call(G),
  459		call(Act),
  460		fail
  461	;	true
  462	).
  463fold(V, G, A):-
  464	(	call(G),
  465		call(A, V),
  466		fail
  467	;	true
  468	).
  469
  470% ?- N=100, time(repeat(N, det_foreach(between(1,5,J), member(J, L)))).
  471%@ % 7,201 inferences, 0.001 CPU in 0.001 seconds (94% CPU, 8277011 Lips)
  472%@ N = 100.
  473% ?- det_foreach(between(1,5,N),  member(r(N),L)).
  474%@ L = [r(1), r(2), r(3), r(4), r(5)|_].
  475% exists M exists L forall J  (between(1,5, J) -> (member(J, L), member(J, M))).
  476% ?- det_foreach(between(1,5, J), (member(J, L), member(J, M))).
  477%@ L = [1, 2, 3, 4, 5|_],
  478% exists L forall J  (between(1,5, J), between(3, 7, J)  -> member(J, L))
  479% ?- det_foreach((between(1,5, J), between(3, 7, J)), member(J, L)).
  480%@ L = [3, 4, 5|_].
  481% exists L forall J  (between(1,5, J); between(3, 7, J))  -> member(J, L))
  482% ?- foreach((between(1,5, J); between(3, 7, J)), member(J, L)).
  483%@ L = [1, 2, 3, 4, 5, 6, 7|_].
  484% ?- foreach(between(1, 5, J), dif(L, J)), L = 3.
  485% ?- time(repeat(10^5, det_foreach(between(1, 5, J), (member(J, L),
  486%	det_foreach(between(6, 8, K), (member(K, L),
  487%	det_foreach(between(9, 10, M), member(M, L)))))))).
  488%@ % 99,800,001 inferences, 13.491 CPU in 14.710 seconds (92% CPU, 7397365 Lips)
  489%@ true.
  490% ?- time(repeat(10, det_foreach(between(1, 5, J), member(J, L)))).
  491% ?- time(repeat(10, foreach(between(1, 5, J), member(J, L)))). % stack limit.
  492
  493det_foreach(Gen, Con):-	term_variables(Gen, Vs),
  494	sort(Vs, Vs0),
  495	term_variables(Con, Ws),
  496	sort(Ws, Ws0),
  497	ord_subtr_var(Ws0, Vs0, Ws1),
  498	once(foreach_by_copy(Gen, Con, Vs0, Ws1)).
  499%
  500foreach(Gen, Con, Vs, Ws):-	once(foreach_by_copy(Gen, Con, Vs, Ws)).
  501
  502% ?- N=200, K = 5, time((repeat(N, once((foreach_by_copy(between(1,5, J), member(J, L), [J], [L]), writeln(L)))))).
  503foreach_by_copy(A, B, Vs, Ws):-
  504	findall(Vs, A, Sol),
  505	copy_of_goal(Sol, Vs, Ws, B, Cs),
  506	maplist(call, Cs).
  507%
  508copy_of_goal([], _, _, _, []).
  509copy_of_goal([A|As], Vs, Ws, B, [G|Gs]):-
  510	copy_term(Vs+Ws+B, A+Ws+G),
  511	copy_of_goal(As, Vs, Ws, B, Gs).
  512%
  513ord_subtr_var([], _, []):-!.
  514ord_subtr_var(X, [], X):-!.
  515ord_subtr_var([X|Xs], [Y|Ys], Zs):- X==Y, !,
  516	ord_subtr_var(Xs, Ys, Zs).
  517ord_subtr_var([X|Xs], [Y|Ys], [X|Zs]):- X@<Y, !,
  518	ord_subtr_var(Xs, [Y|Ys], Zs).
  519ord_subtr_var(Xs, [_|Ys], Zs):- ord_subtr_var(Xs, Ys, Zs).
  520
  521		/**************************************************************
  522		*     foreach by assert/compile_aux: SLOWer than COPY_TERM    *
  523		**************************************************************/
  524
  525% ?- foreach_by_assert(between(1,2,J), member(J, L), [J], [L]).
  526% foreach_by_assert(Gen, Con, Vs, Ws):-
  527% 	retractall('$CONSUMER'(_,_)),
  528% 	assert(( '$CONSUMER'(Vs, Ws):- Con)),
  529% 	Stash = '$STASH'(Ws),
  530% 	(	call(Gen),
  531% 		arg(1, Stash, U),
  532% 		once('$CONSUMER'(Vs, U)),
  533% 		nb_setarg(1, Stash, U),
  534% 		fail
  535% 	;   arg(1, Stash, Ws)
  536% 	).
  537
  538% foreach_by_assert(Gen, Con, Vs, Ws):-
  539% 	context_module(M),
  540% 	pac:expand_core(pred([Vs, Ws]:- Con), M, G, P, []),
  541% 	maplist(assert, P),
  542% 	Stash = '$STASH'(Ws),
  543% 	(	call(Gen),
  544% 		arg(1, Stash, U),
  545% 		once(call(G, Vs, U)),
  546% 		nb_setarg(1, Stash, U),
  547% 		fail
  548% 	;   arg(1, Stash, Ws)
  549% 	).