From: Giannandrea Castaldi
Subject: Use of dynamic variables
Date: 
Message-ID: <c3orc9$q4$1@lacerta.tiscalinet.it>
Hi,
While I'm writing a simple textual spreadsheet and I've noticed that 
several functions/methods have the same argument: the spreadsheet as 2 
dimensional array:
...
(defun eval-spreadsheet (spreadsheet)
   (let ((output (make-array (array-dimensions spreadsheet))))
     (dotimes (row (array-dimension spreadsheet 0) output)
       (dotimes (column (array-dimension spreadsheet 1))
	(setf (aref output row column) (eval-cell (+ column 1) (+ row 1) 
spreadsheet))))))


(defmethod eval-cell ((column string) row spreadsheet)
   (eval-cell (string-number column) row spreadsheet))

(defmethod eval-cell ((column integer) row spreadsheet)
   (let ((cell (aref spreadsheet (- row 1) (- column 1))))
     (if (eq (aref cell 0) #\=)
	  (apply-operation '+
			   (mapcar #'(lambda (substr)
				       (apply-operation '-
					(mapcar (eval-operand spreadsheet)
						(extract-operands substr '-))))
				   (extract-operands (remove #\= cell) '+)))
	  (parse-integer cell))))

(defun apply-operation (operation operands)
   (if (= (length operands) 1)
       (identity (car operands))
       (apply (symbol-function operation) operands)))

(defun eval-operand (spreadsheet)
   #'(lambda (operand)
       (cond ((alpha-char-p (aref operand 0))
	     (eval-cell (scan-to-strings "\\D+" operand)
			(parse-integer (scan-to-strings "\\d+" operand))
			spreadsheet))
	    ((and (eql (aref operand 0) #\-) (alpha-char-p (aref operand 1)))
	     (- (eval-cell (scan-to-strings "\\D+" (remove #\- operand))
			(parse-integer (scan-to-strings "\\d+" operand))
			spreadsheet)))
	    (t (parse-integer operand)))))
...

Then I decided that perhaps it would be better to define a global 
variable (*current-spreadsheet*) and then the outer function 
(eval-spreadsheet) reallocate the same variable so that I can remove the 
spreadsheet argument from the inner methods (sorry, in the code there 
are also other small changes):

(defvar *spreadsheet*)

(defun eval-spreadsheet (spreadsheet)
   (let ((*spreadsheet* spreadsheet)
	(output (make-array (array-dimensions spreadsheet))))
     (dotimes (row (array-dimension *spreadsheet* 0) output)
       (dotimes (column (array-dimension *spreadsheet* 1))
	(setf (aref output row column) (eval-cell (+ column 1) (+ row 1)))))))

(defmethod eval-cell ((column string) row)
   (eval-cell (string-number column) row))

(defmethod eval-cell ((column integer) row)
   (let ((cell (aref *spreadsheet* (- row 1) (- column 1))))
     (if (eq (aref cell 0) #\=)
	(let ((expr (remove #\= cell)))
	  (apply-operation '+
			   (mapcar #'(lambda (expr)
				       (apply-operation '-
							(mapcar #'eval-operand
								(extract-operands expr '-))))
				   (extract-operands expr '+))))
	(parse-integer cell))))

(defun apply-operation (operation operands)
   (if (= (length operands) 1)
       (identity (car operands))
       (apply (symbol-function operation) operands)))

(defun eval-operand (operand)
   (cond ((alpha-char-p (aref operand 0))
	 (eval-cell (scan-to-strings "\\D+" operand)
		    (parse-integer (scan-to-strings "\\d+" operand))))
	((and (eql (aref operand 0) #\-) (alpha-char-p (aref operand 1)))
	 (- (eval-operand (remove #\- operand))))
	(t (parse-integer operand))))

I'm not a expert lisp and then I'd like to know how you consider this 
use of dynamic variable. Is Good?

I've thought if CLOS can help me but I think that in these case I think 
no, is right?

The last question: in this spreadsheet I have to evaluate cell with 
in-fixed math epxressions (ex. =3*2+5*A1) so that I decided to use the 
regular expressions to split it in subexpression (currently only + and 
-) to evaluate single math operation. Is there a simpler solution? I've 
thought I could parse the expression to build a syntax tree but I've 
never done one and I think that for the +,-,* and / is too complex, is 
right?

Thanks for the help.

Giannandrea

From: Kenny Tilton
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <wYT7c.4136$1C1.2243708@twister.nyc.rr.com>
Giannandrea Castaldi wrote:


> Then I decided that perhaps it would be better to define a global 
> variable (*current-spreadsheet*) and then the outer function 
> (eval-spreadsheet) reallocate the same variable so that I can remove the 
> spreadsheet argument from the inner methods (sorry, in the code there 
> are also other small changes):

That technique is useful when you are sitting on top of a huge call tree 
of many different functions, including sometimes intermediate level 
utiltity functions which are not spreadsheet specific, but which will 
call other functions that need to see the spreadsheet. Then it is 
painful to pass the spreadsheet around as an argument.

But in your code, maybe I missed something, but I only see a few 
functions and one place the global gets used. Do you imagine the 
application growing a lot?

kt

-- 
Home? http://tilton-technology.com
Cells? http://www.common-lisp.net/project/cells/
Cello? http://www.common-lisp.net/project/cello/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
Your Project Here! http://alu.cliki.net/Industry%20Application
From: Giannandrea Castaldi
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <c3p9tn$pt3$1@lacerta.tiscalinet.it>
Kenny Tilton wrote:
> 
> 
> Giannandrea Castaldi wrote:
> 
> 
>> Then I decided that perhaps it would be better to define a global 
>> variable (*current-spreadsheet*) and then the outer function 
>> (eval-spreadsheet) reallocate the same variable so that I can remove 
>> the spreadsheet argument from the inner methods (sorry, in the code 
>> there are also other small changes):
> 
> 
> That technique is useful when you are sitting on top of a huge call tree 
> of many different functions, including sometimes intermediate level 
> utiltity functions which are not spreadsheet specific, but which will 
> call other functions that need to see the spreadsheet. Then it is 
> painful to pass the spreadsheet around as an argument.
> 
> But in your code, maybe I missed something, but I only see a few 
> functions and one place the global gets used. Do you imagine the 
> application growing a lot?

Now I'll add * and / but I thought seeing that already now eval-cell and 
eval-operand calls each other passing spreadsheet it's useful use it as 
dynamic variables. Beasides in this way I can directly use eval-operand 
as mapcar argument semplifing both its use and definition.
Another question: I've never used multi-threading in common-lisp but I 
suppose that dynamic variables don't introduce any conflict among 
threads beacause the variable are allocated on the thread frames. Is right?

Thanks.

Giannandrea


> 
> kt
> 
From: Arthur Lemmens
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <opr5bb6mq6k6vmsw@news.xs4all.nl>
Giannandrea Castaldi wrote:

> The last question: in this spreadsheet I have to evaluate cell with in-fixed
> math epxressions (ex. =3*2+5*A1) so that I decided to use the regular expressions
> to split it in subexpression (currently only + and -) to evaluate single math
> operation. Is there a simpler solution?

Have a look at the infix library by Mark Kantrowitz. It translates infix
expressions to Lisp's S-expressions. You could probably just use his parser.

Arthur Lemmens
From: Erann Gat
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <gNOSPAMat-2303040803370001@192.168.1.52>
In article <················@news.xs4all.nl>, Arthur Lemmens
<········@xs4all.nl> wrote:

> Giannandrea Castaldi wrote:
> 
> > The last question: in this spreadsheet I have to evaluate cell with in-fixed
> > math epxressions (ex. =3*2+5*A1) so that I decided to use the regular
expressions
> > to split it in subexpression (currently only + and -) to evaluate
single math
> > operation. Is there a simpler solution?
> 
> Have a look at the infix library by Mark Kantrowitz. It translates infix
> expressions to Lisp's S-expressions. You could probably just use his parser.
> 
> Arthur Lemmens

Or try my "parcil" parser.

E.
From: Sashank Varma
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <none-39BD09.22460924032004@news.vanderbilt.edu>
In article <···········@lacerta.tiscalinet.it>,
 Giannandrea Castaldi <········@tiscali.it> wrote:

> Hi,
> While I'm writing a simple textual spreadsheet and I've noticed that 
> several functions/methods have the same argument: the spreadsheet as 2 
> dimensional array:
> ...
> (defun eval-spreadsheet (spreadsheet)
>    (let ((output (make-array (array-dimensions spreadsheet))))
>      (dotimes (row (array-dimension spreadsheet 0) output)
>        (dotimes (column (array-dimension spreadsheet 1))
> 	(setf (aref output row column) (eval-cell (+ column 1) (+ row 1) 
> spreadsheet))))))
> 
> 
> (defmethod eval-cell ((column string) row spreadsheet)
>    (eval-cell (string-number column) row spreadsheet))
[...]
> 
> Then I decided that perhaps it would be better to define a global 
> variable (*current-spreadsheet*) and then the outer function 
> (eval-spreadsheet) reallocate the same variable so that I can remove the 
> spreadsheet argument from the inner methods (sorry, in the code there 
> are also other small changes):
[...]

Given the structure of your code, I sometimes use global variables.  
Specifically, in your original set of functions, the SPREADSHEET 
parameter is always last.  I'll change these parameters to optional ones 
that default to the value of *SPREADSHEET*, e.g.:

(defmethod eval-cell ((column string) row spreadsheet)
  (eval-cell (string-number column) row spreadsheet))

==>

(defmethod eval-cell ((column string) row &optional (spreadsheet 
*spreadsheet*)
  (eval-cell (string-number column) row spreadsheet))

Then you get the best of both worlds.  If an explicit SPREADSHEET 
argument is supplied, then it is used.  Otherwise, it defaults to the 
value of *SPREADSHEET*.  And, as you do in your revised code: 

> (defvar *spreadsheet*)

> (defun eval-spreadsheet (spreadsheet)
>    (let ((*spreadsheet* spreadsheet)
>    (output (make-array (array-dimensions spreadsheet))))
>      (dotimes (row (array-dimension *spreadsheet* 0) output)
>        (dotimes (column (array-dimension *spreadsheet* 1))
>    (setf (aref output row column) (eval-cell (+ column 1) (+ row 1)))))))
[...]

it's easy to have a top-level function that binds *SPREADSHEET*
to the desired value and then calls the other functions, which
default as appropriate.
From: Drew McDermott
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <c4i5cv$bd1$1@news.wss.yale.edu>
Giannandrea Castaldi wrote:
> Hi,
> While I'm writing a simple textual spreadsheet and I've noticed that 
> several functions/methods have the same argument: the spreadsheet as 2 
> dimensional array:
> ...
> Then I decided that perhaps it would be better to define a global 
> variable (*current-spreadsheet*) and then the outer function 
> (eval-spreadsheet) reallocate the same variable so that I can remove the 
> spreadsheet argument from the inner methods.

In my (long) experience, this is almost always a bad idea.  Never use a 
global variable unless you have a good argument that you will _never_ 
need to have two such objects in existence at once.  For spreadsheets, 
it seems that you almost certainly _will_ require multiple spreadsheets. 
    Then you'll have to rewrite all of your code to evolve it back to 
where it is now.

There are a couple of other ways to cut down on "globalish" variables 
that get passed around a lot without being modified very often:

1 Use 'labels', or a variant with a more flexible syntax, to make many 
of your functions local.  If F has a variable 'spreadsheet,' all the 
local functions can access it lexically.

2 If there are several 'globalish' variables, consider defining a data 
structure that packages them all up.  Then pass that data structure as 
an argument with a name such as 'context'.

   -- Drew McDermott
From: Rahul Jain
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <871xn75e8n.fsf@nyct.net>
Drew McDermott <··················@at.yale.dot.edu> writes:

> Giannandrea Castaldi wrote:
>> Then I decided that perhaps it would be better to define a global
>> variable (*current-spreadsheet*) and then the outer function
>> (eval-spreadsheet) reallocate the same variable so that I can remove
>> the spreadsheet argument from the inner methods.
>
> In my (long) experience, this is almost always a bad idea.  Never use a
> global variable unless you have a good argument that you will _never_
> need to have two such objects in existence at once.  For spreadsheets,
> it seems that you almost certainly _will_ require multiple spreadsheets.
> Then you'll have to rewrite all of your code to evolve it back to where
> it is now.

Ah, but CL doesn't have global (variable) variables. :)

-- 
Rahul Jain
·····@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist
From: Tim Bradshaw
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <ey3y8pe6e06.fsf@cley.com>
* Drew McDermott wrote:

> In my (long) experience, this is almost always a bad idea.  Never use
> a global variable unless you have a good argument that you will
> _never_ need to have two such objects in existence at once.  For
> spreadsheets, it seems that you almost certainly _will_ require
> multiple spreadsheets.   Then you'll have to rewrite all of your code
> to evolve it back to where it is now.

A special variable doesn't imply a global.  Even if it's something
defined with DEFVAR that only implies a global *default*, which may be
null of course.

--tim
From: Erann Gat
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <gNOSPAMat-0204041028010001@k-137-79-50-101.jpl.nasa.gov>
In article <············@news.wss.yale.edu>, Drew McDermott
<··················@at.yale.dot.edu> wrote:

> Giannandrea Castaldi wrote:
> > Hi,
> > While I'm writing a simple textual spreadsheet and I've noticed that 
> > several functions/methods have the same argument: the spreadsheet as 2 
> > dimensional array:
> > ...
> > Then I decided that perhaps it would be better to define a global 
> > variable (*current-spreadsheet*) and then the outer function 
> > (eval-spreadsheet) reallocate the same variable so that I can remove the 
> > spreadsheet argument from the inner methods.
> 
> In my (long) experience, this is almost always a bad idea.  Never use a 
> global variable unless you have a good argument that you will _never_ 
> need to have two such objects in existence at once.

One should qualify that with "... never need to have two such objects in
existence at once PER THREAD" because you can shadow a global binding with
dynamic bindings.

E.
From: Joe Marshall
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <d66qjhj6.fsf@ccs.neu.edu>
·········@flownet.com (Erann Gat) writes:

> In article <············@news.wss.yale.edu>, Drew McDermott
> <··················@at.yale.dot.edu> wrote:
>
>> Giannandrea Castaldi wrote:
>> > Hi,
>> > While I'm writing a simple textual spreadsheet and I've noticed that 
>> > several functions/methods have the same argument: the spreadsheet as 2 
>> > dimensional array:
>> > ...
>> > Then I decided that perhaps it would be better to define a global 
>> > variable (*current-spreadsheet*) and then the outer function 
>> > (eval-spreadsheet) reallocate the same variable so that I can remove the 
>> > spreadsheet argument from the inner methods.
>> 
>> In my (long) experience, this is almost always a bad idea.  Never use a 
>> global variable unless you have a good argument that you will _never_ 
>> need to have two such objects in existence at once.
>
> One should qualify that with "... never need to have two such objects in
> existence at once PER THREAD" because you can shadow a global binding with
> dynamic bindings.

Having multiple threads gives you multiple instances, but since you
can only refer to the instance within your own thread, it isn't much
better than having only one global instance.
From: Erann Gat
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <gNOSPAMat-0204041226430001@k-137-79-50-101.jpl.nasa.gov>
In article <············@ccs.neu.edu>, Joe Marshall <···@ccs.neu.edu> wrote:

> ·········@flownet.com (Erann Gat) writes:
> 
> > In article <············@news.wss.yale.edu>, Drew McDermott
> > <··················@at.yale.dot.edu> wrote:
> >
> >> Giannandrea Castaldi wrote:
> >> > Hi,
> >> > While I'm writing a simple textual spreadsheet and I've noticed that 
> >> > several functions/methods have the same argument: the spreadsheet as 2 
> >> > dimensional array:
> >> > ...
> >> > Then I decided that perhaps it would be better to define a global 
> >> > variable (*current-spreadsheet*) and then the outer function 
> >> > (eval-spreadsheet) reallocate the same variable so that I can remove the 
> >> > spreadsheet argument from the inner methods.
> >> 
> >> In my (long) experience, this is almost always a bad idea.  Never use a 
> >> global variable unless you have a good argument that you will _never_ 
> >> need to have two such objects in existence at once.
> >
> > One should qualify that with "... never need to have two such objects in
> > existence at once PER THREAD" because you can shadow a global binding with
> > dynamic bindings.
> 
> Having multiple threads gives you multiple instances, but since you
> can only refer to the instance within your own thread, it isn't much
> better than having only one global instance.

First, it is not necessarily true that you can only refer to the instance
in your own thread.  MCL, for example, as SYMBOL-VALUE-IN-PROCESS.

Second, even if you can't refer to instances in other threads that is
vastly better than having only one instance per Lisp image for certain
applications.  Multithreaded Web servers with a "connection" object per
thread come to mind.

E.
From: Joe Marshall
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <8yhdsjgi.fsf@comcast.net>
·········@flownet.com (Erann Gat) writes:

> In article <············@ccs.neu.edu>, Joe Marshall <···@ccs.neu.edu> wrote:
>
>> ·········@flownet.com (Erann Gat) writes:
>> 
>> > In article <············@news.wss.yale.edu>, Drew McDermott
>> > <··················@at.yale.dot.edu> wrote:
>> >
>> >> Giannandrea Castaldi wrote:
>> >> > Hi,
>> >> > While I'm writing a simple textual spreadsheet and I've noticed that 
>> >> > several functions/methods have the same argument: the spreadsheet as 2 
>> >> > dimensional array:
>> >> > ...
>> >> > Then I decided that perhaps it would be better to define a global 
>> >> > variable (*current-spreadsheet*) and then the outer function 
>> >> > (eval-spreadsheet) reallocate the same variable so that I can remove the 
>> >> > spreadsheet argument from the inner methods.
>> >> 
>> >> In my (long) experience, this is almost always a bad idea.  Never use a 
>> >> global variable unless you have a good argument that you will _never_ 
>> >> need to have two such objects in existence at once.
>> >
>> > One should qualify that with "... never need to have two such objects in
>> > existence at once PER THREAD" because you can shadow a global binding with
>> > dynamic bindings.
>> 
>> Having multiple threads gives you multiple instances, but since you
>> can only refer to the instance within your own thread, it isn't much
>> better than having only one global instance.
>
> First, it is not necessarily true that you can only refer to the instance
> in your own thread.  MCL, for example, as SYMBOL-VALUE-IN-PROCESS.

Non-portable and clumsy.

> Second, even if you can't refer to instances in other threads that is
> vastly better than having only one instance per Lisp image for certain
> applications.  Multithreaded Web servers with a "connection" object per
> thread come to mind.

Yes, but for a spreadsheet, it seems likely that one would want to use
two at once.

-- 
~jrm
From: Erann Gat
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <gNOSPAMat-0304041504450001@192.168.1.52>
In article <············@comcast.net>, Joe Marshall
<·············@comcast.net> wrote:

> > First, it is not necessarily true that you can only refer to the instance
> > in your own thread.  MCL, for example, as SYMBOL-VALUE-IN-PROCESS.
> 
> Non-portable

That's tautological.  Threads are non-portable in Common Lisp.

> and clumsy.

No clumsier than SYMBOL-VALUE.

E.
From: André Thieme
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <c58sp0$l66$1@ulric.tng.de>
Erann Gat wrote:

> That's tautological.  Threads are non-portable in Common Lisp.

How much work would it be to make them portable?
What would that involve? How much cooperation from what sides?


Andr�
--
From: Erann Gat
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <gNOSPAMat-1004041019480001@192.168.1.51>
In article <············@ulric.tng.de>, =?ISO-8859-1?Q?Andr=E9_Thieme?=
<······································@justmail.de> wrote:

> Erann Gat wrote:
> 
> > That's tautological.  Threads are non-portable in Common Lisp.
> 
> How much work would it be to make them portable?
> What would that involve? How much cooperation from what sides?

It depends on how portable you want them to be :-)

Among implementations that support threads it's not so hard beause all
their APIs are already more or less the same.  On the Remote Agent project
we were able to move code that relied heavily on threads between Allegro,
Harlequin and MCL without too much trouble.  (There are some superficial
differences, but these were easily addressed with macros.)

But there are popular Common Lisp implementations that don't support
threads at all, notably CLisp, and I believe CMUCL and its decendents. 
And ECL claimed to have threads but they didn't work the last time I tried
them (but that was a very long time ago).

E.
From: Don Geddis
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <87fzbb1whp.fsf@sidious.geddis.org>
·········@flownet.com (Erann Gat) wrote on Sat, 10 Apr 2004:
> But there are popular Common Lisp implementations that don't support
> threads at all, notably CLisp, and I believe CMUCL and its decendents. 

CMUCL offers threads on x86 platforms, at least.
_______________________________________________________________________________
Don Geddis                  http://don.geddis.org/               ···@geddis.org
From: Edi Weitz
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <m3zn9j7ke6.fsf@bird.agharta.de>
On Sat, 10 Apr 2004 10:19:48 -0700, ·········@flownet.com (Erann Gat) wrote:

> But there are popular Common Lisp implementations that don't support
> threads at all, notably CLisp, and I believe CMUCL and its
> decendents.

CMUCL has cooperative threads on Linux x86 and FreeBSD x86, SBCL (a
CMUCL descendant) has OS-level threads on Linux x86, Scieneer (another
CMUCL descendant) has OS-level threads on Solaris, HP-UX, and Linux -
32 bit and 64 bit.

Edi.
From: David Golden
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <loYdc.3923$qP2.11249@news.indigo.ie>
Erann Gat wrote:


> 
> But there are popular Common Lisp implementations that don't support
> threads at all, notably CLisp, and I believe CMUCL and its decendents.

Huh?

Well, CMUCL itself only has "green" threading (in java terms), but it's
still pretty good. One of the main reasons for SBCL as far as I can see is
to experiment with implementing good OS threading in a CMUCL variant.

Though as far as I recall, you can't save core images if you use threads.
But I seldom do that - what am I, a smalltalker???
From: André Thieme
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <c59pst$9td$1@ulric.tng.de>
Erann Gat wrote:
> In article <············@ulric.tng.de>, =?ISO-8859-1?Q?Andr=E9_Thieme?=
> <······································@justmail.de> wrote:
> 
> 
>>Erann Gat wrote:
>>
>>
>>>That's tautological.  Threads are non-portable in Common Lisp.
>>
>>How much work would it be to make them portable?
>>What would that involve? How much cooperation from what sides?
> 
> 
> It depends on how portable you want them to be :-)
> 
> Among implementations that support threads it's not so hard beause all
> their APIs are already more or less the same.  On the Remote Agent project
> we were able to move code that relied heavily on threads between Allegro,
> Harlequin and MCL without too much trouble.  (There are some superficial
> differences, but these were easily addressed with macros.)
> 
> But there are popular Common Lisp implementations that don't support
> threads at all, notably CLisp, and I believe CMUCL and its decendents. 
> And ECL claimed to have threads but they didn't work the last time I tried
> them (but that was a very long time ago).
> 
> E.

So at least it seems to me threads could be portable between LispWorks
and Allegro. It would also work to some degree for cmucl (and for sbcl?).
Such a threading package could later be extended to support any other
Lisp as soon it starts to support threads. How much work could such a
project possibly cost (in man hours)?


Andr�
--
From: Marco Antoniotti
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <1dSec.3$a5.941@typhoon.nyu.edu>
Andr� Thieme wrote:

> Erann Gat wrote:
> 
>> In article <············@ulric.tng.de>, =?ISO-8859-1?Q?Andr=E9_Thieme?=
>> <······································@justmail.de> wrote:
>>
>>
>>> Erann Gat wrote:
>>>
>>>
>>>> That's tautological.  Threads are non-portable in Common Lisp.
>>>
>>>
>>> How much work would it be to make them portable?
>>> What would that involve? How much cooperation from what sides?
>>
>>
>>
>> It depends on how portable you want them to be :-)
>>
>> Among implementations that support threads it's not so hard beause all
>> their APIs are already more or less the same.  On the Remote Agent 
>> project
>> we were able to move code that relied heavily on threads between Allegro,
>> Harlequin and MCL without too much trouble.  (There are some superficial
>> differences, but these were easily addressed with macros.)
>>
>> But there are popular Common Lisp implementations that don't support
>> threads at all, notably CLisp, and I believe CMUCL and its decendents. 
>> And ECL claimed to have threads but they didn't work the last time I 
>> tried
>> them (but that was a very long time ago).
>>
>> E.
> 
> 
> So at least it seems to me threads could be portable between LispWorks
> and Allegro. It would also work to some degree for cmucl (and for sbcl?).
> Such a threading package could later be extended to support any other
> Lisp as soon it starts to support threads. How much work could such a
> project possibly cost (in man hours)?

Very much.  This is what you get when there are more than 1.8 
implementations of your favourite language.

Cheers

marco
From: Paolo Amoroso
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <87u0zr7rl5.fsf@plato.moon.paoloamoroso.it>
Andr� Thieme <······································@justmail.de> writes:

> Erann Gat wrote:
>
>> That's tautological.  Threads are non-portable in Common Lisp.
>
> How much work would it be to make them portable?

Something similar has been done, see for example the file
src/port/proc.lisp in the CLOCC source tree.


Paolo
-- 
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film
From: Don Geddis
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <87d66q2low.fsf@sidious.geddis.org>
> Giannandrea Castaldi wrote:
> > Then I decided that perhaps it would be better to define a global variable
> > (*current-spreadsheet*) and then the outer function (eval-spreadsheet)
> > reallocate the same variable so that I can remove the spreadsheet argument
> > from the inner methods.

Drew McDermott <··················@at.yale.dot.edu> writes:
> In my (long) experience, this is almost always a bad idea.  Never use a
> global variable unless you have a good argument that you will _never_ need to
> have two such objects in existence at once.

Dynamic variables let you have multiple instances, simply by binding the
variable to the appropriate instance before calling the relevant functions.

What's wrong with something roughly like this:
        (defvar *current-spreadsheet*)
        (defun eval-spreadsheet (spreadsheet)
          (let ((*current-spreadsheet* spreadsheet))
             ... ))

I've used a structure much like that in a variety of applications, e.g. a
web server that had a client/thread context.

Dynamic variables don't seem incompatible with multiple instances to me.
And I sympathize with the OP's annoyance at passing the same silly "context"
argument into every single function.

        -- Don
_______________________________________________________________________________
Don Geddis                  http://don.geddis.org/               ···@geddis.org
In a survey taken several years ago, all incoming freshman at MIT were asked if
they expected to graduate in the top half of their class.  Ninety-seven percent
responded that they did.
From: Joe Marshall
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <7jwyjesx.fsf@ccs.neu.edu>
Don Geddis <···@geddis.org> writes:

> What's wrong with something roughly like this:
>         (defvar *current-spreadsheet*)
>         (defun eval-spreadsheet (spreadsheet)
>           (let ((*current-spreadsheet* spreadsheet))
>              ... ))
>

It is difficult to write code that spans several spreadsheets this
way.
From: Drew McDermott
Subject: Re: Use of dynamic variables
Date: 
Message-ID: <c4krpq$o55$1@news.wss.yale.edu>
Don Geddis wrote:


> Dynamic variables let you have multiple instances, simply by binding the
> variable to the appropriate instance before calling the relevant functions.
> 
> What's wrong with something roughly like this:
>         (defvar *current-spreadsheet*)
>         (defun eval-spreadsheet (spreadsheet)
>           (let ((*current-spreadsheet* spreadsheet))
>              ... ))
> 
You're quite right.  As are the others who pointed out much the same 
thing.  Even the OP
had a binding for *current-spreadsheet*.  I jumped to a conclusion about 
what he had
said, and responded to that instead of what he actually said.  Sorry for 
wasting everyone's brain bandwidth.

-- 
                                    -- Drew McDermott
                                       Yale Computer Science Department