Marco Antoniotti wrote:
> But the following looks very much like Common Lisp
>
> (use-package "UNIFY")
>
> (defun map2 (fun list-1 list-2)
> (match-case (list list-1 list-2)
> ((() ()) ())
> (((?h1 . ?t1) (?h2 . ?t2))
> (cons (funcall fun h1 h2) (map2 fun t1 t2)))
> ((_ _) (error "Invalid list arguments to map2: ~S ~S." list-1
> list-2)))
>
> Not only it looks like Common Lisp. It is written in Common Lisp and it
> runs on every decent Common Lisp system.
>
> http://common-lisp.net/project/cl-unification
Can I just check: that function is:
let rec map2 f l1 l2 = match l1, l2 with
| [], [] -> []
| h1 :: t1, h2 :: t2 -> f h1 h2 :: map2 f t1 t2
| _ -> invalid_arg "list arguments to map2"
So "?" gives a variable in a pattern, "." is cons in a pattern. What does
"funcall" do?
--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com
Jon Harrop wrote:
> Marco Antoniotti wrote:
>
>>But the following looks very much like Common Lisp
>>
>>(use-package "UNIFY")
>>
>>(defun map2 (fun list-1 list-2)
>> (match-case (list list-1 list-2)
>> ((() ()) ())
>> (((?h1 . ?t1) (?h2 . ?t2))
>> (cons (funcall fun h1 h2) (map2 fun t1 t2)))
>> ((_ _) (error "Invalid list arguments to map2: ~S ~S." list-1
>>list-2)))
>>
>>Not only it looks like Common Lisp. It is written in Common Lisp and it
>>runs on every decent Common Lisp system.
>>
>>http://common-lisp.net/project/cl-unification
>
>
> Can I just check: that function is:
>
> let rec map2 f l1 l2 = match l1, l2 with
> | [], [] -> []
> | h1 :: t1, h2 :: t2 -> f h1 h2 :: map2 f t1 t2
> | _ -> invalid_arg "list arguments to map2"
>
> So "?" gives a variable in a pattern, "." is cons in a pattern. What does
> "funcall" do?
Funcall calls a function that is stored in a variable. This is needed
because Common Lisp is a "Lisp-2" that separates the value namespace
from the function namespace (Unlike Scheme, which is a Lisp-1).
See <http://www.nhplace.com/kent/Papers/Technical-Issues.html> for a
discussion of this very topic.
-- MJF
From: Marco Antoniotti
Subject: "Pattern arguments" in Common Lisp (Re: Ray tracer in Stalin)
Date:
Message-ID: <dgoNe.48$DJ5.69105@typhoon.nyu.edu>
Jon Harrop wrote:
> Marco Antoniotti wrote:
>
>>But the following looks very much like Common Lisp
>>
>>(use-package "UNIFY")
>>
>>(defun map2 (fun list-1 list-2)
>> (match-case (list list-1 list-2)
>> ((() ()) ())
>> (((?h1 . ?t1) (?h2 . ?t2))
>> (cons (funcall fun h1 h2) (map2 fun t1 t2)))
>> ((_ _) (error "Invalid list arguments to map2: ~S ~S." list-1
>>list-2)))
>>
>>Not only it looks like Common Lisp. It is written in Common Lisp and it
>>runs on every decent Common Lisp system.
>>
>>http://common-lisp.net/project/cl-unification
>
>
> Can I just check: that function is:
>
> let rec map2 f l1 l2 = match l1, l2 with
> | [], [] -> []
> | h1 :: t1, h2 :: t2 -> f h1 h2 :: map2 f t1 t2
> | _ -> invalid_arg "list arguments to map2"
>
> So "?" gives a variable in a pattern, "." is cons in a pattern. What does
> "funcall" do?
FUNCALL calls a function stored in a variable because CL is a Lisp-2
(unlike Scheme, Dylan, ML, and OCaml, which are essentially all Lisp-1).
Apart from that, the system I built (which is built in Common Lisp and
it runs under any self-respecting CL implementation - here you should
get the hint why Lispers stick to Lisp) is even more "expressive" than
the OCaml system; I refrain from using the word "powerful" because it
the compiler does not do anything particular with it.
Yet it is more expressive, because the system does full unification and
not only pattern matching. In particular, you have access to the UNIFY
function and can set up your own modified macro that did the folllowing
(actually this is a good idea and I will just go ahead and add it to the
library)
(unifying ()
((foo ?x) (?y bar) (list x y))
(otherwise 42)))
Cheers
--
marco
Marco Antoniotti wrote:
> FUNCALL calls a function stored in a variable because CL is a Lisp-2
> (unlike Scheme, Dylan, ML, and OCaml, which are essentially all Lisp-1).
Ok. But what else could the compiler do? That looks like an unambiguous
function application to me.
> Apart from that, the system I built (which is built in Common Lisp and
> it runs under any self-respecting CL implementation - here you should
> get the hint why Lispers stick to Lisp)
Extensibility? So Lisp should be good for compiler and interpreter writing?
> is even more "expressive" than the OCaml system;
Ok.
> I refrain from using the word "powerful" because it the compiler does not
> do anything particular with it.
You're beginning to lose me here. What do you mean "it doesn't do anything
particular with it"?
> Yet it is more expressive, because the system does full unification and
> not only pattern matching. In particular, you have access to the UNIFY
> function and can set up your own modified macro that did the folllowing
> (actually this is a good idea and I will just go ahead and add it to the
> library)
>
> (unifying ()
> ((foo ?x) (?y bar) (list x y))
> (otherwise 42)))
Now I'm completely lost. What does that do?
To me, "unify" is from a type inference algorithm. I assume this is
something completely different.
--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com
From: Paul Dietz
Subject: Re: "Pattern arguments" in Common Lisp (Re: Ray tracer in Stalin)
Date:
Message-ID: <de5j07$m7d$1@avnika.corp.mot.com>
Jon Harrop wrote:
> Extensibility? So Lisp should be good for compiler and interpreter writing?
Yes. Most lisp compilers are written in lisp.
(Yum. Dogfood.)
Paul
From: David Golden
Subject: Re: "Pattern arguments" in Common Lisp (Re: Ray tracer in Stalin)
Date:
Message-ID: <yqqNe.4141$R5.623@news.indigo.ie>
Jon Harrop wrote:
> Ok. But what else could the compiler do? That looks like an
> unambiguous function application to me.
>
Not okay, because you apparently haven't got what Lisp-1 vs. Lisp-2
means?
"(fun x y)" calls the function that is in the "function-value" of the
symbol fun with x and y.
"(funcall fun x y)" calls the function that is in the "variable-value"
of the symbol fun with x and y.
Any clearer?
Compare english:
"shovel dirt with shovel"
(shovel dirt shovel)
- one shovel is used as a verb, the other a noun, one names the action
of shovelling, one an implement for shovelling.
(though I believe many lispers might write
"(shovel-with shovel dirt)")
Here, english is being a bit Lisp-2-ish.
From: Matthias Buelow
Subject: Re: "Pattern arguments" in Common Lisp (Re: Ray tracer in Stalin)
Date:
Message-ID: <3mn6laF15ej7vU1@news.dfncis.de>
David Golden <············@oceanfree.net> wrote:
>Compare english:
>"shovel dirt with shovel"
>(shovel dirt shovel)
>- one shovel is used as a verb, the other a noun, one names the action
>of shovelling, one an implement for shovelling.
>(though I believe many lispers might write
>"(shovel-with shovel dirt)")
>Here, english is being a bit Lisp-2-ish.
I don't think comparing natural languages with programming languages
will work for an argument; you'll probably always lose such an
argument. If you compare Lisp with English, the following examples
should be equivalent and evaluated the same by Lisp:
(shovel dirt with shovel)
(shovel shovel dirt)
(shovel dirt)
(shovle drit showvl)
(scoop filth with the friggin blade)
mkb.
From: David Golden
Subject: Re: "Pattern arguments" in Common Lisp (Re: Ray tracer in Stalin)
Date:
Message-ID: <BYtNe.4155$R5.879@news.indigo.ie>
Matthias Buelow wrote:
>>Here, english is being a bit Lisp-2-ish.
>
> I don't think comparing natural languages with programming languages
> will work for an argument; you'll probably always lose such an
> argument.
I wouldn't expect to win many arguments solely on a loose analogy to
natural language. On the other hand, I wasn't trying to win any
argument there in the first place?! I was just trying to demonstrate
that in English as in Lisp, the same symbol can stand for different
things in different contexts, because the OP seemed to be stuck on it.
After all, I did say "a bit" - I meant in a vague sense of the same
symbol standing for more than one thing, not anything beyond that.
Anyway, in lisp, to know confidently what "(shovel dirt shovel)" meant,
you'd need to know about a
"(defun shovel (stuff-to-be-shovelled implement-to-shovel-with) ...)"
because ordinary arguments (arguments in the sense I don't _think_ you
meant ?!) are positional - one could imagine another programmer
reversing the argument order in his defun, and thus (other:shovel
shovel dirt) would be what you wanted if using their #'other:shovel, or
you could write a glue macro to juggle the arguments around if you
really couldn't stand the argument order the other programmer picked.
From: Ulrich Hobelmann
Subject: Re: "Pattern arguments" in Common Lisp (Re: Ray tracer in Stalin)
Date:
Message-ID: <3mmoatF171pl9U1@individual.net>
Jon Harrop wrote:
> Marco Antoniotti wrote:
>> FUNCALL calls a function stored in a variable because CL is a Lisp-2
>> (unlike Scheme, Dylan, ML, and OCaml, which are essentially all Lisp-1).
>
> Ok. But what else could the compiler do? That looks like an unambiguous
> function application to me.
At first I hated Lisp-2 too, but after a while it seems to be natural ;)
(list foo bar) creates a list containing foo and bar.
(+ (first list) 4) adds 4 to the first element of "list."
So basically you can use the same name for variables and functions. You
could call a pair "cons" etc.
While this might seem unnecessary, in Common Lisp most things have their
own namespaces (classes; types I think; probably other things too).
>> Apart from that, the system I built (which is built in Common Lisp and
>> it runs under any self-respecting CL implementation - here you should
>> get the hint why Lispers stick to Lisp)
>
> Extensibility? So Lisp should be good for compiler and interpreter writing?
Well, ML is good for compiler writing too, IMHO. Lisp makes it easy to
represent arbitrary structured data as sexps (kindof like XML), so you
don't have to decide on the whole AST type from the beginning.
So compilation, but also symbolic processing in general works nicely.
--
I believe in Karma. That means I can do bad things to people
all day long and I assume they deserve it.
Dogbert
Ulrich Hobelmann wrote:
> Jon Harrop wrote:
>> Marco Antoniotti wrote:
>>> FUNCALL calls a function stored in a variable because CL is a Lisp-2
>>> (unlike Scheme, Dylan, ML, and OCaml, which are essentially all Lisp-1).
>>
>> Ok. But what else could the compiler do? That looks like an unambiguous
>> function application to me.
>
> At first I hated Lisp-2 too, but after a while it seems to be natural ;)
>
> (list foo bar) creates a list containing foo and bar.
>
> (+ (first list) 4) adds 4 to the first element of "list."
>
> So basically you can use the same name for variables and functions. You
> could call a pair "cons" etc.
This is interesting. But I don't understand how Lisp-2 improves over Lisp-1.
In ML you have:
[foo; bar]
List.hd list + 4
Hang on, you mean the first use of "list" is different from the second
because the first is a type constructor and the second is a variable? So
the OCaml equivalent is probably:
List (foo, bar)
List.hd list + 4
and the difference is implied by capitalisation.
> While this might seem unnecessary, in Common Lisp most things have their
> own namespaces (classes; types I think; probably other things too).
>
>> Extensibility? So Lisp should be good for compiler and interpreter
>> writing?
>
> Well, ML is good for compiler writing too, IMHO. Lisp makes it easy to
> represent arbitrary structured data as sexps (kindof like XML), so you
> don't have to decide on the whole AST type from the beginning.
There is probably a much bigger activation barrier for interpreter and
compiler writing in ML than in Lisp. In ML, you have to reimplement
everything yourself. Also, there aren't many decent examples out there. In
Lisp, you can knock up little ideas as you think them up. That would be
really useful.
> So compilation, but also symbolic processing in general works nicely.
Ok.
--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com
From: Ulrich Hobelmann
Subject: Re: "Pattern arguments" in Common Lisp (Re: Ray tracer in Stalin)
Date:
Message-ID: <3mmtj9F17lk1pU1@individual.net>
Jon Harrop wrote:
> This is interesting. But I don't understand how Lisp-2 improves over Lisp-1.
> In ML you have:
>
> [foo; bar]
> List.hd list + 4
>
> Hang on, you mean the first use of "list" is different from the second
> because the first is a type constructor and the second is a variable? So
> the OCaml equivalent is probably:
>
> List (foo, bar)
> List.hd list + 4
>
> and the difference is implied by capitalisation.
Well, actually the List module is like a Lisp package, so you could
write list:hd in Lisp. I think package names also have their own namespace.
Lisp-2 IMHO isn't a big improvement, but it's ok that functions have
their own namespace, because almost everything else does too.
> There is probably a much bigger activation barrier for interpreter and
> compiler writing in ML than in Lisp. In ML, you have to reimplement
> everything yourself. Also, there aren't many decent examples out there. In
> Lisp, you can knock up little ideas as you think them up. That would be
> really useful.
Well, in ML you write the parser, and the AST as a datatype definition.
The rest is pattern-matching, so Lisp doesn't buy you too much there.
Of course, Lisp's other advantages (macros, OO) could help you.
[One of the better compiler books out there IMHO is "Modern compiler
implementation in ML" by Andrew Appel (one of the people behind SML/NJ).
It's instructive to compare that book to the Java version. Talk about
workarounds. :D
]
--
I believe in Karma. That means I can do bad things to people
all day long and I assume they deserve it.
Dogbert
From: Pascal Costanza
Subject: Re: "Pattern arguments" in Common Lisp (Re: Ray tracer in Stalin)
Date:
Message-ID: <3mpd2nF17rsp3U1@individual.net>
Jon Harrop wrote:
> This is interesting. But I don't understand how Lisp-2 improves over Lisp-1.
I think Lisp-2 is better than Lisp-1, but I don't think it's important
enough for someone new to Lisp. It will become clear while working with
Lisp as soon as the difference becomes really important. There are other
issues that are more important in the beginning.
Pascal
--
OOPSLA'05 tutorial on generic functions & the CLOS Metaobject Protocol
++++ see http://p-cos.net/oopsla05-tutorial.html for more details ++++
Jon Harrop <······@jdh30.plus.com> writes:
> What does "funcall" do?
It is a namespace escape. Unlike Scheme, Common Lisp has separate
function and variable namespaces. The first element of a form is
resolved in the function namespace (there's an unimportant exception),
other identifiers are resolved in the variable namespace.
If you find that you want to use the non-default namespace you
need an escape mechanism. The FUNCTION keyword resolves identifiers
in the function namespace. FUNCALL is a bit of a hack: it invokes
its first argument on all the rest of the arguments. Since all
arguments are resolved in the variable namespace, this has the effect
of a namespace operator.
On Fri, 19 Aug 2005 13:50:42 -0400, <···@ccs.neu.edu> wrote:
>
> Jon Harrop <······@jdh30.plus.com> writes:
>
>> What does "funcall" do?
>
> It is a namespace escape....
>
> If you find that you want to use the non-default namespace you
> need an escape mechanism....
Thank you. Between your explanation and the last Hyperspec example, I
see how neat FUNCALL is. Being able to have your cake and eat it too
is tough to beat. The other references I consulted had FUNCALL
explanations similar to Grahams ACL, which is not as good as yours.
--
Program A uses CLOS, Program B is implemented with structs, leading
to a fourfold increase in execution speed. --J. B. Heimatseiten
GP lisper wrote:
> On Fri, 19 Aug 2005 13:50:42 -0400, <···@ccs.neu.edu> wrote:
> >
> > Jon Harrop <······@jdh30.plus.com> writes:
> >
> >> What does "funcall" do?
> >
> > It is a namespace escape....
> >
> > If you find that you want to use the non-default namespace you
> > need an escape mechanism....
>
> Thank you. Between your explanation and the last Hyperspec example, I
> see how neat FUNCALL is. Being able to have your cake and eat it too
> is tough to beat. The other references I consulted had FUNCALL
> explanations similar to Grahams ACL, which is not as good as yours.
It's also worth mentioning that the prescence of function/funcall means
that you can use variable names that have the same names as functions.
In scheme for example you can't call a list "list" because it's the
name of a function.
It does mean a functions aren't really first class, but I don't think
that matters much.
·········@gmail.com wrote:
> Rob Thorpe wrote:
>
> > In scheme for example you can't call a list "list" because it's the
> > name of a function.
>
> Incorrect
I thought if you gave a variable the name "list" then the identifier is
rebound, so it's no longer bound to the function called list (Hence
"Germanic" naming). Is this not the case in Scheme?
"Rob Thorpe" <·············@antenova.com> writes:
> ·········@gmail.com wrote:
>> Rob Thorpe wrote:
>>
>> > In scheme for example you can't call a list "list" because it's the
>> > name of a function.
>>
>> Incorrect
>
> I thought if you gave a variable the name "list" then the identifier is
> rebound, so it's no longer bound to the function called list (Hence
> "Germanic" naming). Is this not the case in Scheme?
It is the case in Scheme, but this doesn't prevent you to name a
variable "list":
[1]> (load"loaders:pseudo")
[2]> (scheme)
This is Pseudoscheme 2.12.
scheme[3]> (let ((scheme-list list)
(list (list 1 2 3))) ; note the lexical scopes!
(scheme-list list list))
((1 2 3) (1 2 3))
And since scheme doesn't treat : specially:
scheme[4]> (symbol->string 'scheme:list)
"SCHEME:LIST"
scheme[5]> (let ((scheme:list list) (list (list 1 2))) (scheme:list list list))
((1 2) (1 2))
--
__Pascal Bourguignon__ http://www.informatimago.com/
Grace personified,
I leap into the window.
I meant to do that.
Rob Thorpe wrote:
> It does mean a functions aren't really first class, but I don't think
> that matters much.
Really? It gives me the eebes. :-)
I especially don't understand why it wouldn't search the function stack for
a variable that is being applied - it must be a function?!
--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com
Jon Harrop wrote:
> Rob Thorpe wrote:
> > It does mean a functions aren't really first class, but I don't think
> > that matters much.
>
> Really? It gives me the eebes. :-)
It's not that nasty, they about 1.5th class. It only really affects
the way a function is accessed slightly, you have to do #'something or
(function something) to refer to the function namespace.
It makes sense in a language with latent/dynamic types, very little
syntax and a huge number of functions. Imagine, you're writing a
program, you want to do something and you look up the function to do
it, and find it's called, say "string=". You then go "oh %$£#", I've
used that name as a variable in 15 different places in the code. That
means wherever you've used it you've unbound the meaning of string= as
a function.
Huge amounts of discussion have gone into this issue, see:
http://www.nhplace.com/kent/Papers/Technical-Issues.html
for example.
If I were writing a new form of lisp I'd probably try to find a better
solution, but having too namespaces isn't really a problem.
> I especially don't understand why it wouldn't search the function stack for
> a variable that is being applied - it must be a function?!
That would be fine for the interpreter - I don't know about the
compiler though. Lisp implementations have to think of ways to do
variable and function accesses that the compiler and the interpreter
can deal with efficiently. And, both have to be able to deal with it
in the same running lisp.
Jon Harrop <······@jdh30.plus.com> writes:
> Rob Thorpe wrote:
>> It does mean a functions aren't really first class, but I don't think
>> that matters much.
>
> Really? It gives me the eebes. :-)
They are first-class, you just have to use a namespace qualifier when
you want to use the function name to refer to them.
> I especially don't understand why it wouldn't search the function stack for
> a variable that is being applied - it must be a function?!
It would lead to bizarre behavior. Suppose I defined foo like this:
(defun foo (bar)
(bar 22))
This won't work correctly because BAR is bound in the variable
namespace, but the form (BAR 22) looks in the function namespace.
But suppose we modified lisp so that it figures `Hey, BAR isn't bound
in the function namespace, but there is this variable binding here
that names a function, he must've meant that.' Now
(foo (lambda (x) (+ x 3)))
=> 25
Great!
But.....
We load a file and suddenly:
(foo (lambda (x) (+ x 3)))
=> #p"/home/~jrm/"
WTF? The file we loaded defined BAR as
(defun bar (x)
(declare (ignore x))
(user-homedir-pathname))
In Common Lisp (without our bizarre extension), you can tell that
identifier BAR names the variable in this expression:
(defun foo (bar)
(funcall bar 22))
and names a global function (if it is defined) in this one:
(defun foo (bar)
(bar 22))
but in the bizarre one, where BAR's binding is resolved to can't be
determined by inspection.
"Rob Thorpe" <·············@antenova.com> writes:
> GP lisper wrote:
>> On Fri, 19 Aug 2005 13:50:42 -0400, <···@ccs.neu.edu> wrote:
>> >
>> > Jon Harrop <······@jdh30.plus.com> writes:
>> >
>> >> What does "funcall" do?
>> >
>> > It is a namespace escape....
>> >
>> > If you find that you want to use the non-default namespace you
>> > need an escape mechanism....
>>
>> Thank you. Between your explanation and the last Hyperspec
>> example, I see how neat FUNCALL is. Being able to have your cake
>> and eat it too is tough to beat. The other references I consulted
>> had FUNCALL explanations similar to Grahams ACL, which is not as
>> good as yours.
>
> It's also worth mentioning that the prescence of function/funcall
> means that you can use variable names that have the same names as
> functions. In scheme for example you can't call a list "list"
> because it's the name of a function.
>
> It does mean a functions aren't really first class, but I don't
> think that matters much.
Uh, you are using some personal definition of "first class" here,
right?
-Peter
--
Peter Seibel * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp * http://www.gigamonkeys.com/book/
Peter Seibel wrote:
> "Rob Thorpe" <·············@antenova.com> writes:
>
> > GP lisper wrote:
> >> On Fri, 19 Aug 2005 13:50:42 -0400, <···@ccs.neu.edu> wrote:
> >> >
> >> > Jon Harrop <······@jdh30.plus.com> writes:
> >> >
> >> >> What does "funcall" do?
> >> >
> >> > It is a namespace escape....
> >> >
> >> > If you find that you want to use the non-default namespace you
> >> > need an escape mechanism....
> >>
> >> Thank you. Between your explanation and the last Hyperspec
> >> example, I see how neat FUNCALL is. Being able to have your cake
> >> and eat it too is tough to beat. The other references I consulted
> >> had FUNCALL explanations similar to Grahams ACL, which is not as
> >> good as yours.
> >
> > It's also worth mentioning that the prescence of function/funcall
> > means that you can use variable names that have the same names as
> > functions. In scheme for example you can't call a list "list"
> > because it's the name of a function.
> >
> > It does mean a functions aren't really first class, but I don't
> > think that matters much.
>
> Uh, you are using some personal definition of "first class" here,
> right?
Unfortunately, a lot of people consider something to be a first class
object only if it behaves in every way like the other first class
objects. This is not the case in CL where they live in the same name
space and must be accessed by "function".
I don't think it's really useful to make the distinction this way
though.
Rob Thorpe wrote:
> Peter Seibel wrote:
>
>>"Rob Thorpe" <·············@antenova.com> writes:
>>
>>>It does mean a functions aren't really first class, but I don't
>>>think that matters much.
>>
>>Uh, you are using some personal definition of "first class" here,
>>right?
>
> Unfortunately, a lot of people consider something to be a first class
> object only if it behaves in every way like the other first class
> objects. This is not the case in CL where they live in the same name
> space and must be accessed by "function".
>
> I don't think it's really useful to make the distinction this way
> though.
It's just wrong. See http://en.wikipedia.org/wiki/First-class_object
Functions in Common Lisp fulfil _all_ of the possible meanings listed at
that page.
Pascal
--
OOPSLA'05 tutorial on generic functions & the CLOS Metaobject Protocol
++++ see http://p-cos.net/oopsla05-tutorial.html for more details ++++
Pascal Costanza wrote:
> Rob Thorpe wrote:
>
> > Peter Seibel wrote:
> >
> >>"Rob Thorpe" <·············@antenova.com> writes:
> >>
> >>>It does mean a functions aren't really first class, but I don't
> >>>think that matters much.
> >>
> >>Uh, you are using some personal definition of "first class" here,
> >>right?
> >
> > Unfortunately, a lot of people consider something to be a first class
> > object only if it behaves in every way like the other first class
> > objects. This is not the case in CL where they live in the same name
> > space and must be accessed by "function".
> >
> > I don't think it's really useful to make the distinction this way
> > though.
>
> It's just wrong. See http://en.wikipedia.org/wiki/First-class_object
>
> Functions in Common Lisp fulfil _all_ of the possible meanings listed at
> that page.
The problem is this one:
"being passable as a parameter to a procedure/function"
If functions are defined the normal way they cannot be directly passed,
though they can be passed through "(function fun)". Of-course if one
puts a function in the variable namespace then they can be passed the
normal way - but I don't think that really counts.
This is why some people would say that functions are not first class in
CL. I don't think that this is a particularly helpful definition, I
was using it only because it's how I've seen other people refer to what
a first-order function is.
None of this is really very important to programming it though.
On 23 Aug 2005 05:13:39 -0700, "Rob Thorpe" <·············@antenova.com> wrote:
> The problem is this one:
> "being passable as a parameter to a procedure/function"
>
> If functions are defined the normal way they cannot be directly
> passed, though they can be passed through "(function fun)".
> Of-course if one puts a function in the variable namespace then they
> can be passed the normal way - but I don't think that really counts.
>
> This is why some people would say that functions are not first class
> in CL. I don't think that this is a particularly helpful
> definition, I was using it only because it's how I've seen other
> people refer to what a first-order function is.
Functions can of course be passed as parameters to other functions
like any other Lisp object. You are confusing functional objects and
their names.
Cheers,
Edi.
--
Lisp is not dead, it just smells funny.
Real email: (replace (subseq ·········@agharta.de" 5) "edi")
Edi Weitz wrote:
> On 23 Aug 2005 05:13:39 -0700, "Rob Thorpe" <·············@antenova.com> wrote:
>
> > The problem is this one:
> > "being passable as a parameter to a procedure/function"
> >
> > If functions are defined the normal way they cannot be directly
> > passed, though they can be passed through "(function fun)".
> > Of-course if one puts a function in the variable namespace then they
> > can be passed the normal way - but I don't think that really counts.
> >
> > This is why some people would say that functions are not first class
> > in CL. I don't think that this is a particularly helpful
> > definition, I was using it only because it's how I've seen other
> > people refer to what a first-order function is.
>
> Functions can of course be passed as parameters to other functions
> like any other Lisp object. You are confusing functional objects and
> their names.
I understand the difference (and how it's generally implemented, and
why). A function can of course be passed as a parameter to a lisp
function, but that isn't really the point. Normally, a function is
defined with defun and therefore placed in the function namespace,
where it needs escaping with special forms to access the object.
Anyway, this is nitpicking, so I'm going to shut-up.
Rob Thorpe wrote:
> Pascal Costanza wrote:
>
>>>>"Rob Thorpe" <·············@antenova.com> writes:
>>>>
>>>>
>>>>>It does mean a functions aren't really first class, but I don't
>>>>>think that matters much.
[...]
>>It's just wrong. See http://en.wikipedia.org/wiki/First-class_object
>>
>>Functions in Common Lisp fulfil _all_ of the possible meanings listed at
>>that page.
>
> The problem is this one:
> "being passable as a parameter to a procedure/function"
>
> If functions are defined the normal way they cannot be directly passed,
> though they can be passed through "(function fun)". Of-course if one
> puts a function in the variable namespace then they can be passed the
> normal way - but I don't think that really counts.
Functions in Common Lisp can be passed to, and returned from, other
functions. Full stop. It doesn't matter how inconvenient this is, and
the inconvenience is even very low. What matters is that this sets a
language apart from other languages in which you cannot pass functions
to, and return from, other functions at all.
Pascal
--
OOPSLA'05 tutorial on generic functions & the CLOS Metaobject Protocol
++++ see http://p-cos.net/oopsla05-tutorial.html for more details ++++
Pascal Costanza <··@p-cos.net> wrote:
> Functions in Common Lisp can be passed to, and returned from, other
> functions. Full stop. It doesn't matter how inconvenient this is, and
> the inconvenience is even very low.
Given that it's in fact so elegant! Isn't it a bit wondrous that it's
Scheme that's a Lisp-1? I mean, I'd expect a ``mysophobian'' to
appreciate not having everything in one big sack but having things
ordered in several distinct baskets instead: it's so more hygienic!
-tcr
Pascal Costanza wrote:
> Rob Thorpe wrote:
>> Unfortunately, a lot of people consider something to be a first class
>> object only if it behaves in every way like the other first class
>> objects. This is not the case in CL where they live in the same name
>> space and must be accessed by "function".
>>
>> I don't think it's really useful to make the distinction this way
>> though.
>
> It's just wrong. See http://en.wikipedia.org/wiki/First-class_object
>
> Functions in Common Lisp fulfil _all_ of the possible meanings listed at
> that page.
Equality?
There is certainly some kind of an artificial distinction for function names
in Lisp that doesn't appear in other FPLs. It sounds as though this is due
to some of Lisp's dynamic features but I still haven't fully understood
why/how.
--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com
On Tue, 23 Aug 2005 12:11:48 +0100, Jon Harrop <······@jdh30.plus.com> wrote:
> Pascal Costanza wrote:
>
>> It's just wrong. See http://en.wikipedia.org/wiki/First-class_object
>>
>> Functions in Common Lisp fulfil _all_ of the possible meanings
>> listed at that page.
>
> Equality?
What do you mean? Functions in Common Lisp are of course "comparable
for equality with other entities."
* (let* ((foo (lambda (x) x))
(bar foo)
(baz 42))
(values (eql foo bar)
(eql foo baz)))
T
NIL
* (eql (lambda (x) x)
(lambda (x) x))
NIL
You might expect the second expression to return T but that's not
required by the definition in question.
Cheers,
Edi.
--
Lisp is not dead, it just smells funny.
Real email: (replace (subseq ·········@agharta.de" 5) "edi")
Edi Weitz wrote:
> What do you mean?
I wasn't sure if functions were comparable in CL.
> Functions in Common Lisp are of course "comparable
> for equality with other entities."
>
> * (let* ((foo (lambda (x) x))
> (bar foo)
> (baz 42))
> (values (eql foo bar)
> (eql foo baz)))
> T
> NIL
> * (eql (lambda (x) x)
> (lambda (x) x))
> NIL
>
> You might expect the second expression to return T but that's not
> required by the definition in question.
Ok. The situation is similar in OCaml, with physical and structural
equality. In Mathematica, there is only structural equality between ASTs.
So closures are first class objects in CL, as you would expect. The
confusion is that there are separate namespaces. Do variables with closure
values appear in the non-function namespace but their exact equivalents as
functions appear in the function namespace? So how you get a closure value
from a function/variable name in CL depends upon how that closure was
defined?
--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com
Jon Harrop wrote:
> So closures are first class objects in CL, as you would expect. The
> confusion is that there are separate namespaces. Do variables with closure
> values appear in the non-function namespace but their exact equivalents as
> functions appear in the function namespace? So how you get a closure value
> from a function/variable name in CL depends upon how that closure was
> defined?
(declaim (notinline foo))
(defun foo (x) (+ x x))
(let ((bar (lambda (x) (* x x))))
(print (foo 5))
(print (funcall bar 6))
(let ((temp (function foo)))
(setf (symbol-function 'foo) bar)
(setf bar temp))
(print (foo 5))
(print (funcall bar 6)))
10
36
25
12
FUNCALL takes a first-class function object and calls it. FUNCTION takes
a name and returns the function associated with it from the function
name space as a first-class function object. SYMBOL-FUNCTION takes a
symbol and returns the function associated with it from the function
name space as a first-class function object. The difference between
FUNCTION and SYMBOL-FUNCTION is that SYMBOL-FUNCTION only works on
global functions whereas FUNCTION also works on local functions. On the
other hand, the symbol passed to SYMBOL-FUNCTION can be a computed value
whereas the name of the function returned by FUNCTION must be statically
known.
In other words:
(foo ...) <=> (funcall (function foo) ...) for local and global foo
functions.
(foo ...) <=> (funcall (symbol-function 'foo) ...) for global foo functions.
As Joe already said, FUNCTION and FUNCALL are operators that shift
values between the function and the value name spaces. Whenever you
divide things up into different name spaces, you need such shifting
operators. That shouldn't be surprising.
Pascal
--
OOPSLA'05 tutorial on generic functions & the CLOS Metaobject Protocol
++++ see http://p-cos.net/oopsla05-tutorial.html for more details ++++
Edi Weitz wrote:
> On Tue, 23 Aug 2005 12:11:48 +0100, Jon Harrop <······@jdh30.plus.com> wrote:
>
>
>>Pascal Costanza wrote:
>>
>>
>>>It's just wrong. See http://en.wikipedia.org/wiki/First-class_object
>>>
>>>Functions in Common Lisp fulfil _all_ of the possible meanings
>>>listed at that page.
>>
>>Equality?
>
> What do you mean? Functions in Common Lisp are of course "comparable
> for equality with other entities."
There are also discussions in papers by Henry Baker, and Sussman and
Steele, how that could be useful. I don't recall the exact papers
though. (Probably "Equal rights for functional objects" and one or more
of the lambda papers.)
Pascal
--
OOPSLA'05 tutorial on generic functions & the CLOS Metaobject Protocol
++++ see http://p-cos.net/oopsla05-tutorial.html for more details ++++
Jon Harrop wrote:
> Pascal Costanza wrote:
>
>>Rob Thorpe wrote:
>>
>>>Unfortunately, a lot of people consider something to be a first class
>>>object only if it behaves in every way like the other first class
>>>objects. This is not the case in CL where they live in the same name
>>>space and must be accessed by "function".
>>>
>>>I don't think it's really useful to make the distinction this way
>>>though.
>>
>>It's just wrong. See http://en.wikipedia.org/wiki/First-class_object
>>
>>Functions in Common Lisp fulfil _all_ of the possible meanings listed at
>>that page.
>
>
> Equality?
Certainly. Whilst you can't compare two _mathematical_ functions for
equality, a Lisp function isn't quite a mathematical function: it's a
particular implementation of an algorithm for applying a mathematical
function.
(equal #'car #'car) --> T
(equal #'car #'cdr) --> NIL
However,
(equal #'car #'first) --> NIL
but that's okay because although CAR and FIRST are the same function in
a mathematical sense, they aren't the same function in a Lisp sense.
Jon Harrop <······@jdh30.plus.com> wrote:
>Marco Antoniotti wrote:
>> But the following looks very much like Common Lisp
>>
>> (use-package "UNIFY")
>>
>> (defun map2 (fun list-1 list-2)
>> (match-case (list list-1 list-2)
>> ((() ()) ())
>> (((?h1 . ?t1) (?h2 . ?t2))
>> (cons (funcall fun h1 h2) (map2 fun t1 t2)))
>> ((_ _) (error "Invalid list arguments to map2: ~S ~S." list-1
>> list-2)))
>>
>> Not only it looks like Common Lisp. It is written in Common Lisp and it
>> runs on every decent Common Lisp system.
>>
>> http://common-lisp.net/project/cl-unification
>
>Can I just check: that function is:
>
>let rec map2 f l1 l2 = match l1, l2 with
> | [], [] -> []
> | h1 :: t1, h2 :: t2 -> f h1 h2 :: map2 f t1 t2
> | _ -> invalid_arg "list arguments to map2"
In SML its:
fun map2 f [] [] = []
| map2 h1::t1, h2::t2 = f h1 h2 :: map2 f t1 t2
The "invalid arguments" case is caught by the compiler at compile
time, and the result is guaranteed to unify.
Looks clea[rn]est to me of the above, imho.
mkb.
Matthias Buelow wrote:
> Jon Harrop <······@jdh30.plus.com> wrote:
>
>>Marco Antoniotti wrote:
>>
>>>But the following looks very much like Common Lisp
>>>
>>>(use-package "UNIFY")
>>>
>>>(defun map2 (fun list-1 list-2)
>>> (match-case (list list-1 list-2)
>>> ((() ()) ())
>>> (((?h1 . ?t1) (?h2 . ?t2))
>>> (cons (funcall fun h1 h2) (map2 fun t1 t2)))
>>> ((_ _) (error "Invalid list arguments to map2: ~S ~S." list-1
>>>list-2)))
>>>
>>>Not only it looks like Common Lisp. It is written in Common Lisp and it
>>>runs on every decent Common Lisp system.
>>>
>>>http://common-lisp.net/project/cl-unification
>>
>>Can I just check: that function is:
>>
>>let rec map2 f l1 l2 = match l1, l2 with
>> | [], [] -> []
>> | h1 :: t1, h2 :: t2 -> f h1 h2 :: map2 f t1 t2
>> | _ -> invalid_arg "list arguments to map2"
>
>
>
> In SML its:
>
> fun map2 f [] [] = []
> | map2 h1::t1, h2::t2 = f h1 h2 :: map2 f t1 t2
>
>
> The "invalid arguments" case is caught by the compiler at compile
> time, and the result is guaranteed to unify.
Well, that is the point of static type checking, isn't it? I didnt'
claim CL (or the UNIFY package) has static type checking (although with
proper declarations some compilers will "flag" the violation at compile
time).
> Looks clea[rn]est to me of the above, imho.
I will definitively grant you that. However, given the UNIFY package
the following
(def fun map2 f () () = ()
or map2 f (?h1 . ?t1) (?h2 . ?t2)
= (cons (funcall f h1 h2) (map2 f t1 t2)))
is only one (DEFINER) macro away :)
Cheers
--
Marco
>
> mkb.
From: Matthias Buelow
Subject: Re: CL and ML patterns (Re: Ray tracer in Stalin)
Date:
Message-ID: <3mmp7pF17g6miU1@news.dfncis.de>
Marco Antoniotti <·······@cs.nyu.edu> wrote:
>(def fun map2 f () () = ()
> or map2 f (?h1 . ?t1) (?h2 . ?t2)
> = (cons (funcall f h1 h2) (map2 f t1 t2)))
>
>is only one (DEFINER) macro away :)
It's surely possible; from what I know, the first ML was implemented
on top of Lisp, although I don't know how much it looked like today's
dialects and I don't know how much that Lisp was like Common Lisp.
mkb.
Matthias Buelow wrote:
> In SML its:
>
> fun map2 f [] [] = []
> | map2 h1::t1, h2::t2 = f h1 h2 :: map2 f t1 t2
>
> The "invalid arguments" case is caught by the compiler at compile
> time, and the result is guaranteed to unify.
I don't understand. The invalid arguments case cannot be caught by the
compiler at compile time because it is necessarily a run-time error. The
compiler should spot that your pattern is incomplete.
If by "unify" you mean it will type check then yes, of course. You wouldn't
get far if it didn't. ;-)
> Looks clea[rn]est to me of the above, imho.
The SML is certainly the shortest. I'm guessing, but a little syntactic
sugar could probably make the Lisp a lot shorter.
--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com
Jon Harrop <······@jdh30.plus.com> wrote:
>I don't understand. The invalid arguments case cannot be caught by the
>compiler at compile time because it is necessarily a run-time error. The
>compiler should spot that your pattern is incomplete.
Hmm, well ok. Using case would make it look very much like the OCaml
version and one can use wildcards in the same way.
mkb
Matthias Buelow wrote:
> In SML its:
>
> fun map2 f [] [] = []
> | map2 h1::t1, h2::t2 = f h1 h2 :: map2 f t1 t2
>
>
> The "invalid arguments" case is caught by the compiler at compile
> time, and the result is guaranteed to unify.
One additional side note: I once happend to read that Bigloo its
pattern-matching facility is more general than OCaml its one.
Although, I am not sure what that means in reality.
That said, one shouldn't forget that neither OCaml (I think) nor Bigloo
features "list comprehension" (e.g. Clean does).
Schneewittchen
PS: OCaml and Bigloo had some common releations in the past, e.g:
http://groups.google.com/group/comp.lang.scheme/browse_frm/thread/23dad0e8a32a20c1/c10d3fd6751b1096?q=Bigloo+pattern+matching&rnum=14#c10d3fd6751b1096
F�rster vom Silberwald wrote:
> One additional side note: I once happend to read that Bigloo its
> pattern-matching facility is more general than OCaml its one.
> Although, I am not sure what that means in reality.
MLs limit themselves to patterns that can be matching in linear time. I'd be
surprised if Bigloo didn't do this too. Mathematica doesn't, which lets you
write complicated algorithms as a simple pattern match but then you've no
idea how long it'll take to run.
OCaml also omits some linear patterns (for no good reason, AFAICT) such as
[|a; b; ..; c|] to match "a" and "b" at the start of a >=3-element array
and "c" at the end.
> That said, one shouldn't forget that neither OCaml (I think) nor Bigloo
> features "list comprehension" (e.g. Clean does).
Yes. I think Haskell has them. I've never used a language with list
comprehensions but I can see why they'd be useful.
> Schneewittchen
> PS: OCaml and Bigloo had some common releations in the past, e.g:
>
http://groups.google.com/group/comp.lang.scheme/browse_frm/thread/23dad0e8a32a20c1/c10d3fd6751b1096?q=Bigloo+pattern+matching&rnum=14#c10d3fd6751b1096
The site linked to no longer exists but it would be an interesting project,
to learn Lisp/Scheme.
--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com
Jon Harrop wrote:
http://groups.google.com/group/comp.lang.scheme/browse_frm/thread/23dad0e8a32a20c1/c10d3fd6751b1096?q=Bigloo+pattern+matching&rnum=14#c10d3fd6751b1096
>
> The site linked to no longer exists but it would be an interesting project,
> to learn Lisp/Scheme.
I am not sure whether I understand you right. However, it seems google
cut the tail. If you read the thread (in comp.lang.lisp) of your ray
tracer in www.deja.com you will be able to follow the link.
The link is an old post of the developers of Bigloo where they
demonstrate how to call and intermix Bigloo modules with OCaml modules.
However, nowadays nobody calls OCaml from Bigloo anymore - I guess.
Schneewittchen
F�rster vom Silberwald wrote:
> Matthias Buelow wrote:
>
>
>>In SML its:
>>
>>fun map2 f [] [] = []
>> | map2 h1::t1, h2::t2 = f h1 h2 :: map2 f t1 t2
>>
>>
>>The "invalid arguments" case is caught by the compiler at compile
>>time, and the result is guaranteed to unify.
>
>
> One additional side note: I once happend to read that Bigloo its
> pattern-matching facility is more general than OCaml its one.
> Although, I am not sure what that means in reality.
>
> That said, one shouldn't forget that neither OCaml (I think) nor Bigloo
> features "list comprehension" (e.g. Clean does).
>
But "list comprehension" is trivial in Common Lisp. :) It can be built
by itself or on top of (shameless plug
http://common-lisp.net/project/cl-enumeration)
Cheers
--
Marco
Jon Harrop wrote:
> So "?" gives a variable in a pattern, "." is cons in a pattern. What
> does "funcall" do?
>
Just in case, as that "in a pattern" might indicate misunderstanding:
"(x . y)" is a cons ... period (groan). i.e. "(x . y)" is how a literal
cons is denoted in lisp - "cons" names a function that returns a fresh
cons of its arguments.
Jon Harrop wrote:
> Marco Antoniotti wrote:
>> But the following looks very much like Common Lisp
>>
>> (use-package "UNIFY")
>>
>> (defun map2 (fun list-1 list-2)
>> (match-case (list list-1 list-2)
>> ((() ()) ())
>> (((?h1 . ?t1) (?h2 . ?t2))
>> (cons (funcall fun h1 h2) (map2 fun t1 t2)))
>> ((_ _) (error "Invalid list arguments to map2: ~S ~S." list-1
>> list-2)))
>>
>> Not only it looks like Common Lisp. It is written in Common Lisp and it
>> runs on every decent Common Lisp system.
>>
>> http://common-lisp.net/project/cl-unification
>
> Can I just check: that function is:
>
> let rec map2 f l1 l2 = match l1, l2 with
> | [], [] -> []
> | h1 :: t1, h2 :: t2 -> f h1 h2 :: map2 f t1 t2
> | _ -> invalid_arg "list arguments to map2"
>
> So "?" gives a variable in a pattern, "." is cons in a pattern. What does
> "funcall" do?
Serious? It calls a function... ;)
I think your Caml does the right thing there.
--
I believe in Karma. That means I can do bad things to people
all day long and I assume they deserve it.
Dogbert
Ulrich Hobelmann wrote:
> Jon Harrop wrote:
>> Marco Antoniotti wrote:
>>> (use-package "UNIFY")
>>>
>>> (defun map2 (fun list-1 list-2)
>>> (match-case (list list-1 list-2)
>>> ((() ()) ())
>>> (((?h1 . ?t1) (?h2 . ?t2))
>>> (cons (funcall fun h1 h2) (map2 fun t1 t2)))
>>> ((_ _) (error "Invalid list arguments to map2: ~S ~S." list-1
>>> list-2)))
>>>
>>> Not only it looks like Common Lisp. It is written in Common Lisp and it
>>> runs on every decent Common Lisp system.
>>>
>>> http://common-lisp.net/project/cl-unification
>>
>> Can I just check: that function is:
>>
>> let rec map2 f l1 l2 = match l1, l2 with
>> | [], [] -> []
>> | h1 :: t1, h2 :: t2 -> f h1 h2 :: map2 f t1 t2
>> | _ -> invalid_arg "list arguments to map2"
>>
>> So "?" gives a variable in a pattern, "." is cons in a pattern. What does
>> "funcall" do?
>
> Serious? It calls a function... ;)
But so is "map2" and that doesn't require "funcall". What happens if you
miss out the "funcall"?
> I think your Caml does the right thing there.
Note that the OCaml can't print the lists easily in the case of an error.
The nearest you'll get is something like:
let string_of_list string_of l =
"["^String.concat "; " (List.map string_of l)^"]"
let rec map2 string_of f l1 l2 = match l1, l2 with
| [], [] -> []
| h1 :: t1, h2 :: t2 -> f h1 h2 :: map2 f t1 t2
| _ -> invalid_arg ("list arguments to map2 "^
string_of_list string_of l1^" "^
string_of_list string_of l2)
But that is the price you pay for optimising away run-time types and keeping
separate compilation.
--
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com
Jon Harrop wrote:
> Ulrich Hobelmann wrote:
>
>>>So "?" gives a variable in a pattern, "." is cons in a pattern. What does
>>>"funcall" do?
>>
>>Serious? It calls a function... ;)
>
>
> But so is "map2" and that doesn't require "funcall". What happens if you
> miss out the "funcall"?
Most likely you will get an UNDEFINED-FUNCTION error.
>
>>I think your Caml does the right thing there.
>
>
> Note that the OCaml can't print the lists easily in the case of an error.
Another reason to stick with Common Lisp :)
Cheers
--
Marco