nil? with block

M

Michiel de Mare

If you have a long chain of method calls, but want to check some
temporary values for nils, for instance to raise an exception,
currently the easiest way is with local variables:

e.g.:

def zipcode_for_user(user)
address = user.personal_data.address
raise 'no address!' unless address
address.zipcode
end

If "nil?" is extended to accept a block, and to return self (for
Object) and the result of the yield (for NilClass), the following
notation becomes possible:

user.personal_data.address.nil?{ raise 'no address!'}.zipcode

This is more concise, and (I think) also more readable. The flow of
the program isn't broken by the nil-check. Apart from raise
statements, it would make sense to use return statements in the
blocks.

The implementation is trivial:
class Object ; def nil? ; block_given? ? self : false ; end ; end
class NilClass ; def nil? ; block_given? ? yield : true ; end ; end

Do you think this is a good idea?
 
R

Robert Klemme

If you have a long chain of method calls, but want to check some
temporary values for nils, for instance to raise an exception,
currently the easiest way is with local variables:

e.g.:

def zipcode_for_user(user)
address = user.personal_data.address
raise 'no address!' unless address
address.zipcode
end

If "nil?" is extended to accept a block, and to return self (for
Object) and the result of the yield (for NilClass), the following
notation becomes possible:

user.personal_data.address.nil?{ raise 'no address!'}.zipcode

This is more concise, and (I think) also more readable.

Actually I am not sure about readability. Lines tend to grow pretty
long that way. I would probably not use it. Also keep in mind that you
will usually get an exception anyway since you're most likely calling a
method that nil does not support.
The flow of
the program isn't broken by the nil-check. Apart from raise
statements, it would make sense to use return statements in the
blocks.

The implementation is trivial:

.... and probably slower than the current implementation as they add
another boolean check.
class Object ; def nil? ; block_given? ? self : false ; end ; end
class NilClass ; def nil? ; block_given? ? yield : true ; end ; end

Do you think this is a good idea?

I am not so sure. But you can easily implement this with another method
name so you don't have to change existing code's behavior. Also, nil
values might be just only one reason to throw an exception so I am not
sure about general usefulness.

Yeah, I know - I'm a conservative skeptic. :)

Kind regards

robert
 
D

David A. Black

Hi --

If you have a long chain of method calls, but want to check some
temporary values for nils, for instance to raise an exception,
currently the easiest way is with local variables:

e.g.:

def zipcode_for_user(user)
address = user.personal_data.address
raise 'no address!' unless address
address.zipcode
end

If "nil?" is extended to accept a block, and to return self (for
Object) and the result of the yield (for NilClass), the following
notation becomes possible:

user.personal_data.address.nil?{ raise 'no address!'}.zipcode

This is more concise, and (I think) also more readable. The flow of
the program isn't broken by the nil-check. Apart from raise
statements, it would make sense to use return statements in the
blocks.

The implementation is trivial:
class Object ; def nil? ; block_given? ? self : false ; end ; end
class NilClass ; def nil? ; block_given? ? yield : true ; end ; end

Do you think this is a good idea?

No, I don't like it. It's unidiomatic for a ?-method to take a block,
and also for a block to serve as a conditional branch. I'd rather see
it unrolled. I understand the reasoning behind it, but it ends up
being idiosyncratic in its semantics.


David

--
Q. What is THE Ruby book for Rails developers?
A. RUBY FOR RAILS by David A. Black (http://www.manning.com/black)
(See what readers are saying! http://www.rubypal.com/r4rrevs.pdf)
Q. Where can I get Ruby/Rails on-site training, consulting, coaching?
A. Ruby Power and Light, LLC (http://www.rubypal.com)
 
S

Sylvain Abélard

I am not so sure. But you can easily implement this with another method
name so you don't have to change existing code's behavior. Also, nil
values might be just only one reason to throw an exception so I am not
sure about general usefulness.

I also doubt this would ever be useful. I like 'long lines' and hate
loads of 'if-statements' but I must admit I find them useful (or at
least, any other solution looks awful to me).


Why not using, let's call them "accessors?" which are "accessors with
a question mark".
Just by hacking with a bit of "method_missing" in both your class and
NilClass, this would not slow exec time much I guess, and the
implementation should also be trivial.

- in the class, you just send(accessor_name) when you get an unknown
accessor_name?
- in nilclass, you return "stuff" when having a '?' method (except
nil? or empty?)

The problem, IMHO, resides in the impossibility to return a coherent "stuff".
You *want* Ruby to NoMethodError you when you fail something.
You *can't* always know what you could prefer when your call fail.
Should "stuff" be nil, 0, empty string, new object ?


I suggest you use that in your project (if that's a big one) and then
tell us in a few weeks/months if that changed your life or not. If
that made your debugging harder.
Then again, this is a matter of personal preference I guess ;)
 
D

Daniel Lucraft

Michiel said:
If "nil?" is extended to accept a block, and to return self (for
Object) and the result of the yield (for NilClass), the following
notation becomes possible:

user.personal_data.address.nil?{ raise 'no address!'}.zipcode

Why not use Object#tap?

user.p_data.address.tap {|a| raise "no address!" unless a}.zipcode

It's included in Ruby 1.9, is easily definable otherwise
(http://rubyurl.com/eG5) and does basically what you want.

best,
Dan
 
G

Gary Wright

No, I don't like it. It's unidiomatic for a ?-method to take a block,

No opinion on nil? but there are a couple examples of ?-methods
with blocks in core: any?, all?.

Gary Wright
 
L

Louis J Scoras

No opinion on nil? but there are a couple examples of ?-methods
with blocks in core: any?, all?.

Agreed. However, the methods you mention use the block in order
determine whether the predicate is satisfied or not. The action bit
is still just returning true or false.

The proposed 'nil?' uses the block to dispatch some unrelated
behavior, and it doesn't return a boolean. I agree with David, et al.
on this one.
 
B

Brian Candler

If you have a long chain of method calls, but want to check some
temporary values for nils, for instance to raise an exception,
currently the easiest way is with local variables:

e.g.:

def zipcode_for_user(user)
address = user.personal_data.address
raise 'no address!' unless address
address.zipcode
end

If "nil?" is extended to accept a block, and to return self (for
Object) and the result of the yield (for NilClass), the following
notation becomes possible:

user.personal_data.address.nil?{ raise 'no address!'}.zipcode

If your result set doesn't include 'false', then you can use 'or'. Mind you,
it gets ugly with the necessary brackets:

(user.personal_data.address or raise "no address!").zipcode

Especially if you go to multiple levels. It looks a bit too much like
LISP...

(((user or raise "no user!").
personal_data or raise "no personal_data!").
address or raise "no address!").zipcode

Regards,

Brian.
 

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

Latest Threads

Top