Paul Graham recommends Ruby

F

Florian Frank

David said:
On Mon, 21 Mar 2005, Florian Frank wrote:
I don't think making Ruby resemble other languages makes it
*self*-consistent, but rather more consistent with languages other
than itself.

Hey, this is the language of my dreams, it does only exist there. In
dreamland I am also smart enough, to make my own language, while in
reality I have to hope, that my dreams and Matz' are compatible. ;)

Moving from to {} for hashes and {} for blocks, to {} only for blocks
and something else for hashes surely does increase self-consistency.
This also would make parsing Ruby easier, consider for example this case:

def foo(h) :eek:k end

foo :hello # => :eek:k

but

foo {} # => ArgumentError: wrong number of arguments (0 for 1)

while

foo({}) # => :eek:k
I'm also not a big believer in meeting nubies'
expectations. Especially for Ruby 2.0... it's definitely past the
point of needing to "make <other language> programmers feel at home."
They will, if they like Ruby, and meanwhile it's important for Ruby
programmers to feel at home :)

I don't have any against it, but I fear it's also a trap to rely solely
one culture and heritage, while ignoring common sense and human
expectation. It's charming to have car and cdr in a language, if you're
interested in history, but it's also difficult to justify in any other
way than just saying, we always did it that way. For new users that
haven't their brains warped already, it's also difficult to understand,
that you have to use length($s) to get the length of a string in Perl,
while you have to use scalar @a to get the length of an array (or even
scalar keys %h for the size of a hash). I'd rather avoid Ruby going into
this direction, if it is possible.
 
D

David A. Black

Hi --

Hey, this is the language of my dreams, it does only exist there. In
dreamland I am also smart enough, to make my own language, while in reality I
have to hope, that my dreams and Matz' are compatible. ;)

Moving from to {} for hashes and {} for blocks, to {} only for blocks and
something else for hashes surely does increase self-consistency. This also
would make parsing Ruby easier, consider for example this case:

def foo(h) :eek:k end

foo :hello # => :eek:k

but

foo {} # => ArgumentError: wrong number of arguments (0 for 1)

while

foo({}) # => :eek:k

Are you saying you'd like to have foo {} be the same as foo({})
(assuming both are lambdas/blocks)? But then, what about:

def foo; end
foo {} # called with block, or wrong # of arguments?

As often happens, the solution:

foo() {}

involves more punctuation :)
I don't have any against it, but I fear it's also a trap to rely solely one
culture and heritage, while ignoring common sense and human expectation.

But Ruby isn't within miles of having that problem. My point is that
I don't like the idea of just putting things in Ruby because they are
the culture and heritage of *other* languages. Nor do I think that if
something is part of the culture and heritage of Ruby, it therefore
has to be removed :) (I know you weren't saying that.)
It's
charming to have car and cdr in a language, if you're interested in history,
but it's also difficult to justify in any other way than just saying, we
always did it that way. For new users that haven't their brains warped
already, it's also difficult to understand, that you have to use length($s)
to get the length of a string in Perl, while you have to use scalar @a to get
the length of an array (or even scalar keys %h for the size of a hash). I'd
rather avoid Ruby going into this direction, if it is possible.

My point exactly :)

When it comes to nubies, I think there's a big difference between (a)
things they might find slightly surprising (but that are actually
completely logical, once you "get" the language), and (b) things that
are going to attract them to the language. If you say to someone:
Ruby offers you the ability to write top-level scripts, like Perl, and
also has OO designed into it from the ground up -- that might get
their attention. If you say: As of version 2.0, you don't have to use
the lambda keyword because {} has been repurposed as a function
constructor -- I don't think that's going to make someone go, "Wow!
That sounds like the language for me!" :)


David
 
F

Florian Frank

David said:
Are you saying you'd like to have foo {} be the same as foo({})

Not necessarily, I only pointed out, that there is a problem, that could
be resolved with a different empty hash constructor, like

def foo(h) h.class end

foo [:] # => Hash

Or even Hash[] and Hash['a': 1, 'b': 2] for Hash.[]. It would also be
possible to have Tree['a': 1, 'b': 2] in this case. What is the impact
on the planned keyword syntax in this case?
(assuming both are lambdas/blocks)? But then, what about:

def foo; end
foo {} # called with block, or wrong # of arguments?

As often happens, the solution:

foo() {}

involves more punctuation :)

True, but the real source of the problem is, that Ruby handles block
parameters differently than other parameters. I don't think, that this
is really necessary, things could be made far easier here.

It's difficult to answer questions, like: Why don't I have to declare
block parameters like other parameters? But if I do, why do I have to
use this weird &-sigil? Why do I have to use it, if I want to pass the
block to another method, that expects a block? Why can I call every
method, that doesn't expect a block, with a block, that will be silently
ingored? Why can't I pass more than one block to a method?

The answers to those question would perhaps include, that the block
syntax wasn't intended be of such a general usefulness for functional
objects, closures and the like, but only as an iteration construct. For
2.0 it would be a good idea, to get rid of this bad legacy. It would
perhaps be a good idea to make {} the Proc constructor, abandon
non-objectified blocks (what about the performance trade off?) in favor of

def foo(block)
block[]
end
foo {}

or

def foo(b1, b2)
b1[]
b2[]
end
foo {}, {}

and perhaps define the following

def foo(b1, b2)
b1.call
yield # always the last block declared is executed
end
But Ruby isn't within miles of having that problem. My point is that
I don't like the idea of just putting things in Ruby because they are
the culture and heritage of *other* languages. Nor do I think that if
something is part of the culture and heritage of Ruby, it therefore
has to be removed :) (I know you weren't saying that.)
I suspect, things got screwed up step by step in Perl, too. This will
always be a problem, if people stop asking questions (like I did above),
why things are done in this and such a way, even if the answers cannot
really satisfy.
 
D

David A. Black

Hi --

True, but the real source of the problem is, that Ruby handles block
parameters differently than other parameters. I don't think, that this is
really necessary, things could be made far easier here.

I still don't have my head around the new block param syntax... but
isn't it going to be more different from methods than the current one?
It's difficult to answer questions, like: Why don't I have to declare block
parameters like other parameters? But if I do, why do I have to use this
weird &-sigil? Why do I have to use it, if I want to pass the block to
another method, that expects a block? Why can I call every method, that
doesn't expect a block, with a block, that will be silently ingored? Why
can't I pass more than one block to a method?

Some of these questions are harder than others :) To the last two, I
would say: every method call can take an optional code block, to which
transfer can be controlled with 'yield'. I guess I accept that as a
design characteristic.
The answers to those question would perhaps include, that the block syntax
wasn't intended be of such a general usefulness for functional objects,
closures and the like, but only as an iteration construct. For 2.0 it would
be a good idea, to get rid of this bad legacy. It would perhaps be a good
idea to make {} the Proc constructor, abandon non-objectified blocks (what
about the performance trade off?) in favor of

def foo(block)
block[]
end
foo {}

or

def foo(b1, b2)
b1[]
b2[]
end
foo {}, {}

and perhaps define the following

def foo(b1, b2)
b1.call
yield # always the last block declared is executed
end

That leaves me asking: if yield has this situation-dependent behavior,
why does it exist at all? I'm afraid to say it -- I don't want to
appear too non-questioning :) -- but I actually like the singularity
of the block/yield chain. If the block is done away with (not likely,
I suspect), then 'yield' makes no sense. If one were designing a
language where blocks were always objectified and always treated as
regular arguments, I don't think one would ever come up with the idea
of a special keyword to call the last one in a list.
I suspect, things got screwed up step by step in Perl, too. This will always
be a problem, if people stop asking questions (like I did above), why things
are done in this and such a way, even if the answers cannot really satisfy.

I don't think we're in any danger of people not questioning Ruby's
design enough :)


David
 
D

Daniel Berger

Daniel said:
I entirely prefer getting rid of the {} empty hash constructor
(leaving us only Hash.new) than the adding block syntax with empty
pipes {|| puts 'eek'}. If the {} hash constructor is the *only* thing
between us and making {} refer to blocks and blocks only, I think it's
worth the loss.

Alternatively, you could make [:] the empty hash constructor. Quite a
shortcut for an associative array, if I do say so myself :)

Dan

I vote we leave well enough alone. All this mess so we can avoid
typing the word "proc"?

As I think David Black mentioned in one of his posts, this doesn't feel
like a unification of the proc/lambda/Proc/block syntax. It feels more
like we're just shifting ownership of "{}" to another class.

Towards what end is this heading?

Regards,

Dan
 
G

gabriele renzi

David A. Black ha scritto:
But this notion of "a callable" collapses things which really aren't
the same.

If I can do this:

a = Object.new; def a.call(x); end
def b(x); end

a(10)
b(10)

but I can't do this:

c = [a,b]

because one of these is an object reference and the other is a method
identifier, then the parallel is only partial and, in my view, causes
more problems than it solves.

but we already have something similar, CapitalNamed methods:NameError: uninitialized constant B

and I think this shows the same point to me, meaning that once the
programmmer knows how it works it has quite an understandable behaviour.
Anyway, I understand your point of view, and I'd just expect matz' choice.
He already did the Right Choices enough to make me confident in future
ones :)
 
N

Navindra Umanee

Daniel Berger said:
Daniel said:
(leaving us only Hash.new) than the adding block syntax with empty
pipes {|| puts 'eek'}. If the {} hash constructor is the *only* thing
between us and making {} refer to blocks and blocks only, I think it's
worth the loss.

Alternatively, you could make [:] the empty hash constructor. Quite a
shortcut for an associative array, if I do say so myself :)

Dan

I vote we leave well enough alone. All this mess so we can avoid
typing the word "proc"?

What mess? Daniel's suggestion unifies the Array/Hash literal syntax
in a pleasant way and makes anonymous block creation a bit more
elegant overall.
As I think David Black mentioned in one of his posts, this doesn't feel
like a unification of the proc/lambda/Proc/block syntax. It feels more
like we're just shifting ownership of "{}" to another class.

I'm not sure if David said that. I think he also said he didn't like
{|| puts "eww"} instead of {puts "this r0x0rs!"}. Unifying the Array/Hash
syntax conveniently provides the latter. I think David also said to
consider how you might design things if you weren't limited by
constraints such as backwards compatibility. People did exactly that.

I'm sure David has other strong opinions that I might have missed though.

Cheers,
Navin.
 
S

Steven Shaw

Christian said:
There are arguments both for Lisp-1 and Lisp-2s. And while I prefer
Lisp-1s, object-oriented languages are "better off" if they are
Lisp-2s IMHO.

Could you expand on why OO languages are better off as Lisp 2?
 
S

Steven Shaw

David said:
Rather,
the question is: if Ruby had been designed from the ground up with a
literal function constructor, would it have been {|| } ?

Do you mean syntactically? Like instead of Smalltalk like [| ]? or
something else?
If so, then
fine. If not, then {|| } would be an add-on that is not properly
integrated into the language.

and here, more specifically, "not properly integrated into the language
syntax"?

Steve.
 
D

David A. Black

Hi --

David said:
Rather,
the question is: if Ruby had been designed from the ground up with a
literal function constructor, would it have been {|| } ?

Do you mean syntactically? Like instead of Smalltalk like [| ]? or something
else?

I mean if Matz had wanted such a constructor from the beginning, what
would he have chosen? So much of the discussion of this and other
changes to Ruby involve just trying to find combinations of
punctuation that aren't already taken....
and here, more specifically, "not properly integrated into the language
syntax"?

"Properly" meaning "in a non-afterthought way". I'm afraid I can't
express it any more technically than that. But think of all the
things in Perl and Python about which people say: that was slapped on
after the language was already designed. There is essentially none of
that in Ruby, which I think is a great situation and one that should
be conserved.


David
 
E

ES

In data 3/22/2005 said:
Hi --

David said:
Rather,
the question is: if Ruby had been designed from the ground up with a
literal function constructor, would it have been {|| } ?

Do you mean syntactically? Like instead of Smalltalk like [| ]? or something
else?

I mean if Matz had wanted such a constructor from the beginning, what
would he have chosen? So much of the discussion of this and other
changes to Ruby involve just trying to find combinations of
punctuation that aren't already taken....
and here, more specifically, "not properly integrated into the language
syntax"?

"Properly" meaning "in a non-afterthought way". I'm afraid I can't
express it any more technically than that. But think of all the
things in Perl and Python about which people say: that was slapped on
after the language was already designed. There is essentially none of
that in Ruby, which I think is a great situation and one that should
be conserved.

I absolutely agree with you on this and can see how this would be a
concern for this particular addition. To me the current HEAD version,
where {||} must be used for a no-argument proc definition, falls in
this category; while it's useful to be able to omit 'lambda' etc.,
this method of doing it feels distinctly tacked-on. I'm certainly
sympathetic to whoever is writing the parser, of course, and I wouldn't
mind the proposed [:]-syntax for Hashes.

I maintain that this all could be solved with an unification of all
callable code into a single first-order function definition :)

E
 
S

Steven Shaw

David said:
Hi --

David said:
Rather,
the question is: if Ruby had been designed from the ground up with a
literal function constructor, would it have been {|| } ?


Do you mean syntactically? Like instead of Smalltalk like [| ]? or
something else?


I mean if Matz had wanted such a constructor from the beginning, what
would he have chosen? So much of the discussion of this and other
changes to Ruby involve just trying to find combinations of
punctuation that aren't already taken....

It's clear that you are talking about syntax. That's all I wanted to
clear up. I'm not making any judgement - just clearing things up.
"Properly" meaning "in a non-afterthought way". I'm afraid I can't
express it any more technically than that. But think of all the
things in Perl and Python about which people say: that was slapped on
after the language was already designed. There is essentially none of
that in Ruby, which I think is a great situation and one that should
be conserved.

Yes, I understand where you are coming from.

Cheers,
Steve.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,074
Latest member
StanleyFra

Latest Threads

Top