initializer expressions by a predefined list in "let"

Q&A's, tips, howto's
Locked
lyl
Posts: 44
Joined: Sun Mar 25, 2018 5:00 am

initializer expressions by a predefined list in "let"

Post by lyl »

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

Code: Select all

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

Code: Select all

(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
Posts: 183
Joined: Sun Mar 27, 2011 3:07 pm
Location: Italy
Contact:

Re: initializer expressions by a predefined list in "let"

Post by cameyo »

Code: Select all

(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:

Code: Select all

(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
Posts: 44
Joined: Sun Mar 25, 2018 5:00 am

Re: initializer expressions by a predefined list in "let"

Post by lyl »

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)) ?

ralph.ronnquist
Posts: 228
Joined: Mon Jun 02, 2014 1:40 am
Location: Melbourne, Australia

Re: initializer expressions by a predefined list in "let"

Post by ralph.ronnquist »

The use of single symbol is not a documented 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.

Code: Select all

(letex (l l) (let l (+ a b)))
and for a more regular need, I'd define me a macro like the following:

Code: Select all

(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

Code: Select all

(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.

Locked