This project is archived and is in readonly mode.

#6321 ✓committed
rubyduo (at gmail)

add improved version of Enumerable#include?

Reported by rubyduo (at gmail) | January 21st, 2011 @ 02:57 PM

Sometimes you want to ask a question like

"Is x 1 or 2?"

Normally, you write this as:

[1,2].include?(x)

which seems backwards to me.

The attached patch to active allows you to instead write:

x.in?(1,2)

I use this all over my code, and thought others might like it.

You can also use in? with an array like so:

x.in?(*my_array)

Other possible names are: one_of?, within?. Any ideas or feedback would be appreciated.

I've attached a patch.

Comments and changes to this ticket

  • Brian Morearty

    Brian Morearty January 21st, 2011 @ 06:07 PM

    I like this extension a lot and am enthusiastically in favor of incorporating this behavior into ActiveSupport, but would suggest one small syntax change.

    I am the the author of the in_enumerable gem which does exactly this. The small difference is that in? takes a single parameter, not a list of *args parameters. Thanks to duck typing, this would allow it to work with any type that implements include?:

       # Array
       a = [1,2,3]
       3.in?(a)             # => true
       4.in?(a)             # => false
    
       # Hash
       h = { "a" => 100, "b" => 200 }
       "a".in?(h)           # => true
       "z".in?(h)           # => false
    
       # String
       "lo".in?("hello")    # => true
       "ol".in?("hello")    # => false
       ?h.in?("hello")      # => true
    
       # Range
       25.in?(1..50)        # => true
       75.in?(1..50)        # => false
    
       # Set
       require 'set'
       s = Set.new([1,2])
       1.in?(s)             # => true
       3.in?(s)             # => false
    
       # Even Module
       module A
       end
       class B
         include A
       end
       class C < B
       end
       A.in?(B)             # => true
       A.in?(C)             # => true
       A.in?(A)             # => false
    

    I have attached an alternate patch that implements in? in this way.

    Although in_enumerable does not have not_in?, I think it's nice idea because it cleans up the 'not' syntax a bit so I've included it in my alternate patch.

    I agree with your initial suggested name: in? seems to me the most obvious choice. In fact early versions of Ruby apparently had an Object#in? method. See the side note at the end of my blog post about in_enumerable: http://ilikestuffblog.com/2009/12/24/now-you-can-use-obj-inarray-in...

    I would be happy to deprecate the in_enumerable gem if this gets put into ActiveSupport.

  • Brian Morearty

    Brian Morearty January 21st, 2011 @ 06:11 PM

    P.S. In a completely bizarre coincidence of timing, just this morning I thought to myself "I really ought to submit a patch to add in_enumerable's behavior to ActiveSupport." So I logged in to Lighthouse and saw rubyduo's suggestion for the exact same behavior, right at the top of the list of tickets.

  • rubyduo (at gmail)

    rubyduo (at gmail) January 21st, 2011 @ 07:52 PM

    I like your change, since now you can write x.in?(1..50)

    On the other hand, it is nice to just type x.in?(1,2) instead of the wordy x.in?([1,2]).

    We could get the best of both worlds, by handling single and multiple arguments slightly differently, like so:

    def in?(*args)
      container = (args.size == 1 && args.responds_to(:include?)) ? args[0] : args
      container.include?(self)
    end
    

    I'm on the fence on this one.

  • Brian Morearty

    Brian Morearty January 21st, 2011 @ 09:29 PM

    Thanks, rubyduo. I also thought about combining them to get the best of both worlds. The problem is it will lead to ambiguous cases:

    names = ["Brian"]
    "B".in?(*names)   # => true
    
    names = ["Brian","rubyduo"]
    "B".in?(*names)   # => false
    

    So the function would be hard to use if it returns different values depending on the length of the array passed in.

    For that reason I think in this case overloading the arguments would lead to hard-to-track-down bugs.

  • rubyduo (at gmail)

    rubyduo (at gmail) January 21st, 2011 @ 10:42 PM

    You're right about the ambiguity. I'm now on your side of the fence. It'd sure be nice to see your patch (object_in_with_duck_typing.diff) applied to ActiveSupport.

  • Brian Morearty
  • Rohit Arondekar

    Rohit Arondekar January 26th, 2011 @ 10:08 AM

    • Importance changed from “” to “Low”

    Brian, could you post your patch suggestion to the core mailing list? http://groups.google.com/group/rubyonrails-core To try and gather some support for this patch. Otherwise it's most likely that it will remain buried in Lighthouse for a long time.

  • Brian Morearty

    Brian Morearty January 26th, 2011 @ 05:34 PM

    Rohit, thanks for the quick lesson in how to garner support for a Rails core patch. I've followed your suggestion. The post is here:

    http://groups.google.com/group/rubyonrails-core/browse_thread/threa...

  • peter_v
  • rails

    rails April 27th, 2011 @ 01:00 AM

    • State changed from “new” to “open”

    This issue has been automatically marked as stale because it has not been commented on for at least three months.

    The resources of the Rails core team are limited, and so we are asking for your help. If you can still reproduce this error on the 3-0-stable branch or on master, please reply with all of the information you have about it and add "[state:open]" to your comment. This will reopen the ticket for review. Likewise, if you feel that this is a very important feature for Rails to include, please reply with your explanation so we can consider it.

    Thank you for all your contributions, and we hope you will understand this step to focus our efforts where they are most helpful.

  • rails

    rails April 27th, 2011 @ 01:00 AM

    • State changed from “open” to “stale”
  • Prem Sichanugrist (sikachu)

    Prem Sichanugrist (sikachu) April 27th, 2011 @ 09:56 AM

    • State changed from “stale” to “committed”

    Actually, this ticket should be marked as committed. I forgot >_<

    This ticket related to this pull request: https://github.com/rails/rails/pull/258

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>

Pages