From: Francogrex on
How does one get around several embedded lets in the simplified
example below? (In relaity I have a function that is much more complex
with many conditions...). Thanks

(defun useless (y x)
(if (= y x) (let ((m1 13)) m1)
(progn
(let* ((f1 75)
(m1 (* f1 f1))) m1)))
(if (= y 5) (let ((m2 78)) m2)
(progn
(let* ((f2 58)
(m2 (* f2 f2))) m2)))
(+ m1 m2)
)

(USELESS 3 5)
From: Captain Obvious on
F> How does one get around several embedded lets in the simplified
F> example below? (In relaity I have a function that is much more complex
F> with many conditions...). Thanks

I do not see "several embedded lets" in the example below.

F> (defun useless (y x)
F> (if (= y x) (let ((m1 13)) m1)
F> (progn
F> (let* ((f1 75)
F> (m1 (* f1 f1))) m1)))
F> (if (= y 5) (let ((m2 78)) m2)
F> (progn
F> (let* ((f2 58)
F> (m2 (* f2 f2))) m2)))

F> (+ m1 m2)

Here m1 and m2 will be unbound. Dude, do you understand how let works at
all? Variables can be seen inside of let, not outside.

Your code is better without lets at all:

(defun useless (y x)
(+
(if (= y x)
13
(* 75 75))
(if (= y 5)
72
(* 58 58))))

As a bonus, it actually works this way.

From: His kennyness on
Captain Obvious wrote:
> F> How does one get around several embedded lets in the simplified
> F> example below? (In relaity I have a function that is much more complex
> F> with many conditions...). Thanks
>
> I do not see "several embedded lets" in the example below.
>
> F> (defun useless (y x)
> F> (if (= y x) (let ((m1 13)) m1)
> F> (progn
> F> (let* ((f1 75)
> F> (m1 (* f1 f1))) m1)))
> F> (if (= y 5) (let ((m2 78)) m2)
> F> (progn
> F> (let* ((f2 58)
> F> (m2 (* f2 f2))) m2)))
>
> F> (+ m1 m2)
>
> Here m1 and m2 will be unbound. Dude, do you understand how let works at
> all? Variables can be seen inside of let, not outside.
>
> Your code is better without lets at all:
>
> (defun useless (y x)
> (+
> (if (= y x)
> 13
> (* 75 75))
> (if (= y 5)
> 72
> (* 58 58))))
>
> As a bonus, it actually works this way.

We're here to help, which means understanding what the person meant
instead of slavishly hewing to what they wrote. Witness the fact that in
conjuring up a non-example to optimize their question they not only
violated Tilton's Law ("Thou shalt not simplify the problem underlying
thine questions.") but also lexical scoping.

To our OP:

Trees. Forest. Please note order.

The problem is in the subject: your problem is not too many lets, it is
(effectively) too imperative a coding style. ie, You see the lets, I see
a failure to program functionally. Step 1 would be:

(defun useless (y x)
(+
(if (= y x)
(let ((m1 13)) m1)
(progn
(let* ((f1 75)
(m1 (* f1 f1))) m1)))
(if (= y 5) (let ((m2 78)) m2)
(progn
(let* ((f2 58)
(m2 (* f2 f2))) m2)))))


Before some yobbo jumps in with the Obvious, no, nothing below the
addition form itself makes any sense. That's why I said Step 1. The OP
needs to take the next steps.

If you have values shared by derivation of the two addends, those can go
in an outer let or even an &aux. If what is shared is a diabolical
derivation we have flet, lables, macrolet, and symbol-macrolet.

What you will be doing is not removing lets but improving functionalness
of your coding, and functional is an absolute good. Your rewrite will
expose what values mean what where and when and be vastly more
understandable. You will then be able to delete any comments.

hth

kt

From: Norbert_Paul on
Maybe it would be helpful if you posted your original
"function which is more complex", maybe even together with
what you expect it to do.

(Besides: Might it be called "useful"?)

Norbert

Francogrex wrote:
> How does one get around several embedded lets in the simplified
> example below? (In relaity I have a function that is much more complex
> with many conditions...). Thanks
>
> (defun useless (y x)
> (if (= y x) (let ((m1 13)) m1)
> (progn
> (let* ((f1 75)
> (m1 (* f1 f1))) m1)))
> (if (= y 5) (let ((m2 78)) m2)
> (progn
> (let* ((f2 58)
> (m2 (* f2 f2))) m2)))
> (+ m1 m2)
> )
>
> (USELESS 3 5)

From: Thomas A. Russ on
Francogrex <franco(a)grex.org> writes:

> How does one get around several embedded lets in the simplified
> example below? (In relaity I have a function that is much more complex
> with many conditions...). Thanks

You may not be able to get around it if you insist on doing this all in
one function. But a few observations

> (defun useless (y x)
> (if (= y x) (let ((m1 13)) m1)
> (progn
> (let* ((f1 75)
> (m1 (* f1 f1))) m1)))
> (if (= y 5) (let ((m2 78)) m2)
> (progn
> (let* ((f2 58)
> (m2 (* f2 f2))) m2)))
> (+ m1 m2)
> )

1. If you have a LET or LET* form as the top-level item in your IF
statement, then you don't need to have the PROGN around it. So anything
that looks exactly like
(PROGN (LET (...) ...)
)
where there is only a single item inside the PROGN means you can remove
the PROGN without changing the meaning. But it could be that the
progn is needed in your more complex real example.

2. You can perhaps eliminate, or rather move, the bindings to another
location or locations, by making the clauses into their own functions
and then calling them. Something more like

(if (= y x)
(f1 13)
(f2 75))
(if (= y 5)
(f1 78)
(f3 58))

along with

(defun f1 (v) v)
(defun f2 (v)
(let ((m (* v v)))
m))
...

3. Depending on what your conditions are, you may also be able to
reduce the nesting depth by using COND or maybe (depending on the
tests) even using generic functions and methods.


--
Thomas A. Russ, USC/Information Sciences Institute