You are on page 1of 15

Lecprog2, a new dialect of Lisp

Author:CristianChidesa
Email:lecprog@gmail.com ,lecprog@yahoo.com

Inmyopinion,adisadvantageinCommonLispprogrammingisitsevaluation
mechanismwhichusesquote,backquoteandcommaoperators.
ThequoteisawayofprotectingLispexpressionsfromevaluationbut,ateach
evaluationstepofamulti-quotedexpression,aquoteisremovedandthe
expressiongloballychanges.
Sometimes,weneedtopreserveintactsomeexpressionsthroughsubsequent
evaluationsandquoteandbackquoteoperatorsdontofferagoodsolutionin
thiscase.

TheexpressionsinLecprog2arebuiltasinCommonLisp,everyexpression
iseitheranatom(string,number,constantsymbol)oralist.
ButunlikeLisp,Lecprog2doesn'tusequoteandbackquoteoperators.
InLecprog2 thereexisttwotypesoflists:listsdelimitedby(round)parenthesis
(i.e."("and")")andlistsdelimitedbysquarebrackets(i.e."["and"]").
Bothtypesoflistscancontainatomsandotherlists.
Listsdelimitedbyparenthesisareusedforfunctioncallswhilelistsdelimited
bysquarebracketsareusedtorepresentdata,functionparameters,(local)
variableswithinaniterativestructure"iter_sequence"andclausesofinstruction
"filter"(instruction"filter"issimilartoinstruction"cond"inCommonLisp).
Thereforealistcanrepresentagenerictreestructurecontainingfunctioncalls
mixedwithdata.
TheaxiomsforevaluatingexpressionsinLecprog2aregivenbelow(textin
bold + italic + green color)but,firstly,let'sseeafewexamplesinLecprog2:

>>> ( ) --> error


>>> [ ] --> [ ]
//i.e.emptydatalist

Lecprog2doesn'thaveaspecialatom"nil".InLecprog2,insteadofatom"t"
thereexiststheatom"true".Lecprog2hasalsotheatom"false"whichis
differentfrom"[ ]".

>>> (is_atomic a) --> true


>>> (is_atomic [a b c]) --> false
>>> (is_atomic [ ]) --> false
>>> (is_atomic false) --> true
>>> (is_atomic true) --> true
>>> (is_atomic error) --> true

>>> (is_list a) --> false


>>> (is_list [a b c]) --> true
>>> (is_list [ ]) --> true

>>> (cons a [b [c d] f]) --> [a b [c d] f]


>>> (car [a b c d]) --> a
>>> (cdr [a b c d]) --> [b c d]


In Lecprog2, an atom is evaluated to itself. We can attach a value to
an atom by using the function "set" but we need to use the function
"get_value" to retrieve the value attached to that atom.
Ex:
>>> (set a w) --> nothing
//i.e.noreturnvalueforfunction"set"
>>> a --> a//nodirectevaluationforanatom(!);needtousefunction"get_value"
>>> (get_value a) --> w
>>> (get_value 7) --> 7
//byconvention,"get_value"appliedtoaconstant
//returnsthatconstant
>>> (get_value "a string") --> "a string"
//thesameconvention

>>> (get_value [2 3 4]) --> error


>>> (get_value car) --> error
//byconvention,"get_value"appliedto
//areservedwordreturnserror.

Fromnowon,forsimplicity,we'llwrite"^a"insteadof"(get_value a)",
"a"beinganatomorafunctionparameterora(local)variablewithinan
iterativestructure"iter_sequence".
>>> (set b c) --> nothing
>>> ^b --> c
>>> (set a ^b) --> nothing
>>> ^a --> c

>>> (set "a string" 7) --> error //byconvention,wecannotattach


//aconstantvaluetoaconstant(number,string,etc)
>>> (set 10 7) --> error

Note:1)"nothing"and"error"arespecialatomsinLecprog2.
"error"isusedasresultofanevaluationthatgiveserror.
2)Anycallof"set"or"defun"functionsalwaysreturns"nothing"or
"error".

Listsdelimitedbysquarebracketsandcontainingonlyatomsexceptingthe
specialatom"nothing",arepuredataanddonotchangethroughevaluation
inLecprog2.
Ex:
>>> [a b c] --> [a b c]//nochanges
>>> [cons 2 [3 4]] --> [cons 2 [3 4]]//nochanges

The first item of a list delimited by (round) parenthesis (i.e."(" and ")")
must be a standard function, or an user-defined function or an anonymous
function (lambda expressions).
The evaluation of such list (delimited by "(" and ")") means to evaluate
the parameters of that function (which may entail recursive evaluation for
parameters that are lists) and then apply that function to those evaluated
parameters.
Evaluating a list delimited by square brackets (i.e. "[" and "]") means
to evaluate sequentially each item of that list (which implies recursive
evaluation if such item is also a list) and the result will be the list
containing these evaluated items.

Note: Thefirstitemofalistdelimitedby(round)parenthesisisnot
evaluated,onlysubsequentitemsfromthelist,i.e.theparametersof
thatfunctioncall,areevaluated(iftheyexist).

Ex:
>>> [ car [cdr [a b c d]] ] --> [car [cdr [a b c d]]]
//nochanges
>>> ( car [cdr [a b c d]] ) --> cdr
>>> [ car (cdr [a b c d]) ] --> [car [b c d]]
>>> ( car (cdr [a b c d]) ) --> b
>>> ( car [(cdr [x y z]) u v] ) --> (car [[y z] u v]) --> [y z]

>>> (is_empty_list [ ]) --> true


>>> (is_empty_list [a b c]) --> false
>>> (is_empty_list an_atom) --> false
//insertatindex:
>>> ( insert 0 y [b c d] ) --> [y b c d]
>>> ( insert 1 y [b c d] ) --> [b y c d]
>>> ( insert 1 nothing [b c d] ) --> [b c d]
>>> ( insert 3 y [b c d] ) --> [b c d y]
>>> ( insert 5 y [b c d] ) --> [b c d y]
>>> ( insert 5 nothing [b c d] ) --> [b c d]
>>> ( insert 1 (cdr [a b c]) [(cons x [u v]) (car [w u])] ) -->
--> ( insert 1 [b c] [[x u v] w] ) -->
--> [[x u v] [b c] w]

//modifyitematindex:
>>> ( set_item 0 y [b c d] ) --> [y c d]
>>> ( set_item 2 y [b c d] ) --> [b c y]
>>> ( set_item 2 nothing [b c d] ) --> [b c]
>>> ( set_item 3 y [b c d] ) --> [b c d]//unchanged
>>> ( set_item 3 nothing [b c d] ) --> [b c d]//unchanged

//getitematindex:
>>> ( get_item 0 [[x u v] [b c] v] ) --> [x u v]
>>> ( get_item 1 [[x u v] [b c] v] ) --> [b c]
>>> ( get_item 3 [[x u v] [b c] v] ) --> nothing
//---------------------------------------------------------
>>> ( apply + [3 4 5] ) --> 12//thesameas:
//(+345)-->12
>>> ( apply cdr [[3 4 5]] ) --> [4 5]//thesameas:
//(cdr[345])-->[45]
>>> ( apply cons [a [b c]] ) --> [a b c] //thesameas:
//(consa[bc])-->[abc]

Afewmoreexampleswithatom"error":
>>> (+ 5 [a b]) --> error
//i.e.theresultistheatom"error"
>>> ( get_error_msg ) -->
--> "all the arguments of function '+' must be numbers"

>>> ( 3 2 ) --> error

>>> ( get_error_msg ) -->


--> "the first item of a list enclosed by round parenthesis must be a
standard function or a user named function or a lambda expression"

>>> (set cdr "some_string") --> error


>>> ( get_error_msg ) -->
--> "an atom representing a reserved word cannot be the first parameter
of function 'set'"

TheevaluationruleinLecprog2shouldbesupplementedwithstatements
aboutatoms"error"and"nothing":

If an item of a list enclosed by square brackets is atom "nothing" then


it will be removed from that list during evaluation.
By convention:
>>> (car [ ]) --> nothing
>>> (cdr [ ]) --> [ ]
Ex:
>>>
>>>
>>>
>>>
>>>
>>>
>>>

[ + 5 nothing 2 ] --> [ + 5 2 ]
[ nothing x nothing u w ] --> [x u w]
[ nothing nothing nothing ] --> [ ]
[ (set x 11) (set y 21) z ] --> [z]
[ (set x 11) (set y 21) ] --> [ ]
(car [nothing (+ 3 4)]) --> (car [7]) --> 7
(car [(set a 4) (* ^a 2)]) --> (car [8]) --> 8

If an item of a list representing a function call (i.e. a list enclosed by


"(" and ")") is the atom "error" then that list will be evaluated to "error"
excepting the following cases:
1) that list represents a call of function "catch_error"
(i.e.(catch_error <some_expression>)or
(catch_error <some_expression> <expression_if_error>) ).
By convention,
>>> (catch_error error) --> nothing
>>> (catch_error error <expression_if_error>) --> <expression_if_error>
2) that list represents a call of function "if" or a call of function "filter" .
3) that list represents a lambda expression.

Note:
1)Thespecialfunction"catch_error"willcatchtheerror,similarto
"try...catch..."inJava(C#,C++,etc),andcanbeusedtopreventthe
propagationofatom"error"tothetoplevelofthetreestructureexpression
duringevaluation.
Examples:
>>> [ 4 error x y ] --> [ 4 error x y ]
//nochanges
>>> [ 4 (3 2) x y ] --> [ 4 error x y ]
>>> ( + 5 (3 2) ) --> error

>>> (catch_error error) --> nothing//byconvention


>>> [ 4 (catch_error error) x y ] --> [4 nothing x y] -->
--> [4 x y]


>>>
>>>
>>>

>>>

>>>
-->

(catch_error (3 2)) --> nothing


[ 4 (catch_error (3 2)) x y ] --> [4 x y]
(catch_error (+ 2 2)) --> 4
( catch_error

error

(car [w z]) ) --> w

( catch_error (3 2) ( get_error_msg ) ) -->


"the first item of a list enclosed by round parenthesis must be a
standard function or a user named function or a lambda expression"

>>> ( catch_error (+ 2 2) ( get_error_msg ) ) --> 4//noerror


>>> ( catch_error (+ 2 2) (3 2) ) --> 4 //noerror;inthiscase,
//"(32)"isnotevaluated

>>> ( catch_error (3 2) (car [w z]) ) --> w


>>> [ 4 (catch_error (3 2) (car [w z])) x y ] --> [4 w x y]
//---------------------------------------------------------
2)Functions"if"and"filter"areexceptionstotheevaluationrule:
>>> ( if (< 4 5) (car [x1 x2]) (cons u [v]) ) --> x1
>>> [ if (< 4 5) (car [x1 x2]) (cons u [v]) ] --> [if true x1 [u v]]

>>> ( if (< 2 3) "ok" error ) --> "ok" //clause"else"isnotevaluated

>>> ( if (< 4 5) error [30 40 50] ) --> error


>>> ( if (< 4 5) [30 40 50] error ) --> [30 40 50] //noerrorbecause
//theelseclause,theatom"error",isnotevaluated
>>> ( if (< 4 5) (30 40 50) [30 40 50] ) --> error//that'sbecause
//thefirstitemin(304050)istheconstant30(notafunction)
>>> ( if (< 4 5) [30 40 50] (30 40 50) ) --> [30 40 50]//noerror
//becausetheelseclause,"(304050)",isnotevaluated
>>> ( filter
[ (is_number 10)
"10 is a number" ]
[ default
error ]
) --> "10 is a number"
//noerrorbecausetheclause"default"isnot
//evaluated
//---------------------------------------------------------

User functions in Lecprog2


AsinCommonLisp,theusercandefineitsownfunctionsinLecprog2byusing
primitive"defun".
Theparametersofauser-definedfunctionareenclosedbysquarebrackets.
Example(recursivefunction):
>>> ( defun sum [ lst ]
( filter
[ (is_empty_list lst)
0]
[ default
(+ (car lst) (sum (cdr lst))) ]
)
) --> nothing
//i.e.noreturnvalueforfunction"defun"

Ex:
>>> (sum [1 2 7]) --> 10

//---------------------------------------------------------
SupposethatLecprog2hasastandardfunction"eq"whichteststheequality
oftwoatomsbutdoesn'tworkforlists:
>>> (eq a a) --> true
>>> (eq a b) --> false
>>> (eq [a b] [a b]) --> false
>>> (eq [ ] [ ]) --> true
>>> (eq <any_atom> <any_list>) --> false
>>> (eq <any_list> <any_atom>) --> false

>>> ( defun equal [ itm1 itm2 ]


( filter
[ (is_atomic itm1)
(eq itm1 itm2) ]
[ (is_atomic itm2)
false ]
[ (equal (car itm1) (car itm2))
(equal (cdr itm1) (cdr itm2))
]
[ default
false ]
)
) --> nothing

Ex:
>>> (equal
[a [[b] c]] [a [[b] c]]) --> true
>>> (equal
[a [[b] c]] [a [b c]]) --> false
//---------------------------------------------------------
>>> (defun append [ l1 l2 ]
(filter
[ (is_empty_list l1)
l2 ]
[ default
(cons (car l1) (append (cdr l1) l2)) ]
)
) --> nothing
Ex:
>>> (append [a b] [x y z]) --> [a b x y z]
//---------------------------------------------------------
Parametersoffunctionscanbeintheirturnfunctions:
>>> ( defun f1 [ x ] (+ x 1) ) --> nothing
>>> ( defun q2 [ h u v ]
(* (apply h [u]) (apply h [v]))
) --> nothing
>>> (q2 f1 4 7) --> 40
//---------------------------------------------------------
Afewmoreexampleswithuser-definedfunctionsinLecprog2:
>>> ( defun is_member [ x lst ]
( filter
[ (is_empty_list lst)
false ]
[ (equal x (car lst))
true ]
[ default
(is_member x (cdr lst)) ]
)
) --> nothing


Ex:
>>> ( is_member
[a [b]]
[x y [a [b]] c d] ) --> true
>>> ( is_member
[a [b]]
[x y a [b] c d] ) --> false
//---------------------------------------------------------
>>> ( defun rec_reverse [ lstSource lstRev ]
( filter
[ (is_empty_list lstSource)
lstRev ]
[ default
(rec_reverse (cdr lstSource)
(cons (car lstSource) lstRev)
)
]
)
) --> nothing

>>> ( defun reverse [ x ]


( if (is_atomic x)
x
(rec_reverse x [ ])
)
) --> nothing

Ex:
>>> ( reverse [a b c d] ) -> [d c b a]

Note: Functions"append","is_member","equal","rec_reverse"canbedefined
inLecprog2inthesamewayasinCommonLisp.
//---------------------------------------------------------
>>> ( defun eval_infix [ x ]
( if(is_atomic x)
// clause"if...then"
( filter
[ (is_reserved_word x)
error ] //like"car","cdr",etc.
[ (is_number ^x)
^x ]
[ default
error ]
)
//clause"else"
( apply
(get_item 1 x)
//i.e.thearithmeticoperator
[ (eval_infix (get_item 0 x))
(eval_infix (get_item 2 x)) ]
)
)
) --> nothing

Ex:
>>> (set a 4) --> nothing
>>> ( eval_infix [[a + 3] * [a - 3]] ) -->
--> (apply * [7 1]) --> 7
//---------------------------------------------------------

Letsconsiderthefunction:

>>> (defun f2 [ u x y ]
( filter
[ (< ^x ^y)
[ (> ^x ^y)
[ default
(if

(- (sqr ^y) (sqr ^x)) ]


(- (sqr ^x) (sqr ^y)) ]
(< ^u 0)
[u (sqr ^x)]
[u (* 12 ^x)]

)
]
)
) --> nothing

>>>
>>>
>>>
>>>

(set c 4) --> nothing


(set a 2) --> nothing
(set b 3) --> nothing
(f2 c a b) --> 5

>>> (set b 2) --> nothing


>>> (f2 c a b) --> [c 24]

Inordertosimplifythebodyofthisfunction,wecoulduseaspecial
function,auto_evalwhichwouldallowadirectevaluationofthe
functionparameters(i.e.evaluatingwithoutusingget_valuefunction):

>>> (defun f2 [ u x y ]
(auto_eval [x y]
(filter
[ (< x y)
(- (sqr y) (sqr x)) ]
[ (> x y)
(- (sqr x) (sqr y)) ]
[ default
(if (< ^u 0)
[u (sqr x)]
[u (* 12 x)]
)
]
)
)
) --> nothing

Note:1)Instruction"auto_eval"isanexceptiontotheevaluationrule.
//---------------------------------------------------------
Twoimportantfunctionswhichcanevaluateexpressionswrittenas
puredata(only"["and"]"):

>>> ( defun eval_in_depth [ fn_lst data ]


( filter
[ (is_atomic data)
data ]
[ (is_member (car data) fn_lst)
(apply (car data)
(eval_data_list fn_lst (cdr data))
)

]
[ default

(eval_data_list

fn_lst

data) ]

)
) --> nothing

>>> ( defun eval_data_list [ fn_lst data_lst ]


( filter
[ (is_empty_list data_lst)
[]]
[ default
(cons (eval_in_depth fn_lst (car data_lst))
(eval_data_list fn_lst (cdr data_lst))
)
]
)
) --> nothing

Ex:
>>> ( eval_in_depth [+ * -]
[* [+ 5 3] [- 7 4]] ) --> 24

>>> ( eval_in_depth [+ -]
[* [+ 5 3] [- 7 4]] ) --> [* 8 3]

>>> ( eval_in_depth [car cdr] [car [cdr [u v w]]] ) --> v

>>> ( eval_data_list [cons car]


[[cons z [m]] [car [a b]] [cdr [u v w]]] ) -->
--> [[z m] a [cdr [u v w]]]
//----------------------------------------------------------

Lecprog2needsalsoiterativestructuresbecausetherearealotoftasks
thatcanbebetterhandlediterativelythanrecursively,forexamplewhen
processingbiglists.

>>> ( iter_sequence [ x y ]
( set x 4 )
( set y 5 )
) --> nothing

>>> ( iter_sequence [ x y ]
( set x 4 )
( set y ^x )
( exit_sequence (* 3 ^y) )
) --> 12

>>> ( iter_sequence [ x y ]
( set x 8 )
( set y 3 )
( if (< ^x ^y)
( exit_sequence (- ^y ^x) )
( exit_sequence (- ^x ^y) )
)
( exit_sequence 100 ) //note:thisinstructionisneverevaluated
) --> 5


>>> ( iter_sequence [ x s ]
( set x 1 )
( set s 0 )
( do
( if (>= ^x 10) (exit_sequence ^s) )
( set s (+ ^s ^x) ) //i.e.s=s+x;
( set x (+ ^x 2) )
//i.e.x=x+2;
)
) --> 25//i.e.:1+3+5+7+9-->25

Note:Instructions"iter_sequence"and"do"areexceptionstotheevaluationrule.
//----------------------------------------------------------

Anonymousfunctions(lambdaexpressions)-exceptiontotheevaluationrule;
we'lldenotelambdaby"@"("@"isaspecialatom):
>>> (@ [u] (+ u 1)) --> (@ [u] (+ u 1)) //nochanges
>>> ( (@ [u] (+ u 1)) 4 ) --> 5
>>> ( defun

q2 [ h u v ]
(* (apply h [u])
--> nothing

>>> ( q2
--> ( *

(@ [u] (+ u 1))

( apply
( apply
) --> 10

>>>
>>>
>>>
>>>

>>>

(
(
(
(

is_list
(@
is_atomic
is_lambda
is_lambda

(apply

[v]))

4 ) -->

(@ [u] (+ u 1))
(@ [u] (+ u 1))

[x] (*
(@ [x]
(@ [x]
[@ [x]

[1] )
[4] )

2 x)) ) --> false


(* 2 x)) ) --> false
(* 2 x)) ) --> true
[* 2 x]] ) --> false

( cons
(@ [x] (* 2 x))
["a string" some_atom

21]

) -->
[ (@ [x] (* 2 x))

>>> ( get_item

2
["a string"

"a string"

some_atom

(@ [x] (* 4 x))

21 ]

(@ [x] (+ x 1))

) -->
(@ [x] (+ x 1))

>>> ( car (@ [x] (* 2 x)) ) --> error


>>> ( get_error_msg ) -->
--> "the parameter of function 'car' must be a list enclosed by
square brackets"
>>> ( cdr (@ [x] (* 2 x)) ) --> error
>>> ( get_error_msg ) -->
--> "the parameter of function 'cdr' must be a list enclosed by
square brackets"

32]

>>> ( get_item 2 (@ [x] (* 2 x)) ) --> error


>>> ( get_error_msg ) -->
--> "the second parameter of function 'get_item' must be a list
enclosed by square brackets"

Function"eq_lambda"teststheequalityoftwolambdaexpressions
afterrenamingboundvariables.
>>> ( eq_lambda
(@ [x] (* 2 x))
(@ [y] (* 2 y)) ) --> true

Note: Thedefinitionsoffunctions"equal","eval_in_depth", "eval_data_list"


needtobemodifiedtotakeaccountoflambdaexpressions.
//---------------------------------------------------------

Reflection in Lecprog2

InthisversionofpdfdocaboutLecprog2,unliketheolderversions,
IusedotherprimitivesforreflectioninLecprog2whichfocusespecially
onlambdaexpressions(anonymousfunctions).

InordertoendowLecprog2withanefficientmechanismofreflection,
itwouldbeusefultohavethefollowingprimitives:

1)"get_lambda",whichgivesthedefinitionofausernamedfunctionas
alambdaexpression.
Ex:
>>> ( defun q2 [ h u v ]
(* (apply h [u]) (apply h [v]))
) --> nothing

>>> ( get_lambda q2 ) -->


--> ( @ [ h u v ]
(* (apply h [u]) (apply h [v])) )

2)"function_from_lambda",whichdefinesafunctionwhosenameisthe
firstparameterandwhoseexpressionisgivenbyalambdaexpressionas
secondparameter.Ex:
>>> ( function_from_lambda
g4
( @ [y] (if (< y 1) (- 1 y) (- y 1)) )
) -->nothing
//i.e.thedefinitionoffunction"g4"wasupdated

Note:Thisisequivalentwith:
>>> ( defun g4 [y]
(if (< y 1) (- 1 y) (- y 1)) ) --> nothing

3)Primitive"turn_lambda_into_data"turnsalambdaexpressionintodata.
Ittakesoneparameterwhichmustbealambdaexpression(i.e"(@ [...] ...)").
All"("willbereplacedwith"[# "andthecorresponding")"willbereplaced
with"]",butwithoneexception,"("and")"ofinternallambdaexpressions.
So,a"turn_lambda_into_data"callactsonlyontheenclosinglambda
expressionandonallinternalfunctioncallsexceptinginternallambda
expressions(ifthereexist).

Buttheexpressionresultingfromafirst"turn_lambda_into_data"call
canbeparsed(asbeingdata)andprimitive"turn_lambda_into_data"can
beusedagain,ifnecessary,inordertoturnanypossibleinternallambda
expressionintodata.
Ex:
>>> ( turn_lambda_into_data
(@ [x y] (+ (sqr x) (sqr y))) ) -->
--> [ # @ [_x21 _y22] [# + [# sqr _x21] [# sqr _y22]] ]
Note:"#"isaspecialatom.
>>> ( cons # [car [b c]] ) --> [# car [b c]]
>>> ( car [# + 3 4] ) --> #
>>> ( set # <some_expression> ) --> error

Anotherexample:
>>> ( turn_lambda_into_data
( @ [x]
( filter
[ (< x 1)
(@ [y] (* 2 y)) ]
[ (< x 3)
(iter_sequence [w]
(set w 7)
(exit_sequence ^w)
)
]
[ default
(@ [y] (* 5 y)) ]
)
)
) -->

--> [# @ [_x23]
[# filter
[ [# < _x23 1]
(@ [y] (* 2 y)) ]
[ [# < _x23 3]
[# iter_sequence [_w24]
[# set _w24 7]
[# exit_sequence [# get_value _w24]]
]
]
[ default
(@ [y] (* 5 y)) ]
]
]

Note:1)Intheexampleabove,internallambdaexpressions"(@ [y] (* 2 y))"


and"(@ [y] (* 5 y))"arenotaffectedbythis"turn_lambda_into_data"call.

2)Iftheparameterina"turn_lambda_into_data"callisalambdaexpression
havingparameterslikeintheexamplesabove,thenweneedtouseaspecial
typeofsymbolsinLecprog2,let'scallthemauxiliarysymbols(orunregistered
symbols,unlikeatomswhichareregisteredsymbolswithinLecprog2
environment).
Byconvention,thenameofanauxiliarysymbolbeginswith"_".

We'llsupposealsothatLecprog2environmentmanagesaglobalcounterwhich

isautomaticallyincrementedateachcalloffunction"turn_lambda_into_data"
foralambdaexpressionorateachcallofaprimitive"new_aux_symb".
Thelambdaexpression'sparametersandlocalvariablesoftheenclosinglambda
expressionwillberenamedtoauxiliarysymbolsbyusingnewvaluesofthiscounter.

Intheexamplesabove,theglobalcountervalueforauxiliarysymbolswas20
beforethefirst"turn_lambda_into_data"callandbecame24afterthesecondcall.
Inthefirstexample,parameter"x"wasreplacedwiththeauxiliarysymbol"_x21"
andparameter"y"wasreplacedwiththeauxiliarysymbol"_y22".
Inthesecondexample,parameter"x"wasreplacedwiththeauxiliarysymbol
"_x23"andlocalvariable"w"ofinstruction"iter_sequence"wasreplacedwiththe
auxiliarysymbol"_w24".

Newauxiliarysymbolscanalsobegeneratedbyusingprimitive"new_aux_symb".
Ex:
>>> ( set atom1 (new_aux_symb "aux") ) --> nothing
>>> ^atom1 --> _aux25
//theglobalcountervalueis25now

Byconvention,anauxiliarysymbolwillbehavelikeanatomexceptingwhen
itisusedwithfunctions"set"and"get_value":
>>> ( cons _aux31 [a b c] ) --> [_aux31 a b c]
>>> ( get_item 1 [b _aux17 "some string" _aux5] ) --> _aux17
>>> ( is_atomic _aux31 ) --> true
>>> ( is_aux_symb _aux31 ) --> true
>>> ( is_aux_symb [a b c] ) --> false
>>> ( is_aux_symb "a string" ) --> false
>>> ( set _aux31 "some string as value" ) --> error
>>> ( get_error_msg ) -->
--> "the first parameter of function 'set' cannot be
an auxiliary symbol"
>>> ( get_value _aux31 ) --> error
>>> ( get_error_msg ) -->
--> "the parameter of function 'get_value' cannot be
an auxiliary symbol"
//---------------------------------
4)Primitive"get_lambda_from_data"constructsalambdaexpressionfromdata.
Ittakestwoparameters:
-alistofauxiliarysymbols(whichcanbeanemptydatalist)representingthe
futurelambdaexpression'sparameterlist;
-anexpressionrepresentingthefuturelambdaexpression'sbody.
"get_lambda_from_data"replaceswithinitssecondparameter(i.e.future
lambdaexpression'sbody)allthe"[#"with"("andthecorresponding"]"with")",
exceptinginsideanyexistinginternallambdaexpressions(i.e.existinginternal
lambdaexpressionsareignored).
Allthesereplacements(i.e"[# ...]"<--"( ... )")aremadewithoutevaluation.

If"_x"isanauxiliarysymboloccurringinboth(future)lambdaexpression's
parameterlistand(future)lambdaexpression'sbodythen"_x"willbereplaced
with"x"insidebothofthem;afterwards,alltheoccurrencesof"x"frominside
thelambdaexpression'sbodywillbeboundtoparameter"x"(fromlambda
expression'sparameterlist).
Thus,theresultofa"get_lambda_from_data"callwillbealambdaexpression

constructedinthisway.
Ex:
>>> ( get_lambda_from_data
[]
[atom1 "a string"
--> ( @ [] [atom1 "a string" 12] )

>>> ( get_lambda_from_data
[_y _z]
[# + [# sqr _y] [# sqr _z]]
) -->
( @ [y z] (+ (sqr y) (sqr z)) )

Anotherexample:
>>> ( get_lambda_from_data

12] ) -->

[_x]

[# filter
[ [# < _x 1]
(@ [y] (* 2 y)) ]
[ [# < _x 3]
[# iter_sequence [_w]
[# set _w 7]
[# exit_sequence [#
]
]
[ default
(@ [y] (* 5 y)) ]
]

get_value

_w]]

) -->

(@

[x]
( filter
[ (< x 1)
(@ [y] (* 2 y)) ]
[ (< x 3)
(iter_sequence [w]
(set w 7)
(exit_sequence ^w)
)
]
[ default
(@ [y] (* 5 y)) ]
)

)
//---------------------------------
Let'ssupposethatweobtainedprogrammaticallyinLecprog2an"iter_sequence"
expressionrepresentedaspuredataandwewanttorunthissourcecode.
Firstly,we'lluseprimitive"get_lambda_from_data"inordertocreate
alambdaexpressionwhosebodyisexactlythat"iter_sequence"expression.
Thelambdaexpression'sparameterlistwillbeempty.
Forconvenience,wecanstorethatlambdaexpressionasvalueofanatom
"atom_for_lambda"andthen,we'llmakeacallofthatlambdaexpression
byusingfunction"apply":

>>> ( set atom_for_lambda

( get_lambda_from_data
[]
[#

]
)

//i.e.noparametersforthefuturelambdaexpression
iter_sequence [_x]
[# set _x 25]
[# exit_sequence
[# (@ [y] (* 2 ^y))
//endof"[#iter_sequence ..."

)
--> nothing

>>> ( apply

--> (apply
(@

^atom_for_lambda

[] ) -->

[]
( iter_sequence [ x ]
(set x 25)
( exit_sequence ((@ [y] (* 2 ^y)) x) )
)

)
[]
) -->
(* 2 25) --> 50

//---------------------------------------------------------
Remark:
Obviously,wecanbuildprogrammaticallyatruntimeexpressionscontaining
onlyatomsandlistsenclosedbysquarebrackets(i.e"["and"]")whichmay
possiblystartwith"#"(i.e.puredata).
So,theuseofprimitives"get_lambda","turn_lambda_into_data",
"new_aux_symb","get_lambda_from_data","function_from_lambda"
couldallowustoprogrammaticallydefinenewfunctionsatruntime,towrite
functionswhichmodifyotherfunctionsoreventowritefunctionswhich
modifythemselvesatruntime.
ThisfeaturecouldmakeLecprog2reallysuitableforMachineLearning,
ConstraintProgrammingandotherbranchesofArtificialIntelligence.

Conclusion:
Inmyopinion,anewprogramminglanguagewouldbereallyusefulifthat
languagecouldofferamaximumofflexibilityandpowerforprogramming
byusingaminimalsetofconventionsandprogrammingrules.
IintendtodefinetheaxiomsofLecprog2followingthisprinciple.

_x] ]

You might also like