使对象的行为类似于 Ruby 中并行赋值的数组
假设您在 Ruby 中执行此操作:
ar = [1, 2]
x, y = ar
那么,x == 1 且 y == 2。我可以在自己的类中定义一个方法来产生相同的效果吗? 例如
rb = AllYourCode.new
x, y = rb
,到目前为止,我对这样的赋值所能做的就是使 x == rb 且 y = nil。 Python有一个这样的特性:
>>> class Foo:
... def __iter__(self):
... return iter([1,2])
...
>>> x, y = Foo()
>>> x
1
>>> y
2
Suppose you do this in Ruby:
ar = [1, 2]
x, y = ar
Then, x == 1 and y == 2. Is there a method I can define in my own classes that will produce the same effect? e.g.
rb = AllYourCode.new
x, y = rb
So far, all I've been able to do with an assignment like this is to make x == rb and y = nil. Python has a feature like this:
>>> class Foo:
... def __iter__(self):
... return iter([1,2])
...
>>> x, y = Foo()
>>> x
1
>>> y
2
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的。 定义#to_ary。 这将使您的对象被视为分配的数组。
#to_a
和#to_ary
的区别在于#to_a
用于尝试转换将给定对象转换为数组,如果我们可以将给定对象视为数组,则 #to_ary 可用。 这是一个微妙的区别。
Yep. Define
#to_ary
. This will let your object be treated as an array for assignment.The difference between
#to_a
and#to_ary
is that#to_a
is used to try to converta given object to an array, while
#to_ary
is available if we can treat the given object as an array. It's a subtle difference.几乎:
Splat 将尝试调用
to_ary
,然后尝试调用to_a
。 我不确定你为什么要这样做,这实际上是一个语法功能,恰好在其实现中使用了 Array,而不是 Array 的功能。换句话说,多重赋值的用例如下:
换句话说,大多数时候从(
Array
)分配的对象甚至不明显。Almost:
Splat will try to invoke
to_ary
, and then try to invoketo_a
. I'm not sure why you want to do this though, this is really a syntactical feature that happens to useArray
in its implementation, rather than a feature ofArray
.In other words the use cases for multiple assignment are things like:
In other words, most of the time the object being assigned from (the
Array
) isn't even apparent.您无法重新定义赋值,因为它是一个运算符而不是一个方法。 但如果您的 AllYourCode 类继承自 Array,您的示例就可以工作。
当 Ruby 遇到赋值时,它会查看右侧,如果有多个右值,则会将它们收集到一个数组中。 然后它看向左侧。 如果那里有一个左值,则将其分配给该数组。
如果有多个左值(更具体地说,如果它看到逗号),它会连续分配右值并丢弃多余的值。
正如您所发现的,如果返回数组,您也可以进行并行分配。
因此,在您的示例中,如果 rb 是数组或继承自数组,则 x 和 y 将被分配其前 2 个值。
You can't redefine assignment, because it's an operator instead of a method. But if your AllYourCode class were to inherit from Array, your example would work.
When Ruby encounters an assignment, it looks at the right hand side and if there is more than one rvalue, it collects them into an array. Then it looks at the left hand side. If there is one lvalue there, it is assigned the array.
If there is more than one lvalue (more specifically, if it sees a comma), it assigns rvalues successively and discards the extra ones.
You can do parallel assignment if an array is returned, too, as you have discovered.
So in your example, if rb is an Array or inherits from Array, x and y will be assigned its first 2 values.