syntactic sugar buzz

J

Jeff Pritchard

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
 
T

Trans

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

blah = (foo.bar || "").split

Works just fine. Not sure what you mean by "well known object type".

T.
 
S

Seth Reno

Trans said:
Works just fine. Not sure what you mean by "well known object type".
I think he means you cant use this if the object on the right of ||
doesn't have the method defined.

So (foo.bar || "").split works but (foo.bar || "").blah() doesn't.
 
C

Chad Perrin

Please reserve the term "syntactic sugar" for cutesy systems that don't
provide for lean and incredibly expressive statements that scale very well!

I tend to use "syntactic sugar" to refer to a way to make something look
more succinct and pretty, but that isn't strictly necessary, e.g.:

a, b = b, a

. . is syntactic sugar for:

c = a; a = b; b = c

Whether it's "cutesy" or "scales well" is kind of immaterial, as far as
I'm concerned.
 
G

Gavin Kistner

Jeff said:
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?

Well, yes. What if bar is nil? Do you want blah to be nil? An empty
array?

I personally go with:
blah = foo.bar.split unless foo.bar.nil?

But really, I think the answer to your question (how do I do what I
want) is the answer to your question (what do I want to do under this
case). It seems that there is no good general answer for "perform the
rough equivalent of method XYZ on nil and give me a reasonable result".
 
S

SonOfLilit

If it were me, I'd simply rescue a method-not-existent error and
return an empty dataset.

What do you guys think? It can even be made a method that accepts a block...


Aur
 
D

dblack

Hi --

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?

I would tend not to view it as a candidate for chaining if I couldn't
be sure that the result of one operation would respond to the next
operation. That's more like a case for conditional flow, so I'd do
something like:

x = a.b
y = x.c if x


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
D

Daniel Lucraft

Sometimes I think the brackets spoil how the expression reads. You could
define a method that looks like this:

blah = foo.bar.or("").split

Trainwreck though...

Dan
 
J

Jeff Pritchard

Daniel said:
Sometimes I think the brackets spoil how the expression reads. You could
define a method that looks like this:

blah = foo.bar.or("").split

Trainwreck though...

Dan

Thanks everyone. This has at least convinced me that I wasn't missing
some well known way to do this.

My choice of split confused the issue. I should have used something
unknown like "fred".

I was looking for a solution which, like the || operator, works with all
object types, not just a string object, so that it could be used as a
general rather than a specific solution.

In other words, the (something || "") solution works for split, because
there is a convenient syntax for "empty string".

I was hoping for a more general (something ||
whateverneedstobeheretomakewhatfollowsworkright).fred

As another poster mentioned or hinted at, since "something" may not have
a type yet, there's no way to get the needed object type from that. I
was hoping for something that can't be done without mind reading
interpreters.

Ruby rocks, but it still lacks a generalized "you know what I mean"
operator. :)

jp
 
R

Robert Klemme

2007/7/18 said:
Thanks everyone. This has at least convinced me that I wasn't missing
some well known way to do this.

I believe another (obvious?) solution has not been mentioned so far:

# note, I used the empty array as replacement
# because split would return an array
blah = foo.bar.split rescue []

I find it pretty elegant, too.
I was looking for a solution which, like the || operator, works with all
object types, not just a string object, so that it could be used as a
general rather than a specific solution.

In other words, the (something || "") solution works for split, because
there is a convenient syntax for "empty string".

I was hoping for a more general (something ||
whateverneedstobeheretomakewhatfollowsworkright).fred

As another poster mentioned or hinted at, since "something" may not have
a type yet, there's no way to get the needed object type from that.

Well, you do not need the type. You just need the method signature.
I.e., in your case something like this would be sufficient:

o=Object.new
def o.fred() your_default_value end
I was hoping for something that can't be done without mind reading
interpreters.

"can" or "can't"?
Ruby rocks, but it still lacks a generalized "you know what I mean"
operator. :)

Hm...

Kind regards

robert
 
B

benjohn

*snip*
As another poster mentioned or hinted at, since "something" may not have
a type yet, there's no way to get the needed object type from that. I
was hoping for something that can't be done without mind reading
interpreters.
*snip*

I think it's a bit nastier than that. It's not just that you don't know
what type to use when the thing could be nil. You also possibly don't
know what value to use either.

[This seems related to the identity element in a group.]

For example, for a multiplication operation on integers, we might want 1
to replace nil. For an addition operation, we would probably prefer 0.
To illustrate:

I use .magic as the method that you can call on nil that "does the right
thing"

1 + 1.magic => 2
1 + nil.magic => 1
# nil.magic => 0

1 * 1.majic => 1
1 * nil.magic => 1
# nil.magic => 1

Which is kind of interesting? :)

Cheers,
Benjohn
 
M

Martin DeMello

Please reserve the term "syntactic sugar" for cutesy systems that don't
provide for lean and incredibly expressive statements that scale very well!

First derogatory references to "monkey-patching" and now this -
whatever happened to the spirit of ruby? I thought we *liked*
syntactic sugar (otherwise we'd all just go use lisp).

martin
 
P

Peter Hickman

Phlip said:
Please reserve the term "syntactic sugar" for cutesy systems that don't
provide for lean and incredibly expressive statements that scale very well!


I have a nagging suspicion that Matz himself has used this term. It is
certainly not a derogatory term when used within the Ruby community and
I have a feeling that it is not a derogatory term anywhere else either.
It is simply a description of a feature of a language. Many languages
have syntactic sugar, heck arrays in C are syntactic sugar. The line "a
+= 12" is syntactic sugar for "a = a + 12", Ruby has benefited greatly
from "syntactic sugar" (as have many other languages), just imaging the
outcry that there would be if it was all stripped from the language.
Image how much slower the language would have taken up if we had to
enter all our code in long form. There is enough kvetching from C/C++
and Java programmer about the lack of pre and post ++/-- operators to
show how important syntactic sugar is to people.

Let us not disrespect our heritage even if it is not very "Enterprisey".
 
R

Robert Dober

2007/7/18 said:
Thanks everyone. This has at least convinced me that I wasn't missing
some well known way to do this.

I believe another (obvious?) solution has not been mentioned so far: I believe Aur has ...

# note, I used the empty array as replacement
# because split would return an array
blah = foo.bar.split rescue []
... and I think it is nice.

I lost the fight with myself to propose this :)

class Nil
def split; [] end
def join(x); "" end
def each &blk; end
etc.etc
end

now there might be many reasons against this, and I believe that they
outweight the benefits, but look at this

irb(main):005:0> nil.to_i
=> 0
irb(main):006:0> ## and worse
irb(main):007:0* Integer(nil)
=> 0

so I am still suffering from Ruby's inconsistency (do not laugh Lionel).

<snip>
robert
 
D

dblack

Hi --

2007/7/18 said:
Daniel Lucraft wrote:
This could be written:
blah = (foo.bar||"").split

Sometimes I think the brackets spoil how the expression reads. You could
define a method that looks like this:

blah = foo.bar.or("").split

Trainwreck though...

Dan

Thanks everyone. This has at least convinced me that I wasn't missing
some well known way to do this.

I believe another (obvious?) solution has not been mentioned so far: I believe Aur has ...

# note, I used the empty array as replacement
# because split would return an array
blah = foo.bar.split rescue []
... and I think it is nice.

I lost the fight with myself to propose this :)

class Nil
def split; [] end
def join(x); "" end
def each &blk; end
etc.etc
end

now there might be many reasons against this, and I believe that they
outweight the benefits, but look at this

irb(main):005:0> nil.to_i
=> 0
irb(main):006:0> ## and worse
irb(main):007:0* Integer(nil)
=> 0

so I am still suffering from Ruby's inconsistency (do not laugh Lionel).

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'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 :)


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
J

James Edward Gray II

Sometimes I think the brackets spoil how the expression reads. You
could
define a method that looks like this:

blah = foo.bar.or("").split

Trainwreck though...

Then just use:

blah = foo.bar.to_s.split

It's the same thing in this case.

James Edward Gray II
 
R

Robert Dober

Hi --

2007/7/18, Jeff Pritchard <[email protected]>:
Daniel Lucraft wrote:
This could be written:
blah = (foo.bar||"").split

Sometimes I think the brackets spoil how the expression reads. You
could
define a method that looks like this:

blah = foo.bar.or("").split

Trainwreck though...

Dan

Thanks everyone. This has at least convinced me that I wasn't missing
some well known way to do this.

I believe another (obvious?) solution has not been mentioned so far: I believe Aur has ...

# note, I used the empty array as replacement
# because split would return an array
blah = foo.bar.split rescue []
... and I think it is nice.

I lost the fight with myself to propose this :)

class Nil
def split; [] end
def join(x); "" end
def each &blk; end
etc.etc
end

now there might be many reasons against this, and I believe that they
outweight the benefits, but look at this

irb(main):005:0> nil.to_i
=> 0
irb(main):006:0> ## and worse
irb(main):007:0* Integer(nil)
=> 0

so I am still suffering from Ruby's inconsistency (do not laugh Lionel).

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.
I do have problems with such err strict statements, and I have never
seen such from you before. I am however challenging the usefulness of
Integer(nil) =>0 and doubting the usefulness of nil.to_s => 0.
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 :)
No sorry I can only disagree.
Matz has tons of my respect but should that be any reason not to be
consistent or symmetric.

Asymmetrical behavior is not very POLS and once a user has learned
that Integer("david") will throw an exception she will expect the same
for Integer(nil).

nil.to_i => 0 is exactly the same as nil.split => []
expressing equivalancy of different forms of void.
I do not agree with this equivalency but I believe it should be
expressed consistently.

Hmm I feel it is too easy to say look "Ruby is just perfect thus you
shalt not criticize", well that's how I interpreted your reply.
David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
Cheers
Robert
 
D

dblack

Hi --

Hmm I feel it is too easy to say look "Ruby is just perfect thus you
shalt not criticize", well that's how I interpreted your reply.

Read it again :) It's not that Ruby's perfect; it's that the process
in place for improving Ruby is, in my view, more nuanced and careful
than if everything were made to be sort of homogenous and uniform.

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.

(Of course, it all depends on what level of abstraction you're dealing
with. I could say, for example: "Ruby is completely consistent, in
the sense that every feature has been carefully designed by Matz" :)
But I know that's not what you mean.)


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
R

Robert Dober

Hi --



Read it again :) It's not that Ruby's perfect; it's that the process
in place for improving Ruby is, in my view, more nuanced and careful
than if everything were made to be sort of homogenous and uniform.

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.

(Of course, it all depends on what level of abstraction you're dealing
with. I could say, for example: "Ruby is completely consistent, in
the sense that every feature has been carefully designed by Matz" :)
But I know that's not what you mean.)

Oh well that, actually you are completely right, but that was not at
all I was thinking about :(

I feel that there are some, let us say "rules" that really hurt and
that's what I wanted to discuss, but that will hijack the thread,
which was not my intention, because Nil#split would help OP, so I will
just move this out slowly...
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

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top