Lambda the Ultimate

inactiveTopic Whither Self
started 9/12/2003; 7:58:13 AM - last post 9/21/2003; 4:54:31 AM
Ehud Lamm - Whither Self  blueArrow
9/12/2003; 7:58:13 AM (reads: 21740, responses: 22)
Whither Self
And an Erlang language design discussion.

Shouldn't there be a Self in funs? ... writing

	Fac = fun(0) -> 1;	
		 (N) -> N*Self(N-1) end

I always make sure to follow the discussions Richard A. O'Keefe participates in.

Luke, I thought erlang was your beat...
Posted to functional by Ehud Lamm on 9/12/03; 8:03:26 AM

Patrick Logan - Re: Wither Self  blueArrow
9/12/2003; 9:42:55 AM (reads: 1345, responses: 0)
The subsequent message about mutual recursion proposes a new function syntax for Erlang...

	define
		Fac = fun/1
			0 -> 1;
			N -> N * Fac (N - 1)
		end
		some_constant = 2;
		Even = fun/1
			0 -> True;
			N -> odd (N - 1)
		end
		Odd = fun/1
			1 -> False;
			N -> Even (N - 1)
		end
	end

...which brings up the point about language design and "axioms"... mutual recursion per se should be "axiomatically" distinct in a language from function definition per se. Otherwise you get piecemeal growth of partially useful language features.

logarithm - Re: Wither Self  blueArrow
9/12/2003; 11:54:58 AM (reads: 1302, responses: 0)
i think it's a good idea for lambda functions to provide an implicit variable that is the lambda function itself. Self in this sense is that variable, though one might as well call it Y. maybe lambdas that recurse in functions like map(...) wouldn't look so hairy?

Luke Gorrie - Re: Wither Self  blueArrow
9/12/2003; 12:29:39 PM (reads: 1296, responses: 0)
My beat? I just hack Emacs. :-)

Mark Evans - Re: Wither Self  blueArrow
9/12/2003; 5:56:07 PM (reads: 1227, responses: 0)

Emacs: "It's a nice OS, but to compete with Linux or Windows, it needs a better text editor." - Alexander Duscheleit

Tim Sweeney - Re: Wither Self  blueArrow
9/14/2003; 12:01:25 AM (reads: 1078, responses: 0)
"Self" or "this" only work nicely in languages that don't support nesting in a fully general way. For example, in C++, "this" is unambiguous because there is at most one class lexically enclosing the current block of code. But in Java, you have to be very careful to modify occurances of "this" as you move code between inner classes and outer classes.

When defining functions that may include recursive lexically enclosed lambda expressions, the name you associate with a function ("Fac" in the author's example) provides an unambiguous way to refer to that function, while "self" would beg the question: which self? The nearest one lexically, or the outermost one? Obviously, a language could pick one convention or another, but then the meaning of "self" would change if you, i.e., move an expression in or out of a given lambda.

The same problem exists for classes and records when you support nesting them (for example, with inner class or virtual class semantics): It's no longer obvious which "this" you're referring to. In languages that support a "thistype" construct, the same problem exists there.

You could solve this by making "self" constructs indexed: instead of "self", you only have "self[0]", "self[1]", etc. But then you have reinvented de Bruijn indices and, though they work well for procedural manipulation of terms, they aren't very human-friendly.

If one's language supports nesting in a fully general way, I think it is worth considering eliminating any "this" or "self" as standalone constructs, and instead require that any such things be referred to by name.

In the case of functions, this is unambiguous (mod shadowing of variable names): "f" refers to the enclosing function f.

In the case of classes, it's trickier because, depending on your language, there may be up to three things that a name refers to: the current instance (like C++ "this"), the current instance's type (like some languages' "thistype"), and the literal type (like referring to class name directly in C++). Possible syntaxes for these are "c.this", "c.thistype", and "c".

Vesa Karvonen - Re: Wither Self  blueArrow
9/14/2003; 5:01:06 AM (reads: 1051, responses: 0)
If one's language supports nesting in a fully general way, I think it is worth considering eliminating any "this" or "self" as standalone constructs, and instead require that any such things be referred to by name.

While I agree that a language should always offer the option of explicitly naming every binding, I quite often prefer the use of pronouns, when the context is small enough that there isn't much chance to misinterpret things.

Frank Atanassow - Re: Wither Self  blueArrow
9/14/2003; 7:07:05 AM (reads: 1044, responses: 0)
Shouldn't there be a Self in funs?

The syntactic distance between this new syntax and just using Y (or a letrec) does not seem big enough to justify adding new syntax.

The subsequent message about mutual recursion proposes a new function syntax for Erlang

The syntactic distance between this new syntax and just using letrec (or whatever Erlang's equivalent is) does not seem big enough to justify adding new syntax. (Besides, what does that expression return? The value bound by the first name, in this case Fac?)

Well, I dunno much about Erlang; is the problem that Erlang doesn't support something like letrec in the first place?

[Oh, never mind; O'Keefe's post makes it clear that Erlang indeed lacks letrec.]

P.S. It should be "whither". :)

John Carter - Re: Wither Self  blueArrow
9/14/2003; 2:31:15 PM (reads: 1005, responses: 0)
Try Ruby...
class Integer
  def fac
    return 1 if self <= 1
    self * (self-1).fac
  end
end

10.fac 3628800

Luke Gorrie - Re: Wither Self  blueArrow
9/14/2003; 8:29:33 PM (reads: 969, responses: 1)
Scheme's named-let is cute. Do other languages have it too?

(define (with-factorial-of n f)
  (f (let fact ((m n))
       (if (zero? m) 1 (* m (fact (- m 1)))))))
can be used to print the factorial of 10 like this:
(with-factorial-of 10 print)

i.e. you define a local function that can call itself, and you include the initial values for its arguments. Control is passed straight to the function without you having to separately call it. This makes it convenient to write inline "loops".

The equivalent with letrec is more verbose:

(define (with-factorial-of n f)
  (f (letrec ((fact (lambda (m)
                      (if (zero? m) 1 (* m (fact (- m 1)))))))
       (fact n))))

Matt Hellige - Re: Wither Self  blueArrow
9/15/2003; 8:41:26 AM (reads: 847, responses: 0)
I agree that named-let is a nice construct, but I confess that I've never understood why it was chosen over a named lambda, which seems to be more general in every way. Further, named-let seems to needlessly confuse the pleasantly separate ideas of abstraction and local binding. Does anybody know the history of this construct, or whether there was/is any technical reason to prefer it to something like the following?

(lambda fact (n) (if (zero? n) 1 (* n (fact (- n 1)))))

Patrick Logan - Re: Whither Self  blueArrow
9/15/2003; 10:16:27 PM (reads: 766, responses: 0)
I confess that I've never understood why it was chosen over a named lambda

"Chosen" is a loose term in Scheme. "Named let" is optional syntax. I remember defining it before it was included in the spec, having lifted it from whatever implementation where I found it, for use in whatever implementation did not have it.

So if you want "named lambda" or "case lambda", or whatever you want, you have only to define the syntax, load, and go.

I have no recollection which implementation had "named let" first. I believe it was around a good many years before showing up in the spec.

Further, named-let seems to needlessly confuse the pleasantly separate ideas of abstraction and local binding.

The syntax is very useful and easy on the eyes, for what that is worth.

Luke Gorrie - Re: Whither Self  blueArrow
9/16/2003; 8:02:19 AM (reads: 743, responses: 2)
I suppose the reason named-lambda was not chosen in Scheme, even though it's more general than named-let, is that letrec is in turn more general than named-lambda :-).

The advantage of named-let is in very real human factors, as Patrick observed. Consider my example written in all three styles, assuming your named-lambda syntax (which would not work in scheme because "lambda-lists" can be symbols!):

;; named-let
(define (with-factorial-of n f)
  (f (let fact ((m n))
       (if (zero? m) 1 (* m (fact (- m 1)))))))
 
;; named-lambda
(define (with-factorial-of n f)
  (f ((lambda fact (m)
        (if (zero? m) 1 (* m (fact (- m 1)))))
      n)))
 
;; letrec
(define (with-factorial-of n f)
  (f (letrec ((fact (lambda (m)
                      (if (zero? m) 1 (* m (fact (- m 1)))))))
       (fact n))))

What I like about the first one is that it reads linearly. With the other two, you have to look ahead in the code to see what the initial value going into the loop is.

Darius Bacon once pointed out the importance of this to me ("otherwise, why use let instead of lambda?"). He had devised a single macro for more generally putting arguments lexically close to their bindings, but I don't remember what it was and didn't appreciate it at the time. If he's reading, perhaps he will post it with an explanation.

Frank Atanassow - Re: Whither Self  blueArrow
9/16/2003; 10:21:08 AM (reads: 746, responses: 1)
The advantage of named-let is in very real human factors, as Patrick observed.

(I know you're all getting tired of my harping on about this, but...)

Since you want to go there: it's also the disadvantage, because it means you now have three ways to write the same thing, all of which closely resemble each other, and any one of which can be used to define the other two.

I'm not saying I oppose redundant syntax, but most of these human factors arguments cut both ways; that's why I don't like them. To settle them, you really need to do some empirical measurements, and even then the premises are all too often open to criticism.

BTW, can an irresistible force displace an immovable object?

Ehud Lamm - Re: Whither Self  blueArrow
9/16/2003; 10:58:45 AM (reads: 772, responses: 0)
By immovable object you are referring to yourself, Frank? ()

Patrick Logan - Re: Whither Self  blueArrow
9/16/2003; 7:36:24 PM (reads: 704, responses: 0)
I'm not saying I oppose redundant syntax, but most of these human factors arguments cut both ways; that's why I don't like them. To settle them, you really need to do some empirical measurements, and even then the premises are all too often open to criticism.

And in the darkness bind them.

It's all lambdas underneath, that's what makes redundant syntax so great in Lisp. If you don't like it, change it.

Frank Atanassow - Re: Whither Self  blueArrow
9/17/2003; 3:41:26 AM (reads: 677, responses: 0)
By immovable object you are referring to yourself, Frank?

haha, that really made me laugh out loud! The truth is, I would rather be the irresistible force, but I often feel like a big stick-in-the-mud around here, spoiling everyone else's fun.

It's all lambdas underneath, that's what makes redundant syntax so great in Lisp. If you don't like it, change it.

Yes, you're right of course. If we're talking about Scheme. (I prefer not to use the L-word. :)

If we're talking about Erlang, though, or some language which doesn't support syntactic extension, then personally I would come down on the side of economy, and only support the usual letrec, because there's only so much syntax to go around.

But, whatever... the more I remark on this, the more hypocritical I feel. :) So I will stop now.

Patrick Logan - Re: Whither Self  blueArrow
9/17/2003; 11:17:47 PM (reads: 619, responses: 1)
I prefer not to use the L-word

We all have someone back in our family tree we might not want to parade around. But why be ashamed of Lisp?

Frank Atanassow - Re: Whither Self  blueArrow
9/18/2003; 7:57:09 AM (reads: 609, responses: 0)
We all have someone back in our family tree we might not want to parade around. But why be ashamed of Lisp?

Nevermind, I was just being a prig.

Let's just say I like Schemers more than Lispers.

Luke Gorrie - Re: Whither Self  blueArrow
9/20/2003; 1:36:53 AM (reads: 551, responses: 1)
Present company excepted I hope. :-)

Frank Atanassow - Re: Whither Self  blueArrow
9/20/2003; 7:01:12 AM (reads: 560, responses: 0)
Present company excepted I hope. :-)

For the sake of general amity, let's say yes---on the condition that present company promise not to invoke Philip Greenspun's tenth "law" or any of that other nonsense, in which case all bets are off and I'll ride their ass like a cowboy on a bronco. :)

Patrick Logan - Re: Whither Self  blueArrow
9/20/2003; 11:44:04 AM (reads: 526, responses: 1)
...in which case all bets are off and I'll ride their ass like a cowboy on a bronco. :)

I'm in line. I'm in line. Mum's the word.

Frank Atanassow - Re: Whither Self  blueArrow
9/21/2003; 4:54:31 AM (reads: 542, responses: 0)
haha. You're a good sport, Patrick.

Sorry if I went overboard there.