将自定义方法从自定义 class 传递到 .map
Passing custom method from custom class to .map
我正在为 exercism.io 做一个练习 - 说明很长而且与这个问题无关,但你可以找到我的完整解决方案 here。
基本上我有一个 Robot
class 和 3 个私有方法:
def rand_letters
('A'..'Z').to_a[rand(26)]
end
def rand_numbers
(0..9).to_a[rand(10)]
end
我想做的是将它们传递给另一个私有方法,如下所示:
def set_name
@name = ((1..2).map(&:rand_letters) + (3..5).map(&:rand_numbers)).join
end
执行此操作时出现错误:undefined method 'rand_letters' for 1:Fixnum
。在查看 之后,我认为问题可能在于我的 class 没有 to_proc 方法。不幸的是,我不确定如何纠正这个问题。我尝试让我的 class 继承自 Proc
,但我仍然不知道如何覆盖 to_proc
。任何帮助我指出正确方向的帮助将不胜感激。
解决方法如下:
def rand_letters
('A'..'Z').to_a[rand(26)]
end
def rand_numbers
(0..9).to_a[rand(10)]
end
p ((1..2).map { rand_letters } + (1..3).map { rand_numbers }).join
当您使用 map(&:rand_letters)
语法时,您会向集合中的每个元素发送消息。在我们的例子中,Fixnum
对象收到消息 (:rand_letters) 并且无法响应该消息,因为它未在 class Fixnum
中定义
在我的示例中,消息 :rand_letters
和 :rand_numbers
没有传递给 Fixnum
实例,而是传递给定义了它们的 self
。
这里是如何在 class 中使用它的方法:
class A
def rand_letters
('A'..'Z').to_a[rand(26)]
end
def rand_numbers
(0..9).to_a[rand(10)]
end
def name
(1..2).map { rand_letters } + (1..3).map { rand_numbers }.join
end
end
A.new.name
首先:您可以使用 array.sample
而不是 array[rand(x)]
从数组中获取随机元素。
此外,您可以将 (1..n).map
替换为 n.times.map
:
(2.times.map { rand_letters } + 3.times.map { rand_numbers }).join
但是使用 map
对我来说有违直觉。如果我们可以简单地随机抓取 3 个字母,是不是会容易得多?
这可以通过 returning Enumerator
而不是单个值来实现。复数命名已经表明 rand_
方法应该 return 多个值:
def rand_letters
return enum_for(__method__) unless block_given?
loop { yield ('A'..'Z').to_a.sample }
end
def rand_numbers
return enum_for(__method__) unless block_given?
loop { yield (0..9).to_a.sample }
end
这样我们就可以调用 Enumerable#take
:
(rand_letters.take(2) + rand_numbers.take(3)).join
#=> "ZJ010"
或使用 [...]
文字:
[rand_letters.take(2), rand_numbers.take(3)].join
我正在为 exercism.io 做一个练习 - 说明很长而且与这个问题无关,但你可以找到我的完整解决方案 here。
基本上我有一个 Robot
class 和 3 个私有方法:
def rand_letters
('A'..'Z').to_a[rand(26)]
end
def rand_numbers
(0..9).to_a[rand(10)]
end
我想做的是将它们传递给另一个私有方法,如下所示:
def set_name
@name = ((1..2).map(&:rand_letters) + (3..5).map(&:rand_numbers)).join
end
执行此操作时出现错误:undefined method 'rand_letters' for 1:Fixnum
。在查看 Proc
,但我仍然不知道如何覆盖 to_proc
。任何帮助我指出正确方向的帮助将不胜感激。
解决方法如下:
def rand_letters
('A'..'Z').to_a[rand(26)]
end
def rand_numbers
(0..9).to_a[rand(10)]
end
p ((1..2).map { rand_letters } + (1..3).map { rand_numbers }).join
当您使用 map(&:rand_letters)
语法时,您会向集合中的每个元素发送消息。在我们的例子中,Fixnum
对象收到消息 (:rand_letters) 并且无法响应该消息,因为它未在 class Fixnum
在我的示例中,消息 :rand_letters
和 :rand_numbers
没有传递给 Fixnum
实例,而是传递给定义了它们的 self
。
这里是如何在 class 中使用它的方法:
class A
def rand_letters
('A'..'Z').to_a[rand(26)]
end
def rand_numbers
(0..9).to_a[rand(10)]
end
def name
(1..2).map { rand_letters } + (1..3).map { rand_numbers }.join
end
end
A.new.name
首先:您可以使用 array.sample
而不是 array[rand(x)]
从数组中获取随机元素。
此外,您可以将 (1..n).map
替换为 n.times.map
:
(2.times.map { rand_letters } + 3.times.map { rand_numbers }).join
但是使用 map
对我来说有违直觉。如果我们可以简单地随机抓取 3 个字母,是不是会容易得多?
这可以通过 returning Enumerator
而不是单个值来实现。复数命名已经表明 rand_
方法应该 return 多个值:
def rand_letters
return enum_for(__method__) unless block_given?
loop { yield ('A'..'Z').to_a.sample }
end
def rand_numbers
return enum_for(__method__) unless block_given?
loop { yield (0..9).to_a.sample }
end
这样我们就可以调用 Enumerable#take
:
(rand_letters.take(2) + rand_numbers.take(3)).join
#=> "ZJ010"
或使用 [...]
文字:
[rand_letters.take(2), rand_numbers.take(3)].join