From: Joshua Taylor on
On 2010.04.28 12:28 PM, Joshua Taylor wrote:
> On 2010.04.28 8:32 AM, Francogrex wrote:
>> On Apr 27, 4:37 pm, Norbert_Paul<norbertpauls_spam...(a)yahoo.com>
>> wrote:
>>> 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.
>>
>> ok The actual function is not that complex but it calls other libaries
>> at some point. Here with all the setf it works ok but as such it's a
>> function full of "landmines".
>>
>> load "c:/emacs/zscripts/C-EMBED/rcl.fas")
>> (in-package :rcl)
>> (r-init)
>>
>> (defun OR-MUE (lst)
>> (setf y1 (nth 0 lst) n1 (nth 1 lst) y2 (nth 2 lst) n2 (nth 3 lst))
>>
>> (if (= y1 n1) (setf p_1u 1)
>> (progn
>> (setf F_u (* (/ (+ y1 1) (- n1 y1)) (r "qf" 0.5 (* 2 (+ y1
>> 1)) (* 2 (- n1 y1)))))
>> (setf p_1u (/ F_u (+ 1 F_u)))))
>>
>> (if (= y1 0) (setf p_1l 0)
>> (progn
>> (setf F_l (* (/ (+ (- n1 y1) 1) y1) (r "qf" 0.5 (* 2 (+ (- n1
>> y1) 1)) (* 2 y1))))
>> (setf p_1l (/ 1 (+ 1 F_l)))))
>>
>> (setf p1_mue (* 0.5 (+ p_1l p_1u)))
>>
>> (if (= y2 n2) (setf p_2u 1)
>> (progn
>> (setf F_u (* (/ (+ y2 1) (- n2 y2)) (r "qf" 0.5 (* 2 (+ y2
>> 1)) (* 2 (- n2 y2)))))
>> (setf p_2u (/ F_u (+ 1 F_u)))))
>> (if (= y2 0) (setf p_2l 0)
>> (progn
>> (setf F_l (* (/ (+ (- n2 y2) 1) y2) (r "qf" 0.5 (* 2 (+ (- n2
>> y2) 1)) (* 2 y2))))
>> (setf p_2l (/ 1 (+ 1 F_l)))))
>>
>> (setf p2_mue (* 0.5 (+ p_2l p_2u)))
>>
>> (setf or_mue (/ (* p1_mue (- 1 p2_mue)) (* p2_mue (- 1 p1_mue)))))
>>
>>
>> ;;(OR-MUE (list 4 14 0 11))
>
> If all those variables really shouldn't be bound via LET, how about the
> following:
>
> (defun OR-MUE (lst)
> (multiple-value-setq (y1 n1 y2 n2) (values-list lst))
>
> (cond
> ((= y1 0) ; or (zerop y1)
> (setf p_1l 0))
> ((= y1 n1)
> (setf p_1u 1))
> ((setf F_u (* (/ (+ y1 1)
> (- n1 y1))
> (r "qf" 0.5
> (* 2 (+ y1 1))
> (* 2 (- n1 y1))))
> p_1u (/ F_u (+ 1 F_u))
> F_l (* (/ (+ (- n1 y1) 1) y1)
> (r "qf" 0.5
> (* 2 (+ (- n1 y1) 1))
> (* 2 y1)))
> p_1l (/ 1 (+ 1 F_l)))))
>
> (cond
> ((= y2 0) ; (or (zerop y2))
> (setf p_2l 0))
> ((= y2 n2)
> (setf p_2u 1))
> ((setf F_u (* (/ (+ y2 1) (- n2 y2))
> (r "qf" 0.5
> (* 2 (+ y2 1))
> (* 2 (- n2 y2))))
> p_2u (/ F_u (+ 1 F_u))
> F_l (* (/ (+ (- n2 y2) 1) y2)
> (r "qf" 0.5
> (* 2 (+ (- n2 y2) 1))
> (* 2 y2)))
> p_2l (/ 1 (+ 1 F_l)))))
>
> (setf p1_mue (* 0.5 (+ p_1l p_1u))
> p2_mue (* 0.5 (+ p_2l p_2u))
> or_mue (/ (* p1_mue (- 1 p2_mue))
> (* p2_mue (- 1 p1_mue)))))
>
>
> If these can be local variables, you can do something like the following
> (which also pulls out some common computations). Your original code had
> paths that didn't set all the p_nx value, so you probably had some
> useful non-local values in those variables. Even so, the following could
> still be a useful starting point if you replace the NILs with default
> values and use some MULTIPLE-VALUE-SETQs (or (SETF VALUES)) rather than
> DESTRUCTURING-BIND and MULTIPLE-VALUE-BINDs.
>
>
> (defun OR-MUE (lst)
> (flet ((F_u (y n &aux (1+y (1+ y)) (d (- n y)))
> (* (/ 1+y d)
> (r "qf" 0.5
> (* 2 1+y)
> (* 2 d))))
> (F_l (y n &aux (d+1 (1+ (- n y)))
> (* (/ d+1 y)
> (r "qf" 0.5
> (* 2 d+1)
> (* 2 y)))))
> (ps (y n)
> "Return p_nu, p_nl as multiple values."
> (cond
> ((= y 0)
> (values nil 0)) ; probably shouldn't have nil here
> ((= y n)
> (values 1 nil))
> ((let ((F_u (F_u y n))
> (F_l (F_l y n)))
> (values (/ F_u (1+ F_u))
> (/ (1+ F_l))))))))
> (destructuring-bind (y1 n1 y2 n2) lst
> (multiple-value-bind (p_1u p_1l) (ps y1 n1)
> (multiple-value-bind (p_2u p_2l) (ps y2 n2)
> (let ((p1_mue (* 0.5 (+ p_1l p_1u)))
> (p2_mue (* 0.5 (+ p_2l p_2u))))
> (/ (* p1_mue (1- p2_mue))
> (* p2_mue (1- p1_mue)))))))
>
>
> //JT

The second code block should have been what follows, using LABELS rather
than FLET (since ps uses F_u and F_1), and with t as the test-form of
the last COND clause, since in COND's default cases it only returns the
primary value of the test-form.

(defun OR-MUE (lst)
(labels ((F_u (y n &aux (1+y (1+ y)) (d (- n y)))
(* (/ 1+y d)
(r "qf" 0.5
(* 2 1+y)
(* 2 d))))
(F_l (y n &aux (d+1 (1+ (- n y)))
(* (/ d+1 y)
(r "qf" 0.5
(* 2 d+1)
(* 2 y)))))
(ps (y n)
"return as multiple values p_nu, p_nl"
(cond
((= y 0)
(values nil 0)) ; probably shouldn't have nil here
((= y n)
(values 1 nil))
(t
(let ((F_u (F_u y n))
(F_l (F_l y n)))
(values (/ F_u (1+ F_u))
(/ (1+ F_l))))))))
(destructuring-bind (y1 n1 y2 n2) lst
(multiple-value-bind (p_1u p_1l) (ps y1 n1)
(multiple-value-bind (p_2u p_2l) (ps y2 n2)
(let ((p1_mue (* 0.5 (+ p_1l p_1u)))
(p2_mue (* 0.5 (+ p_2l p_2u))))
(/ (* p1_mue (1- p2_mue))
(* p2_mue (1- p1_mue)))))))))


//JT
From: His kennyness on
Francogrex wrote:
> 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?

Because you knew the crappy example would make it impossible to answer
your question? What the hell were you thinking? Oh, I know, what I said
before: you had already decided that the problem was too many lets,
meaning you decided what we should know about the poblem and you decided
what we should work on and what we should offer.

Contact Merriam-Webster: your picture next to "obtuse" needs updating.
From: His kennyness on
Francogrex wrote:
> On Apr 27, 4:37 pm, Norbert_Paul <norbertpauls_spam...(a)yahoo.com>
> wrote:
>> 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.
>
> ok The actual function is not that complex but it calls other libaries
> at some point. Here with all the setf it works ok but as such it's a
> function full of "landmines".
>
> load "c:/emacs/zscripts/C-EMBED/rcl.fas")
> (in-package :rcl)
> (r-init)
>
> (defun OR-MUE (lst)
> (setf y1 (nth 0 lst) n1 (nth 1 lst) y2 (nth 2 lst) n2 (nth 3 lst))

Can you say "destructuring-bind"? Sher ya can.

Otherwise, don't feel bad: having to prime four (?) globals given four
parameters will never look elegant.

kzo

>
> (if (= y1 n1) (setf p_1u 1)
> (progn
> (setf F_u (* (/ (+ y1 1) (- n1 y1)) (r "qf" 0.5 (* 2 (+ y1
> 1)) (* 2 (- n1 y1)))))
> (setf p_1u (/ F_u (+ 1 F_u)))))
>
> (if (= y1 0) (setf p_1l 0)
> (progn
> (setf F_l (* (/ (+ (- n1 y1) 1) y1) (r "qf" 0.5 (* 2 (+ (- n1
> y1) 1)) (* 2 y1))))
> (setf p_1l (/ 1 (+ 1 F_l)))))
>
> (setf p1_mue (* 0.5 (+ p_1l p_1u)))
>
> (if (= y2 n2) (setf p_2u 1)
> (progn
> (setf F_u (* (/ (+ y2 1) (- n2 y2)) (r "qf" 0.5 (* 2 (+ y2
> 1)) (* 2 (- n2 y2)))))
> (setf p_2u (/ F_u (+ 1 F_u)))))
> (if (= y2 0) (setf p_2l 0)
> (progn
> (setf F_l (* (/ (+ (- n2 y2) 1) y2) (r "qf" 0.5 (* 2 (+ (- n2
> y2) 1)) (* 2 y2))))
> (setf p_2l (/ 1 (+ 1 F_l)))))
>
> (setf p2_mue (* 0.5 (+ p_2l p_2u)))
>
> (setf or_mue (/ (* p1_mue (- 1 p2_mue)) (* p2_mue (- 1 p1_mue)))))
>
>
> ;;(OR-MUE (list 4 14 0 11))
From: Tim X on
Francogrex <franco(a)grex.org> writes:

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


I assumed you called it useless because even if it worked it did nothing
and was useless. The point is your example was more than useless - it
was completely broken and would not have worked *at all* without
throwing reference to unbound symbol errors.

Your question was about how to get rid of/reduce embedded let forms.
However, your example indicates you don't even understand how let forms
worke. If you didn't understand something that simple,
you are unlikely to understand how to get rid of embedded let forms.

If you do understand how let works then you could have created an
example which actually /works/ for no more effort and people would not
have been distracted by errors in your example and would have addressed
your actual question, assuming of course the question you asked did
reflect what you wanted to know.

If your exampoe was just something you dumped out in a hurry, indicating
you couldn't even put in the effort to provide a clear and concise
example of what you were referring to, then why should anyone else try
to put in the effort to help you.

The quality of responses you get are usually a reflection of the quality
and effort you put into forming the question.

--
tcross (at) rapttech dot com dot au