From: Raymond Tam
Subject: two newbie qustions :
Date: 
Message-ID: <19828935.0204191612.65141b35@posting.google.com>
I had the following closure

(setf my-fun
  (let ((my-var 1))
    (lambda (x)
      (+ x my-var))))


at run-time, how do I find out the value of my-var is, iteractively in
my interpreter?
(I'm using clisp, emacs if this help)



2nd question, I'm doing pg's ANSI common lisp exercise, p97, ex9 :
given a list of number, define a function which return true iff the
difference btw each successive pairs of them is 1, using 'mapc' and
'return'

here is my attemp:
(defun map-diff1? (list)
  (mapc my-diff1?
	list))

(setf my-diff1?
  (let ((init nil))
    (lambda (x)
      (if (null init)
	  (setq init x)
	(if (eq 1
		(abs (- x init)))
	    (setq init x)
	  (return nil))))))

(map-diff1? '(1 2 3 4 3))
(map-diff1? '(1 2 3 4 6))


It sort of work, but the (return nil) is wrong usage, and my clisp
interpreter
complains :
*** - RETURN-FROM: no block named NIL is currently visible

what's the rigth sytax/usage for return in my case?
and also, my gut feeling is the 'my-diff1' doesn't look good,
any comment on my code style above is appreciated.


thanks
raymond

From: Gabe Garza
Subject: Re: two newbie qustions :
Date: 
Message-ID: <7kn23lxd.fsf@kynopolis.org>
··········@hotmail.com (Raymond Tam) writes:

> 2nd question, I'm doing pg's ANSI common lisp exercise, p97, ex9 :
> given a list of number, define a function which return true iff the
> difference btw each successive pairs of them is 1, using 'mapc' and
> 'return'
> 
> here is my attemp:
> (defun map-diff1? (list)
>   (mapc my-diff1?
> 	list))
> 
> (setf my-diff1?
>   (let ((init nil))
>     (lambda (x)
>       (if (null init)
> 	  (setq init x)
> 	(if (eq 1
> 		(abs (- x init)))
> 	    (setq init x)
> 	  (return nil))))))
> 
> (map-diff1? '(1 2 3 4 3))
> (map-diff1? '(1 2 3 4 6))
> 
> 
> It sort of work, but the (return nil) is wrong usage, and my clisp
> interpreter
> complains :
> *** - RETURN-FROM: no block named NIL is currently visible
> what's the rigth sytax/usage for return in my case?

   In Common Lisp, there's a special operator called BLOCK that essentially
gives a name to a series of forms (its body).  For example,

(block double-reeds
  (print 'oboe)
  (print 'bassoon))

creates a block named double-reeds whose body is the forms (print 'oboe) 
and (print 'bassoon).  Inside a block--but nowhere else--you can use the
operator RETURN-FROM.  RETURN-FROM takes one or two arguments.  The first
argument is always the name of a block and the second can be any other
legal Common Lisp form.  The effect of a RETURN-FROM form being executed
is simple: no more forms in the named block are executed, and the value
of the block is whatever the second argument evaluates to (or NIL, if you
didn't supply a second argument).

For example, executing

(block double-reeds
  (print 'oboe)
  (print 'bassoon)
  (return-from double-reeds (+ 1 2))
  (print 'english-horn))

would cause this to happen:

OBOE would be printed.
BASSOON would be printed.
3 would be returned.

This is because the RETURN-FROM stops the forms after it in the block
named DOUBLE-REEDS from being printed and makes the value of
the block whatever (+ 1 2) evaluates too (hopefully 3).

   But sometimes it doesn't make much sense for a block to have a name 
but you still want to be able to exit from it.  Common Lisp addresses
this by allowing you to `name' a block NIL.  Inside a block named NIL,
you can use RETURN-FROM with the argument NIL just like you could
in any other block.  But that's kind of cumbersome, so Common Lisp lets
you type (RETURN ..) instead of (RETURN-FROM NIL ...): they're the same
thing.
 
   The (return nil) generates an error because it gets transformed into
(return-from nil nil): the problem is that it's not inside a block!
Remember that RETURN-FROM only works inside a block.  It has to be in
a named block or in a block created (implicitly) by some other form.
Unfortunately, none of the forms in your LAMBDA expression create
such a block, either explicitly or implicitly.  Thus, if you want to
exit the LAMBDA with RETURN, you'd need something like:

(lambda (x)
  (block nil
    (if (null init)
        (setq init x)
        (if (eq 1 (abs (- x init)))
   	    (setq init x)
 	    (return nil)))))

There's probably a less verbose and more precise way of explaining all
that. 8)

Gabe Garza
From: Kenny Tilton
Subject: Re: two newbie qustions :
Date: 
Message-ID: <3CC114F9.F68A5B68@nyc.rr.com>
Raymond Tam wrote:

> 2nd question, I'm doing pg's ANSI common lisp exercise, p97, ex9 :
> given a list of number, define a function which return true iff the
> difference btw each successive pairs of them is 1, using 'mapc' and
> 'return'
> 
> here is my attemp:
> (defun map-diff1? (list)
>   (mapc my-diff1?
>         list))
> 
> (setf my-diff1?
>   (let ((init nil))
>     (lambda (x)
>       (if (null init)
>           (setq init x)
>         (if (eq 1
>                 (abs (- x init)))
>             (setq init x)
>           (return nil))))))
> 
> It sort of work, but the (return nil) is wrong usage, and my clisp
> interpreter
> complains :
> *** - RETURN-FROM: no block named NIL is currently visible

an error is "sort of working"? :)  Reminds me of C/C++, where landing in
the debugger was a relief, it meant I had not crashed the OS altogether.

hint: syntax is fine, the error message tells you what to do, and so
does page 82. :)

But! You better check the doc to see what mapc returns.

And you better test with '(1 2 3 5 6), not '(1 2 3 4 6)

You have quite a few things to sort out here... i'd offer more but i
don't want to spoil the fun. once you see what mapc returns i think
you'll see your whole scheme is in trouble.

btw, what was wrong with (mapc (lambda.....?

one more thing: init is the initial value only for the first iteration,
after that it is the prior or preceding value, so I have a problem with
that dataname.

good luck with the exercise. not a bad first try at all.


-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Kenny Tilton
Subject: Re: two newbie qustions :
Date: 
Message-ID: <3CC1B9DE.AF304BFB@nyc.rr.com>
I forgot to mention something:

Kenny Tilton wrote:
> 
> Raymond Tam wrote:
> 
....
> >     (lambda (x)
> >       (if (null init)
> >           (setq init x)
> >         (if (eq 1
> >                 (abs (- x init)))
> >             (setq init x)
> >           (return nil))))))
> >
> > It sort of work, but the (return nil) is wrong usage

Hint: (IF <test> 42) returns nil if the test fails. (And most prefer
(WHEN <test> 42) in this case.) So at a glance that "(RETURN nil)" seems
like overkill. But! (RETURN nil) is not the same as NIL... again see p82
to get a solid understnding of (RETURN nil) before making yourself crazy
on this.

The mapc/return requirement (along with the overall requirement that one
not search the whole list unless necessary) makes this a tricky
exercise, but you also gotta be clear on MAPC returns to see this.

So this is a good exercise, overall; you have to understand the two
forms pretty well before discovering the gotcha into which you have
fallen through mere albeit earnest hacking.

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Raymond Tam
Subject: Re: two newbie qustions :
Date: 
Message-ID: <19828935.0204201407.3d1629c9@posting.google.com>
yeah, the more I think about it, the more tricky it seems.

mapc operate on each list, yet the result is not collected
and since I can't escape from the dynamic env using return (right?)
the result of mapc just get dropped, so I guess mapc is *only* useful
for side effect (right?)

so one way to do it is to have a 'special' variable and let mapc to modify
this variable....  doesn't seems a good approach to me..

tricky bussiness...
raymond




Kenny Tilton <·······@nyc.rr.com> wrote in message news:<·················@nyc.rr.com>...
> I forgot to mention something:
> 
> Kenny Tilton wrote:
> > 
> > Raymond Tam wrote:
> > 
>  ....
> > >     (lambda (x)
> > >       (if (null init)
> > >           (setq init x)
> > >         (if (eq 1
> > >                 (abs (- x init)))
> > >             (setq init x)
> > >           (return nil))))))
> > >
> > > It sort of work, but the (return nil) is wrong usage
> 
> Hint: (IF <test> 42) returns nil if the test fails. (And most prefer
> (WHEN <test> 42) in this case.) So at a glance that "(RETURN nil)" seems
> like overkill. But! (RETURN nil) is not the same as NIL... again see p82
> to get a solid understnding of (RETURN nil) before making yourself crazy
> on this.
> 
> The mapc/return requirement (along with the overall requirement that one
> not search the whole list unless necessary) makes this a tricky
> exercise, but you also gotta be clear on MAPC returns to see this.
> 
> So this is a good exercise, overall; you have to understand the two
> forms pretty well before discovering the gotcha into which you have
> fallen through mere albeit earnest hacking.
From: Kenny Tilton
Subject: Re: two newbie qustions :
Date: 
Message-ID: <3CC23FE8.7B504348@nyc.rr.com>
Raymond Tam wrote:
> 
> yeah, the more I think about it, the more tricky it seems.

I think it is not an accident that mapc/return was the third combo
assigned--it is also the trickiest and really it is a trick question in
that it is artifcially constrained to disallow straightforward
solutions.


> 
> mapc operate on each list, yet the result is not collected
> and since I can't escape from the dynamic env using return (right?)
> the result of mapc just get dropped...

quibble: mapc's result does not "get dropped" unless you drop it. but in
this example you may as well drop it since getting back list-1 does not
help. like i said, just a quibble.

> ...., so I guess mapc is *only* useful
> for side effect (right?)

right.

> 
> so one way to do it is to have a 'special' variable and let mapc to modify
> this variable....  doesn't seems a good approach to me..

good idea, but it does not stop you from visiting nodes needlessly
(after one pair has failed the test) and I am pretty sure that is an
unstated requirment of this exercise.

> 
> tricky bussiness...

i just bought some Sherlock Holmes for a friend, so I am tempted to say
"elementary":

OK, you are told you have to use mapc and return, so first write the
code:

   (mapc (lambda (item) <much like what you had including: (return
nil)>) list)

The (return nil) will give you an error which by now you understand
pretty well, having studied up on RETURN and pg 82. So you know what to
do to make (return nil) compile at least.

Now test against '(1 2 3 5 6). It /may/ not work. (If it /does/ work you
figured out the trick, congrats, but make sure it works the other way on
'(1 2 3) and (1 3 4) and (1 2 4) etc.)

If it does not work, change the (return nil) to (progn (print "Bingo!!!!
Returning nil!!!!")(return nil)). This will likely confirm that you are
returning nil to no avail, and I see from the above you now realize why.
That "why" might tip you off to a simple fix.

Hint: you ever answered my question as to why you did not put the lambda
form as a direct argument to mapc. 

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Raymond Tam
Subject: Re: two newbie qustions :
Date: 
Message-ID: <19828935.0204210144.28e6713c@posting.google.com>
> Hint: you ever answered my question as to why you did not put the lambda
> form as a direct argument to mapc.

this hint saved me, everything seems straight and simple now.
somehow I got the wrong feeling that if I'm using 'lambda' 
it'll create another env so it doens't matter if put the code in 
one lexical block or have a separate function. 
(of course, turns out i'm completely wrong.)

thanks for helping.
From: Gabe Garza
Subject: Re: two newbie qustions :
Date: 
Message-ID: <3cxp3aax.fsf@kynopolis.org>
Kenny Tilton <·······@nyc.rr.com> writes:

OP, don't read if you still haven't solved it. ;)

> Raymond Tam wrote:
> > 
> > yeah, the more I think about it, the more tricky it seems.
> 
> I think it is not an accident that mapc/return was the third combo
> assigned--it is also the trickiest and really it is a trick question in
> that it is artifcially constrained to disallow straightforward
> solutions.
;; Snip
> OK, you are told you have to use mapc and return, so first write the
> code:
> 
>    (mapc (lambda (item) <much like what you had including: (return
> nil)>) list)

Maybe "straightforward" solutions won't follow the above MAPC invocation 
pattern. 8)


(defun problem-from-book (list)
  (block nil
    (mapc (lambda (item next)
	    (when (/= (- next item) 1)
	      (return nil)))
	  list
	  (cdr list))
    t))
	  
Gabe Garza
From: Raymond Tam
Subject: Re: two newbie qustions :
Date: 
Message-ID: <19828935.0204210152.6e930518@posting.google.com>
> (defun problem-from-book (list)
>   (block nil
>     (mapc (lambda (item next)
> 	    (when (/= (- next item) 1)
> 	      (return nil)))
> 	  list
> 	  (cdr list))
>     t))
> 	  
> Gabe Garza


wow, your approach is much more elegant than mine, 
good to see someone else's solution, thanks!
From: Kenny Tilton
Subject: Re: two newbie qustions :
Date: 
Message-ID: <3CC2CA65.17B513CD@nyc.rr.com>
Gabe Garza wrote:
> 
> Kenny Tilton <·······@nyc.rr.com> writes:
> > that mapc/return ... is artifcially constrained to disallow straightforward
> > solutions.
> ;; Snip
> >
> >    (mapc (lambda (item) <much like what you had including: (return
> > nil)>) list)
> 
> Maybe "straightforward" solutions won't follow the above MAPC invocation
> pattern. 8)
> 
> (defun problem-from-book (list)
>   (block nil
>     (mapc (lambda (item next)
>             (when (/= (- next item) 1)
>               (return nil)))
>           list
>           (cdr list))
>     t))

(1) doesn't that follow my pattern? the essence of which is "using
return in a mapc function"? I did not know that trick for avoiding
tracking a prior value. Thx, very cool. But the extra work of
maintaining a prior value was not the basis of my "unstraightforward"
whining.

(2) our definitions of straightforward differ. :) If I do not have to
use mapc, I can (co-opting your trick):

   (notany (lambda (prior item)
              (/= 1 (abs (- item prior))))
         list (cdr list))

... or if I can at least use return-from:

   (block bingo .... (mapc (lambda ... (return-from bingo...

...to me that is straightforward. 

The double-whammy of mapc/return struck me as a set-up backing us into a
corner we could escape only with "(block nil...", and (block nil...)
seems to be more for macros supporting return than for coding in-line.


-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Tim Moore
Subject: Re: two newbie qustions :
Date: 
Message-ID: <a9uv58$2ja$0@216.39.145.192>
I know the OP's problem was a exercise calling for mapc and return,
but I feel I need to wave the flag for the loop macro:

(defun problem-from-book (list)
  (loop
      for (a b) on list by #'cddr
      unless (= (- b a) 1)
      return nil
      finally (return t)))

Tim

On Sun, 21 Apr 2002 14:13:19 GMT, Kenny Tilton <·······@nyc.rr.com> wrote:
>
>
>Gabe Garza wrote:
>> 
>> Kenny Tilton <·······@nyc.rr.com> writes:
>> > that mapc/return ... is artifcially constrained to disallow straightforward
>> > solutions.
>> ;; Snip
>> >
>> >    (mapc (lambda (item) <much like what you had including: (return
>> > nil)>) list)
>> 
>> Maybe "straightforward" solutions won't follow the above MAPC invocation
>> pattern. 8)
>> 
>> (defun problem-from-book (list)
>>   (block nil
>>     (mapc (lambda (item next)
>>             (when (/= (- next item) 1)
>>               (return nil)))
>>           list
>>           (cdr list))
>>     t))
>
>(1) doesn't that follow my pattern? the essence of which is "using
>return in a mapc function"? I did not know that trick for avoiding
>tracking a prior value. Thx, very cool. But the extra work of
>maintaining a prior value was not the basis of my "unstraightforward"
>whining.
>
>(2) our definitions of straightforward differ. :) If I do not have to
>use mapc, I can (co-opting your trick):
>
>   (notany (lambda (prior item)
>              (/= 1 (abs (- item prior))))
>         list (cdr list))
>
>... or if I can at least use return-from:
>
>   (block bingo .... (mapc (lambda ... (return-from bingo...
>
>...to me that is straightforward. 
>
>The double-whammy of mapc/return struck me as a set-up backing us into a
>corner we could escape only with "(block nil...", and (block nil...)
>seems to be more for macros supporting return than for coding in-line.
>
>
>-- 
>
> kenny tilton
> clinisys, inc
> ---------------------------------------------------------------
>"Harvey has overcome not only time and space but any objections."
>                                                        Elwood P. Dowd
From: Paul F. Dietz
Subject: Re: two newbie qustions :
Date: 
Message-ID: <3CC305D3.41B8F0C1@interaccess.com>
Tim Moore wrote:
> 
> I know the OP's problem was a exercise calling for mapc and return,
> but I feel I need to wave the flag for the loop macro:
> 
> (defun problem-from-book (list)
>   (loop
>       for (a b) on list by #'cddr
>       unless (= (- b a) 1)
>       return nil
>       finally (return t)))

(defun problem-from-book (list)
  (loop
      for (a b) on list by #'cddr
      always (= (- b a) 1)))

	Paul
From: Tim Moore
Subject: Re: two newbie qustions :
Date: 
Message-ID: <a9v1du$1s3$0@216.39.145.192>
On Sun, 21 Apr 2002 13:32:51 -0500, Paul F. Dietz <·····@interaccess.com> wrote:
>Tim Moore wrote:
>> 
>> I know the OP's problem was a exercise calling for mapc and return,
>> but I feel I need to wave the flag for the loop macro:
>> 
>> (defun problem-from-book (list)
>>   (loop
>>       for (a b) on list by #'cddr
>>       unless (= (- b a) 1)
>>       return nil
>>       finally (return t)))
>
>(defun problem-from-book (list)
>  (loop
>      for (a b) on list by #'cddr
>      always (= (- b a) 1)))
>
>	Paul

Even better :)
Tim
From: Kenny Tilton
Subject: Re: two newbie qustions :
Date: 
Message-ID: <3CC32D0C.AFFFEE21@nyc.rr.com>
Loop is /so/ weird.

Tim Moore wrote:
> Even better :)

Speaking of which, I started to use every then rejected it. I cannot for
the life of me recall why. :)

  (every (lambda (prior item)
           (= 1 (abs (- item prior))))
         list (cdr list))

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Dr. Edmund Weitz
Subject: Re: two newbie qustions :
Date: 
Message-ID: <m3hem4ahq0.fsf@bird.agharta.de>
······@sea-tmoore-l.dotcast.com (Tim Moore) writes:

> On Sun, 21 Apr 2002 13:32:51 -0500, Paul F. Dietz <·····@interaccess.com> wrote:
> >Tim Moore wrote:
> >> 
> >> I know the OP's problem was a exercise calling for mapc and
> >> return, but I feel I need to wave the flag for the loop macro:
> >> 
> >> (defun problem-from-book (list)
> >>   (loop
> >>       for (a b) on list by #'cddr
> >>       unless (= (- b a) 1)
> >>       return nil
> >>       finally (return t)))
> >
> >(defun problem-from-book (list)
> >  (loop
> >      for (a b) on list by #'cddr
> >      always (= (- b a) 1)))
> >
> >	Paul
> 
> Even better :)
> Tim

If my understanding of 'each successive pair' (not being a native
speaker) is correct, both of these solutions would return wrong
results, e.g.

  USER> (problem-from-book '(4 5 1 2))
  T

while it should be NIL 'cause the difference between 5 and 1 is not
1. In other words, they only test half of the pairs that should be
tested.

Also, they obviously don't work on lists with odd numbers of elements
like the two examples from the OP:

  USER> (problem-from-book '(1 2 3 4 3))
  
  Argument X is not a NUMBER: NIL.
  
  Restarts:
    0: [ABORT] Return to Top-Level.
  
  Debug  (type H for help)
  
  (KERNEL:TWO-ARG-- NIL 3)
  Source: Error finding source: 
  Error in function DEBUG::GET-FILE-TOP-LEVEL-FORM:  Source file no longer exists:
    target:code/numbers.lisp.

But at least I've learned another idiom of using LOOP... :)

Thanks,
Edi.
  
-- 

Dr. Edmund Weitz Hamburg Germany

The Common Lisp Cookbook
<http://cl-cookbook.sourceforge.net/>
From: Tim Moore
Subject: Re: two newbie qustions :
Date: 
Message-ID: <a9vk6q$g09$0@216.39.145.192>
On 21 Apr 2002 23:01:59 +0200, Dr. Edmund Weitz <···@agharta.de> wrote:
>······@sea-tmoore-l.dotcast.com (Tim Moore) writes:
>
>> On Sun, 21 Apr 2002 13:32:51 -0500, Paul F. Dietz <·····@interaccess.com> wrote:
>> >Tim Moore wrote:
>> >> 
>> >> I know the OP's problem was a exercise calling for mapc and
>> >> return, but I feel I need to wave the flag for the loop macro:
>> >> 
>> >> (defun problem-from-book (list)
>> >>   (loop
>> >>       for (a b) on list by #'cddr
>> >>       unless (= (- b a) 1)
>> >>       return nil
>> >>       finally (return t)))
>> >
>> >(defun problem-from-book (list)
>> >  (loop
>> >      for (a b) on list by #'cddr
>> >      always (= (- b a) 1)))
>> >
>> >	Paul
>> 
>> Even better :)
>> Tim
>
>If my understanding of 'each successive pair' (not being a native
>speaker) is correct, both of these solutions would return wrong
>results, e.g.
>
>  USER> (problem-from-book '(4 5 1 2))
>  T
>
>while it should be NIL 'cause the difference between 5 and 1 is not
>1. In other words, they only test half of the pairs that should be
>tested.
>
>Also, they obviously don't work on lists with odd numbers of elements
>like the two examples from the OP:
>
>  USER> (problem-from-book '(1 2 3 4 3))
>  

Good point.  A small tweak fixes both problems:

(defun problem-from-book (list)
  (loop
      for (a b) on list
      always (or (null b) (= (- b a) 1))))

or

(defun problem-from-book (list)
  (loop
      for (a b) on list
      until (null b)
      always (= (- b a) 1)))

Tim
From: Bruce Hoult
Subject: Re: two newbie qustions :
Date: 
Message-ID: <bruce-AD3D90.13360020042002@copper.ipg.tsnz.net>
In article <····························@posting.google.com>,
 ··········@hotmail.com (Raymond Tam) wrote:

> I had the following closure
> 
> (setf my-fun
>   (let ((my-var 1))
>     (lambda (x)
>       (+ x my-var))))
> 
> 
> at run-time, how do I find out the value of my-var is, iteractively in
> my interpreter?
> (I'm using clisp, emacs if this help)

(funcall my-fun 0)

There is no other way, short of using a debugger or other introspection 
facilities.  For example, in CMUCL if you just type "my-fun" then the 
interpreter replies:

#<Interpreted Function "LET ((MY-VAR 1))" {4801D721}>


If you want you could return two or more closures from within the "let" 
by using multiple-values or putting them into a list or other data 
structure.  So you could make another closure which just returns the 
value of my-var.

-- Bruce
From: Raymond Tam
Subject: Re: two newbie qustions :
Date: 
Message-ID: <19828935.0204201311.5f241aa9@posting.google.com>
thanks everyone's help so far, there is one issue puzzling me.

in the following code

(defun abc ()
  (return-from abc 'ok))

(defun def ()
  (def-aux))

(defun def-aux ()
  (return-from def 'ok))


I don't understand why the (abc) works but not (def) ?
(resulted my same old friend *** - RETURN-FROM: no block named DEF is
currently visible ...)
is it true that 'block' is only visible in the current lexical frame, 
and it won't search the parent env? 


thanks,
raymond
From: Kenny Tilton
Subject: Re: two newbie qustions :
Date: 
Message-ID: <3CC1E204.B3E1D1F6@nyc.rr.com>
Raymond Tam wrote:
> is it true that 'block' is only visible in the current lexical frame,
> and it won't search the parent env?

right. catch-throw would let you work off the dynamic environment

-- 

 kenny tilton
 clinisys, inc
 ---------------------------------------------------------------
"Harvey has overcome not only time and space but any objections."
                                                        Elwood P. Dowd
From: Kent M Pitman
Subject: Re: two newbie qustions :
Date: 
Message-ID: <sfwbscekned.fsf@shell01.TheWorld.com>
··········@hotmail.com (Raymond Tam) writes:

> thanks everyone's help so far, there is one issue puzzling me.
> 
> in the following code
> 
> (defun abc ()
>   (return-from abc 'ok))
> 
> (defun def ()
>   (def-aux))
> 
> (defun def-aux ()
>   (return-from def 'ok))
> 
> 
> I don't understand why the (abc) works but not (def) ?
> (resulted my same old friend *** - RETURN-FROM: no block named DEF is
> currently visible ...)
> is it true that 'block' is only visible in the current lexical frame, 
> and it won't search the parent env? 

That's not a bug, that's a feature.  Consider:

 (defun ghi (y)
   (block blah
     (phi #'(lambda (x) (return-from blah x))
          y)))

 (defun phi (fn datum)
   (1+ 
     (block blah
       (funcall fn datum))))

 (ghi 1) => 1

The nice thing about lexical blocks is that you can understand where they
are going to just by examining the lexical code and not having to consider
the dynamic call chain.   You don't want an internal lexical change to 
PHI (such as the deletion of the useless block BLAH) to make a change in the
GHI function's lexically apparent meaning.

 (defun ghi0 (y)
   (block blah
     (phi0 #'(lambda (x) (return-from blah x))
          y)))

 (defun phi0 (fn datum)
   (1+ 
     (funcall fn datum)))

 (ghi0 1) => 1

Moreover, the reason you know it's safe to have removed the spurious block
(between phi and phi0) was that you knew that you didn't have to look at
any other function than phi0 ot see that the block was unused.

Sometimes you really need dynamic hookups, but they are prone to confusion
if you make changes to the dynamic call chain, so they're harder to reason
about.  So if you do:

 (defun ghi2 (y)
   (catch 'blah
     (phi2 #'(lambda (x) (throw 'blah x))
           y)))

 (defun phi2 (fn datum)
   (1+
     (catch 'blah
       (funcall fn datum))))

 (ghi2 1) => 2

you'll get one answer but if you do

 (defun ghi2 (y)
   (catch 'blah
     (phi2 #'(lambda (x) (throw 'blah x))
           y)))

 (defun phi2 (fn datum)
   (1+
     (funcall fn datum)))

 (ghi3 1) => 1
From: Raymond Tam
Subject: Re: two newbie qustions :
Date: 
Message-ID: <19828935.0204202246.53d1b3f2@posting.google.com>
ic, stupid me, 
it's the same reason why lexical var is more preferable
than dynamic variable....

thanks.


Kent M Pitman <······@world.std.com> wrote in message > 
> The nice thing about lexical blocks is that you can understand where they
> are going to just by examining the lexical code and not having to consider
> the dynamic call chain.   You don't want an internal lexical change to 
> PHI (such as the deletion of the useless block BLAH) to make a change in the
> GHI function's lexically apparent meaning.
>
From: Rahul Jain
Subject: Re: two newbie qustions :
Date: 
Message-ID: <878z7hpi1t.fsf@photino.sid.rice.edu>
··········@hotmail.com (Raymond Tam) writes:

> it's the same reason why lexical var is more preferable
> than dynamic variable....

Lexical vars are more preferable when they have the semantics you
desire. Dynamic vars are more preferable when they have the semantics
you desire. What's truely more preferable is the ability to choose
which one you want when you want it.

-- 
-> -/                        - Rahul Jain -                        \- <-
-> -\  http://linux.rice.edu/~rahul -=-  ············@techie.com   /- <-
-> -/ "Structure is nothing if it is all you got. Skeletons spook  \- <-
-> -\  people if [they] try to walk around on their own. I really  /- <-
-> -/  wonder why XML does not." -- Erik Naggum, comp.lang.lisp    \- <-
|--|--------|--------------|----|-------------|------|---------|-----|-|
   (c)1996-2002, All rights reserved. Disclaimer available upon request.