This project is archived and is in readonly mode.
Clean try syntax
Reported by Amos King | June 30th, 2010 @ 05:35 AM
The syntax for try is really ugly with array/hash access. ie. list.try(:[],4)
I would really like to see try return a proxy object when the original object is a NilObject. This would allow try to be used like:
list.try[2]
other methods can be called right off of try:
list.try.size
Comments and changes to this ticket
-
Amos King June 30th, 2010 @ 05:41 AM
- Tag changed from active_support, core_ext, rails3 to active_support, core_ext, patch, rails3
here is a patch, and it keeps backwards compatibility.
-
Amos King June 30th, 2010 @ 05:44 AM
- Tag changed from active_support, core_ext, patch, rails3 to active_support, core_ext, documentation, patch, rails3
I also updated the documentation in the same patch.
-
José Valim June 30th, 2010 @ 12:18 PM
- State changed from new to wontfix
- Importance changed from to Low
Thanks for the patch, but the syntax something.try[2] is not obvious (for me). try(:[], 2) is simpler with no extra tricks in the implementation.
-
José Valim June 30th, 2010 @ 01:11 PM
Yes, but I don't see a reason to support a more complex syntax to be used rather rarely (in :[] cases).
-
yairgo June 30th, 2010 @ 02:54 PM
+1
Are you really going to disregard this patch because the syntax "is not obvious" for you?
I've worked with 5 or 6 people at my company on a rails project that I'm part time on and I've shown at least 4 of them the try(:[], 4) syntax. They've all pretty much said afterward that they would have never even thought to use 'try' that way.
something.try[2] makes a lot more sense to me than something.try(:[],2), one says here try this on my object the other says here is a method and some params try them on my object.
"Yes, but I don't see a reason to support a more complex syntax which is used rather rarely." Is the patch really introducing a more complex syntax?
try[2] vs try(:[], 2) -
Amos King June 30th, 2010 @ 03:00 PM
Why not support both syntaxes for a little while, and see where the community goes with it. Then we can deprecate one, or maybe decide to keep both?
-
José Valim June 30th, 2010 @ 03:28 PM
- Assigned user set to José Valim
Sorry, when I said "complex", I was referring about the implementation required to support such syntax and difficulty to understand what is going on:
self.try(:[], 2) #=> is a method that sends the given method unless self is nil self.try[2] #=> is a method that returns self if not nil, else a proxy that discards any call
A proxy just adds complexity:
object.try(:freeze) #=> return nil if object nil object.try.freeze #=> freezes the proxy and returns the proxy if object nil
Another possible failure is with to_json:
require 'json' #=> Ruby 1.9.2 nil.to_json #=> "null" object.try(:to_json) #=> nil object.try.to_json #=> "#<Try:0x00000101826fe8>"
There are several other cases where returning a proxy might have a surprising behavior. Note that this is nothing new, we had this discussion a long time ago because there were solutions like andand which had a similar approach to try+proxy and we voted to be explicit with try, since it has no special cases or caveats.
Edited to add proper formatting to block codes.
-
Amos King June 30th, 2010 @ 04:03 PM
What if the implementation used BasicObject if the implementation is Ruby 1.9? I'm not in a place where I can test that right now.
-
José Valim June 30th, 2010 @ 04:11 PM
We could consider that in the future when we drop support for Ruby 1.8.x, but not right now because the implementation would behave considerably different depending on the Ruby version (something that ActiveSupport tries to minimize).
-
Jeremy Kemper June 30th, 2010 @ 05:15 PM
I agree
maybe_hash_maybe_nil.try(:[], key)
is ugly. But the proxy approach is error-prone and less obvious.A third way is to use
instance_eval
:list.try { self[2] }
orobject.try { to_json }
. That's clear, but line-noisey.I think the simplest choice is to use
try
for simple cases and simply do not use it for the few ugly cases. -
Amos King July 11th, 2010 @ 05:46 AM
irb(main):003:0> require 'json'
=> true irb(main):005:0> Try = Class.new(BasicObject) { def method_missing(*) nil; end }
=> Try irb(main):006:0> Try.new.to_json
=> nilThis was with 1.9, and with 1.8.7 it did the same thing.
I'm not sure how you got the Try object with the to_json call.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>