wrapping mind around functional programming

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
31 messages Options
12
Reply | Threaded
Open this post in threaded view
|

wrapping mind around functional programming

Josh Stratton
When developing a large program with data structures in data
structures, does using a functional approach in scala slow performance
for really large data structures?

If class A holds a bunch of class Bs, which holds a bunch of class Cs
and they're all immutable, does changing C require A to be rebuilt?
Is this detrimental if A is up to 100 MBs large and is being down a a
hundred times a second?  Like if a GUI slider is quickly changing the
value of C's members?  Or is object copying usually negligible in
terms of performance impact?  Does Scala have any type of way to
reduce these kind of problems?

Josh
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Richard Wallace
On Tue, Jul 14, 2009 at 4:59 PM, Josh Stratton<[hidden email]> wrote:

> When developing a large program with data structures in data
> structures, does using a functional approach in scala slow performance
> for really large data structures?
>
> If class A holds a bunch of class Bs, which holds a bunch of class Cs
> and they're all immutable, does changing C require A to be rebuilt?
> Is this detrimental if A is up to 100 MBs large and is being down a a
> hundred times a second?  Like if a GUI slider is quickly changing the
> value of C's members?  Or is object copying usually negligible in
> terms of performance impact?  Does Scala have any type of way to
> reduce these kind of problems?
>
> Josh
>

It depends on the object graph and on the changes you are making.
But, if, for instance you are creating a new A and you are only
removing or adding a C to one of the B's then you can generally use
some combination of filtering for lazily removing
<http://www.scala-lang.org/docu/files/api/scala/Array.html#filter%28%28A%29%3D%3EBoolean%29>
and mapping <http://www.scala-lang.org/docu/files/api/scala/Array.html#map%28%28A%29%3D%3EB%29>
and concatenation
<http://www.scala-lang.org/docu/files/api/scala/Array.html#%2B%2B%28Iterable%5BB%5D%29>
to lazily add items just to the field containing your Cs and otherwise
copying the references for the other fields (no need to do a deep
copy, since they're immutable objects).

Rich
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Robert Fischer
In reply to this post by Josh Stratton
There are lots of smart ways that functional languages gain substantial efficiency with their data
structures, and even more smart ways that the JVM optimizes that kind of memory behavior.  In
general, it is safe to assume that "these kind of problems" aren't a problem, and it's safe to move
forward without the FUD.

~~ Robert.

Josh Stratton wrote:

> When developing a large program with data structures in data
> structures, does using a functional approach in scala slow performance
> for really large data structures?
>
> If class A holds a bunch of class Bs, which holds a bunch of class Cs
> and they're all immutable, does changing C require A to be rebuilt?
> Is this detrimental if A is up to 100 MBs large and is being down a a
> hundred times a second?  Like if a GUI slider is quickly changing the
> value of C's members?  Or is object copying usually negligible in
> terms of performance impact?  Does Scala have any type of way to
> reduce these kind of problems?
>
> Josh
>

--
~~ Robert Fischer, Smokejumper IT Consulting.
Enfranchised Mind Blog http://EnfranchisedMind.com/blog

Check out my book, "Grails Persistence with GORM and GSQL"!
http://www.smokejumperit.com/redirect.html
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Vlad Patryshev
In reply to this post by Josh Stratton
That's probably where zippers come handy. 

2009/7/14 Josh Stratton <[hidden email]>
When developing a large program with data structures in data
structures, does using a functional approach in scala slow performance
for really large data structures?

If class A holds a bunch of class Bs, which holds a bunch of class Cs
and they're all immutable, does changing C require A to be rebuilt?
Is this detrimental if A is up to 100 MBs large and is being down a a
hundred times a second?  Like if a GUI slider is quickly changing the
value of C's members?  Or is object copying usually negligible in
terms of performance impact?  Does Scala have any type of way to
reduce these kind of problems?

Josh



--
Thanks,
-Vlad
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Randall R Schulz-2
On Tuesday July 14 2009, Vlad Patryshev wrote:
> That's probably where zippers come handy.

And for a certain class of problems and representation schemes,
strategy-based term rewriting as pioneered by Stratego/XT [1] and
implemented in Scala by Kiama [2] is a tremendous advantage. I did
modify it to minimize the creation of new instances when sub-term
transformations don't alter the actual values returned and to operate
on non-case classes (actually, in stock form it works on any Product
sub-class, not just case classes).


[1] <http://strategoxt.org/>
[2] <http://code.google.com/p/kiama/>


Randall Schulz


> 2009/7/14 Josh Stratton <[hidden email]>
>
> > When developing a large program with data structures in data
> > structures, does using a functional approach in scala slow
> > performance for really large data structures?
> >
> > If class A holds a bunch of class Bs, which holds a bunch of class
> > Cs and they're all immutable, does changing C require A to be
> > rebuilt? Is this detrimental if A is up to 100 MBs large and is
> > being down a a hundred times a second?  Like if a GUI slider is
> > quickly changing the value of C's members?  Or is object copying
> > usually negligible in terms of performance impact?  Does Scala have
> > any type of way to reduce these kind of problems?
> >
> > Josh


Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Daniel Sobral
In reply to this post by Josh Stratton
Short answer, it depends.

You can certainly have efficient data structures for functional manipulation. For instance, Scala's List is very efficient for that. For example, "head", "tail", and "::" are all constant-time. Now, "::" is constant time because many lists can point to the same tail, and that is possible because the List is not doubly-linked, so a "tail" doesn't know it's "head". And, by the same token, a "head :: tail" doesn't know if it isn't someone else's tail.

A functional Map can work by having "layers". If you add or change a key/value, you add a layer which is consulted first, with a reference to the structure it originated from. So even if a different key/value is found on lower layers, what is returned is the one on the higher layer.

There is lots of research into this kind of thing, to make these structures efficient. So it's possible, but you'd better either research about it, or use something that is ready.

Another way you can gain performance is through projections and lazy evaluation. Basically, when you use a projection you store the functions passed to map/filter/flatMap, instead of applying them to produce a new structure. This is particularly effective when you know you won't need all of the final result -- for instance, if you will only want the first element in the collection with a certain property (or up to that element).

As for lazy evaluation, it simply postpones the computation of some data to the time it is actually needed. Again, you save when you know not all of the data will be actually needed.

Now, for the GUI slider, in particular, it seems a projection is more appropriate. You don't actually "copy" the data structure, you just "view" it through a filter that makes it seems like what you want. In fact, on Scala 2.8 "projection" has been replaced with "view".


On Tue, Jul 14, 2009 at 8:59 PM, Josh Stratton <[hidden email]> wrote:
When developing a large program with data structures in data
structures, does using a functional approach in scala slow performance
for really large data structures?

If class A holds a bunch of class Bs, which holds a bunch of class Cs
and they're all immutable, does changing C require A to be rebuilt?
Is this detrimental if A is up to 100 MBs large and is being down a a
hundred times a second?  Like if a GUI slider is quickly changing the
value of C's members?  Or is object copying usually negligible in
terms of performance impact?  Does Scala have any type of way to
reduce these kind of problems?

Josh



--
Daniel C. Sobral

Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Ben Hutchison-2
In reply to this post by Josh Stratton
On Wed, Jul 15, 2009 at 9:59 AM, Josh Stratton<[hidden email]> wrote:
> When developing a large program with data structures in data
> structures, does using a functional approach in scala slow performance
> for really large data structures?

Its a worthwhile question.

Intuitively, it seems the limiting lower bound on the amount of data
that must be copied on update is log(N) of total data N. This is
assuming you use a tree or similar, where only the updated branch,
running back to the root, is copied. Other structures, especially
heavily interlinked one, will require much more than log(N).

If you look at the way functional programs structure data, its
typically using fine-grained, incrementally update-able structures
without back-refs (trees, singly linked lists, in contrast to arrays)
that can re-use part of their previous structure on copy.

Its sufficiently troubling to some people in the FP community that
projects like DDC, a Haskell dialect with mutable data & an effect
system, have been developed [http://www.haskell.org/haskellwiki/DDC].

>
> If class A holds a bunch of class Bs, which holds a bunch of class Cs
> and they're all immutable, does changing C require A to be rebuilt?

Yes, if you need to see A again with the change in C, you'll need to
copy it + everything in between.

> Is this detrimental if A is up to 100 MBs large and is being down a a
> hundred times a second?  Like if a GUI slider is quickly changing the
> value of C's members?  Or is object copying usually negligible in
> terms of performance impact?

Probably less than traditionally imagined. AFAIK the JVM's generation
GC in the young generation does work proportional to the quantity of
surviving live data, so short lived objects are cheap to cleanup.

Does Scala have any type of way to
> reduce these kind of problems?

- Selective use of mutable structures. (Note also: if you need to
communicate with the "outside world" (even other threads), some use of
mutable state is inevitable.)

- Zippers ("subjective" data structures), as has been mentioned

-Ben
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Colin Bullock
If you're interested in further reading on the subject, I can't recommend [1] enough. It gives a through treatment of a wide variety of persistent immutable data structures, many of them implemented using laziness. The code is in ML (with Haskell version in an appendix), but all implementations are discussed thoroughly and in depth; it should be fairly easy to follow the code even with little ML/Haskell experience.

- Colin

[1] Purely Functional Data Structures. Okasaki, Chris. 1998 Cambridge University Press
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Randall R Schulz-2
On Wednesday July 15 2009, Colin Bullock wrote:
> If you're interested in further reading on the subject, I can't
> recommend [1] enough. It gives a through treatment of a wide variety
> of persistent immutable data structures, ...

Every time this recommendation comes up, I check the prices
on this book and decide not to purchase it.

Does it cover concepts that one might apply outside of writing
collections classes or other code that's usually found in libraries
already?


> - Colin
>
> [1] Purely Functional Data Structures. Okasaki, Chris. 1998 Cambridge
> University Press


Randall Schulz
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Robert Fischer
Randall R Schulz wrote:
> Every time this recommendation comes up, I check the prices
> on this book and decide not to purchase it.
>
Your local university library probably has it.  And that's really the best way to acquire it: it's
like Knuth, in that you hit places where the book is invaluable, but unless you're deep into the
bowels of a standard library, those places happen only on rare occasion.

> Does it cover concepts that one might apply outside of writing
> collections classes or other code that's usually found in libraries
> already?
>
Having read the book only after working in FP languages for a while, I found the value of the book
is less in the data structures themselves and more in the approach and exploration of how to think
and code in a functional way.  Even with a fair amount of experience, Okasaki showed me some
patterns and approaches that I hadn't encountered/thought of before.

~~ Robert Fischer, Smokejumper IT Consulting.
Enfranchised Mind Blog http://EnfranchisedMind.com/blog

Check out my book, "Grails Persistence with GORM and GSQL"!
http://www.smokejumperit.com/redirect.html
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Erik Engbrecht
In reply to this post by Randall R Schulz-2
Okasaki PhD thesis of the same title is available online: http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf

It's probably not a perfect substitute but it is readily available.

On Wed, Jul 15, 2009 at 9:52 AM, Randall R Schulz <[hidden email]> wrote:
On Wednesday July 15 2009, Colin Bullock wrote:
> If you're interested in further reading on the subject, I can't
> recommend [1] enough. It gives a through treatment of a wide variety
> of persistent immutable data structures, ...

Every time this recommendation comes up, I check the prices
on this book and decide not to purchase it.

Does it cover concepts that one might apply outside of writing
collections classes or other code that's usually found in libraries
already?


> - Colin
>
> [1] Purely Functional Data Structures. Okasaki, Chris. 1998 Cambridge
> University Press


Randall Schulz



--
http://erikengbrecht.blogspot.com/
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Randall R Schulz-2
In reply to this post by Robert Fischer
On Wednesday July 15 2009, Robert Fischer wrote:
> Randall R Schulz wrote:
> > Every time this recommendation comes up, I check the prices
> > on this book and decide not to purchase it.
>
> Your local university library probably has it.  And that's really the
> best way to acquire it: it's like Knuth, in that you hit places where
> the book is invaluable, but unless you're deep into the bowels of a
> standard library, those places happen only on rare occasion.

Given that for me the "local university library" is Stanford, that's
almost certainly true. (As far as I can tell, they get every single
volume of the LNCS and LNAI series!) I can even check things out of San
Jose State and they might have it, too, though they're nowhere near as
convenient to get to.


> > Does it cover concepts that one might apply outside of writing
> > collections classes or other code that's usually found in libraries
> > already?
>
> Having read the book only after working in FP languages for a while,
> I found the value of the book is less in the data structures
> themselves and more in the approach and exploration of how to think
> and code in a functional way.  Even with a fair amount of experience,
> Okasaki showed me some patterns and approaches that I hadn't
> encountered/thought of before.

Thanks. I figure I'm maybe about a quarter of the way to really thinking
in a FP way at this point, so that's probably very worthwhile. For
whatever it might mean, I still routinely reach for mutable sets and
maps for transient calculations inside of my classes but mostly write
immutable types (and occassionally a mutable + immutable pair).


> ~~ Robert Fischer


Randall Schulz
Reply | Threaded
Open this post in threaded view
|

RE: wrapping mind around functional programming

Tim Pigden
In reply to this post by Josh Stratton
Amazon uk has it for £23 - about the same price as a trip to my local university
New edition 2008


-----Original Message-----
From: Randall R Schulz [mailto:[hidden email]]
Sent: 15 July 2009 14:53
To: [hidden email]
Subject: Re: [scala-user] wrapping mind around functional programming

On Wednesday July 15 2009, Colin Bullock wrote:
> If you're interested in further reading on the subject, I can't
> recommend [1] enough. It gives a through treatment of a wide variety
> of persistent immutable data structures, ...

Every time this recommendation comes up, I check the prices
on this book and decide not to purchase it.

Does it cover concepts that one might apply outside of writing
collections classes or other code that's usually found in libraries
already?


> - Colin
>
> [1] Purely Functional Data Structures. Okasaki, Chris. 1998 Cambridge
> University Press


Randall Schulz
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Josh Stratton
In reply to this post by Erik Engbrecht
> Okasaki PhD thesis of the same title is available online:
> http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf
>
> It's probably not a perfect substitute but it is readily available.

Great, I'll start reading that.

So on the subject of appropriate times for OO and functional
paradigms, would writing a image manipulation program like gimp, for
example, be a poor choice for functional languages since the one huge
data array is constantly changing?  Or since most GUI APIs are so
heavily dependent on state?

Looking over various types of applications, it seems that functional
languages fit nicely into any particular situation be it a web server
or ssh daemon.  But does anyone consider certain types of programs
such as those involving complex GUIs a poor choice for functional
languages?  I've done some reading on Reactive Functional Programming,
but it seems very abstract (possibly just because relatively few
people have done it).

Reading papers like Okasaki's, where he comments,

"Although some data structures
designed for imperative languages such as C can be quite easily adapted to a
functional setting, most cannot, usually because they depend in
crucial ways on assignments,
which are disallowed, or at least discouraged, in functional languages..."

Is designing a more elegant data structure than an OO paradigm a
significant bottleneck in functional programming to get the touted
benefits?

Josh
Reply | Threaded
Open this post in threaded view
|

RE: wrapping mind around functional programming

Tim Pigden
In reply to this post by Josh Stratton
How about
User asks for record from database
User updates 2 fields of 30 record field
User writes data to database
?

For example in an ERP type context.
I can see it could be done functionally, but would it give me any real
advantage?

Tim

-----Original Message-----
From: Josh Stratton [mailto:[hidden email]]
Sent: 15 July 2009 17:35
To: Erik Engbrecht
Cc: Randall R Schulz; [hidden email]
Subject: Re: [scala-user] wrapping mind around functional programming

> Okasaki PhD thesis of the same title is available online:
> http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf
>
> It's probably not a perfect substitute but it is readily available.

Great, I'll start reading that.

So on the subject of appropriate times for OO and functional
paradigms, would writing a image manipulation program like gimp, for
example, be a poor choice for functional languages since the one huge
data array is constantly changing?  Or since most GUI APIs are so
heavily dependent on state?

Looking over various types of applications, it seems that functional
languages fit nicely into any particular situation be it a web server
or ssh daemon.  But does anyone consider certain types of programs
such as those involving complex GUIs a poor choice for functional
languages?  I've done some reading on Reactive Functional Programming,
but it seems very abstract (possibly just because relatively few
people have done it).

Reading papers like Okasaki's, where he comments,

"Although some data structures
designed for imperative languages such as C can be quite easily adapted
to a
functional setting, most cannot, usually because they depend in
crucial ways on assignments,
which are disallowed, or at least discouraged, in functional
languages..."

Is designing a more elegant data structure than an OO paradigm a
significant bottleneck in functional programming to get the touted
benefits?

Josh
Reply | Threaded
Open this post in threaded view
|

RE: wrapping mind around functional programming

Tim Pigden
In reply to this post by Josh Stratton
Sorry should be 30 field record..

-----Original Message-----
From: Tim Pigden [mailto:[hidden email]]
Sent: 15 July 2009 17:47
To: Josh Stratton; Erik Engbrecht
Cc: Randall R Schulz; [hidden email]
Subject: RE: [scala-user] wrapping mind around functional programming

How about
User asks for record from database
User updates 2 fields of 30 record field
User writes data to database
?

For example in an ERP type context.
I can see it could be done functionally, but would it give me any real
advantage?

Tim

-----Original Message-----
From: Josh Stratton [mailto:[hidden email]]
Sent: 15 July 2009 17:35
To: Erik Engbrecht
Cc: Randall R Schulz; [hidden email]
Subject: Re: [scala-user] wrapping mind around functional programming

> Okasaki PhD thesis of the same title is available online:
> http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf
>
> It's probably not a perfect substitute but it is readily available.

Great, I'll start reading that.

So on the subject of appropriate times for OO and functional
paradigms, would writing a image manipulation program like gimp, for
example, be a poor choice for functional languages since the one huge
data array is constantly changing?  Or since most GUI APIs are so
heavily dependent on state?

Looking over various types of applications, it seems that functional
languages fit nicely into any particular situation be it a web server
or ssh daemon.  But does anyone consider certain types of programs
such as those involving complex GUIs a poor choice for functional
languages?  I've done some reading on Reactive Functional Programming,
but it seems very abstract (possibly just because relatively few
people have done it).

Reading papers like Okasaki's, where he comments,

"Although some data structures
designed for imperative languages such as C can be quite easily adapted
to a
functional setting, most cannot, usually because they depend in
crucial ways on assignments,
which are disallowed, or at least discouraged, in functional
languages..."

Is designing a more elegant data structure than an OO paradigm a
significant bottleneck in functional programming to get the touted
benefits?

Josh
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

thompson4822
Tim -

On Wed, Jul 15, 2009 at 10:47 AM, Tim Pigden <[hidden email]> wrote:
Sorry should be 30 field record..

-----Original Message-----
From: Tim Pigden [mailto:[hidden email]]
Sent: 15 July 2009 17:47
To: Josh Stratton; Erik Engbrecht
Cc: Randall R Schulz; [hidden email]
Subject: RE: [scala-user] wrapping mind around functional programming

How about
User asks for record from database
User updates 2 fields of 30 record field
User writes data to database
?

I think it could be.  Since databases are quite functional in nature anyway, having a functional language might mean that there is less cognitive dissonance between what you want to do and how you express it.

This is especially true WRT databases that offer so-called native queries.  For example, here is how you might query Db4o or NeoDatis:

db.filter[Person](p => p.firstName == "Jack" && p.spouse.age > 20) foreach println

To me this is a lot easier to think about than the same code written in a more imperative style, such as how it would look in Java.

That said, once you start drinking the immutable kool-aid, it feels somewhat uncomfortable to have a bunch of entities that need to remain for the most part fully alterable.  I feel that this has been helpful though for me in recognizing the distinction between what Evans (Domain Driven Design) calls value and entity objects.

Hope that helps and best regards,


Steve

--
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Alex Cruise-2
In reply to this post by Tim Pigden
Tim Pigden wrote:
> New edition 2008
>  
[citation needed] :)

I've been waiting for a new edition to buy it; if it really exists I'll
buy it immediately; if it's forthcoming I'll wait a bit longer. :)

-0xe1a
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Daniel Sobral
In reply to this post by Josh Stratton
I agree to no such thing! :-)
 
Middle-end and high-end image manipulation programs often keep copies of original bitmaps, so that you manipulate the filters and transformations being applied -- change order, change parameters. The displayed image is a "preview" of the final result, but you are always working with the original bitmap. Of course, you do not reapply transformations that were not changed.
 
Most OO GUIs are surely heavily dependent on state. Of course, they are OO! Functional GUIs exists, though, and they are superior both in correctness -- as they are declarative in nature -- and in scalability through concurrency.
Functional Reactive Programming was not done "by a few people". Lisp Cells is widely succesful in the Lisp community, for instance. Of course, it's not common in the OO community -- it's functional!
 
And, no, I don't see any bottleneck with regard to designing functional data structures. Most code doesn't use anything more complex than collections, and you don't have to design those data structures.
 
Dealing with inheritance -- or not having it -- that is a drawback when adopting functional programming. And Scala's ability to deal with that is one of it's strongest points.
On Wed, Jul 15, 2009 at 1:34 PM, Josh Stratton <[hidden email]> wrote:
> Okasaki PhD thesis of the same title is available online:
> http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf
>
> It's probably not a perfect substitute but it is readily available.

Great, I'll start reading that.

So on the subject of appropriate times for OO and functional
paradigms, would writing a image manipulation program like gimp, for
example, be a poor choice for functional languages since the one huge
data array is constantly changing?  Or since most GUI APIs are so
heavily dependent on state?

Looking over various types of applications, it seems that functional
languages fit nicely into any particular situation be it a web server
or ssh daemon.  But does anyone consider certain types of programs
such as those involving complex GUIs a poor choice for functional
languages?  I've done some reading on Reactive Functional Programming,
but it seems very abstract (possibly just because relatively few
people have done it).

Reading papers like Okasaki's, where he comments,

"Although some data structures
designed for imperative languages such as C can be quite easily adapted to a
functional setting, most cannot, usually because they depend in
crucial ways on assignments,
which are disallowed, or at least discouraged, in functional languages..."

Is designing a more elegant data structure than an OO paradigm a
significant bottleneck in functional programming to get the touted
benefits?

Josh



--
Daniel C. Sobral

Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.
Reply | Threaded
Open this post in threaded view
|

Re: wrapping mind around functional programming

Randall R Schulz-2
In reply to this post by Alex Cruise-2
On Wednesday July 15 2009, Alex Cruise wrote:
> Tim Pigden wrote:
> > New edition 2008
>
> [citation needed] :)

According to the US Amazon site:

-==--==--==--==--==--==--==--==--==--==--==--==--==-
Product Details:
    * Paperback: 220 pages
    * Publisher: Cambridge University Press (January 12, 2008)
    * Language: English
    * ISBN-10: 0521663504
    * ISBN-13: 978-0521663502
-==--==--==--==--==--==--==--==--==--==--==--==--==-

The frontmatter in Amazon's book viewer shows a first edition was
published in 1998 (paperback in 1999).

On the other hand, the CUP site itself makes no mention of a later
edition.

Looking at the many copies available for sale used via Alibris.com, it
would appear that editions were published in 1998 or 1999 and 2003 (and
one listing mentions 2009). I get the feeling those dates are either
printing dates or are simply unreliable.


> I've been waiting for a new edition to buy it; if it really exists
> I'll buy it immediately; if it's forthcoming I'll wait a bit longer.
> :)
>
> -0xe1a


Randall Schulz
12