Besides brevity is there any other case for implicit return values? I love little lambdas as much as the next guy but does the cost have to be that every one of my functions returns something unless I write an extra line to the contrary?
I'd rather pay the price of typing
return self.shipping = false
to make the function return false if I actually wanted it to do so, rather than
self.shipping = false
true
which just looks bizarre to me and doesn't make its motive clear (you wind up only including it when your last expression evaluates to false). I have vague, unpleasant memories of also encountering this gotcha with Perl in RT scrips, where you would suffix silly little 1;'s and 0;'s to everything to make the next action run or not run.
I don't know about everybody else, but I don't FP to the extent that I never write subprocedures. Isn't this still typical?
This is one of the reasons why you should learn Ruby throughly before you could become a Rails master. The value of last expression executed within the function becomes the return value of the function itself.
"If a before_* callback returns false, all the later callbacks and the associated action are cancelled. If an after_* callback returns false, all the later callbacks are cancelled. Callbacks are generally run in the order they are defined, with the exception of callbacks defined as methods on the model, which are called last."
before_filter in controllers used to work the same way, but somewhere along the way it was changed to check #performed? on the controller. That way before_filters only cancel the action if it redirects or renders a template.
How else would you do that for callbacks though? Force the user to raise something like ActiveRecord::CancelCallback? Use the obscure throw/catch statements?
Raising an exception is a good method. A better method would be a condition system [1], which enables more fine grained handling of such things. throw and catch are a kind of bad implementation of this, but there is no reason you couldn't use them, except that very few people do.
In practice, maybe a Ruby linter could/should pick this pattern up and warn about it? It wouldn't be hard to identify functions which return a value based on a block if with no else say.
5 comments
[ 5.9 ms ] story [ 28.5 ms ] threadI'd rather pay the price of typing
to make the function return false if I actually wanted it to do so, rather than which just looks bizarre to me and doesn't make its motive clear (you wind up only including it when your last expression evaluates to false). I have vague, unpleasant memories of also encountering this gotcha with Perl in RT scrips, where you would suffix silly little 1;'s and 0;'s to everything to make the next action run or not run.I don't know about everybody else, but I don't FP to the extent that I never write subprocedures. Isn't this still typical?
See the section "Cancelling Callbacks" in the docs for ActiveRecord::Callback: http://rails.rubyonrails.org/classes/ActiveRecord/Callbacks....
"If a before_* callback returns false, all the later callbacks and the associated action are cancelled. If an after_* callback returns false, all the later callbacks are cancelled. Callbacks are generally run in the order they are defined, with the exception of callbacks defined as methods on the model, which are called last."
before_filter in controllers used to work the same way, but somewhere along the way it was changed to check #performed? on the controller. That way before_filters only cancel the action if it redirects or renders a template.
How else would you do that for callbacks though? Force the user to raise something like ActiveRecord::CancelCallback? Use the obscure throw/catch statements?
In practice, maybe a Ruby linter could/should pick this pattern up and warn about it? It wouldn't be hard to identify functions which return a value based on a block if with no else say.
[1] http://www.gigamonkeys.com/book/beyond-exception-handling-co...