> In article <3150898143617...@naggum.no>, Erik Naggum wrote:
> >(mapcar #'funcall <list-of-functions> ...)
> I cannot think of any situations in which this is useful. Could you > please give an example? Thanks in advance!
Emacs-style hooks. Say gnus-article-display-hook is a list of functions. Now, whenever an article is displayed, use the above idiom to call each function in the list on the article. In this case, the functions do things like highlight urls, hide headers, de-mime the message, etc.
Or, lists of actions that you associate with an event in a user interface. Say you've got a button "destroy world." When the user clicks the button, you funcall all the functions in the destroy-world-function-list.
There was no EVAL in Scheme until the very R5RS. IEEE Scheme doesn't counts. Anyway, did you noticed that your lambda expression is the same as funcall described by Erik? :)
* Michael Livshin <cmm+n...@verisity.com> | the Scheme "moral equivalent" (if we assume that a hook is a list | of symbols, not closures) would be: | | (map (lambda (sym . args) (apply (eval sym) args)) | <list-of-names> ...) | | that's too easy, so I probably don't get something here ;(.
indeed. the point is that you have to write your own FUNCALL by hand.
I also happen to do (apply #'funcall <list>) at times. I guess Scheme's (apply (eval (car list)) (cdr list)) is much more _elegant_. hee hee!
I think the arguments for much of Scheme's purported elegance are really stupid and it doesn't help when Schemers don't even recognize that they are arguing against electronic gas lighters because they can make do with their beautifully carved flint stones.
#:Erik -- Attention Microsoft Shoppers! MS Monopoly Money 6.0 are now worthless.
In article <87k8nrmzhu....@nightfly.apk.net>, R. Matthew Emerson wrote: >roms...@janus.uio.no (Tord Kallqvist Romstad) writes:
>> In article <3150898143617...@naggum.no>, Erik Naggum wrote:
>> >(mapcar #'funcall <list-of-functions> ...)
>> I cannot think of any situations in which this is useful. Could you >> please give an example? Thanks in advance!
>Emacs-style hooks. Say gnus-article-display-hook is a list of functions. >Now, whenever an article is displayed, use the above idiom to >call each function in the list on the article. In this case, the >functions do things like highlight urls, hide headers, de-mime the message, >etc.
Thank you for answering, but there is still one thing I don't understand: How do you pass the argument(s) to the functions in list-of-functions?
> * Michael Livshin <cmm+n...@verisity.com> > | the Scheme "moral equivalent" (if we assume that a hook is a list > | of symbols, not closures) would be: > | > | (map (lambda (sym . args) (apply (eval sym) args)) > | <list-of-names> ...) > | > | that's too easy, so I probably don't get something here ;(.
[Responding to Michael Livshin <cmm+n...@verisity.com>]
As a matter of fact, it _is_ too easy, since EVAL takes two arguments (by R5RS):
Of course, then the list of symbols representing procedures and the list of arguments must be of the same length, which begs the question of just what, exactly, you are trying to do?
As I've seen them, hooks are generally applied to arguments, with all hooks receiving the same arguments, which in Scheme would likely resemble:
> indeed. the point is that you have to write your own FUNCALL by hand.
> I also happen to do (apply #'funcall <list>) at times. I guess Scheme's > (apply (eval (car list)) (cdr list)) is much more _elegant_. hee hee!
True, true. (apply #'funcall <list>) is quite a bit more elegant than the latter; however, this is generally not the way work gets done in Scheme, as you no doubt know. There is almost never any reason that one opts to retain the symbol bound to a location containing a function over retaining the function itself, especially when the CDR of the list contains EVAL'ed arguments for the CAR of the list...I just don't get it. The above inelegant Scheme form should just be:
> I think the arguments for much of Scheme's purported elegance are really > stupid and it doesn't help when Schemers don't even recognize that they > are arguing against electronic gas lighters because they can make do with > their beautifully carved flint stones.
I tend to agree with the sentiment that much of the elegance of Scheme is due to the sparsity of the language; however, formulating arguments which only prove that _you_ are capable of constructing a solution in Scheme, which is extremely ugly in the face of the elegant Common Lisp solution, really doesn't tell me very much about the Scheme _language_.
well, I wasn't trying to be pedantic. note that in Scheme, you don't usually store symbols that name functions, you store the functions themselves (well, you do note that below). also, if I would store symbols, I wouldn't look them up with eval, because that doesn't make any sense. presumably I know the context in which I want the symbols to name things, and I look them up in that context, by whatever means are appropriate (hook-symbol->procedure or something).
> Of course, then the list of symbols representing procedures and the list > of arguments must be of the same length, which begs the question of just > what, exactly, you are trying to do?
sloppily illustrate an irrelevant point, as it turned out ;)
> > I think the arguments for much of Scheme's purported elegance are really > > stupid and it doesn't help when Schemers don't even recognize that they > > are arguing against electronic gas lighters because they can make do with > > their beautifully carved flint stones.
> I tend to agree with the sentiment that much of the elegance of Scheme is > due to the sparsity of the language; however, formulating arguments which > only prove that _you_ are capable of constructing a solution in Scheme, > which is extremely ugly in the face of the elegant Common Lisp solution, > really doesn't tell me very much about the Scheme _language_.
at the risk of misunderstanding Erik (again), the point seems to be, basically, that Common Lisp has this nice function called `funcall', and Scheme doesn't. as well as an awful lot of other useful things.
> Chris.
--mike
-- newsgroup volume is a measure of discontent. -- Erik Naggum
[snip] > Thank you for answering, but there is still one thing I don't understand: > How do you pass the argument(s) to the functions in list-of-functions?
In article <382872E3.CA955...@cit.org.by>, Eugene Zaikonnikov wrote: >Tord Kallqvist Romstad wrote:
>[snip] >> Thank you for answering, but there is still one thing I don't understand: >> How do you pass the argument(s) to the functions in list-of-functions?
This works, of course, but I thought matt meant that all the functions in list-of-functions should be used on the same argument (in his example, a news article). Having to construct a list of copies of this single argument of the same length as the list of functions seems very inconvenient.
> >[snip] > >> Thank you for answering, but there is still one thing I don't understand: > >> How do you pass the argument(s) to the functions in list-of-functions?
> This works, of course, but I thought matt meant that all the functions > in list-of-functions should be used on the same argument (in his example, > a news article). Having to construct a list of copies of this single > argument of the same length as the list of functions seems very inconvenient.
> Tord
In this situation, i would use something like:
(mapcar #'(lambda (next) (funcall next my-arg)) list-of-functions)
No need for a list of copies of my-arg. This will apply your list of functions, in turn, on the same argument and return a list containing the results of each funcall.
Just curious now, if a function returns multiple values, i imagine you'll only get the first? How would you get all the return values out of a mapcar? (no particular purpose in mind, maybe this is something to avoid even trying...)
Coby Beck wrote: > Just curious now, if a function returns multiple values, i imagine you'll > only get the first? How would you get all the return values out of a > mapcar? (no particular purpose in mind, maybe this is something to avoid > even trying...)
You don't get all the multiple values out of a mapcar.
Instead of (mapcar f stuff) you'd have to do something like (mapcar (lambda (x) (multiple-value-list (funcall f x))) stuff) (or you might prefer the results of MAPCAN).
This isn't something one often wants, though...
-- Gareth McCaughan Gareth.McCaug...@pobox.com sig under construction
> Isn't one of the attractions of Lisp that it can do whatever the > programmer wants? If you firmly believe the imperative style to > always be inferior, fine - you can write pure functional programs. > Personally, I find that sometimes the best way to solve a problem is > with functional code, sometimes, with imperative, and usually with a > mix.
You are certainly right (other than misquoting me), and most people use a mixed style in Lisp. I use imperative features when it is either of local effect, and I don't have to worry about its consequences beyond the boundaries of the containing function, or is a means of implementing (or meta-) levels of abstractions, e.g., via macros.
Although Lisp definitely supports imperative style, I think that using special variables, destructive operations and side effects all over and globally is an underutilization of Lisp's abstraction capabilities, which does not scale well with problem complexity. I would guess your programs are also more on the functional side.
> > Just curious now, if a function returns multiple values, i imagine > > you'll only get the first? How would you get all the return values > > out of a mapcar? (no particular purpose in mind, maybe this is > > something to avoid even trying...)
> You don't get all the multiple values out of a mapcar.
> Instead of (mapcar f stuff) you'd have to do something like > (mapcar (lambda (x) (multiple-value-list (funcall f x))) stuff) > (or you might prefer the results of MAPCAN).
I'd guess there is no way to avoid consing this way.
Here's an example from CLtL2 on using series functions with functions returning multiple values:
* Christophe Kirkwood-Watts 0790340 <kirkw...@cna0790340.rsc.raytheon.com> | True, true. (apply #'funcall <list>) is quite a bit more elegant than the | latter; however, this is generally not the way work gets done in Scheme, | as you no doubt know.
please get your attributions right. I'm taking a Schemer's proposed code as a given. I make no representation to write elegant Scheme code. far from it, I think Scheme is an _inelegant_ language the exact same way I think anything else that is beautiful only when tiny and undeveloped grows into huge morasses of disgustitude when actually put to real use, like GUILE. it actually amazes me constantly that the elegance of Scheme does not scale beyond the standard and the core language, but it's like they say in biology: an insect is built the way it is because it is so small, and an elephant the way it is because it is so big. both work quite well with their body builds, while neither would work with the others' body build even when scaled appropriately. design a language as elegant and small as an insect, and it will collapse under its own weight if it tries to grow big, but design a language able to grow big systems, and it will necessarily look extremely bloated if scaled down to the insect size that some people use to jugde languages and applications, like the size of "hello, world" programs, to take the glaring example.
| I tend to agree with the sentiment that much of the elegance of Scheme is | due to the sparsity of the language; however, formulating arguments which | only prove that _you_ are capable of constructing a solution in Scheme, | which is extremely ugly in the face of the elegant Common Lisp solution, | really doesn't tell me very much about the Scheme _language_.
just you get your attributions right, mister, and this will all rectify itself automatically. and check your blood pressure while you're at it. I don't like Scheme, and I make no bones about it. if you don't like that somebody thinks Scheme is ugly and the Scheme community silly for its insistence on elegance through missing features, learn to live with.
#:Erik -- Attention Microsoft Shoppers! MS Monopoly Money 6.0 are now worthless.
* Tord Kallqvist Romstad | This works, of course, but I thought matt meant that all the functions in | list-of-functions should be used on the same argument (in his example, a | news article). Having to construct a list of copies of this single | argument of the same length as the list of functions seems very | inconvenient.
it would indeed, so we don't. given this very useful function:
Tim Bradshaw <t...@tfeb.org> wrote: +--------------- | * Tord Kallqvist Romstad wrote: | > I cannot think of any situations in which this is useful. Could you | > please give an example? Thanks in advance! | | I have code that looks like: | (funcall (if multiprocessing-p #'process-run-function #'funcall) | #'(lambda () | ...)) +---------------
But since in Scheme the "function" position is evaluated with the *same* rules as the "arg" positions -- that is, the function position can be *any* expression that evaluates to a function -- you can accomplish the above in Scheme with:
Michael Livshin <cmm+n...@verisity.com> wrote: +--------------- | Erik Naggum <e...@naggum.no> writes: | > well, Emacs Lisp calls them "hooks" -- lists of functions to call to | > allow users to customize the behavior of internal functions. | | hmmm. what you are talking about is mapc'ing funcall over a list | of symbols, right? | | the Scheme "moral equivalent" (if we assume that a hook is a list | of symbols, not closures) would be: | | (map (lambda (sym . args) (apply (eval sym) args)) | <list-of-names> ...) | | that's too easy, so I probably don't get something here ;(. +---------------
What you didn't get [and thereby triggered an otherwise needless flamefest from Erik! ;-} ;-} ] is that the "Scheme moral equivalent" is *NOT* a "list of symbols", but (as you *almost* said) "a list of closures" themselves. So no "eval" is needed at all:
(for-each (lambda (x) (x)) *foo-hook*)
or if there are per-function-dependent args to be passed:
> (map (lambda (f a1 a2) (f a1 a2)) (list + - * /) ; "list", not "quote": get the the *values*! '(1 2 3 4) '(5 6 7 8)) (6 -4 21 1/2) >
Or more generally, using the more general definition of Scheme "funcall" I gave in another reply in this thread:
Scheme and Common Lisp have *very* different "natural" styles in some areas, and the "Lisp1" nature of Scheme and the fact that the function position of a call is evaluated *exactly* the same way as the argument positions means that in most situations where a Common Lisp programmer might pass around the *name* of a function -- knowing that "symbol-function" is cheap and does not require "eval" -- the Scheme programmer will simply pass around the function itself.
Unlike Erik [whose opinion I respect], I do like Scheme... for some things. But I definitely have learned that Scheme is *not* a "subset" or even "dialect" of Common Lisp (though my opinion, which various others agree *and* disagree with, is that Scheme is certainly a member of the generic "Lisp family"), and that it is best not to try to argue detailed comparisons between them (other than maybe presenting rough crib sheets for use by people trying to move from one to the other, for whatever reason).
-Rob
----- Rob Warnock, 8L-846 r...@sgi.com Applied Networking http://reality.sgi.com/rpw3/ Silicon Graphics, Inc. Phone: 650-933-1673 1600 Amphitheatre Pkwy. FAX: 650-933-0511 Mountain View, CA 94043 PP-ASEL-IA
Rob Warnock wrote: > What you didn't get [and thereby triggered an otherwise needless flamefest > from Erik! ;-} ;-} ] is that the "Scheme moral equivalent" is *NOT* a > "list of symbols", but (as you *almost* said) "a list of closures" themselves. > So no "eval" is needed at all:
> Scheme and Common Lisp have *very* different "natural" styles in some areas, > and the "Lisp1" nature of Scheme and the fact that the function position > of a call is evaluated *exactly* the same way as the argument positions > means that in most situations where a Common Lisp programmer might pass > around the *name* of a function -- knowing that "symbol-function" is cheap > and does not require "eval" -- the Scheme programmer will simply pass around > the function itself.
*cough* The "_modern_Lisp_ moral equivalent" is to pass closures, not global function names.
-- Fernando D. Mato Mira Real-Time SW Eng & Networking Advanced Systems Engineering Division CSEM Jaquet-Droz 1 email: matomira AT acm DOT org CH-2007 Neuchatel tel: +41 (32) 720-5157 Switzerland FAX: +41 (32) 720-5720
r...@rigden.engr.sgi.com (Rob Warnock) writes: > Tim Bradshaw <t...@tfeb.org> wrote: > +--------------- > | * Tord Kallqvist Romstad wrote: > | > I cannot think of any situations in which this is useful. Could you > | > please give an example? Thanks in advance! > | > | I have code that looks like: > | (funcall (if multiprocessing-p #'process-run-function #'funcall) > | #'(lambda () > | ...)) > +---------------
> But since in Scheme the "function" position is evaluated with the *same* > rules as the "arg" positions -- that is, the function position can be > *any* expression that evaluates to a function -- you can accomplish the > above in Scheme with:
> I think Scheme is an _inelegant_ language the exact same way I > think anything else that is beautiful only when tiny and undeveloped > grows into huge morasses of disgustitude when actually put to real use, > like GUILE. it actually amazes me constantly that the elegance of Scheme > does not scale beyond the standard and the core language, but it's like
Have you had a chance to look at the SRFIs (Scheme Requests For Implementation <http://srfi.schemers.org/>)? I'd be interested in whether you think the scaling problem holds there. The whole SRFI processs seems to be the first, general, community based attempt to expand the scope of (portable) Scheme. (I think certain particular Scheme implementations have done fairly well at adding a higher level, but "elegant" superstructure onto core Scheme (EdScheme comes to mind and maybe Bigloo? RScheme is rather nice too; of course, they're incompatible!)
A more general possible counterexample is Smalltalk. The core language (syntax and semantics) is very simple (simpler than Scheme's, I'd say), but a large, nicely elegant system was built with it (the prime example being the general Smalltalk-80 system).
(Of course, I'm not entirely sure what the property is that would cause disgustitude. In a formal system, there's generally a tradeoff between simplicity of the base/primative concepts and simplicity of representing interesting ones. Just because all the logical particles of the first order predicate calculas can be replaced with Sheffer stroke doesn't mean you'd want to write anything as simple as '(A & B) -> B' using nothing be Sheffer strokes.)
> Have you had a chance to look at the SRFIs (Scheme Requests For > Implementation <http://srfi.schemers.org/>)? I'd be interested in > whether you think the scaling problem holds there.
To chime in without being asked (this is not an answer anyway):
There has been a significant progress in Scheme (referring to SRFI's and the Guile Object-Oriented Language), and tt seems Scheme is slowly but surely getting closer to where Common Lisp is. It is clearly beneficial, as it allows people write more and more code efficiently (in terms of run-time and development time) and portably.
On the other hand, you recognize that it adds to language size and complexity, which is not a problem, as these things are often being done now in one implementation or another, and tools that scale well with problems are usually a bit more complex than ones where tool size minimalism matters more.
I'm sure that there are lots of legacy stuff in Common Lisp. As I have only been using lisp for a few years, and I have never had to deal with legacy code, I for sure must be someone who is be pissed off by legacy considerations, and I must have been open to Lisp and Scheme equally. Indeed, I had to be more open towards Scheme, because it's a toolset easier to learn in its completeness.
I found myself, however, preferring CL more and more for its maturity, completeness and portability. Although I have sometimes been terrified with what I do not know about CL, I gained confidence step by step in that eventually I would be able to use all CL facilities, and I can manage now without knowing everything.
The reason I preferred maturity, completeness and portability over language simplicity is not only the availability of commercial implementations, but also the fact that I need it as a tool that I can rely on, rather than a draft (no pun intended) I need to work on myself (yes, I consider myself a user of the language rather than an implementor - of course, I would not even think about aspiring to be a language _designer_, when there is so much more to catch up with in Common Lisp).
I'd like to illustrate my point with a simple example. For quite some time, I did not occur to me why APPLY can take multiple arguments plus a rest argument. It didn't bother me enough to think, read or ask about it. When I wanted to pass on arguments through multiple function calls with the ability to use some of them, but simply passing on other keyword arguments blindly until they reach their destination, I got enlightened about the simple, yet powerful approach, and I could only feel grateful for people who put in so much work, thought and practical experience into the design of this language, and that it was readily available when I needed it.
Also, while legacy may bother people, I just found myself not being reliant on them. I guess some lispers of much longer experience than mine consider CLOS nothing more than an abstraction layer built on structures and other things (as the first OO implementations sometimes were), but I instead consider structures to be but a simplified, dumbed down CLOS, and in fact I don't even use them. I never used the CL facility to print a number in English, but its existence has never hurt me - maybe it comes handy one day.
So to reverse the question you asked: don't you think Scheme (or maybe even Java to a lesser extent) eventually finds its way towards being comparable to CL* (both in size and features), but you have to carry the burden of ever-evolving and growing Scheme interpreters/compilers? Aren't you spending quite some time already designing and implementing new Scheme features, looking up CL specifications for inspiration and juggling Scheme environments? In the meantime, I always _use_ the language when I start a CL environment.
Bijan, please don't think I have always been biased - I was simply being practical, fond of powerful and clean abstractions. These are not rhetorical questions. Relative to the history of Scheme and CL, I am a newcomer, open-minded about making my choice of language for the time horizons that matter to me. I'm also prone to go my way and re-innovate, but I have often find it unproductive.
Also, not everybody is bound to _Scheme_ by legacy, and I'm sure people who understand the trend and significance of Scheme's evolution are also willing to base decisions not just on (their) Scheme legacy but on a fresh, serious look at Common Lisp.
Regards Robert
* People having doubts about Scheme playing catch-up with CL should indeed go to http://srfi.schemers.org to see things like string library, multiple values, exceptions (OK, not conditions) and dynamic scoping. Also, OO and macro facilities are more similar to those of CL than RxRS. (I think that the term "portable and yet useful code" is somewhat unfortunate, but indicative of the current state of Scheme.)
Marco Antoniotti <marc...@parades.rm.cnr.it> wrote: +--------------- | > But since in Scheme the "function" position is evaluated with the *same* | > rules as the "arg" positions -- that is, the function position can be | > *any* expression that evaluates to a function -- you can accomplish the | > above in Scheme with: | > | > ((if multiprocessing-p process-run-function (lambda (x) (x))) | > (lambda () | > ...)) | | If multiprocessing is on then 'process-run-function' executes the | lambda, otherwise the lambda is sipmply returned as a value. +---------------
You're not reading what I typed clsoely enough. What you said would have be true if I had typed *this*:
but I didn't. In what I typed (which you quoted correctly), if multiprocessing is on the lambda on the following lines is passed as a parameter to the "process-run-function", otherwise the lambda is passed as a parameter to the unnamed function "(lambda (x) (x))", which *calls* it! (...with no args.) Again:
(lambda (x) (x)) ; calls its arg (lambda (x) x) ; returns its arg
+--------------- | > p.s. A definition of "funcall" that would work with the above *and* | > handle the more general uses of "funcall" is: | > (define (funcall f . rest) (apply f rest)) | > Then you could say: | > | > ((if multiprocessing-p process-run-function funcall) | > (lambda () | > ...)) | | Now, this would work. +---------------
Both forms work as originally posted.
-Rob
----- Rob Warnock, 8L-846 r...@sgi.com Applied Networking http://reality.sgi.com/rpw3/ Silicon Graphics, Inc. Phone: 650-933-1673 1600 Amphitheatre Pkwy. FAX: 650-933-0511 Mountain View, CA 94043 PP-ASEL-IA
Tim Bradshaw <t...@tfeb.org> wrote: +--------------- | * Fernando D Mato Mira wrote: | | > *cough* The "_modern_Lisp_ moral equivalent" is to pass closures, | > not global function names. | | I thought there was just a whole thread about how this was actually a | bad thing to do sometimes: | | (cons #'foo *hooks*) | | (defun foo () | ;; oops | ...) +---------------
Exactly. CL gives you the *choice* of binding lateness versus effeciency, because "symbol-function" is in the language standard and is relatively cheap, compared to "eval". I didn't mean to imply that CL *couldn't* pass closures, or that it wasn't usually "the right thing", but only that Scheme-the-standard doesn't give you a *choice* other than (presumably slow) "eval", so passing closures is usually considered the "only right thing".
Having said that, of course, someone will chide me about how specific *implementations* of Scheme give you "(global-defined-value <symbol>)" [which, for Scheme, a Lisp-1, is the closest equivalent of "symbol-function" and presumably as cheap] or the like, but I think we're talking mostly about the standard-defined languages here, yes? Implementation extensions don't count in such discussions.
-Rob
p.s. Due credit: "global-defined-value" is from MzScheme
----- Rob Warnock, 8L-846 r...@sgi.com Applied Networking http://reality.sgi.com/rpw3/ Silicon Graphics, Inc. Phone: 650-933-1673 1600 Amphitheatre Pkwy. FAX: 650-933-0511 Mountain View, CA 94043 PP-ASEL-IA
] ]- Suggestions also appear to list the available paradigms as if they ]were somehow equivalent, or of the same value. Even though imperative ]style is well supported in Lisp (it even has the equivalent of GOTO),
hi
this makes me so curious. how csn one implement GOTO in lisp?
]hopefully people consider it inferior to the functional style. (Of ]course, local deviations like ones in elaborate macros are a different ]story.) Even though Lisp gives support for imperative style, I would ]say that Lisp is fundamentally a functional (albeit impure) language. ] ]- Re Eugene's messages: ] ]> If you will not use side-effect constructions Lisp would be *almost* ]> functional language, but then you'd better use Scheme for that ] ]> if you drop out all side-effecting features from CL, it wouldn't be ]> any better than Scheme without them :) ] ]First, it suggests that Scheme is a pure functional language, which it ]isn't. Second, it assumes that functional programming in CL means ]little more than what Lisp 1.5 in the fifties could do. Even though ]class definitions have to be stored somewhere, it is perfectly possible ]to use CLOS and retain functional programming with all of its benefits. ]As for object persistence or I/O, even pure FL's have their constructs ](monads), which are stylistically close to techniques of impure ]languages. ] ]I am yet to see a CL application programmed in imperative style, or a ]functional language with the power of CL (YMMV)- heck, you can even use ]lazy evaluation techniques described in CLtL2! ] ]Robert ] ]