Prev: Do as the Romans do
Next: managing large table of data
From: mdj on 2 Feb 2010 23:15 On Feb 3, 1:01 pm, Madhu <enom...(a)meer.net> wrote: > * D Herring <hkan0f$9u...(a)news.eternal-september.org> : > Wrote on Tue, 02 Feb 2010 21:28:31 -0500: > > | Again, I will recommend that people check out Conium. Its basically > | the Slime CL code, stripped of all Slime's client/server and emacs > | code. > | > |http://gitorious.org/conium > > And it adds at least 5 gratuituous dependencies dependencies on at least > five 3rd party libraries (directly) > > This is not a good thing unles youre in the library selling business It makes more sense to me when developing a portability library to make use of existing portability abstractions and avoid re-inventing those particular wheels. It makes it far easier to test code across multiple CL implementations which is a good thing(tm). Matt
From: Thomas F. Burdick on 3 Feb 2010 09:02 On Feb 3, 3:28 am, D Herring <dherr...(a)at.tentpost.dot.com> wrote: > On 02/02/2010 02:13 AM, Duane Rettig wrote: > > > > > Someone else also mentioned an internal function called arglist (in > > the implementation's internal package), and I submit that that is more > > likely to be of use to you if it really is the arglist you want. I > > recall someone (but I don't remember who it was, sorry) who posted on > > c.l.l. an implementation independent version of arglist for all of the > > CLs on which he was working, which called whatever version of arglist > > was appropriate for the implementation (Allegro CL's is excl:arglist, > > by the way). Maybe a google search (or perhaps a reminder from > > someone who created or who uses that definition) might be helpful > > here. The reason why I think it is a better bet than f-l-e is because > > although the lambda source is mostly expendable when a function is > > compiled, the argument list is not; it must be used by debuggers to > > decide where arguments actually reside; it allows IDEs to name > > argument lists while you are in the editor writing code; it allows > > programs to decide arity, etc., and it is also less likely to be > > elided from an implementation because of its necessity. So it is more > > likely that the tradeoffs in whether to keep the argument list or not > > are more in your favor than that of the entire source for the > > function. > > Again, I will recommend that people check out Conium. Its basically > the Slime CL code, stripped of all Slime's client/server and emacs code. > > http://gitorious.org/conium Awesome! You mentioned it before, but hadn't mentioned *what* it was (and its name doesn't help). Thanks for pointing it out, this will save me some effort.
From: slash dot on 3 Feb 2010 15:50 On Feb 1, 11:43 pm, Leandro Rios <leandroprograma...(a)gmail.com> wrote: > slash dot <tynty...(a)gmail.com> writes: > > > Well, you are an alert reader. "Unless your code does (read)..." > > My code doesn't (read), it gets the lambdas from an array and > > picks them by index as needed. Some of the lambdas need an argument, > > some don't. The caller inspects the lambda by one way or the other > > and passes an argument if needed. The alternative is to make all > > lambdas uniform in that all of them accept an argument, but some > > simply ignore it. However, there is a problem: the caller traverses > > a sequence and leaves maintaining the iterator to other parts of > > the system. If the caller fetches a value, passes it to the lambda, > > and the lambda does not need it, the system gets out of sync. The > > caller > > does something like > > > (funcall my-lambda (next-item)) > > > where (next-byte) advances the iterator. If the called lambda > > does not consume the passed value, it is supposed to be process > > by a subsequent call to a (potentially other) lambda. > > Do you have control about how lambdas are generated? If so, it would > be easy to do: > > (funcall my-lambda #'next-item) > > where all lambdas would take a parameter and would behave like this: > > Lambdas not using next-item: > > #'(lambda (item-fn) > (declare (ignore item-fn)) > ... stuff ...) > > Lambdas using next-item: > > #'(lambda (item-fn) > (let ((item (funcall item-fn))) > ... stuff with item ...)) > > Would that be a viable solution? It's just ANSI CL :) > I thought it is, but what you could not know and I did not notice at first is this. The lambda called as (funcall the-lambda (next-item)) has this declaration: #'(lambda (x) (merge (do-something-with x) (do-something-more-with x))) Note that 'x' is used twice here. If I have uniform lambdas, all with a function argument, then I need an extra 'let' to keep the x: #'(lambda (item-fn) (let ((x (funcall item-fn))) (merge (do- something-with x) (do-something-more-with x)))) This would not be that much of a problem if it wasn't for readability. Again, those lambdas are part of a table and data. It should be readable without much effort by a human, so conciseness is an issue. Anyways, thanks all the same.
From: slash dot on 3 Feb 2010 15:57 On Feb 2, 3:44 pm, Pillsy <pillsb...(a)gmail.com> wrote: > On Feb 1, 5:45 pm, slash dot <tynty...(a)gmail.com> wrote: > [...] > > > The caller does this with a lambda retrieved by index: > > (funcall my-lambda (next-item)) ; note the call to 'next-item' > > ; this is the argument we are > > ; talking about > > However, there is a problem: the caller traverses > > a sequence, calling lambdas for processing data items in packs that > > are of various length. The caller leaves maintaining the iterator to > > other parts of the system. If the caller fetches a value, passes it > > to the lambda, and the lambda does not need it, the system gets > > out of sync. If the called lambda does not consume the passed value, > > it is supposed to be process by a subsequent call to a (potentially > > other) lambda. > > Well, here's one possible solution which carries the first-class > function thing a tiny bit further. Right now, presumably, you have > some anonymous functions that look like this: > > (lambda () > (do-stuff-without-consuming-an-item)) > > and other anonymous functions that look like this: > > (lambda (item) > (do-stuff-with item)) > > However, if you change the place these functions are called to look > like this: > > (funcall my-lambda #'next-item) > > you can rewrite those anonymous functions to have a uniform argument > list without having to take extra care to keep things synchronized. > Like so: > > (lambda (next-item-thunk) > (declare (ignore next-item-thunk)) > (do-stuff-without-consuming-an-item))) > > (lambda (next-item-thunk) > (let ((item (funcall next-item-thunk))) > (do-stuff-with item))) > > This allows you to push all the responsibility for "knowing" whether a > given function in the array consumes an item in the sequence onto that > function itself, which could be a worthwhile simplification, all > issues of introspection aside. > > HTH, > Pillsy Thanks, you have come to the same conclusion as the author of this admittedly beautiful suggestion: http://groups.google.com/group/comp.lang.lisp/msg/fc313562e05a524a However, in this particular case it didn't look as attractive after some head-scratching and thought-experiment. (There is an explanation and handwaving in the reply, if you are interested in the details.) Thanks all the same.
From: Thomas A. Russ on 3 Feb 2010 17:14
slash dot <tyntyfax(a)gmail.com> writes: > On Feb 1, 11:43�pm, Leandro Rios <leandroprograma...(a)gmail.com> wrote: > > Lambdas not using next-item: > > > > #'(lambda (item-fn) > > � � (declare (ignore item-fn)) > > � � ... stuff ...) > > > > Lambdas using next-item: > > > > #'(lambda (item-fn) > > � � (let ((item (funcall item-fn))) > > � � � ... stuff with item ...)) > > > > Would that be a viable solution? It's just ANSI CL :) > > > > I thought it is, but what you could not know and > I did not notice at first is this. > > The lambda called as > > (funcall the-lambda (next-item)) > > has this declaration: > > #'(lambda (x) (merge (do-something-with x) (do-something-more-with x))) > > Note that 'x' is used twice here. If I have uniform lambdas, all > with a function argument, then I need an extra 'let' to keep > the x: > > #'(lambda (item-fn) > (let ((x (funcall item-fn))) > (merge (do-something-with x) (do-something-more-with x)))) > > This would not be that much of a problem if it wasn't for > readability. Again, those lambdas are part of a table and > data. It should be readable without much effort by a human, > so conciseness is an issue. Well, formatting it with indentation helps readabilty. But if you want concise, then you can always use &aux for the lambdas that actually use their argument: #'(lambda (item-fn &aux (x (funcall item-fn))) (merge (do-something-with x) (do-something-more-with x))) Or if more readability is needed, then you could always use a macro to help you define the lambda expressions, and that macro could hide the extra level of the LET macro. Presumably the readability is at the source code level, right? I would think that the normal printed form of the code would be rather opaque in most lisp implementations. So all you need to do is make the source form look good: (defconsumer (x) (merge (do-something-with x) (do-something-more-with x))) (defskipper (do-something-for-side-effect-only)) where you would create the following: (defmacro defconsumer ((var) &body code) (let ((fn-arg-var (gensym "F-"))) `(lambda (,fn-arg-var) (let ((,x (funcall ,fn-arg-var))) ,@code)))) (defmacro defskipper (&body code) (let ((fn-arg-var (gensym "F-"))) `(lambda (,fn-arg-var) (declare (ignore ,fn-arg-var)) ,@code))) -- Thomas A. Russ, USC/Information Sciences Institute |