syntactic sugar buzz

G

Gavin Kistner

unknown said:
I don't mean I think that there should be weird or confusing
exceptions to things -- and people certainly disagree as to what's
weird or confusing -- but only that I don't generally find symmetry or
consistency, as such, to be sufficient reasons for design decisions in
Ruby.

Ralph Waldo Emerson wrote:
"A foolish consistency is the hobgoblin of little minds, adored by
little statesman and philosophers and divines. With consistency a great
soul has simply nothing to do."

Consistency is very helpful in some situations. (If everything in system
XX worked in the same way, it would be very easy to figure out how a new
proposed feature should behave, and it would be very easy for a newcomer
to know exactly how it worked, since it wouldn't be a special case.)

But like an unyielding policeman who still writes you a ticket for
speeding when you're rushing to the hospital with your sick daughter, a
foolish consistency makes no allowance for special cases. It blindly
applies the set of rules with no consideration if there might be a good
argument for an exception.

This is what I think of when I hear Matz argue for certain
inconsistencies. Handcrafted features may show nicks and scratches from
inconsistent application. They may not have the pure, clean lines of
something that was honed by a machine. But those special cases carve out
bumps that (by and large) make sense for the common case.

A final example: blocks. It would be more notionally pure to allow an
arbitrary number of blocks to be passed to a method. It would be
consistent with other method arguments if the method validated that the
right number of blocks were passed. It would be consistent if the blocks
passed as parameters were objects assigned to variables that you had to
call methods on to get them to do something.

(And, of course, you can do this if you want.)

But what we have is the special handcrafted notation of one-block per
method, a special block that is optional, and that can be called simply
with the "yield" keyword. And I find it elegant, and appropriate for 95%
of the cases. I don't think I'd call it pure or consistent, but I'd be
angry if it were removed from the language.

And...a final comparison. I program in Lua for a living. It is a great
language because at its core it's very simple, very consistent. It's
very, very easy to learn, because there are so very few special cases.
It has very little syntactic sugar. (You can't even write a+=b, but must
write out a = a+b.) I loved learning Lua, in large part because of its
consistency. And I really don't like writing in it much, because it is
so rigid and simple-minded.
 
R

Robert Dober

Ralph Waldo Emerson wrote:
"A foolish consistency is the hobgoblin of little minds, adored by
little statesman and philosophers and divines. With consistency a great
soul has simply nothing to do."
Gavin I am astonished, by what reason do you throw good ol'Emerson at me?
Is there a single indication that I was talking about foolish consistencies=
?
BTW the sentence of RWE is quite ( I spare you the adjective ) would
be nice to see the context.
Consistency for me is much more to react logically, much in G=F6dels' sense=
,
Extreme examples:
Integer#to_f implies Array#to_f that would be a stupid consistency.
String#to_i implies Nil#to_i what do you think about this?

Object#to_s for an intelligent consistency
Consistency is very helpful in some situations. (If everything in system
XX worked in the same way,
that's not consistency that is conformism
it would be very easy to figure out how a new
proposed feature should behave, and it would be very easy for a newcomer
to know exactly how it worked, since it wouldn't be a special case.)
and hence there would be no power to achieve anything, of course.
But like an unyielding policeman who still writes you a ticket for
speeding when you're rushing to the hospital with your sick daughter, a
foolish consistency makes no allowance for special cases. It blindly
applies the set of rules with no consideration if there might be a good
argument for an exception.
Please read again, what is this all about?
This is what I think of when I hear Matz argue for certain
inconsistencies.
Than let us argue for certain inconsitencies
Handcrafted features may show nicks and scratches from
inconsistent application. They may not have the pure, clean lines of
something that was honed by a machine. But those special cases carve out
bumps that (by and large) make sense for the common case.

A final example: blocks. It would be more notionally pure to allow an
arbitrary number of blocks to be passed to a method. It would be
consistent with other method arguments if the method validated that the
right number of blocks were passed.
Honestly these are much too strong statements to be postulated like that.
It would be consistent if the blocks
passed as parameters were objects assigned to variables that you had to
call methods on to get them to do something.
Well they are, so what are you trying to say?
(And, of course, you can do this if you want.)

But what we have is the special handcrafted notation of one-block per
method, a special block that is optional, and that can be called simply
with the "yield" keyword. And I find it elegant, and appropriate for 95%
of the cases. I don't think I'd call it pure or consistent, but I'd be
angry if it were removed from the language.
Well I call it pure and consistent and you are talking about something
completely unrelated here.
And...a final comparison. I program in Lua for a living. It is a great
language because at its core it's very simple, very consistent. I was indeed intrigued by that
It's
very, very easy to learn, because there are so very few special cases.
It has very little syntactic sugar. (You can't even write a+=3Db, but mus= t
write out a =3D a+b.) I loved learning Lua, in large part because of its
consistency. And I really don't like writing in it much, because it is
so rigid and simple-minded.
Completely agree!

But to draw a conclusion, you have thrown all that at me because I said tha=
t
Integer(nil) -> 0 is inconsistent in itself and that it's usefulness
could be discussed and that I feel that Nil#split -->[] might be more
useful, and that I consider this kind of design choices inconsistent,
and I was hoping to have some explanations about that, and I get
"Ruby's cool" and good ol' Waldo.

It is somehow disappointing.

Robert


--=20
I always knew that one day Smalltalk would replace Java.
I just didn't know it would be called Ruby
-- Kent Beck
 
K

Ken Bloom

I'm a relative newbie. I'm finally getting the hang of some of the
syntactic sugar provided, such as the whole thing about using the "or"
operator to provide a default value if something is nil:

foo = bar || "emptiness"


One thing I keep running into over and over and over and over that I
wish there was some syntactic sugar for is the whole business of calling
a method on an object, and doing something intelligent if the object is
nil.

If I have a string of stuff like:
blah = foo.bar.split

what if bar is nil? There are obvious long hand ways to deal with this,
but then you loose the smoothness of lining up things like this in Ruby.

I guess what I want is some syntactic sugar that means "this object, or
an empty one of these if this is nil", so that I would get an empty
result instead of a nil object missing method error.

I would like to be able to write:
blah = foo.bar||empty(bar).split

This could be written:
blah = foo.bar||"".split

But that requires a well known object type for bar. What if it is: blah
= foo.bar.whatchamacallit()

where bar is some oddball object of your own imagining.

Have you veteran Rubyists come up with a nice way to write stuff like
this that keeps the nice clean flow of Ruby's chaining in place, but
solves the problems with potentially nil intermediate results?

thanks,
jp

I happen to program in both Groovy and Ruby, and while I prefer Ruby's
paradigms to Groovy's (they're actually geared to make quite different
things convenient), I noticed Groovy's ?. operator and asked myself "Why
doesn't Ruby have this?" The ?. operator in Groovy calls the method if
the expression on the left side is non-null, and returns its value. It
returns null of the object on the left side is null, and never calls the
method. It might be a nice feature to adopt.

Probably the best way to do this in Ruby is
"blah = foo.bar rescue nil", although this has the potential to soak up a
lot of other kinds of errors that you may actually want to propagate.

--Ken
 
R

Robert Dober

I happen to program in both Groovy and Ruby, and while I prefer Ruby's
paradigms to Groovy's (they're actually geared to make quite different
things convenient), I noticed Groovy's ?. operator and asked myself "Why
doesn't Ruby have this?" The ?. operator in Groovy calls the method if
the expression on the left side is non-null, and returns its value. It
returns null of the object on the left side is null, and never calls the
method. It might be a nice feature to adopt.

Probably the best way to do this in Ruby is
"blah = foo.bar rescue nil", although this has the potential to soak up a
lot of other kinds of errors that you may actually want to propagate.

Would be interesting discussing this. I shall have a look at some of
my code how that would change, looks ugly at first, but that normally
changes when getting the habit.
Robert
 
C

Chad Perrin

My favorite slogan for Ruby is:

The triumph of balance over symmetry.

It means, for example, that it might make sense for nil to have #to_s
-- and that it still might *not* make sense for nil to have #split.
One does not imply the other. Every decision is made carefully, one
at a time, in the interest of the usefulness of the system overall.

That makes perfect sense, since the logical way to use split would be
with something like nil.to_s.split. If you really want split to return
something "useful" from nil directly, I'd say add your own split to
NilClass and be done with it.

That's why I don't care about symmetry or consistency (which I think
in this case mean much the same thing). We're lucky enough to have
Matz hand-crafting the language with the greatest care; I think that's
a higher-percentage prospect than a principle of uniformity :)

I care about consistency -- in a way that makes sense, of course. I
don't see how nil lacking a split() violates that.
 
R

Robert Dober

That makes perfect sense, since the logical way to use split would be
with something like nil.to_s.split. If you really want split to return
something "useful" from nil directly, I'd say add your own split to
NilClass and be done with it.
It makes perfect sense, but it is an example ex nihilis as I was
complaining about nil.to_i and Integer(nil), or am I in the wrong
thread (has happened to me before :()?
I care about consistency -- in a way that makes sense, of course. I
don't see how nil lacking a split() violates that.
Nor do I, nor did I say so, I just wanted to say, hey if nil has to_i,
it can have split too, that would be no big deal at all.

Cheers
Robert
 
C

Chad Perrin

It makes perfect sense, but it is an example ex nihilis as I was
complaining about nil.to_i and Integer(nil), or am I in the wrong
thread (has happened to me before :()?

Nor do I, nor did I say so, I just wanted to say, hey if nil has to_i,
it can have split too, that would be no big deal at all.

Unless nil.split simply returned nil, like:
Class NilClass
def split
self
end
end
. . I don't see how NilClass.split could reasonably be incorporated as
a standard part of the language. The only other alternatives that
spring to mind would be to return false (as though split() were a
boolean test in this case) or to return an empty list. I don't think
either of those really works very well, since returning false doesn't
bring anything new to the table and an empty list would be turning
nothing (nil) into something (even if it's an empty something), which is
a severely broken approach in my opinion.

Unfortunately, returning nil is also a little troublesome, since split()
is expected to return a list, but nil is definitely not a list.

Maybe nil.split should just return an exception. Oh, wait . . .
 
R

Robert Dober

Unless nil.split simply returned nil, like:
Class NilClass
def split
self
end
end
. . . I don't see how NilClass.split could reasonably be incorporated as
a standard part of the language. The only other alternatives that
spring to mind would be to return false (as though split() were a
boolean test in this case) or to return an empty list. I don't think
either of those really works very well, since returning false doesn't
bring anything new to the table and an empty list would be turning
nothing (nil) into something (even if it's an empty something), which is
a severely broken approach in my opinion.

Unfortunately, returning nil is also a little troublesome, since split()
is expected to return a list, but nil is definitely not a list.

Maybe nil.split should just return an exception. Oh, wait . . .
do you mean NoMethodError ;) ?
Your thoughts are intriguing me, I am really surprised for me split
shall return an array, but wait, split might be intended from the
Chronograph module and it should return 0.

Hmmm, nil#split makes not much sense I agree, but what about
nil#to_i?
Actually that is Off-Topic, I have to admit :(.Robert
 
C

Chad Perrin

Hmmm, nil#split makes not much sense I agree, but what about
nil#to_i?
Actually that is Off-Topic, I have to admit :(.

I think to_i() fits in well enough. You're specifically returning a
different type in this case. While an array looks like a type, from a
certain perspective, it's actually a collection of "things" of some other
type(s) -- it's a data structure, not a datum. As such, I'm not sure the
same rules should apply.

The closest thing to a nil.split that makes sense to me is nil.to_a
which, by the way, already exists.
ri NilClass#to_a
---------------------------------------------------------- NilClass#to_a
nil.to_a => []
 
S

Sam Smoot

I'm a relative newbie. I'm finally getting the hang of some of the
syntactic sugar provided, such as the whole thing about using the "or"
operator to provide a default value if something is nil:

foo = bar || "emptiness"

One thing I keep running into over and over and over and over that I
wish there was some syntactic sugar for is the whole business of calling
a method on an object, and doing something intelligent if the object is
nil.

If I have a string of stuff like:
blah = foo.bar.split

what if bar is nil? There are obvious long hand ways to deal with this,
but then you loose the smoothness of lining up things like this in Ruby.

I guess what I want is some syntactic sugar that means "this object, or
an empty one of these if this is nil", so that I would get an empty
result instead of a nil object missing method error.

I would like to be able to write:
blah = foo.bar||empty(bar).split

This could be written:
blah = foo.bar||"".split

But that requires a well known object type for bar. What if it is:
blah = foo.bar.whatchamacallit()

where bar is some oddball object of your own imagining.

Have you veteran Rubyists come up with a nice way to write stuff like
this that keeps the nice clean flow of Ruby's chaining in place, but
solves the problems with potentially nil intermediate results?

thanks,
jp

It feels like it could be shortened, perhaps the :type is unnecessary,
but I was thinking of something like this for my DataMapper to ease
the pain of using object graphs in simple tabular reporting views...

class Object
def default(type)
self || type.new
end
end

class Person
attr_accessor :name
def initialize(name)
@name = name
end
end

people = [ Person.new('Bob'), nil ]

for person in people
puts "Hello " + person.default(Person).name
end


Which isn't _too_ ugly I think. On the other hand you could end up
with something like this:

puts @photo.default(Article).article.default(Category).category.name

Instead of:

puts @photo.article.category.name

But that's obviously more than a bit contrived. Any ideas would be
welcome though...
 
R

Robert Klemme

2007/7/19 said:
I'm a relative newbie. I'm finally getting the hang of some of the
syntactic sugar provided, such as the whole thing about using the "or"
operator to provide a default value if something is nil:

foo = bar || "emptiness"

One thing I keep running into over and over and over and over that I
wish there was some syntactic sugar for is the whole business of calling
a method on an object, and doing something intelligent if the object is
nil.

If I have a string of stuff like:
blah = foo.bar.split

what if bar is nil? There are obvious long hand ways to deal with this,
but then you loose the smoothness of lining up things like this in Ruby.

I guess what I want is some syntactic sugar that means "this object, or
an empty one of these if this is nil", so that I would get an empty
result instead of a nil object missing method error.

I would like to be able to write:
blah = foo.bar||empty(bar).split

This could be written:
blah = foo.bar||"".split

But that requires a well known object type for bar. What if it is:
blah = foo.bar.whatchamacallit()

where bar is some oddball object of your own imagining.

Have you veteran Rubyists come up with a nice way to write stuff like
this that keeps the nice clean flow of Ruby's chaining in place, but
solves the problems with potentially nil intermediate results?

thanks,
jp

It feels like it could be shortened, perhaps the :type is unnecessary,
but I was thinking of something like this for my DataMapper to ease
the pain of using object graphs in simple tabular reporting views...

class Object
def default(type)
self || type.new
end
end

class Person
attr_accessor :name
def initialize(name)
@name = name
end
end

people = [ Person.new('Bob'), nil ]

for person in people
puts "Hello " + person.default(Person).name
end

I think you can save more typing if you default the type parameter to
self.class. Then you have

puts "Hello " + person.default.name
Which isn't _too_ ugly I think. On the other hand you could end up
with something like this:

puts @photo.default(Article).article.default(Category).category.name

Instead of:

puts @photo.article.category.name

But that's obviously more than a bit contrived. Any ideas would be
welcome though...

Hm... One thing I do not like about this is that there has to be a
new object created for every "missing" instance. I'd do your sample
differently: either remove nils from the array beforehand or add a "
if person" at the end of the "puts" statement.

Kind regards

robert
 

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,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top