Reputation: 8055
I read in another answer that the []
method can take an array as an argument.
Both the examples given in the linked post don't illustrate what the actual result is from using this technique.
I tried some examples which also don't provide much information:
[11] pry(main)> a = %w( foo bar baz )
=> ["foo", "bar", "baz"]
[12] pry(main)> a[[1,2]]
TypeError: no implicit conversion of Array into Integer
from (pry):11:in '[]'
[13] pry(main)> a[['foo', 'bar']]
TypeError: no implicit conversion of Array into Integer
from (pry):12:in '[]'
[14] pry(main)> b = { foo: 42, bar: "dolphins", baz: "towels" }
=> {:foo=>42, :bar=>"dolphins", :baz=>"towels"}
[15] pry(main)> b[[:foo, :bar]]
=> nil
[16] pry(main)> b[["dolphins"]]
=> nil
What does it mean for the []
to take an array as an argument? What context is this technique used?
Would appreciate some runnable examples that will help me understand why all my examples return either nil
or an error.
Upvotes: 1
Views: 91
Reputation: 27793
[]
is just another method.
Unlike other languages, Ruby operators are just method and any method can take any object as argument, including an array.
class A
def [](key)
p key
end
def example(key)
p key
end
end
And then
a = A.new
a[1] # => 1
a[[1, 2, 3]] # => [1, 2, 3]
a.[](1) # => 1
a.[]([1, 2, 3]) # => [1, 2, 3]
a.example(1) # => 1
a.example([1, 2, 3]) # => [1, 2, 3]
a.send(:'[]', 1) # => 1
a.send(:'[]', [1, 2, 3]) # => [1, 2, 3]
a.send(:example, 1) # => 1
a.send(:example, [1, 2, 3]) # => [1, 2, 3]
Other operator methods in Ruby are
def []=(key, value)
def +(other)
def -(other)
def *(other)
def /(other)
def %(other)
def &(other)
def |(other)
def ^(other)
def ~(other)
def ==(other)
def ===(other)
def <=>(other)
def <=(other)
def >=(other)
def <(other)
def >(other)
def <<(other)
def !
def ~
def +@
as in +a
def -@
as in -a
Upvotes: 1
Reputation: 120990
This is ruby. Whatever#[]
is just a method. Consider Hash
class, defining class method Hash#[]
. It is used for constructing a Hash
instance out of an array of 2-sized arrays:
Hash[[[:foo, 42]]]
#⇒ { :foo => 42 }
Also, Hash
itself might have arrays as keys:
hash = { [1, 2, 3] => :foo }
hash[[1, 2, 3]]
#⇒ :foo
Upvotes: 0
Reputation: 54213
Receiver could be a Hash, with Arrays as keys
You could also splat the array :
a = %w( foo bar baz )
a[*[1,2]]
#=> ["bar", "baz"]
This syntax is equivalent to a[1,2]
and means take 2 values beginning at index 1
You could also define a custom class and a []
method, accepting any object :
class MyObject
def self.[](argument)
"MyObject[] has been called with an #{argument.class}"
# do something with argument
end
end
puts MyObject[[1,2,3]] #=> MyObject[] has been called with an Array
puts MyObject[Object.new] #=> MyObject[] has been called with an Object
Upvotes: 0
Reputation: 8055
Going off @Jared's answer, the important point is a hash's key can be an array. Another way to say this is a hash's []
method can take an array as an argument.
Also from another perspective: an array's index cannot be an array. Another way to say this is an array's []
method cannot take an array as an argument.
Now the examples above make sense.
[11] pry(main)> a = %w( foo bar baz )
=> ["foo", "bar", "baz"]
[12] pry(main)> a[[1,2]]
TypeError: no implicit conversion of Array into Integer
from (pry):11:in `[]'
[13] pry(main)> a[['foo', 'bar']]
TypeError: no implicit conversion of Array into Integer
from (pry):12:in `[]'
As mentioned above, this is an error because an array takes an integer as an index, not an array.
[14] pry(main)> b = { foo: 42, bar: "dolphins", baz: "towels" }
=> {:foo=>42, :bar=>"dolphins", :baz=>"towels"}
[15] pry(main)> b[[:foo, :bar]]
=> nil
[16] pry(main)> b[["dolphins"]]
=> nil
This isn't an error because a hash's key can be an array. However, the keys [:foo, :bar]
and ["dolphins"]
haven't been defined so they return nil
Another more illustrative example is:
[1] pry(main)> h = { foo: 42, bar: "cats" }
=> {:foo=>42, :bar=>"cats"}
[2] pry(main)> h[[:foo, :bar]]
=> nil
[3] pry(main)> h[[:foo, :bar]] = "dogs"
=> "dogs"
[4] pry(main)> h[[:foo, :bar]]
=> "dogs"
[5] pry(main)> h
=> {:foo=>42, :bar=>"cats", [:foo, :bar]=>"dogs"}
In [3]
we define the key [:foo, :bar]
in the hash h
to have the value "dogs"
so in [4]
that's what gets returned, and in [5]
we can see the key-value pair inside the hash.
Upvotes: 0
Reputation: 1184
If it is a hash you can have the key be an array. So you can look up via that. In your examples you are trying to do something similar on b
but it has no matching keys to your array param.
foo = {['bar'] => 'value'}
foo[['bar']]
=> "value"
Upvotes: 0