1

I recently discovered that in Python, you can do this:

array = [1, 2, 3, 4]
if 3 in array:
  print("Yep!")

Then, I thought to myself: "Mh, why is it different in Ruby? if 3 in array is more readable than if array.include? 3." Then, I realized, that Ruby is pure OOP and this approach is keyword-based.

But still, I am wondering. If the Python approach is not OOP, why can't there be another, shorter way in Ruby that is even more readable? When thinking, I don't think "Does this list include that element?", but "Is this element in that list?".

Let's assume, the following code was possible:

array = [1, 2, 3, 4]

if 3.in? array
  print "Yep!
end

I see that it is a turn-around from list.method(element) to element.method(list). So, I am wondering: Which ruby principles/rules speak against the above-metioned code?

EDIT: Oops, I wrote "keyboard-based" but meant of course "keyword-based". To emphasize this: I am not looking for methods that behave like the in? method; I am looking for reasons why it is not implemented in Ruby that way.

Aaron Kurtzhals
  • 2,036
  • 3
  • 17
  • 21
Above
  • 235
  • 2
  • 3
  • 9
  • I asked this question once! :) http://stackoverflow.com/q/8133397/125816 – Sergio Tulentsev Feb 06 '13 at 16:05
  • @SergioTulentsev, you know, "keyboard-based" as opposed to "mouse-based". – the Tin Man Feb 06 '13 at 16:08
  • Just to be clear, whether you prefer the Python approach or the Ruby approach here isn't about whether "the Python approach is not OOP", whatever that means. Whether a language has a certain syntax to hook into a method of the right hand side object -- such as `__contains__` -- has nothing to do with being more or less object-oriented. – DSM Feb 06 '13 at 16:18
  • I don't think your second code would be possible in any sense. You cannot end a script in the middle of a string literal. – sawa Feb 06 '13 at 16:31

6 Answers6

7

Which ruby principles/rules speak against the above-metioned code?

It's not a Ruby principle, but rather the general OOP principle of encapsulation: the Fixnum class should not need to know anything about arrays. However, because Array's primary responsibility is to contain collections of objects, #in? or #include? clearly falls under Array's responsibility.

Mark Rushakoff
  • 249,864
  • 45
  • 407
  • 398
0

In rails (active_support) there is a helper in?, which works exactly like you want

require 'active_support/core_ext'

3.in?([1, 2, 3]) # => true
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
0

From an OO point of view, this makes sense as include? is a method of Array, as opposed to being a method of everything else (or Object).

The Python variant looks like it is simply a form of syntactic sugar.

rausch
  • 3,148
  • 2
  • 18
  • 27
0

Your last sentence explains the problem you're seeing: You're thinking you should be able to ask an object if it exists in an array, which makes no sense. How would it know how to search an array, or array-like object.

Turning it around makes sense: "Does this array contain the object". The array, or array-like object knows how to search itself, and can try comparing the object to the elements in the array.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
0

(I have zero Python experience, so I am merely relaying what I read on the internet.)

in is an operator in Python, not a method.

Python has membership operators, which test for membership in a sequence, such as strings, lists, or tuples. There are two membership operators explained below:

in Evaluates to true if it finds a variable in the specified sequence and false otherwise.

not in Evaluates to true if it does not finds a variable in the specified sequence and false otherwise.

http://www.tutorialspoint.com/python/python_basic_operators.htm

I am a Ruby novice; I do not know of any Ruby principles that would discourage writing the object before the array.

Aaron Kurtzhals
  • 2,036
  • 3
  • 17
  • 21
0

I think Mark best answers your question, and for your purpose, case statement has the effect of reversing the relation unless you are dealing with elements like module, regex, etc.:

array = [1, 2, 3, 4]

case 3; when *array
  do_something
end
sawa
  • 165,429
  • 45
  • 277
  • 381