[comp.lang.lisp.x] Possible bug: trouble with

tony@oha.UUCP (Tony Olekshy) (12/23/90)

Question for xlisp internals gurus follows below...

I just spent way too long debugging:

        (mapcar '(lambda (son) (send son :rpt-output menu$width))
	    (reverse menu$sons))

The problem is, of course, that the single quote should either be left off,
or replaced with #'.  I have taken the later course with all things that
should be functions, as is done in xlstat.

The reason this took so long to debug is that the quoted form was mostly
working (!), but on long enough data sets there would arise cases where other
instances of local variables named son were being garbage collected, and
cases where xlisp would simply core dump.  Since I've just been through the
experience of adding c functions to xlisp, I was uncertain as to whether or
not this was being caused by improperly protected temporary lvals in my code. 
Furthermore, I could only reproduce the problem with large data sets, and they
take time to run.  Oh well.

Now my question for xlisp internals gurus is: is there some trivial code that
would either: 1) promote a quoted lambda expression, as the first expression
to mapcar, to a function (since it works on short data sets, perhaps the code
to do such promotion is just missing the protection of the temporary lvals),
or 2) produce an error message when mapcar's first argument is not a valid
form?

--
Yours etc., Tony Olekshy.       Internet: tony%oha@CS.UAlberta.CA
				  BITNET: tony%oha.uucp@UALTAMTS.BITNET
				    uucp: alberta!oha!tony
Blowing is not playing the flute, you must make use of your fingers.--Goethe

This is JaMira speaking ) (12/27/90)

In article <467@oha.UUCP> tony@oha.UUCP (Tony Olekshy) writes:
   >>I just spent way too long debugging:
   >>
   >>	     (mapcar '(lambda (son) (send son :rpt-output menu$width))
   >>		 (reverse menu$sons))

     I had a same problem, and

*** xleval.c.orig	Fri Jul 20 16:53:25 1990
--- xleval.c	Fri Jul 20 16:54:24 1990
***************
*** 155,160 ****
--- 155,163 ----
      LVAL *oldargv,fun,val;
      int oldargc;
      
+     /* protect some pointers */
+     xlsave1(fun);
+ 
      /* get the function */
      fun = xlfp[1];
  
***************
*** 204,209 ****
--- 207,215 ----
      /* remove the call frame */
      xlsp = xlfp;
      xlfp = xlfp - (int)getfixnum(*xlfp);
+ 
+     /* restore the stack */
+     xlpop();
  
      /* return the function value */
      return (val);


this works well so far.

     I hope this works for your case, too.

--
 Yosh Nishinaka (nisinaka@sra.co.jp)
"One for all. All for one. Three for Five."

toma@sail.LABS.TEK.COM (Tom Almy) (12/28/90)

In article <NISINAKA.90Dec27030519@sraco1.us.sra.co.jp> nisinaka@sraco1.us.sra.co.jp ( Hello!!  This is JaMira speaking ) writes:
>In article <467@oha.UUCP> tony@oha.UUCP (Tony Olekshy) writes:
>   >>I just spent way too long debugging:
>   >>	     (mapcar '(lambda (son) (send son :rpt-output menu$width))
>   >>		 (reverse menu$sons))

>     I had a same problem, and

[fix involving protecting pointer fun in xlapply deleted]

>this works well so far.

>     I hope this works for your case, too.

Yes it will work, but it doesn't truly address the problem and wastes
a position in the stack. Normally fun would not need to be protected, since
its value is the same as that in the argument stack (which also gets
garbage collected). The problem comes when fun is a CONS (as in the
original posting), and gets reassigned. Sometime ago, a fix was posted
by Paul vanNiekerk that addresses the problem by storing the new function
back into the argument stack.

To fix, in xlapply() find the line "fun = xlclose(..." and replace
with "xlfp[1] = fun = xlclose(...".

Copies of xlisp distributed by me have this patch applied.

As to the original poster's comment about the functional arguments
	(lambda ...)
	'(lambda ...)
	#'(lambda ...)
seemingly performing the same way. The don't, and its not an error.
The documentation states that the function argument given to eval can be
a closure (first and third case) or a cons where the car is LAMBDA.
In the second case, the closure will be built within the mapcar (in this case)
function, and thus will have different free variable bindings than in the
first or third case. The first and third case are identical in operation.

Note that if a defined function was used instead of the lambda expression,
then only #'fun will work since the other forms will use the value binding
of fun.

--
Tom Almy
toma@sail.labs.tek.com <<< Note new address
Standard Disclaimers Apply