5 ms·
I agree with you, Lisp is "the" language to meet. But I think that one can go a little beyond ... I would say before, towards its foundations. Lisp is a child o
by martyalain 6y ago
I agree with you, Lisp is "the" language to meet. But I think that one can go a little beyond ... I would say before, towards its foundations. Lisp is a child of the lambda-calculus, Lisp focuses on lists (cons, car, cdr, ...) but IMHO I think that there are other choices, different ways which can be followed with some interesting results.
I would like to know what you can think of this one, the lambdaway project (http://lambdaway.free.fr/lambdaspeech/ http://lambdaway.free.fr/lambdaspeech/),
easy to install and use in any web browser.
Alain Marty
- kazinator 6y agoHi Marty; remember we had that discussion a few years ago about scoping and I pointed out that you can implement lexical scoping in the substitution-based evaluation strategy, like lambdaway. Did you ever try that?
- martyalain 6y agoHi Kazinator, Thank you for reply, I didn't remember our discussion and no, sadly, I didn't found how to implement lexical scoping until now. The workaround is a kind of "manual closure" as illustrated in http://lambdaway.free.fr/lambdawalks/?view=closure http://lambdaway.free.fr/lambdawalks/?view=closure http://lambdaway.free.fr/lambdawalks/?view=lambda http://lambdaway.free.fr/lambdawalks/?view=lambda where is used the capability of lambdas to accept partial calls and IIFE build the bridge. Time going on I improved lambdatalk, in a total loneliness. Except Ward Cunningham who finds some interest in a language which could replace in wikis the boring standard Markdown syntax. I would like to know what you think of such an introduction http://lambdaway.free.fr/lambdawalks/?view=fromroots2canopy http://lambdaway.free.fr/lambdawalks/?view=fromroots2canopy and, for instance http://lambdaway.free.fr/lambdawalks/?view=reduce http://lambdaway.free.fr/lambdawalks/?view=reduce Thank you once more for your kind reply. Alain Marty
- kazinator 6y agoI found some past discussions but not sure if that was the right one. Anyway, suppose we have a pencil-and-paper Lisp dialect, where everything is evaluated by rewriting objects on paper. We can have lexical scoping. That is to say, lexical scoping is achievable by substituting terms for variables. In particular, let us restrict to immutable variables. Like say we have (let ((x <whatever>) (y <whatever-else>)) (body x y)) Suppose that is just a picture: a character string or pencil marks on paper. We see what the scope is of the let and can basically just substitute: (body <whatever> <whatever-else>) It is the same with lambda. Say we have a lambda definition like (lambda (x y) (body x y)) When we call this with parameters <foo> and <bar>, whatever those things are, we substitute the arguments for x and y into the body: (body <foo> <bar>). This substitution can take place by a recursive walk of the code which respects scope, so for instance, if we have: (lambda (x y) (let ((x <xyzzy>)) (body x y))) the substitution will not just blindly replace the x as a character string. It walks the expression, and processes the (let ...) recursively, recognizing that x is shadowed by a new definition. The (let ...) part is recursively expanded and then substituted in place and so on. You need to pass down some environment object during the expansion. But: your lambdas do not have to have captured environments! They can be fully substituted. So that is to say: (let ((x <captured>)) (lambda (y) (+ x y))) can produce something like (lambda (y) (+ <captured> y)) no environment. The expansion/substitution process of (let ...) naturally took care of substituting the x value. The lambda parameter y remains unsubstituted: that happens at call time. The substitute function should probably be aware of lambda and keep track of the y, but specially annotated in the environment as "this is a lambda variable: do not substitute now". That sort of thing. My main point is that if you don't need mutable environments, then pencil-and-paper lexical scoping can be simulated in character strings by substitution. (Mutation throws a monkey wrench into things, like if you want to have stateful lambda procedures that return an incrementing counter whose initial value is a captured lexical.)
- martyalain 6y agoThank you for these explanations. As introduced in this page http://lambdaway.free.fr/lambdawalks/?view=lambda http://lambdaway.free.fr/lambdawalks/?view=lambda, in lambdatalk everything begins with such a text replacement process: replace :a0 :a1 ... an-1 in expression containing some occurences of :ai by v0 v1 ... vp-1 rewritten in a prefixed parenthesized form {{lambda {:a0 :a1 ... an-1} expression containing some occurences of :ai // it's a string } v0 v1 ... vp-1} It's nothing but an IIFE, (Immediately Invoked Function Expression). This is a simple example: 1) {{lambda {x y} {+ x y}} 3 4} -> 7 2) {{lambda {x y} {+ x y}} 3} -> {lambda {y} {+ 3 y}} 3) {{lambda {y} {+ 3 y}} 4} -> 7 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 http://lambdaway.free.fr/lambdawalks/?view=reduce