As is this my first post to this group (hi group!), let me describe
where I'm coming from and what I'm trying to do. (you can skip to
** the question/problem ** below if you're not interested)
Where I'm coming from:
I'm very new to Lisp - I've read the "Practical Common Lisp" book
and skimmed some online resources, but not much else.
I do have about 20 years of programming experience (a bit more if you
count C=64/MSX BASIC) and the last 10 years of those have been
professional in web development - mostly Perl, Java, JavaScript and
(some) C, C++ and Ruby.
What I'm trying to do:
For my own personal enjoyment/curiosity I'm writing a system that will
allow the user to construct a... wel let's call it a modular synthesizer:
a sound-producing/processing system that can be build up from simple parts
(which I will call "processors" here) and basically takes input and
output streams (currently implemented as simple vectors of floats) and
mangle them in whatever way through multiple processors to produce new
streams (and the complete system can be viewed as a processor that
contains other processors recursively)
My current idea is that, abstractly, a good way to get this kind of
system working is to view a processor as a function (actually, a closure).
** the question/problem **
Basically, what I want is an idiomatic way to specify a closure that
takes zero or more (preferably named) arguments and returns zero or more
(preferably named) arguments.
Also: it would be nice if I could refer *back* to that function/closure's
last execution and get one or more of the other named return values.
I do already have some code that accomplishes this through, basically,
creating two closures: that processes the input and creates all output
values and another that just let's the caller specify one of the named
outputs: see bottom of post.
What I'm asking is: is there already a good/standard/idiomatic way of
doing this?
I found a vague reference to "named return values" in this thread:
http://groups.google.co.id/group/comp.lang.lisp/tree/browse_frm/
month/1994-12/9fcf4ea2bcf9e4f0?rnum=221&_done=%2Fgroup%2Fcomp.lang.lisp%
2Fbrowse_frm%2Fmonth%2F1994-12%3F
but nothing immediately useful.
Thanks in advance,
Joost Diepenmaat
Zeekat Softwareontwikkeling.
** parts of current code follows (please skip if not interested) **
(defun %output-port-declaration (port)
(let ((type (second port)))
(list (car port) (cond ((eql type :scalar) 0.0)
((eql type :stream) '(make-array *buffer-
size* :element-type 'float))))))
(defmacro with-output-ports (output-ports &body body)
`(let ,(mapcar #'%output-port-declaration output-ports)
,@body))
(defmacro processor-body (output-ports input-ports &body body)
`(list
#'(lambda (return-port &key ,@(mapcar #'first input-ports))
,@body
(getf (list ,@(%output-ports-by-sym output-ports)) return-port))
#'(lambda (return-port)
(getf (list ,@(%output-ports-by-sym output-ports)) return-port))))
(defmacro defprocessor (name output-ports input-ports static-vars &body
body)
"define a constructor function for a processor type.
name will be the name of the constructor function, output-ports and input-
ports
are lists of the form ((var :scalar) (var2 :stream))
static-vars is a (let) list of variables that will be closed over by the
body
of each instantiated processor (not shared among instances)"
`(defun ,name ()
(with-output-ports ,output-ports
(let ,static-vars
(processor-body ,output-ports ,input-ports
,@body)))))
; Where (defprocessor ...) creates a named "constructor" that
; creates a new processor consisting of a list of 1. the actual
; processing code and 2. a closure that will return one of the cached
; values of 1.
; Called like this:
(defprocessor panner
((left :stream) (right :stream))
((input :stream) (panning :stream))
()
(dotimes (i *num-frames*)
(setf (aref left i) (* (aref input i) (/ (+ 1 (aref panning i)) 2)))
(setf (aref left i) (* (aref input i) (/ (- 1 (aref panning i))
-2)))))
; please excuse the crudeness of this example -
Joost Diepenmaat wrote:
> As is this my first post to this group (hi group!), let me describe
> where I'm coming from and what I'm trying to do. (you can skip to
> ** the question/problem ** below if you're not interested)
>
>
> Where I'm coming from:
>
> I'm very new to Lisp - I've read the "Practical Common Lisp" book
> and skimmed some online resources, but not much else.
>
> I do have about 20 years of programming experience (a bit more if you
> count C=64/MSX BASIC) and the last 10 years of those have been
> professional in web development - mostly Perl, Java, JavaScript and
> (some) C, C++ and Ruby.
>
>
> What I'm trying to do:
>
> For my own personal enjoyment/curiosity I'm writing a system that will
> allow the user to construct a... wel let's call it a modular synthesizer:
> a sound-producing/processing system that can be build up from simple parts
> (which I will call "processors" here) and basically takes input and
> output streams (currently implemented as simple vectors of floats) and
> mangle them in whatever way through multiple processors to produce new
> streams (and the complete system can be viewed as a processor that
> contains other processors recursively)
>
> My current idea is that, abstractly, a good way to get this kind of
> system working is to view a processor as a function (actually, a closure).
>
>
> ** the question/problem **
>
> Basically, what I want is an idiomatic way to specify a closure that
> takes zero or more (preferably named) arguments and returns zero or more
> (preferably named) arguments.
What's wrong with a struct? That names its slots. Something like an
a-list (one alternative) would be a lot less efficient, and somehow this
sounds like it needs to be efficient.
kt
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
On Sat, 03 Nov 2007 00:26:48 -0400, Ken Tilton wrote:
>> ** the question/problem **
>>
>> Basically, what I want is an idiomatic way to specify a closure that
>> takes zero or more (preferably named) arguments and returns zero or
>> more (preferably named) arguments.
>
> What's wrong with a struct? That names its slots. Something like an
> a-list (one alternative) would be a lot less efficient, and somehow this
> sounds like it needs to be efficient.
Thanks, I hadn't even considered structs (I'm using a p-list at the
moment). That could work very well, I think.
Joost.
Joost Diepenmaat wrote:
> On Sat, 03 Nov 2007 00:26:48 -0400, Ken Tilton wrote:
>>> ** the question/problem **
>>>
>>> Basically, what I want is an idiomatic way to specify a closure that
>>> takes zero or more (preferably named) arguments and returns zero or
>>> more (preferably named) arguments.
>> What's wrong with a struct? That names its slots. Something like an
>> a-list (one alternative) would be a lot less efficient, and somehow this
>> sounds like it needs to be efficient.
>
> Thanks, I hadn't even considered structs (I'm using a p-list at the
> moment). That could work very well, I think.
Structs have the problem that they need to be defined upfront, whereas
property lists can be created on the fly. So there's a trade off here.
As to your original question, when a function returns a property list,
you can conveniently retrieve variable bindings using lambda or
destructuring-bind:
(destructuring-bind
(&key a b c) (some-function ...)
... some code ...)
or:
(apply (lambda (&key a b c)
... some code ...)
(some-function ...))
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
Pascal Costanza wrote:
> Joost Diepenmaat wrote:
>
>> On Sat, 03 Nov 2007 00:26:48 -0400, Ken Tilton wrote:
>>
>>>> ** the question/problem **
>>>>
>>>> Basically, what I want is an idiomatic way to specify a closure that
>>>> takes zero or more (preferably named) arguments and returns zero or
>>>> more (preferably named) arguments.
>>>
>>> What's wrong with a struct? That names its slots. Something like an
>>> a-list (one alternative) would be a lot less efficient, and somehow this
>>> sounds like it needs to be efficient.
>>
>>
>> Thanks, I hadn't even considered structs (I'm using a p-list at the
>> moment). That could work very well, I think.
>
>
> Structs have the problem that they need to be defined upfront, whereas
> property lists can be created on the fly. So there's a trade off here.
Where do you see a need to conjure up names on the fly? The guy is doing
sound synthesis and modulation fer chrissakes, sounds like a problem
operating on well-defined data needing C-like throughout because it also
sounds real-time dont ask why and you are recommending
consing/destructuring? No way, dude.
kt
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
On Sat, 03 Nov 2007 11:05:15 -0400, Ken Tilton wrote:
>> Structs have the problem that they need to be defined upfront, whereas
>> property lists can be created on the fly. So there's a trade off here.
>
> Where do you see a need to conjure up names on the fly? The guy is doing
> sound synthesis and modulation fer chrissakes, sounds like a problem
> operating on well-defined data needing C-like throughout because it also
> sounds real-time dont ask why and you are recommending
> consing/destructuring? No way, dude.
While I do have performance in mind when building this thing, for now I
can live with some latency, since I'm not at a stage where I really know
what I will need when I start adding more involved audio processing code.
Nr 1 on my todo list is getting LADSPA plugins to work with the system:
when that works I should have a nice set of ready-made tools to
experiment with.
Anyway, the audio data is send around in chunks (float vectors) of X
samples. If there is no "live" input or some lagging is allowed (for
instance; influence a filter based on mouse movement every 1/10th second)
those chunks could be fairly large - up to, say, 2500 samples per
'function call'. Using a "non-optimal" way to get at those arrays may not
have *that* much influence on overall performance. If there is live input
that needs to be "in sync" with the output that will be different, but
I'll try to deal with that when I get there and it's not my highest
priority.
Right now I'm trying to keep the mechanics of how the data is passed
around in a few strategic macros, so I can experiment with different
strategies while keeping most of the "real" audio processing code the
same.
Joost.
Joost Diepenmaat wrote:
> On Sat, 03 Nov 2007 11:05:15 -0400, Ken Tilton wrote:
>
>>>Structs have the problem that they need to be defined upfront, whereas
>>>property lists can be created on the fly. So there's a trade off here.
>>
>>Where do you see a need to conjure up names on the fly? The guy is doing
>>sound synthesis and modulation fer chrissakes, sounds like a problem
>>operating on well-defined data needing C-like throughout because it also
>>sounds real-time dont ask why and you are recommending
>>consing/destructuring? No way, dude.
>
>
> While I do have performance in mind when building this thing, for now I
> can live with some latency, since I'm not at a stage where I really know
> what I will need when I start adding more involved audio processing code.
Uh, the real question is "do you not know what the names will be?" If
so, why write an interpreter, which is pretty much what you are doing
when you go for an assoc for a struct. If not, fine, write an interpreter.
kt
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
On Sat, 03 Nov 2007 21:50:06 -0400, Ken Tilton wrote:
>> While I do have performance in mind when building this thing, for now I
>> can live with some latency, since I'm not at a stage where I really
>> know what I will need when I start adding more involved audio
>> processing code.
>
> Uh, the real question is "do you not know what the names will be?" If
> so, why write an interpreter, which is pretty much what you are doing
> when you go for an assoc for a struct. If not, fine, write an
> interpreter.
I will know what the names are after a processor has been instantiated
but not always before then. Some of the processors will be generated from
whatever LADSPA plugins (these are shared objects following a standard C
API) happen to be installed on the system, input/output names included,
and others may have a variable number of inputs and outputs depending on
how exactly they were instantiated (for instance, a mixer could be
instantiated with 2 to X number of channels).
Joost.
Joost Diepenmaat wrote:
> On Sat, 03 Nov 2007 21:50:06 -0400, Ken Tilton wrote:
>
>>>While I do have performance in mind when building this thing, for now I
>>>can live with some latency, since I'm not at a stage where I really
>>>know what I will need when I start adding more involved audio
>>>processing code.
>>
>>Uh, the real question is "do you not know what the names will be?" If
>>so, why write an interpreter, which is pretty much what you are doing
>>when you go for an assoc for a struct. If not, fine, write an
>>interpreter.
>
>
> I will know what the names are after a processor has been instantiated
> but not always before then. Some of the processors will be generated from
> whatever LADSPA plugins (these are shared objects following a standard C
> API) happen to be installed on the system, input/output names included,
> and others may have a variable number of inputs and outputs depending on
> how exactly they were instantiated (for instance, a mixer could be
> instantiated with 2 to X number of channels).
Well of course 2 to x sounds more like a vector than an assoc.
meanwhile, hashtables can be faster than assoc's above X pairs where I
am not really sure what X is except someone once said they compared and
X was around twenty.
In one of my current projects I have a similar situation prossing CSVs
and I use one hash table to map from name to index and then data goes in
vectors so I am not forever consing up an assoc row after row. You might
be in the same boat.
kt
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
Ken Tilton wrote:
>
>
> Joost Diepenmaat wrote:
>> On Sat, 03 Nov 2007 21:50:06 -0400, Ken Tilton wrote:
>>
>>>> While I do have performance in mind when building this thing, for now I
>>>> can live with some latency, since I'm not at a stage where I really
>>>> know what I will need when I start adding more involved audio
>>>> processing code.
>>>
>>> Uh, the real question is "do you not know what the names will be?" If
>>> so, why write an interpreter, which is pretty much what you are doing
>>> when you go for an assoc for a struct. If not, fine, write an
>>> interpreter.
>>
>>
>> I will know what the names are after a processor has been instantiated
>> but not always before then. Some of the processors will be generated
>> from whatever LADSPA plugins (these are shared objects following a
>> standard C API) happen to be installed on the system, input/output
>> names included, and others may have a variable number of inputs and
>> outputs depending on how exactly they were instantiated (for instance,
>> a mixer could be instantiated with 2 to X number of channels).
>
> Well of course 2 to x sounds more like a vector than an assoc.
>
> meanwhile, hashtables can be faster than assoc's above X pairs where I
> am not really sure what X is except someone once said they compared and
> X was around twenty.
I once compared and got a number around 50. I don't remember the details
though: The number is highly dependent on implementation, optimization
settings, probably CPU used, etc.
I also think that property lists are generally faster than association
lists, although in one implementation (MCL) it was the other way around.
(But I am not sure about that anymore.)
Anyway, the numbers were high enough such that I have drawn two
conclusions: (a) I use assocation lists and property lists more often
than not, and (b) I decide what to use based on how convenient the API
for these data structures are, not what their efficiency is.
Having said that, hashtables have the most convenient / complete API,
but are generally much less efficient than assocation lists and property
lists for small numbers. (That's why, for example, I use property lists
for caches in ContextL.)
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
On Sun, 04 Nov 2007 14:15:39 +0100, Pascal Costanza wrote:
> Ken Tilton wrote:
>>
>> Well of course 2 to x sounds more like a vector than an assoc.
>>
>> meanwhile, hashtables can be faster than assoc's above X pairs where I
>> am not really sure what X is except someone once said they compared and
>> X was around twenty.
>
> I once compared and got a number around 50. I don't remember the details
> though: The number is highly dependent on implementation, optimization
> settings, probably CPU used, etc.
>
> I also think that property lists are generally faster than association
> lists, although in one implementation (MCL) it was the other way around.
> (But I am not sure about that anymore.)
<snip>
> Having said that, hashtables have the most convenient / complete API,
> but are generally much less efficient than assocation lists and property
> lists for small numbers. (That's why, for example, I use property lists
> for caches in ContextL.)
That's interesting. I'll have to do some testing myself and see what
works best.
Thank you both for the insights.
Joost.
From: Kent M Pitman
Subject: Re: (cached) named return values?
Date:
Message-ID: <u4pg1hi9i.fsf@nhplace.com>
Pascal Costanza <··@p-cos.net> writes:
> Having said that, hashtables have the most convenient / complete API,
> but are generally much less efficient than assocation lists and
> property lists for small numbers. (That's why, for example, I use
> property lists for caches in ContextL.)
In Common Lisp on Symbolics Genera (Lisp Machine Lisp), I recall a
large amount of work being done on hash tables to basically have them
use property lists internally and to morph into an alternate
representation at the efficiency crossover point. There's some small
small storage&time overhead issue of shifting at the right moment
and some theoretical issues about how to advise whether and when to
switch back to avoid thrashing, but nothing in the spec for hash
tables requires a particular implementation.
Kent M Pitman wrote:
> Pascal Costanza <··@p-cos.net> writes:
>
>> Having said that, hashtables have the most convenient / complete API,
>> but are generally much less efficient than assocation lists and
>> property lists for small numbers. (That's why, for example, I use
>> property lists for caches in ContextL.)
>
> In Common Lisp on Symbolics Genera (Lisp Machine Lisp), I recall a
> large amount of work being done on hash tables to basically have them
> use property lists internally and to morph into an alternate
> representation at the efficiency crossover point. There's some small
> small storage&time overhead issue of shifting at the right moment
> and some theoretical issues about how to advise whether and when to
> switch back to avoid thrashing, but nothing in the spec for hash
> tables requires a particular implementation.
Er, are you sure? Maybe I am missing something, but property lists are
required to compare keys using eq, while with hashtables, you can choose
from eq, eql, equal and equalp. That should make a difference, no?
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Kent M Pitman
Subject: Re: (cached) named return values?
Date:
Message-ID: <ulk9dbp6u.fsf@nhplace.com>
Pascal Costanza <··@p-cos.net> writes:
> Kent M Pitman wrote:
> > Pascal Costanza <··@p-cos.net> writes:
> >
> >> Having said that, hashtables have the most convenient / complete API,
> >> but are generally much less efficient than assocation lists and
> >> property lists for small numbers. (That's why, for example, I use
> >> property lists for caches in ContextL.)
> > In Common Lisp on Symbolics Genera (Lisp Machine Lisp), I recall a
> > large amount of work being done on hash tables to basically have them
> > use property lists internally and to morph into an alternate
> > representation at the efficiency crossover point. There's some small
> > small storage&time overhead issue of shifting at the right moment
> > and some theoretical issues about how to advise whether and when to
> > switch back to avoid thrashing, but nothing in the spec for hash
> > tables requires a particular implementation.
>
> Er, are you sure? Maybe I am missing something, but property lists are
> required to compare keys using eq, while with hashtables, you can
> choose from eq, eql, equal and equalp. That should make a difference,
> no?
My saying property lists did not mean CL-defined property list
functions. That is, one can emulate property list effects by
traversing lists up to some threshold size; one doesn't have to use
the specific implementations to CL's GET (which isn't parameterizable
for predicates). After all, some hash table implementations hash to
get to a bucket that is a list, and then do search of that list ... so
if you assume a single bucket, you'd get the same effect.
As for whether I'm sure Genera did it, I just remember a thing called
the "new table system" which was intended to address that. I think it
made into product. (It's been more than a dozen years since I was
using this stuff regularly, so it's easy to make a mistake on such a
thing.) My LispM isn't powered on at the moment, but if I get time
I'll boot it up and look--maybe someone has one online that can answer
first. If you even just look at the class name you get from
MAKE-HASH-TABLE it should be obvious, unless I'm just totally
misremembering, since I believe it will actually do CHANGE-CLASS (or
the New Flavors equivalent) when it morphs.
One reason for users NOT to do this themselves is that the threshold
point for where you should switch over is implementation-dependent.
It's important that vendors, knowing the details of the various
low-level representations and the implementation of hashing, be the
ones to decide where he cutover is. I'm sure, for example, that it's
VERY different for clisp [byte-interpreted], Genera (hardware support
for some operations), and other Common Lisps (using native
instructions on what we at Symbolics used to call "stock hardware"
... you might call it "general purpose hardware", I suppose).
On Sun, 04 Nov 2007 17:50:33 -0500, Kent M Pitman wrote:
> One reason for users NOT to do this themselves is that the threshold
> point for where you should switch over is implementation-dependent. It's
> important that vendors, knowing the details of the various low-level
> representations and the implementation of hashing, be the ones to decide
> where he cutover is. I'm sure, for example, that it's VERY different
> for clisp [byte-interpreted], Genera (hardware support for some
> operations), and other Common Lisps (using native instructions on what
> we at Symbolics used to call "stock hardware" ... you might call it
> "general purpose hardware", I suppose).
So what you're saying is that on some systems at least, using hash tables
will always be the most efficient option compared to a/p-lists even if
many of the tables/lists are below a certain size limit - unless you
*know* beforehand they won't grow above that limit?
Joost.
Joost Diepenmaat wrote:
> On Sun, 04 Nov 2007 17:50:33 -0500, Kent M Pitman wrote:
>
>>One reason for users NOT to do this themselves is that the threshold
>>point for where you should switch over is implementation-dependent. It's
>>important that vendors, knowing the details of the various low-level
>>representations and the implementation of hashing, be the ones to decide
>>where he cutover is. I'm sure, for example, that it's VERY different
>>for clisp [byte-interpreted], Genera (hardware support for some
>>operations), and other Common Lisps (using native instructions on what
>>we at Symbolics used to call "stock hardware" ... you might call it
>>"general purpose hardware", I suppose).
>
>
> So what you're saying is that on some systems at least, using hash tables
> will always be the most efficient option compared to a/p-lists even if
> many of the tables/lists are below a certain size limit - unless you
> *know* beforehand they won't grow above that limit?
I am greatly enjoying this steady degeneration of the original question
from useless syntax language feature obsession into mind-boggling oh
gosh my assoc is faster than your assoc phobia, because it occurred to
me as I was sucking down beers and free peanuts at the local sports bar
that the OQ itself was doomed. Oh, I am doing this, what is the
preferred magical special Lisp way of doing that. We get that a lot
around here. Lisp just has every way imaginable to do anything you might
reasonably want to do, it is thoroughly not a magical superspecial
orgasmic new way of programming so get back to work and when the way you
settle on starts telling you I really do not want to be doing this pick
another way. The more monkeys you have trying more ways obviously the
better.
kt
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
On Sun, 04 Nov 2007 19:42:50 -0500, Ken Tilton wrote:
> I am greatly enjoying this steady degeneration of the original question
> from useless syntax language feature obsession into mind-boggling oh
> gosh my assoc is faster than your assoc phobia, because it occurred to
> me as I was sucking down beers and free peanuts at the local sports bar
> that the OQ itself was doomed.
Something like this has occurred to me too. I'm not even sure if I should
have asked such an ambiguous question as the one I originally posted in
such a cynical newsgroup as this one. Especially concidering my minimal
knowledge of Lisp and my not-exactly-perfect knowledge of English.
> Oh, I am doing this, what is the
> preferred magical special Lisp way of doing that. We get that a lot
> around here. Lisp just has every way imaginable to do anything you might
> reasonably want to do, it is thoroughly not a magical superspecial
> orgasmic new way of programming so get back to work and when the way you
> settle on starts telling you I really do not want to be doing this pick
> another way. The more monkeys you have trying more ways obviously the
> better.
I think I'm currently just too drunk to make sense of this part of your
post. I'll take another look at it tomorrow.
Joost.
Joost Diepenmaat wrote:
> On Sun, 04 Nov 2007 19:42:50 -0500, Ken Tilton wrote:
>
>
>>I am greatly enjoying this steady degeneration of the original question
>>from useless syntax language feature obsession into mind-boggling oh
>>gosh my assoc is faster than your assoc phobia, because it occurred to
>>me as I was sucking down beers and free peanuts at the local sports bar
>>that the OQ itself was doomed.
>
>
> Something like this has occurred to me too. I'm not even sure if I should
> have asked such an ambiguous question as the one I originally posted in
> such a cynical newsgroup as this one. Especially concidering my minimal
> knowledge of Lisp and my not-exactly-perfect knowledge of English.
>
>
>>Oh, I am doing this, what is the
>>preferred magical special Lisp way of doing that. We get that a lot
>>around here. Lisp just has every way imaginable to do anything you might
>>reasonably want to do, it is thoroughly not a magical superspecial
>>orgasmic new way of programming so get back to work and when the way you
>>settle on starts telling you I really do not want to be doing this pick
>>another way. The more monkeys you have trying more ways obviously the
>>better.
>
>
> I think I'm currently just too drunk to make sense of this part of your
> post. I'll take another look at it tomorrow.
There's nothing more there to be found except something that newcomers
to Lisp often need to hear: the magic of Lisp is not in any particular
mechanism, feature, or style. We often get folks obsessed with doing
things The Magical Lisp Way, it's just the Unbearable Powerfulness of a
lot of things engineered really well. Well, OK, the monkeys* over here
just suggested the parentheses are magical, I can see that...
My concern with named variables is that we end up with some function
that can be named no better than do-something-useful taking one
argument, this-stuff. Pascal agonized over a struct being maintained as
well as a caller and a callee. No. A function should take a couple of
specific arguments (not an equally obscurant struct) and return a
specific result. Functions that are just huge pipes, anything in
anything out, just hide the meat of a program, and to find that meat I
am now looking at lines and lines of code. Granularity of function lets
us look no further -- oh, this call obviously does that.
kt
* Monkeys: plural noun. Kenny's explanation of his programming style.
Enough monkeys typing long enough will eventually produce Cells. k
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
Ken Tilton <·········@gmail.com> wrote:
+---------------
| >>Lisp just has every way imaginable to do anything you might
| >>reasonably want to do, it is thoroughly not a magical superspecial
| >>orgasmic new way of programming so get back to work and when the way you
| >>settle on starts telling you I really do not want to be doing this pick
| >>another way. The more monkeys you have trying more ways obviously the
| >>better.
...
| * Monkeys: plural noun. Kenny's explanation of his programming style.
| Enough monkeys typing long enough will eventually produce Cells. k
+---------------
Yes, but the monkeys need to communicate with each other so that
after one has produced Cells [or whatever the target-of-the-week is]
the others know to *stop*!
I thought that's what "c.l.lisp" was for -- communication between
us randomly-typing monkeys to prune the search tree. No?
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
Ken Tilton wrote:
> Pascal agonized over a struct being maintained as
> well as a caller and a callee.
I haven't agonized over it.
Idiot.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
Pascal Costanza wrote:
> Ken Tilton wrote:
>
>> Pascal agonized over a struct being maintained as well as a caller and
>> a callee.
>
>
> I haven't agonized over it.
"Loss of development speed" is considered agony around here, pal.
>
> Idiot.
>
I feel sorry for the next undergrad you'll be bullying because of your
frustration with me.
You are tool-blinded, dude, work on it, don't shoot the messenger.
kt
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
Ken Tilton wrote:
>
>
> Pascal Costanza wrote:
>> Ken Tilton wrote:
>>
>>> Pascal agonized over a struct being maintained as well as a caller
>>> and a callee.
>>
>>
>> I haven't agonized over it.
>
> "Loss of development speed" is considered agony around here, pal.
>
>>
>> Idiot.
>>
>
> I feel sorry for the next undergrad you'll be bullying because of your
> frustration with me.
>
> You are tool-blinded, dude, work on it, don't shoot the messenger.
Stop being so arrogant. That's annoying. You have no idea what you're
talking about. It's also unfortunate, because your posts are otherwise
typically very useful.
You're producing a lot of noise by diving into these meta-discussions...
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
Pascal Costanza wrote:
> Ken Tilton wrote:
>
>>
>>
>> Pascal Costanza wrote:
>>
>>> Ken Tilton wrote:
>>>
>>>> Pascal agonized over a struct being maintained as well as a caller
>>>> and a callee.
>>>
>>>
>>>
>>> I haven't agonized over it.
>>
>>
>> "Loss of development speed" is considered agony around here, pal.
>>
>>>
>>> Idiot.
>>>
>>
>> I feel sorry for the next undergrad you'll be bullying because of your
>> frustration with me.
>>
>> You are tool-blinded, dude, work on it, don't shoot the messenger.
>
>
> Stop being so arrogant. That's annoying. You have no idea what you're
> talking about. It's also unfortunate, because your posts are otherwise
> typically very useful.
>
> You're producing a lot of noise by diving into these meta-discussions...
I think we give better help to noobs if we respond intelligently, and
reflection and self-criticism is how we improve the help we give. I am
sorry you always end up in the dunce corner, but I am also astonished at
your inability to learn from me. Don't worry, I won't give up on you!
kt
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
Ken Tilton wrote:
> I think we give better help to noobs if we respond intelligently, and
> reflection and self-criticism is how we improve the help we give. I am
> sorry you always end up in the dunce corner, but I am also astonished at
> your inability to learn from me. Don't worry, I won't give up on you!
A lot of your postings typically follow the template "I am right, and
you are wrong," without backing things up much. I don't see a lot of
reflection and self-criticism in there.
But I didn't expect an apology. Not from you.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
Pascal Costanza wrote:
> Ken Tilton wrote:
>
>> I think we give better help to noobs if we respond intelligently, and
>> reflection and self-criticism is how we improve the help we give. I am
>> sorry you always end up in the dunce corner, but I am also astonished
>> at your inability to learn from me. Don't worry, I won't give up on you!
>
>
> A lot of your postings typically follow the template "I am right, and
> you are wrong," without backing things up much. I don't see a lot of
> reflection and self-criticism in there.
There enough good critics on c.l.l that I am confident if ever I were to
be wrong I would soon hear it, and I always do and it is great fun,
google "I hate you guys so much".
Back OT, i think the OP needs a defplugin macro or at least an API
plugins have to satisfy, hell that is what plugins do, so I really do
not see why a class (structure or standard) will not do.
> But I didn't expect an apology. Not from you.
I figure if I am gracious enough to ignore "idiot" and "arrogant" and
this latest onslaught of increasingly personal abuse without responding
in kind you would be thanking me.
Well, I don't want to torment you any further, and Harrop has me
thinking "killfile", we'll make you two the founding fathers of this
incarnation.
peace, kt
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
Ken Tilton wrote:
>
>
> Pascal Costanza wrote:
>> Ken Tilton wrote:
>>
>>> I think we give better help to noobs if we respond intelligently, and
>>> reflection and self-criticism is how we improve the help we give. I
>>> am sorry you always end up in the dunce corner, but I am also
>>> astonished at your inability to learn from me. Don't worry, I won't
>>> give up on you!
>>
>>
>> A lot of your postings typically follow the template "I am right, and
>> you are wrong," without backing things up much. I don't see a lot of
>> reflection and self-criticism in there.
>
> There enough good critics on c.l.l that I am confident if ever I were to
> be wrong I would soon hear it, and I always do and it is great fun,
> google "I hate you guys so much".
The first result I get after typing this into google has the subject
line "Why do you guys hate pirates so much?"
Not very helpful. ;)
> Back OT, i think the OP needs a defplugin macro or at least an API
> plugins have to satisfy, hell that is what plugins do, so I really do
> not see why a class (structure or standard) will not do.
You're thinking too much about getting work done.
Other people are interested in exploring new, potentially useless, but
nevertheless interesting programming styles. Every now and then, you
accidentally stumble over something that is actually worthwhile and
makes you more productive - but you wouldn't have thought of that idea
upfront in the first place.
Lisp came into being like that. Object-oriented programming was
discovered like that. Generic functions were discovered like that. I
know from first-hand sources that ContextL was discovered like that. And
I am pretty sure that Cells was also the culmination of diving into
several directions that turned out to be useless.
Keyword arguments have been praised as productivity enablers, because
they allow you to evolve software in a smooth way, without having to
update several, unrelated places in your program. This is actually
something that you can experience yourself when trying it out.
What I found interesting about the OP is the idea to do the same for
returning results in a 'keyword argument list'-style. _Without knowing
whether this will eventually work out or not_, I think it is worthwhile
to explore that path to see what the potential benefits and pitfalls are.
I don't think you have tried that path, otherwise you would have already
stated so. So you cannot possibly know either what comes out of this.
Still you decide to continuously interrupt discussions in an obnoxious
way between people who are interested in just this kind of discussion,
instead of shutting up because this is just not your cup of coffee.
Discussing only proven practice is boring and uninspiring.
Note that I am not saying that your perspective is useless. I fully
agree that it's worthwhile to criticize and reflect upon such
discussions. But your style of including gratuitous personal attacks is
sometimes just annoying.
>> But I didn't expect an apology. Not from you.
>
> I figure if I am gracious enough to ignore "idiot" and "arrogant" and
> this latest onslaught of increasingly personal abuse without responding
> in kind you would be thanking me.
I was referring to your original "Pascal agonized over a struct being
maintained as well as a caller and a callee." You have to accept the
fact that I find the wording insulting.
Maybe I shouldn't have contributed to escalating the situation, but at
least my attacks weren't gratuitous, but just responses.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
Pascal Costanza <··@p-cos.net> wrote on Mon, 05 Nov 2007:
> "Why do you guys hate pirates so much?"
On the contrary, the modern lack of pirates is the reason we're now
experiencing global warming:
http://www.venganza.org/wp-content/uploads/2007/10/hq-graphcopy2_800.jpg
_______________________________________________________________________________
Don Geddis http://don.geddis.org/ ···@geddis.org
My friends tell me that I have a tendency to point out problems without
offering solutions, but they never tell me what I should do about it.
-- Daniel Gilbert, "Stumbling on Happiness"
Don Geddis <···@geddis.org> wrote:
+---------------
| Pascal Costanza <··@p-cos.net> wrote on Mon, 05 Nov 2007:
| > "Why do you guys hate pirates so much?"
|
| On the contrary, the modern lack of pirates is the reason we're now
| experiencing global warming:
| http://www.venganza.org/wp-content/uploads/2007/10/hq-graphcopy2_800.jpg
+---------------
Indeed, as all decent Pastafarians know.
May His Munificent Noodliness be praised!
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
Don Geddis wrote:
> Pascal Costanza <··@p-cos.net> wrote on Mon, 05 Nov 2007:
>> "Why do you guys hate pirates so much?"
>
> On the contrary, the modern lack of pirates is the reason we're now
> experiencing global warming:
> http://www.venganza.org/wp-content/uploads/2007/10/hq-graphcopy2_800.jpg
:)
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
Ken Tilton <···········@optonline.net> writes:
> kt
>
> * Monkeys: plural noun. Kenny's explanation of his programming
> style. Enough monkeys typing long enough will eventually produce
> Cells. k
Yeah - another one for the Kenny Fortunes File! I really like that
one. ;-)
Frank
--
Frank Goenninger
frgo(at)mac(dot)com
"Don't ask me! I haven't been reading comp.lang.lisp long enough to
really know ..."
On Sun, 04 Nov 2007 21:03:36 -0500, Ken Tilton wrote:
> There's nothing more there to be found except something that newcomers
> to Lisp often need to hear: the magic of Lisp is not in any particular
> mechanism, feature, or style. We often get folks obsessed with doing
> things The Magical Lisp Way, it's just the Unbearable Powerfulness of a
> lot of things engineered really well. Well, OK, the monkeys* over here
> just suggested the parentheses are magical, I can see that...
Ok then. It's just that I would like to have my code be easily be
understood by whoever does Lisp currently. Which is basically what I
meant originally with "idiomatic".
As I stated in my originial post, I've done quite a lot of Perl
programming. In perl, idiom is pretty important, since the language is
flexible enough to drive people crazy. From what I understand of Lisp
right now, it's even more flexible than Perl *and* it's been around a lot
longer, so my assumption was that there was were "normal ways" of doing
what I wanted to do.
In other words, I wasn't exactly looking for "the most efficient" way, I
was looking for the "clearest way" of expressing my strategy in Lisp.
I might start a new thread/write a blog post about this topic in general
seperately, since it's interesting but getting *really* off-topic.
> My concern with named variables is that we end up with some function
> that can be named no better than do-something-useful taking one
> argument, this-stuff. Pascal agonized over a struct being maintained as
> well as a caller and a callee. No. A function should take a couple of
> specific arguments (not an equally obscurant struct) and return a
> specific result. Functions that are just huge pipes, anything in
> anything out, just hide the meat of a program, and to find that meat I
> am now looking at lines and lines of code. Granularity of function lets
> us look no further -- oh, this call obviously does that.
Yeah, well, but most languages - including Lisp - that I know do not
allow for multiple return values. Sure you can return a struct, or a list
or a multidimensional array, but if you compare that to the multitude of
options you can get when you're specifying a functions's (input)
arguments, it all seems pretty low-level and sparse.
Joost.
Joost Diepenmaat wrote:
> On Sun, 04 Nov 2007 21:03:36 -0500, Ken Tilton wrote:
>
>
>>There's nothing more there to be found except something that newcomers
>>to Lisp often need to hear: the magic of Lisp is not in any particular
>>mechanism, feature, or style. We often get folks obsessed with doing
>>things The Magical Lisp Way, it's just the Unbearable Powerfulness of a
>>lot of things engineered really well. Well, OK, the monkeys* over here
>>just suggested the parentheses are magical, I can see that...
>
>
> Ok then. It's just that I would like to have my code be easily be
> understood by whoever does Lisp currently. Which is basically what I
> meant originally with "idiomatic".
>
> As I stated in my originial post, I've done quite a lot of Perl
> programming. In perl, idiom is pretty important, since the language is
> flexible enough to drive people crazy. From what I understand of Lisp
> right now, it's even more flexible than Perl *and* it's been around a lot
> longer, so my assumption was that there was were "normal ways" of doing
> what I wanted to do.
Probably, but then this is where I would fall back on "I think we need a
fuller specification". I am a little fuzzy on how plug-ins get to define
their own language (as in their own names for variables) such that some
form of data structure would be unworkable.
>
> In other words, I wasn't exactly looking for "the most efficient" way, I
> was looking for the "clearest way" of expressing my strategy in Lisp.
>
> I might start a new thread/write a blog post about this topic in general
> seperately, since it's interesting but getting *really* off-topic.
>
>
>>My concern with named variables is that we end up with some function
>>that can be named no better than do-something-useful taking one
>>argument, this-stuff. Pascal agonized over a struct being maintained as
>>well as a caller and a callee. No. A function should take a couple of
>>specific arguments (not an equally obscurant struct) and return a
>>specific result. Functions that are just huge pipes, anything in
>>anything out, just hide the meat of a program, and to find that meat I
>>am now looking at lines and lines of code. Granularity of function lets
>>us look no further -- oh, this call obviously does that.
>
>
> Yeah, well, but most languages - including Lisp - that I know do not
> allow for multiple return values.
<cough> See VALUES. :)
> Sure you can return a struct, or a list
> or a multidimensional array, but if you compare that to the multitude of
> options you can get when you're specifying a functions's (input)
> arguments, it all seems pretty low-level and sparse.
Well then you'd love PC's suggestion whereby the return result can be,
well, destructured with destructuring-bind, but then I am definitely
having visions of this one big pipe called
do-something-useful-and-say-something-back. I have dealt with functions
like that, and they are a curse upon productivity, intractably opaque.
In this case, I am a bit frightened by the idea of a function consing up
a plist just to return its result to its caller, but now I hear you
lusting for the same power in the "return" direction as you have with
parameter lists, so yes PC has given you the syntax you need but no this
is not something anyone has ever done before. :)
Sure, functions can build plists and return those, but then that is in
the spirit of "make", not "return". If you know the idioms. :)
kt
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
On Wed, 07 Nov 2007 01:14:53 +0000, Joost Diepenmaat wrote:
> Yeah, well, but most languages - including Lisp - that I know do not
> allow for multiple return values. Sure you can return a struct, or a
> list or a multidimensional array, but if you compare that to the
> multitude of options you can get when you're specifying a functions's
> (input) arguments, it all seems pretty low-level and sparse.
In other words, I'm trying to bend the meaning of a lambda call to include
multiple return values and to allow (nested) statements to refer to the
call later in the same statement. I should probably post an example.
(write-audio stream
(<- m
:input-1 (<- :output-1 sine :frequency 0.1)
:factor-1 0.2
:input-2 (<- :output-2 ^sine)
:factor-2 0.1)))))
Where <- :output-2 ^sine refers to the <- :output-1 sine call before and
(<- :output-1 sine :frequency 0.1) returns the "named output
parameter" :output-1 of (sine frequency 0.1) .
> Joost.
Oh dear I'm talking to myself.
Joost.
Joost Diepenmaat wrote:
> Yeah, well, but most languages - including Lisp - that I know do not
> allow for multiple return values.
Haven't really been following this thread, but taken in isolation that
statement is iffy: you can certainly return multiple _unnamed_ values
in common lisp. It's up to the caller to bind them to something or
discard them. Some lisp functions return auxiliary information as
their second return values (but note that the condition system
exists for signalling warnings and errors).
(defun sumdiff (a b)
(values (+ a b) (- a b)))
(multiple-value-bind (x y) (sumdiff 3 2)
(print x)
(print y))
Joost Diepenmaat wrote:
> It's just that I would like to have my code be easily be
> understood by whoever does Lisp currently. Which is basically what I
> meant originally with "idiomatic".
>
> As I stated in my originial post, I've done quite a lot of Perl
> programming. In perl, idiom is pretty important, since the language is
> flexible enough to drive people crazy. From what I understand of Lisp
> right now, it's even more flexible than Perl *and* it's been around a lot
> longer, so my assumption was that there was were "normal ways" of doing
> what I wanted to do.
>
> In other words, I wasn't exactly looking for "the most efficient" way, I
> was looking for the "clearest way" of expressing my strategy in Lisp.
I don't know much about Perl, but in Common Lisp, idioms don't play such
an important role. There a number of common programming styles, but a
typical approach is also to develop your own (possibly domain-specific)
extensions to the language and work with those (alongside the built-in
ones). The problem in Perl is probably not in the diversity of styles,
but probably rooted somewhere else.
If you google for it, you can also find a number of documents with
recommendations for good Lisp style (typically centered around the
built-in constructs, but also on how to name and design your own
functions and macros, etc.).
Back to your original question: You can return multiple values from
functions using VALUES and receive them using MULTIPLE-VALUE-BIND. This
is quite common, but typically in a way where the first return value is
the 'important' one that you're typically always interested in, while
the other return values are 'less important', and can more often than
not be omitted. The HyperSpec has a number of good examples that take
advantage of this idiom - see for example GETHASH. It's rare that VALUES
is used to return 'equally important' results, but not unheard of.
When you want to return multiple 'equally important' results, it's
probably more common to return lists. Among other reasons, there is a
limit on the number of values you can return with VALUES.
DESTRUCTURING-BIND is less common, as far as I can tell, but definitely
not 'shocking'. Most Common Lispers should know that it exists. ;)
Returning property lists to return multiple values is indeed uncommon.
(However, returning property lists _as such_ is not, but then your aim
to return 'just' property lists, not multiple values.)
Summary: You don't upset anybody when you use
VALUES/MULTIPLE-VALUE-BIND, and you will still be safe when you use
DESTRUCTURING-BIND. Other approaches discussed in this thread may raise
some eyebrows, as you have probably already noticed. ;)
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
Joost Diepenmaat wrote:
> On Sun, 04 Nov 2007 19:42:50 -0500, Ken Tilton wrote:
>
>> I am greatly enjoying this steady degeneration of the original question
>> from useless syntax language feature obsession into mind-boggling oh
>> gosh my assoc is faster than your assoc phobia, because it occurred to
>> me as I was sucking down beers and free peanuts at the local sports bar
>> that the OQ itself was doomed.
>
> Something like this has occurred to me too. I'm not even sure if I should
> have asked such an ambiguous question as the one I originally posted in
> such a cynical newsgroup as this one. Especially concidering my minimal
> knowledge of Lisp and my not-exactly-perfect knowledge of English.
Don't worry - part of problem solving is always finding out what the
right question is, not only what the right answers are.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
On Mon, 05 Nov 2007 09:43:34 +0100, Pascal Costanza <··@p-cos.net>
wrote:
>part of problem solving is always finding out what the
>right question is, not only what the right answers are.
Part of c.l.l'ing is posting an answer to the question you think
should have been asked in the first place ;)
George
--
for email reply remove "/" from address
Joost Diepenmaat wrote:
>> Oh, I am doing this, what is the
>> preferred magical special Lisp way of doing that. We get that a lot
>> around here. Lisp just has every way imaginable to do anything you might
>> reasonably want to do, it is thoroughly not a magical superspecial
>> orgasmic new way of programming so get back to work and when the way you
>> settle on starts telling you I really do not want to be doing this pick
>> another way. The more monkeys you have trying more ways obviously the
>> better.
>
> I think I'm currently just too drunk to make sense of this part of your
> post. I'll take another look at it tomorrow.
ITYM "not drunk enough" HTH
It certainly makes me want another beer, anyway.
-dan
···@telent.net wrote:
> Joost Diepenmaat wrote:
>
>>> Oh, I am doing this, what is the
>>> preferred magical special Lisp way of doing that. We get that a lot
>>> around here. Lisp just has every way imaginable to do anything you might
>>> reasonably want to do, it is thoroughly not a magical superspecial
>>> orgasmic new way of programming so get back to work and when the way you
>>> settle on starts telling you I really do not want to be doing this pick
>>> another way. The more monkeys you have trying more ways obviously the
>>> better.
>>
>>
>> I think I'm currently just too drunk to make sense of this part of
>> your post. I'll take another look at it tomorrow.
>
>
> ITYM "not drunk enough" HTH
>
> It certainly makes me want another beer, anyway.
Meanwhile in another thread my agonizing over the architecture most
appropriate to signs has culminated in a dopeslap upside my head
producing the stunningly obvious result of both plus and minus simply
being unary operators (which is what they are fer chrissakes) but this
only happened because the monkeys went down tools and refused to deal an
LOC longer with my clever alternative of a binary "signing" operator
with a plus or minus as the first operand. That daftitude arose as an
intermediate step towards enlightenment much as Python and Ruby were
steps towards Lisp from an original conceptualization in which a sign
was shorthand for a multiplication by -1 or 1, bringing us back to
Tilton's Law: Don't lie to the computer.
hth, kzo
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
On Tue, 06 Nov 2007 00:45:10 -0500, Ken Tilton wrote:
> Meanwhile in another thread my agonizing over the architecture most
> appropriate to signs has culminated in a dopeslap upside my head
> producing the stunningly obvious result of both plus and minus simply
> being unary operators (which is what they are fer chrissakes) but this
> only happened because the monkeys went down tools and refused to deal an
> LOC longer with my clever alternative of a binary "signing" operator
> with a plus or minus as the first operand. That daftitude arose as an
> intermediate step towards enlightenment much as Python and Ruby were
> steps towards Lisp from an original conceptualization in which a sign
> was shorthand for a multiplication by -1 or 1, bringing us back to
> Tilton's Law: Don't lie to the computer.
>
> hth, kzo
That just gave me another headache.
Thanks a lot Ken.
Joost.
Joost Diepenmaat wrote:
> On Tue, 06 Nov 2007 00:45:10 -0500, Ken Tilton wrote:
>
>
>>Meanwhile in another thread my agonizing over the architecture most
>>appropriate to signs has culminated in a dopeslap upside my head
>>producing the stunningly obvious result of both plus and minus simply
>>being unary operators (which is what they are fer chrissakes) but this
>>only happened because the monkeys went down tools and refused to deal an
>>LOC longer with my clever alternative of a binary "signing" operator
>>with a plus or minus as the first operand. That daftitude arose as an
>>intermediate step towards enlightenment much as Python and Ruby were
>>steps towards Lisp from an original conceptualization in which a sign
>>was shorthand for a multiplication by -1 or 1, bringing us back to
>>Tilton's Law: Don't lie to the computer.
>>
>>hth, kzo
>
>
> That just gave me another headache.
>
> Thanks a lot Ken.
The bad news is that in despair as the refactoring got unpleasant I
opened a beginner's algebra book (one of the best) and it handled
(-2x^2)(-3x^3) as (-2)(-3)x^2x^3 then 6x^5, whereas my above
ecstatically beautifully pure result wanted to do (-(-(2*3)x^2x^3)) as
the intermediate step, displayed as --2*3x^2x^3.
The good news is that I do not have to do Yet Another Refactoring to
Handle Signs Differently. The bad news is I was halfway thru it. The
good news is I've been drinking.
hth,kzo
ps. A little acupressure tip: firm pressure at the base of the right
thumbnail (maybe left, too?) will stop a headache. Also breathe deep,
exhale, feel a big release in the neck, eyes closed. Keep it till you
can stop and the pain does not return. kt
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
"Ken Tilton" <···········@optonline.net> wrote in message
·····················@newsfe08.lga...
[...]
> I am greatly enjoying this steady degeneration of the original question from
> useless syntax language feature obsession into mind-boggling oh gosh my assoc
> is faster than your assoc phobia, because it occurred to me as I was sucking
> down beers and free peanuts at the local sports bar that the OQ itself was
> doomed.
Dehydrated after running today's NYC Marathon no doubt!
clt
From: Kent M Pitman
Subject: Re: (cached) named return values?
Date:
Message-ID: <uejf5cvnl.fsf@nhplace.com>
Joost Diepenmaat <·····@zeekat.nl> writes:
> So what you're saying is that on some systems at least, using hash tables
> will always be the most efficient option compared to a/p-lists even if
> many of the tables/lists are below a certain size limit - unless you
> *know* beforehand they won't grow above that limit?
I'm saying it's certainly worth users taking the posture that the
standard doesn't command that tables be slow, and asking questions in
cases where they are. The standard doesn't require any vendor to
optimize this, but it doesn't preclude it either. In most places
where the standard doesn't require a reasonable thing, it's because
market forces are expected to sort things out. That won't happen if
the market doesn't get involved, though. :)
On Sun, 04 Nov 2007 20:45:34 -0500, Kent M Pitman wrote:
> I'm saying it's certainly worth users taking the posture that the
> standard doesn't command that tables be slow, and asking questions in
> cases where they are. The standard doesn't require any vendor to
> optimize this, but it doesn't preclude it either. In most places where
> the standard doesn't require a reasonable thing, it's because market
> forces are expected to sort things out. That won't happen if the market
> doesn't get involved, though. :)
I'll investigate and test further. Thanks again.
Joost.
On Sun, 04 Nov 2007 20:45:34 -0500, Kent M Pitman wrote:
> I'm saying it's certainly worth users taking the posture that the
> standard doesn't command that tables be slow, and asking questions in
> cases where they are. The standard doesn't require any vendor to
> optimize this, but it doesn't preclude it either. In most places where
> the standard doesn't require a reasonable thing, it's because market
> forces are expected to sort things out. That won't happen if the market
> doesn't get involved, though. :)
I'll investigate and test further. Thanks.
Joost.
In article <·············@nhplace.com>,
Kent M Pitman <······@nhplace.com> wrote:
> Pascal Costanza <··@p-cos.net> writes:
>
> > Kent M Pitman wrote:
> > > Pascal Costanza <··@p-cos.net> writes:
> > >
> > >> Having said that, hashtables have the most convenient / complete API,
> > >> but are generally much less efficient than assocation lists and
> > >> property lists for small numbers. (That's why, for example, I use
> > >> property lists for caches in ContextL.)
> > > In Common Lisp on Symbolics Genera (Lisp Machine Lisp), I recall a
> > > large amount of work being done on hash tables to basically have them
> > > use property lists internally and to morph into an alternate
> > > representation at the efficiency crossover point. There's some small
> > > small storage&time overhead issue of shifting at the right moment
> > > and some theoretical issues about how to advise whether and when to
> > > switch back to avoid thrashing, but nothing in the spec for hash
> > > tables requires a particular implementation.
> >
> > Er, are you sure? Maybe I am missing something, but property lists are
> > required to compare keys using eq, while with hashtables, you can
> > choose from eq, eql, equal and equalp. That should make a difference,
> > no?
>
> My saying property lists did not mean CL-defined property list
> functions. That is, one can emulate property list effects by
> traversing lists up to some threshold size; one doesn't have to use
> the specific implementations to CL's GET (which isn't parameterizable
> for predicates). After all, some hash table implementations hash to
> get to a bucket that is a list, and then do search of that list ... so
> if you assume a single bucket, you'd get the same effect.
>
> As for whether I'm sure Genera did it, I just remember a thing called
> the "new table system" which was intended to address that. I think it
> made into product. (It's been more than a dozen years since I was
> using this stuff regularly, so it's easy to make a mistake on such a
> thing.) My LispM isn't powered on at the moment, but if I get time
> I'll boot it up and look--maybe someone has one online that can answer
> first. If you even just look at the class name you get from
> MAKE-HASH-TABLE it should be obvious, unless I'm just totally
> misremembering, since I believe it will actually do CHANGE-CLASS (or
> the New Flavors equivalent) when it morphs.
At least the documentation writes longish about this table facility.
>
> One reason for users NOT to do this themselves is that the threshold
> point for where you should switch over is implementation-dependent.
> It's important that vendors, knowing the details of the various
> low-level representations and the implementation of hashing, be the
> ones to decide where he cutover is. I'm sure, for example, that it's
> VERY different for clisp [byte-interpreted], Genera (hardware support
> for some operations), and other Common Lisps (using native
> instructions on what we at Symbolics used to call "stock hardware"
> ... you might call it "general purpose hardware", I suppose).
Kent M Pitman wrote:
> Pascal Costanza <··@p-cos.net> writes:
>
>> Kent M Pitman wrote:
>>> Pascal Costanza <··@p-cos.net> writes:
>>>
>>>> Having said that, hashtables have the most convenient / complete API,
>>>> but are generally much less efficient than assocation lists and
>>>> property lists for small numbers. (That's why, for example, I use
>>>> property lists for caches in ContextL.)
>>> In Common Lisp on Symbolics Genera (Lisp Machine Lisp), I recall a
>>> large amount of work being done on hash tables to basically have them
>>> use property lists internally and to morph into an alternate
>>> representation at the efficiency crossover point. There's some small
>>> small storage&time overhead issue of shifting at the right moment
>>> and some theoretical issues about how to advise whether and when to
>>> switch back to avoid thrashing, but nothing in the spec for hash
>>> tables requires a particular implementation.
>> Er, are you sure? Maybe I am missing something, but property lists are
>> required to compare keys using eq, while with hashtables, you can
>> choose from eq, eql, equal and equalp. That should make a difference,
>> no?
>
> My saying property lists did not mean CL-defined property list
> functions. That is, one can emulate property list effects by
> traversing lists up to some threshold size; one doesn't have to use
> the specific implementations to CL's GET (which isn't parameterizable
> for predicates).
OK - yes, this occurred to me after I posted my question...
Thanks,
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
On Nov 4, 8:15 am, Pascal Costanza <····@p-cos.net> wrote:
> I once compared and got a number around 50. I don't remember the details
> though: The number is highly dependent on implementation, optimization
> settings, probably CPU used, etc.
>
Indeed. I've done a lot of my own tests on this for implementing sets
and (unsurprisingly) it varies a lot. My rule of thumb at this point
is that when the size is under 20, you might as well use a list and
that I only start to care when the size gets up to around 50.
> Having said that, hashtables have the most convenient / complete API,
> but are generally much less efficient than assocation lists and property
> lists for small numbers. (That's why, for example, I use property lists
> for caches in ContextL.)
Even when the cost of lookup is the same for small sets with hash
tables and lists, the cost of creating a hash table tends to be a lot
more than that of a list. I've found that dropping in a hash table
for a list in places where few get created doesn't make much of a
difference, but when the number allocated gets high, lists are
noticeably faster.
On Sat, 03 Nov 2007 12:27:28 +0100, Pascal Costanza wrote:
> Structs have the problem that they need to be defined upfront, whereas
> property lists can be created on the fly. So there's a trade off here.
Yes, I was just thinking that, too. That may complicate things in my
setup. I'm wondering if plists are that much less efficient than structs
when they only contain a few (usually between 1 and 4) elements.
> As to your original question, when a function returns a property list,
> you can conveniently retrieve variable bindings using lambda or
> destructuring-bind:
>
> (destructuring-bind
> (&key a b c) (some-function ...)
> ... some code ...)
>
> or:
>
> (apply (lambda (&key a b c)
> ... some code ...)
> (some-function ...))
Nice. I can probably use those constructs in one or two places. :-)
Joost.
Joost Diepenmaat wrote:
> On Sat, 03 Nov 2007 12:27:28 +0100, Pascal Costanza wrote:
>
>> Structs have the problem that they need to be defined upfront, whereas
>> property lists can be created on the fly. So there's a trade off here.
>
> Yes, I was just thinking that, too. That may complicate things in my
> setup. I'm wondering if plists are that much less efficient than structs
> when they only contain a few (usually between 1 and 4) elements.
I don't know. It's probably worthwhile to investigate this.
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
In article <··············@mid.individual.net>,
Pascal Costanza <··@p-cos.net> wrote:
> Joost Diepenmaat wrote:
> > On Sat, 03 Nov 2007 00:26:48 -0400, Ken Tilton wrote:
> >>> ** the question/problem **
> >>>
> >>> Basically, what I want is an idiomatic way to specify a closure that
> >>> takes zero or more (preferably named) arguments and returns zero or
> >>> more (preferably named) arguments.
> >> What's wrong with a struct? That names its slots. Something like an
> >> a-list (one alternative) would be a lot less efficient, and somehow this
> >> sounds like it needs to be efficient.
> >
> > Thanks, I hadn't even considered structs (I'm using a p-list at the
> > moment). That could work very well, I think.
>
> Structs have the problem that they need to be defined upfront, whereas
> property lists can be created on the fly. So there's a trade off here.
>
> As to your original question, when a function returns a property list,
> you can conveniently retrieve variable bindings using lambda or
> destructuring-bind:
Sometimes it is handy to have a property-list-mixin for CLOS
objects.
For example during debugging or testing, one can
attach arbitrary data to objects and experiment with that.
>
> (destructuring-bind
> (&key a b c) (some-function ...)
> ... some code ...)
>
> or:
>
> (apply (lambda (&key a b c)
> ... some code ...)
> (some-function ...))
>
>
> Pascal
or use CLOS
(with-slots (foo bar)
(some-function)
... some code ...)
Also: WITH-ACCESSORS
(defclass baz ()
((foo :accessor baz-foo :initarg :foo)
(bar :accessor baz-bar :initarg :bar)))
(defun make-baz ()
(make-instance 'baz :foo 1 :bar 2))
(with-accessors ((a baz-foo) (b baz-bar))
(make-baz)
(list a b))
Pascal Costanza <··@p-cos.net> wrote:
+---------------
| As to your original question, when a function returns a property list,
| you can conveniently retrieve variable bindings using lambda or
| destructuring-bind:
|
| (destructuring-bind
| (&key a b c) (some-function ...)
| ... some code ...)
|
| or:
|
| (apply (lambda (&key a b c)
| ... some code ...)
| (some-function ...))
+---------------
Nice. The GET-PROPERTIES standard function will do part of this
for you [looking for multiple indicators at once], but you have
to write a loop around it to get the same results as the above.
Caveat: To use the above in the general case, some additional
constraints are needed:
1. Either: (a) the property lists SOME-FUNCTION returns need
to use keywords as markers, not just any old symbols; or else
(b) each parameter X in the lambda lists must be re-written
as ((X X)) [rather ugly, IMHO, but does work].
2. If you're only binding a few of the indicators in the supplied
property list, your lambda list also needs &ALLOW-OTHER-KEYS.
But that said, it is a neat hack, well worth remembering:
> (defun some-function ()
(list :x 0 :c 3 :y 234 :b 2 :sldk 34 :a 1 :kdjf 12))
SOME-FUNCTION
> (destructuring-bind (&key a b c &allow-other-keys)
(some-function)
(list a b c))
(1 2 3)
> (apply (lambda (&key a b c &allow-other-keys)
(list b c a))
(some-function))
(2 3 1)
>
And if you really need non-keyword indicators:
> (defun some-other-function ()
(list 'x 0 'c 6 'y 234 'b 5 'sldk 34 'a 4 'kdjf 12))
SOME-OTHER-FUNCTION
> (destructuring-bind (&key ((a a)) ((b b)) ((c c)) &allow-other-keys)
(some-other-function)
(list a b c))
(4 5 6)
> (apply (lambda (&key ((a a)) ((b b)) ((c c)) &allow-other-keys)
(list b c a))
(some-other-function))
(5 6 4)
>
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
Rob Warnock wrote:
> Pascal Costanza <··@p-cos.net> wrote:
> +---------------
> | As to your original question, when a function returns a property list,
> | you can conveniently retrieve variable bindings using lambda or
> | destructuring-bind:
> |
> | (destructuring-bind
> | (&key a b c) (some-function ...)
> | ... some code ...)
> |
> | or:
> |
> | (apply (lambda (&key a b c)
> | ... some code ...)
> | (some-function ...))
> +---------------
>
> Nice.
But if you know the variables you can use defstruct or defclass.
Meanwhile, the OP has indicated the variable names are not known.
Who was it that said Lisp has a kazillion ways to do anything but 1- of
them are wrong? Has anyone mentioned F#?
kzo
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
Ken Tilton wrote:
>
>
> Rob Warnock wrote:
>> Pascal Costanza <··@p-cos.net> wrote:
>> +---------------
>> | As to your original question, when a function returns a property
>> list, | you can conveniently retrieve variable bindings using lambda
>> or | destructuring-bind:
>> | | (destructuring-bind
>> | (&key a b c) (some-function ...)
>> | ... some code ...)
>> | | or:
>> | | (apply (lambda (&key a b c)
>> | ... some code ...)
>> | (some-function ...))
>> +---------------
>>
>> Nice.
>
> But if you know the variables you can use defstruct or defclass.
> Meanwhile, the OP has indicated the variable names are not known.
If your variable names are not known, when you use defstruct or
defclass, you have to change three places in your code whenever your
names change: The call site, the called site and the definition site.
With 'keyword results', you only have to change the call site and the
called site. That may not make a big difference, but can potentially
increase your development speed (similar to keyword arguments).
I haven't used keywords for returning results yet, so this is just
speculation, but I can imagine that this could be worthwhile...
Pascal
--
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
Pascal Costanza wrote:
> Ken Tilton wrote:
>
>>
>>
>> Rob Warnock wrote:
>>
>>> Pascal Costanza <··@p-cos.net> wrote:
>>> +---------------
>>> | As to your original question, when a function returns a property
>>> list, | you can conveniently retrieve variable bindings using lambda
>>> or | destructuring-bind:
>>> | | (destructuring-bind
>>> | (&key a b c) (some-function ...)
>>> | ... some code ...)
>>> | | or:
>>> | | (apply (lambda (&key a b c)
>>> | ... some code ...)
>>> | (some-function ...))
>>> +---------------
>>>
>>> Nice.
>>
>>
>> But if you know the variables you can use defstruct or defclass.
>> Meanwhile, the OP has indicated the variable names are not known.
>
>
> If your variable names are not known, when you use defstruct or
> defclass, you have to change three places in your code whenever your
> names change: The call site, the called site and the definition site.
> With 'keyword results', you only have to change the call site and the
> called site. That may not make a big difference, but can potentially
> increase your development speed (similar to keyword arguments).
A little reductio adsurbum takes us to all functions taking one argument
and passing back the same value, viz, "whatever I said in the a-list".
Code (including our own) no longer reveals itself to the reader, and we
cannot tell what are the parameters to a function by examining a call,
we must inspect the source to find out in what things the function is
interested. This is somewhat akin to a class instance, but then I also
try to not make that mistake with those -- I break out the one or two
slots that matter and make those parameters, so I can also use the
function with values not yet wrapped up in an instance.
btw, I am not speaking hypothetically, I myself ended up at one point
with functions that managed to become opaque, brittle, and inflexible
playing this game and regretted the difficulty of working with said code.
>
> I haven't used keywords for returning results yet, so this is just
> speculation, but I can imagine that this could be worthwhile...
Funny, I woke up this morning and decided to challenge you or Rob
"Nice!" Warnock to find anywhere in any project (let alone your own
code) a usage like the suggested keyword-rich destructuring-bind on a
function call. Given that the OP asked for "a good/standard/idiomatic
way of doing this"...
All in all I think the problem is underspecified, a Bad Thing given
Lisp's many ways to get things done.
kzo
--
http://www.theoryyalgebra.com/
"In the morning, hear the Way;
in the evening, die content!"
-- Confucius
Ken Tilton <·········@gmail.com> wrote:
+---------------
| Pascal Costanza wrote:
| > I haven't used keywords for returning results yet, so this is just
| > speculation, but I can imagine that this could be worthwhile...
|
| Funny, I woke up this morning and decided to challenge you or Rob
| "Nice!" Warnock to find anywhere in any project (let alone your own
| code) a usage like the suggested keyword-rich destructuring-bind on a
| function call. Given that the OP asked for "a good/standard/idiomatic
| way of doing this"...
+---------------
I haven't used it *yet*, but in my web application server ("appsrv")
there are places where a "keyword-rich destructuring-bind" might be
an improvement over how I *currently* do it, "it" being to destructure
an HTTP query that might have the sub-items of the query in *any* order
and match them up with the requirements of a table whose columns need
to be presented in a fixed order. Right now what I do is stuff the
pairs of "keyword=value" into a hash table, and then extract them
in the needed fixed order. A "keyword-rich destructuring-bind" would
have saved a lot of coding had I thought of it at the time [circa 2002,
when I was first writing serious CL code in anger], but I'm not sure
it would be any more efficient or maintainable. It probably depends
on whether the underlying implementation does anything smarter than
my hash table code.
So please don't be confused by my "Nice!". A "neat hack" is just that.
It's *NOT* necessarily something you want to actually use in production
code. As noted above, using a keyword-rich destructuring-bind or
function call might be a "neat" way to do it, but it also might not
be the best way.
-Rob
-----
Rob Warnock <····@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607
Here's another option for named return values. It's not too difficult
to define macros that map keywords to return-value positions, so you
can say e.g.
(foo-values :bar 1 :zap 2)
to generate/return the values, and e.g.
(bind-foo (&zap y &bar x)
(foo-returning-function)
...)
to bind them. This would expand to essentially
(values 1 2)
and
(multiple-value-bind (bar zap)
(foo-returning-function)
...)
respectively. The next step would be to write a macro-generating macro
such that
(define-named-values foo bar zap)
would achieve the above.
--
Frode Vatvedt Fjeld