[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

avoiding nil.methodcalls short and cheap

Thorsten Rossner

6/22/2007 9:54:00 AM

Hi,

I often have to check if a methodcall A is not returning nil before
calling another method on the return value of the methodcall A. I'm
looking for a short and cheap (avoiding to call method A two times like
in this example where xmltag.get_text is method A:
textvalue = xmltag.get_text.value if xmltag.get_text
)
The ideal solution would be a oneliner with only little complexity
calling method A just one time. Am I using the wrong approach here
anyway?

Thanks,
tr!

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

16 Answers

akbarhome

6/22/2007 10:00:00 AM

0

On Jun 22, 4:53 pm, Thorsten Rossner <ross...@gmx.de> wrote:
> Hi,
>
> I often have to check if a methodcall A is not returning nil before
> calling another method on the return value of the methodcall A. I'm
> looking for a short and cheap (avoiding to call method A two times like
> in this example where xmltag.get_text is method A:
> textvalue = xmltag.get_text.value if xmltag.get_text
> )
> The ideal solution would be a oneliner with only little complexity
> calling method A just one time. Am I using the wrong approach here
> anyway?
>
> Thanks,
> tr!
>
> --
> Posted viahttp://www.ruby-....
Consider this:

begin
textvalue = xmltag.get_text.value
rescue NoMethodError
end



Farrel Lifson

6/22/2007 10:04:00 AM

0

On 22/06/07, Thorsten Rossner <rossnet@gmx.de> wrote:
> textvalue = xmltag.get_text.value if xmltag.get_text

textvalue = (text = xmltag.get_text) && text.value

Farrel

Eivind Eklund

6/22/2007 10:24:00 AM

0

On 6/22/07, Thorsten Rossner <rossnet@gmx.de> wrote:
> Hi,
>
> I often have to check if a methodcall A is not returning nil before
> calling another method on the return value of the methodcall A. I'm
> looking for a short and cheap (avoiding to call method A two times like
> in this example where xmltag.get_text is method A:
> textvalue = xmltag.get_text.value if xmltag.get_text

Variations using just logic operators and conditionals - I think the
last two are probably best (though it vary by context)

# Short, unclear
textvalue = xmltag.get_text
textvalue &&= textvalue.value

# With if
textvalue = textvalue.value if textvalue = xmltag.get_text

# Longer, clearer
if textvalue = xmltag.get_text
textvalue = textvalue.value
end

# Re-using the variable, one-line
textvalue = xmltag.get_text and textvalue = textvalue.value

# With new variable, possibly the cleanest
textvalue = (text = xmltag.get_text and text.value)

# You can also redefine the object in question
def xmltag.get_text_value
text = get_text && text.value
end
textvalue = xmltag.get_text_value




> )
> The ideal solution would be a oneliner with only little complexity
> calling method A just one time. Am I using the wrong approach here
> anyway?
>
> Thanks,
> .tr!
>
> --
> Posted via http://www.ruby-....
>
>


--
Hazzle free packages for Ruby?
RPA is available from http://www.rubyar...

Michal Suchanek

6/22/2007 11:13:00 AM

0

On 22/06/07, Eivind Eklund <eeklund@gmail.com> wrote:
> On 6/22/07, Thorsten Rossner <rossnet@gmx.de> wrote:
> > Hi,
> >
> > I often have to check if a methodcall A is not returning nil before
> > calling another method on the return value of the methodcall A. I'm
> > looking for a short and cheap (avoiding to call method A two times like
> > in this example where xmltag.get_text is method A:
> > textvalue = xmltag.get_text.value if xmltag.get_text
>
> Variations using just logic operators and conditionals - I think the
> last two are probably best (though it vary by context)
>
> # Short, unclear
> textvalue = xmltag.get_text
> textvalue &&= textvalue.value
>
> # With if
> textvalue = textvalue.value if textvalue = xmltag.get_text
>
> # Longer, clearer
> if textvalue = xmltag.get_text
> textvalue = textvalue.value
> end
>
> # Re-using the variable, one-line
> textvalue = xmltag.get_text and textvalue = textvalue.value
>
> # With new variable, possibly the cleanest
> textvalue = (text = xmltag.get_text and text.value)
>
> # You can also redefine the object in question
> def xmltag.get_text_value
> text = get_text && text.value
> end
> textvalue = xmltag.get_text_value
>

I would avoid code that relies on logical operators to preserve values.
That is any code that uses logical operators and would break if you
put !!() around the expression is quite dodgy in my book.

Thanks

Michal

Eivind Eklund

6/22/2007 11:24:00 AM

0

On 6/22/07, Michal Suchanek <hramrach@centrum.cz> wrote:
> I would avoid code that relies on logical operators to preserve values.
> That is any code that uses logical operators and would break if you
> put !!() around the expression is quite dodgy in my book.

And I would strongly disagree with this.

Returning the value of the true expression is defined behavior, and it
allows for considerable simplification of code. Having simpler code
means that you have less chance of errors and spend less time when
reading the code.

To my mind, dodgy code is code that is difficult to understand or
increase chance of errors, ie, the opposite of code that does
appropriate use of the preservation of values in logical operators.

Not that I'm particularly happy with any of the cases above - the
closest to "good" I found was textvalue = (text = tag.get_text and
text.get_value)

Eivind.

Trans

6/22/2007 3:49:00 PM

0



On Jun 22, 5:53 am, Thorsten Rossner <ross...@gmx.de> wrote:
> Hi,
>
> I often have to check if a methodcall A is not returning nil before
> calling another method on the return value of the methodcall A. I'm
> looking for a short and cheap (avoiding to call method A two times like
> in this example where xmltag.get_text is method A:
> textvalue = xmltag.get_text.value if xmltag.get_text
> )
> The ideal solution would be a oneliner with only little complexity
> calling method A just one time. Am I using the wrong approach here
> anyway?

The conceptually simplest is:

get_text = xmltag.get_text
textvalue = get_text.value if get_text

But as you will note, it takes up two lines. Of course you can always
fix that:

get_text = xmltag.get_text; textvalue = get_text.value if get_text

Even so, I often write this as:

if get_text = xmltag.get_text
textvalue = get_text.value
end

Simply b/c I often find long one liners unpleasant to read.

However, I just want to point out that if there is no get_text, than
textvalue is not being assigned at all. Unless you have previously set
textvalue to a default, that could lead to an undefined local variable
error. So you might consider:

textvalue = (get_text = xmltag.get_text) ? get_text.value : nil

T.



Thorsten Rossner

6/22/2007 4:01:00 PM

0

Thanks for quick and helpful answers! I hope all of you will have a
great weekend!

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

Daniel Martin

6/23/2007 10:44:00 AM

0

Thorsten Rossner <rossnet@gmx.de> writes:

> The ideal solution would be a oneliner with only little complexity
> calling method A just one time. Am I using the wrong approach here
> anyway?

Since no one has pointed this out, I'll remind you that this *is*
Ruby, which has the relatively uncommon feature of allowing one to add
to core classes, so we can use that if there's only one or two methods
you'd like to call frequently. First note:

irb(main):001:0> nil.freeze
=> nil

Then, doing this somewhere:

class NilClass
alias value freeze
end

Lets us do this in the main code:

textvalue = xmltag.get_text.value

And nils automatically get propagated.

--
s=%q( Daniel Martin -- martin@snowplow.org
puts "s=%q(#{s})",s.to_a.last )
puts "s=%q(#{s})",s.to_a.last

Daniel DeLorme

6/23/2007 1:17:00 PM

0

Thorsten Rossner wrote:
> Hi,
>
> I often have to check if a methodcall A is not returning nil before
> calling another method on the return value of the methodcall A. I'm
> looking for a short and cheap (avoiding to call method A two times like
> in this example where xmltag.get_text is method A:
> textvalue = xmltag.get_text.value if xmltag.get_text
> )
> The ideal solution would be a oneliner with only little complexity
> calling method A just one time. Am I using the wrong approach here
> anyway?

This the solution I use in *my* code for this common problem:
textvalue = xmltag.get_text.ergo.value

This is my personal solution and I've never seen anyone use something
like this, so it may not be a "common and accepted idiom" but it works
well for me. YMMV

code for "ergo":

class NilClass
def ergo
@blackhole ||= Object.new.instance_eval do
class << self
for m in public_instance_methods
undef_method(m.to_sym) unless m =~ /^__.*__$/
end
end
def method_missing(*args); nil; end
self
end
@blackhole unless block_given?
end
end

class Object
def ergo
if block_given?
yield(self)
else
self
end
end
end



Trans

6/23/2007 2:10:00 PM

0



On Jun 23, 9:17 am, Daniel DeLorme <dan...@dan42.com> wrote:
> Thorsten Rossner wrote:
> > Hi,
>
> > I often have to check if a methodcall A is not returning nil before
> > calling another method on the return value of the methodcall A. I'm
> > looking for a short and cheap (avoiding to call method A two times like
> > in this example where xmltag.get_text is method A:
> > textvalue = xmltag.get_text.value if xmltag.get_text
> > )
> > The ideal solution would be a oneliner with only little complexity
> > calling method A just one time. Am I using the wrong approach here
> > anyway?
>
> This the solution I use in *my* code for this common problem:
> textvalue = xmltag.get_text.ergo.value
>
> This is my personal solution and I've never seen anyone use something
> like this, so it may not be a "common and accepted idiom" but it works
> well for me. YMMV
>
> code for "ergo":
>
> class NilClass
> def ergo
> @blackhole ||= Object.new.instance_eval do
> class << self
> for m in public_instance_methods
> undef_method(m.to_sym) unless m =~ /^__.*__$/
> end
> end
> def method_missing(*args); nil; end
> self
> end
> @blackhole unless block_given?
> end
> end
>
> class Object
> def ergo
> if block_given?
> yield(self)
> else
> self
> end
> end
> end

Interesting... I like this. Nice use of fluent / magic dot notation.
This is a good use case for Functor too (see Facets):

class NilClass
def ergo
@blackhole ||= Functor.new{ nil }
@blackhole unless block_given?
end
end

One question, I'm not sure what you expect to be returned if a block
is given.

Besides that one issue, I'd like to add this to Facets and credit you.

T.