Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Author: Ulrich Neumerkel
- E-mail: ulrich@complang.tuwien.ac.AT
- Copyright (C): 2009 Ulrich Neumerkel. All rights reserved.
- Redistribution AND use in source AND binary forms, with OR without
- modification, are permitted provided that the following conditions are
- met:
- 1. Redistributions of source CODE must retain the above copyright
- notice, this list of conditions AND the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions AND the following disclaimer in the
- documentation AND/OR other materials provided with the distribution.
- THIS SOFTWARE IS PROVIDED BY Ulrich Neumerkel ``AS IS'' AND ANY
- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Ulrich Neumerkel OR
- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- The views AND conclusions contained in the software AND documentation
- are those of the authors AND should NOT be interpreted AS representing
- official policies, either expressed OR implied, of Ulrich Neumerkel.
- */
- :- module(rec_lambda, [
- (^)/3, (^)/4, (^)/5, (^)/6, (^)/7, (^)/8, (^)/9,
- (\)/1, (\)/2, (\)/3, (\)/4, (\)/5, (\)/6, (\)/7,
- (+\)/2, (+\)/3, (+\)/4, (+\)/5, (+\)/6, (+\)/7,
- (recl)/0, (recl)/1, (recl)/2, (recl)/3, (recl)/4, (recl)/5, (recl)/6,
- ctn/2,
- recval/2,
- letrec/2,
- op(201,xfx,+\)]).
- /** <module> Lambda expressions
- This library provides lambda expressions TO simplify higher order
- programming based on call/N.
- Lambda expressions are represented by ordinary Prolog terms.
- There are two kinds of lambda expressions:
- Free+\X1^X2^ ..^XN^Goal
- \X1^X2^ ..^XN^Goal
- The second is a shorthand FOR t+\X1^X2^..^XN^Goal.
- Xi are the parameters.
- Goal is a goal OR continuation. Syntax note: Operators within Goal
- require parentheses due TO the low precedence of the ^ operator.
- Free contains variables that are valid outside the scope of the lambda
- expression. They are thus free variables within.
- All other variables of Goal are considered local variables. They must
- NOT appear outside the lambda expression. This restriction is
- currently NOT checked. Violations may lead TO unexpected bindings.
- In the following example the parentheses around X>3 are necessary.
- ==
- ?- use_module(library(lambda)).
- ?- use_module(library(apply)).
- ?- maplist(\X^(X>3),[4,5,9]).
- true.
- ==
- In the following X is a variable that is shared by both instances of
- the lambda expression. The second query illustrates the cooperation of
- continuations AND lambdas. The lambda expression is in this case a
- continuation expecting a further argument.
- ==
- ?- Xs = [A,B], maplist(X+\Y^dif(X,Y), Xs).
- Xs = [A, B],
- dif(X, A),
- dif(X, B).
- ?- Xs = [A,B], maplist(X+\dif(X), Xs).
- Xs = [A, B],
- dif(X, A),
- dif(X, B).
- ==
- The following queries are all equivalent. TO see this, use
- the fact f(x,y).
- ==
- ?- call(f,A1,A2).
- ?- call(\X^f(X),A1,A2).
- ?- call(\X^Y^f(X,Y), A1,A2).
- ?- call(\X^(X+\Y^f(X,Y)), A1,A2).
- ?- call(call(f, A1),A2).
- ?- call(f(A1),A2).
- ?- f(A1,A2).
- A1 = x,
- A2 = y.
- ==
- Further discussions
- http://www.complang.tuwien.ac.AT/ulrich/Prolog-inedit/ISO-Hiord
- @tbd Static expansion similar TO apply_macros.
- @author Ulrich Neumerkel
- */
- :- meta_predicate ctn(?,?).
- ctn(I,O):-copy_term_nat(I,O).
- :- meta_predicate
- letrec(+,+),
- recval(+,?),
- recl(),
- recl(?),
- recl(?,?),
- recl(?,?,?),
- recl(?,?,?,?),
- recl(?,?,?,?,?),
- recl(?,?,?,?,?,?).
- letrec(N,rec_lambda(FC)):-!, atom_concat('$rec_lambda',N,Key), b_setval(Key,FC),!.
- % TODO only DO this IF the lamda will need it
- letrec(N,user:FC):-!, once(( atom_concat('$rec_lambda',N,Key), b_setval(Key,FC))).
- letrec(N,FC):- once((atom_concat('$rec_lambda',N,Key), b_setval(Key,FC))).
- recval(N,FC):- atom_concat('$rec_lambda',N,Key), nb_current(Key,FC),!,FC\=[].
- recl :-recval(0,FC),call(FC).
- recl(V1):-recval(1,FC),call(FC,V1).
- recl(V1,V2):-recval(2,FC),call(FC,V1,V2).
- recl(V1,V2,V3):-recval(3,FC),call(FC,V1,V2,V3).
- recl(V1,V2,V3,V4):-recval(4,FC),call(FC,V1,V2,V3,V4).
- recl(V1,V2,V3,V4,V5):-recval(5,FC),call(FC,V1,V2,V3,V4,V5).
- recl(V1,V2,V3,V4,V5,V6):-recval(6,FC),call(FC,V1,V2,V3,V4,V5,V6).
- :- meta_predicate no_hat_call(0).
- :- meta_predicate
- ^(?,0,?),
- ^(?,1,?,?),
- ^(?,2,?,?,?),
- ^(?,3,?,?,?,?),
- ^(?,4,?,?,?,?,?),
- ^(?,5,?,?,?,?,?,?),
- ^(?,6,?,?,?,?,?,?,?).
- ^(V1,Goal,V1) :-
- letrec(1,Goal),
- no_hat_call(Goal).
- ^(V1,Goal,V1,V2) :-
- letrec(2,Goal),
- call(Goal,V2).
- ^(V1,Goal,V1,V2,V3) :-
- letrec(3,Goal),
- call(Goal,V2,V3).
- ^(V1,Goal,V1,V2,V3,V4) :-
- letrec(4,Goal),
- call(Goal,V2,V3,V4).
- ^(V1,Goal,V1,V2,V3,V4,V5) :-
- letrec(5,Goal),
- call(Goal,V2,V3,V4,V5).
- ^(V1,Goal,V1,V2,V3,V4,V5,V6) :-
- letrec(6,Goal),
- call(Goal,V2,V3,V4,V5,V6).
- ^(V1,Goal,V1,V2,V3,V4,V5,V6,V7) :-
- letrec(7,Goal),
- call(Goal,V2,V3,V4,V5,V6,V7).
- :- meta_predicate
- \(0),
- \(1,?),
- \(2,?,?),
- \(3,?,?,?),
- \(4,?,?,?,?),
- \(5,?,?,?,?,?),
- \(6,?,?,?,?,?,?).
- \(FC) :-
- letrec(0,FC),
- ctn(FC,C),no_hat_call(C).
- \(FC,V1) :-
- letrec(1,FC),
- ctn(FC,C),call(C,V1).
- \(FC,V1,V2) :-
- letrec(2,FC),
- ctn(FC,C),call(C,V1,V2).
- \(FC,V1,V2,V3) :-
- letrec(3,FC),
- ctn(FC,C),call(C,V1,V2,V3).
- \(FC,V1,V2,V3,V4) :-
- letrec(4,FC),
- ctn(FC,C),call(C,V1,V2,V3,V4).
- \(FC,V1,V2,V3,V4,V5) :-
- letrec(5,FC),
- ctn(FC,C),call(C,V1,V2,V3,V4,V5).
- \(FC,V1,V2,V3,V4,V5,V6) :-
- letrec(6,FC),
- ctn(FC,C),call(C,V1,V2,V3,V4,V5,V6).
- :- meta_predicate
- +\(?,0),
- +\(?,1,?),
- +\(?,2,?,?),
- +\(?,3,?,?,?),
- +\(?,4,?,?,?,?),
- +\(?,5,?,?,?,?,?),
- +\(?,6,?,?,?,?,?,?).
- +\(GV,FC) :-
- letrec(0,FC),
- ctn(GV+FC,GV+C),no_hat_call(C).
- +\(GV,FC,V1) :-
- letrec(1,FC),
- ctn(GV+FC,GV+C),call(C,V1).
- +\(GV,FC,V1,V2) :-
- letrec(2,FC),
- ctn(GV+FC,GV+C),call(C,V1,V2).
- +\(GV,FC,V1,V2,V3) :-
- letrec(3,FC),
- ctn(GV+FC,GV+C),call(C,V1,V2,V3).
- +\(GV,FC,V1,V2,V3,V4) :-
- letrec(4,FC),
- ctn(GV+FC,GV+C),call(C,V1,V2,V3,V4).
- +\(GV,FC,V1,V2,V3,V4,V5) :-
- letrec(5,FC),
- ctn(GV+FC,GV+C),call(C,V1,V2,V3,V4,V5).
- +\(GV,FC,V1,V2,V3,V4,V5,V6) :-
- letrec(6,FC),
- ctn(GV+FC,GV+C),call(C,V1,V2,V3,V4,V5,V6).
- %% no_hat_call(:Goal)
- %
- % Like call, but issues an error FOR a goal (^)/2. Such goals are
- % likely the result of an insufficient number of arguments.
- no_hat_call(MGoal) :-
- strip_module(MGoal, _, Goal),
- ( nonvar(Goal),
- Goal = (_^_)
- -> throw(error(existence_error(lambda_parameters,Goal),_))
- ; call(MGoal)
- ).
- % I would like TO replace this by:
- % V1^Goal :- throw(error(existence_error(lambda_parameters,V1^Goal),_)).
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement