initializer expressions by a predefined list in "let"

Started by lyl, June 15, 2019, 05:10:10 PM

Previous topic - Next topic

lyl

I think the following two examples of using "let" say the same thing but they get different result:

Example #1:
(setq l '((a 1) (b 2)))
(let l (+ a b)) ;; ERR: invalid let parameter list in function let : l

Example #2:
(let ((a 1) (b 2)) (+ a b)) ;; get 3 as expected

Why is the first example a wrong way using "let"? And is there a way to give initializer expressions of "let" with a predefined list as shown in the first example?

cameyo

#1
(setq a 1 b 2)
(let (l (+ a b)) (println l))
;-> 3

(let (a 4 b 5 l (+ a b)) (println a { } b { } l))
;-> 4 5 3
; l = 3 because in the expression (+ a b), a = 1 and b = 2.

Use letn to solve this:
(letn (a 4 b 5 l (+ a b)) (println a { } b { } l))
;-> 4 5 9
; Now l = 9 because inside the letn expression a = 4 and b = 5.

lyl

#2
Since l in my example has the same structure as the initializer expressions of let, why does not it work in :

(setq l '((a 1) (b 2)))

(let l (+ a b)) ?

rrq

#3
The use of  single symbol is not a documented http://www.newlisp.org/downloads/newlisp_manual.html#let">syntax form, and generally, that second element of the let term is not evaluated but processed as is (and only evaluated in parts). So that syntax form is a DIY opportunity :)



For a once-off need, I'd wrap it into a letex, as in the following.
(letex (l l) (let l (+ a b))) and for a more regular need, I'd define me a macro like the following:
(define-macro (lett)
    (if (list? (args 0)) (apply let (args))
        (apply let (cons (eval (pop (args))) (args))) ))

The latter would be a new function lett that kind of extends the function of let, but also lets me have a symbol as second element, in which case that symbol is evaluated so as to obtain an actual second argument for the let term. Thus, for your example, you would use (lett l (+ a b))

However, the resulting syntax is a case of non-local variable references (since the lett body includes a and b as out of context references), and that is something I would generally try to avoid, as I find it rather lacking in clarity, More specifically, the passing in of a variable assignment list into a let form conflates meta level and object level logic for no obvious reason, since the passed in list has to include the particular assignments that the body of the let form expects/requires anyhow, to be of any use. So if this would be used in a program, then that program would be slightly harder to read and understand than the equivalent program without using this feature.