In lambdatalk the implementation makes lambdas true "combinators", knowing nothing but global constants (primitives and user defined ones). No free variables, no closures, pure functions, entirely independent of any context. Pure functions without any side effect. True referential transparency.
The lack of closures (I love them in Javascript) can fortunately be compensated by the fact that lambdas accept de facto "partial calls", and transfers of values can be done by "IIFE".
I'am happy to know that that stuff can have closures but I'm not smart enough to implement them. I am a retired architect and not a professional coder. Meanwhile this is the workaround I use. For instance, the area of any triangle of sides[a,b,c] is given by the formula
area = √s*(s-a)*(s-b)*(s-c) where s = (a+b+c)/2
If the intermediate variable s is provided alone in an IIFE, like this :
{def area1 {lambda {:a :b :c}
{{lambda {:s} // it's an IIFE where :s will be replaced ...
{sqrt {* :s {- :s :a} {- :s :b} {- :s :c}}} // ... here ...
} {/ {+ :a :b :c} 2}}}} // ... by this value computed once
-> area1
{area1 3 4 5}
-> NaN // Not a Number
it doesn't work, simply because [:a :b :c] are not in the inner function's arguments list and a function knows nothing about its context. It is necessary to manually add the arguments of the calling function
{def area2 {lambda {:a :b :c}
{{lambda {:a :b :c :s} // :a :b :c are redefined ...
{sqrt {* :s {- :s :a} {- :s :b} {- :s :c}}}
} :a :b :c // ... get values from the outer func ...
{/ {+ :a :b :c} 2}} // ... and from the new computed value
}}
-> area2
{area2 3 4 5}
-> 6
For information lambdas are implemented at the beginning of this javascript file http://lambdaway.free.fr/lambdawalks/meca/JS.js I wouldn't want to complicate the code too much and especially lose the automatic partial application, which seems to me incompatible with closures.
The let special form is a syntactic sugar for IIFEs which has the advantage of highlighting local variables ; so the previous area2 function can be rewritten this way:
{def area3
{lambda {:a :b :c}
{let { {:a :a} // in fact, it's a hidden lambda
{:b :b} // we must redefine the outer lambda's arguments
{:c :c} // as kind of "manual" closure
{:s {/ {+ :a :b :c} 2}} // and add the new computed variable
} {sqrt {* :s {- :s :a} {- :s :b} {- :s :c}}} everything is known
}}}
As introduced in this page http://lambdaway.free.fr/lambdawalks/?view=lambda,
in lambdatalk everything begins with such a text replacement process:
rewritten in a prefixed parenthesized form It's nothing but an IIFE, (Immediately Invoked Function Expression).This is a simple example:
In lambdatalk the implementation makes lambdas true "combinators", knowing nothing but global constants (primitives and user defined ones). No free variables, no closures, pure functions, entirely independent of any context. Pure functions without any side effect. True referential transparency.The lack of closures (I love them in Javascript) can fortunately be compensated by the fact that lambdas accept de facto "partial calls", and transfers of values can be done by "IIFE".
Arrays are the only one mutable objects and I use them to avoid recursion's stackoverflow, for instance in this page http://lambdaway.free.fr/lambdawalks/?view=reduce