From: Tim X 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
>
> (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)

Your simplified example makes no sense.

This raises two issues. Firstly, be very careful of simplified examples.
If you don't really understand something, your simplification is likely
to remove the key bit of information required to understand the issue
and more often than not, will distract from the core issue. Respondants
will focus on the bit they are comfortable with, which will likely be
your errors in simplification rather than the issue you wanted explored.

The second issue exposed by this simplificaiton is that I doubt you
actually understand let, let*, scope and value binding. If you did, you
would have realised your simplified example doesn't work.

Therefore, my advice is that before you even consider modifying any
code, spend some time to understand let and scoping. This will be
essential knowledge if you plan to modify how let is used. Make sure you
udnerstand the difference between lexical and dynamic scope, defvar and
let, let and let* etc. As a test, come back afterwards and look at your
simplificaiton and see if you can spot why it doesn't work. If it still
looks to you like a good example, study some more.

It is likely that once you understand this better, you won't see the
embedded let forms in the code your working on as being as big an issue
as you think it is. Most likely, it is just a difference in programming
style. If what you are doing is code maintenance, an important skill to
acquire is the ability to work with code written in different styles. If
you start modifying perfectly working code simply because you don't like
its style, you will no longer be maintaining code, but rather
re-implementing it. re-implementation is fine if thats what you want to
do, but if your supposed to be adding new functionality or fixing buggy
functionality, it is really a distraction that is reducing your
productivity. You will almost certainly also be adding new bugs.

Tim


--
tcross (at) rapttech dot com dot au
From: Wade on
The ONLY solution is to use more Lisp functionality.
Use &optional and &aux lambda args.

(defun useless (y x &optional (f1 72) (f2 58)
&aux
(m1 (if (= y x) 13 (* f1 f1)))
(m2 (if (= y 5) 78 (* f2 f2))))
(+ m1 m2))

Wade
From: Wade on
There might be ONE more solution.

(defmacro linear-execute (&body body)
(let ((forms (butlast body))
(result (car (last body))))
`(let ,(mapcar 'car forms)
,@(mapcar (lambda (form) (cons 'setf form)) forms)
,result)))

(defun useless (y x)
(linear-execute
(f1 72)
(f2 58)
(m1 (if (= y x) 13 (* f1 f1)))
(m2 (if (= y 5) 78 (* f2 f2)))
(+ m1 m2)))

macroexpansion...
(PROGN (CCL::%DEFUN (NFUNCTION USELESS
LAMBDA
(Y X)
(DECLARE (CCL::GLOBAL-FUNCTION-NAME
USELESS))
(BLOCK USELESS
(LET (F1 F2 M1 M2)
(SETQ F1 72)
(SETQ F2 58)
(SETQ M1 (IF (= Y X) 13 (* F1 F1)))
(SETQ M2 (IF (= Y 5) 78 (* F2 F2)))
(+ M1 M2))))
'NIL)
'USELESS)

Wade

From: Captain Obvious on
W> There might be ONE more solution.

W> (defmacro linear-execute (&body body)
W> (let ((forms (butlast body))
W> (result (car (last body))))
W> `(let ,(mapcar 'car forms)
W> ,@(mapcar (lambda (form) (cons 'setf form)) forms)
W> ,result)))

W> (defun useless (y x)
W> (linear-execute
W> (f1 72)
W> (f2 58)
W> (m1 (if (= y x) 13 (* f1 f1)))
W> (m2 (if (= y 5) 78 (* f2 f2)))
W> (+ m1 m2)))

How is it different from

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

? LET* is just as good as your linear-execute, but it is standard.
From: Francogrex on
On Apr 28, 12:15 am, Tim X <t...(a)nospam.dev.null> wrote:
> The second issue exposed by this simplificaiton is that I doubt you
> actually understand let, let*, scope and value binding. If you did, you
> would have realised your simplified example doesn't work.

Did you seriously think that I didn't know in advance that my
"useless" example doesn't work? Why do you think I called it useless
and asked the question then?