[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

syntactic sugar buzz

Jeff Pritchard

7/18/2007 1:52:00 AM

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

--
Posted via http://www.ruby-....

32 Answers

Trans

7/18/2007 2:48:00 AM

0



On Jul 17, 6:52 pm, Jeff Pritchard <j...@jeffpritchard.com> wrote:
> 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.


Phlip

7/18/2007 3:37:00 AM

0

Jeff Pritchard wrote:

> 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"

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

> If I have a string of stuff like:
> blah = foo.bar.split
>
> what if bar is nil?

Large scale, look up something called the "Null Object Refactor". (And note
it's a refactor, not a pattern!)

Then implement it, small scale, like this:

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

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

Oooh, at a guess, we could go long-winded again:

blah = (foo.bar || OpenStruct.new(:split => '')).split

> But that requires a well known object type for bar.

Are you coming from Java? Look up "Duck Typing". The /de-facto/ type in our
statement flows right-to-left, not left-to-right like in Java. We need a
thing that can be split, so we get it from a mock object or from .bar. Right
to left.

There might be some way to reduce my OpenStruct experiment. I use that
trick, not small-scale, but large scale, for example with a website that can
entertain both logged-in users and un-logged-in guests. The former don't
deserve a real User model record, so they get an OpenStruct object that
provides the minimum User behavior.

Then I hide this OpenStruct. So you should next think about putting your ||
nil detector _inside_ that bar.

You can generally always get inside a method!

--
Phlip
http://www.oreilly.com/catalog/9780...
"Test Driven Ajax (on Rails)"
assert_xpath, assert_javascript, & assert_ajax


Seth Reno

7/18/2007 3:38:00 AM

0

Trans wrote:
>
> 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.

--
Posted via http://www.ruby-....

Phlip

7/18/2007 3:38:00 AM

0

Trans wrote:

>> 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".

What if split were another method, something that only real 'bar's can do?

--
Phlip
http://www.oreilly.com/catalog/9780...
"Test Driven Ajax (on Rails)"
assert_xpath, assert_javascript, & assert_ajax


Chad Perrin

7/18/2007 4:19:00 AM

0

On Wed, Jul 18, 2007 at 12:40:12PM +0900, Phlip wrote:
> Jeff Pritchard wrote:
>
> > 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"
>
> 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.

--
CCD CopyWrite Chad Perrin [ http://ccd.ap... ]
Amazon.com interview candidate: "When C++ is your hammer, everything starts
to look like your thumb."

Gavin Kistner

7/18/2007 5:22:00 AM

0

Jeff Pritchard wrote:
> 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".


--
Posted via http://www.ruby-....

SonOfLilit

7/18/2007 6:22:00 AM

0

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

dblack

7/18/2007 6:34:00 AM

0

Daniel Lucraft

7/18/2007 6:50:00 AM

0

> On Jul 17, 6:52 pm, Jeff Pritchard <j...@jeffpritchard.com> 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

--
Posted via http://www.ruby-....

Jeff Pritchard

7/18/2007 8:08:00 AM

0

Daniel Lucraft wrote:
>> On Jul 17, 6:52 pm, Jeff Pritchard <j...@jeffpritchard.com> 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.

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

--
Posted via http://www.ruby-....