This project is archived and is in readonly mode.

#5013 ✓wontfix
Amos King

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

    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

    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

    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.

  • Amos King

    Amos King June 30th, 2010 @ 01:06 PM

    This patch supports both syntaxes.

  • José Valim

    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

    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

    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

    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

    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

    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

    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] } or object.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

    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
    => nil

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

People watching this ticket

Attachments

Pages