我重写了map
方法:
def my_map(input, &block)
mod_input = []
x = -1
while x < input.length - 1
x = x + 1
if block == nil
return input
break
end
mod_input.push(block.call(input[x]))
end
return mod_input
end
我需要调用此代码,因为我会调用map
或reverse
。有谁知道它的语法?
答案 0 :(得分:4)
您是否在询问如何将方法放入模块中?那是微不足道的:
module Enumerable
def my_map(&block)
mod_input = []
x = -1
while x < length - 1
x = x + 1
if block == nil
return self
break
end
mod_input.push(block.call(self[x]))
end
return mod_input
end
end
[1, 2, 3, 4, 5].my_map(&2.method(:*))
# => [2, 4, 6, 8, 10]
或者您是否在询问如何使您的方法成为Enumerable
方法?这更复杂:您的方法目前使用的许多方法都不属于Enumerable
API。因此,即使如果使其成为Enumerable
模块的成员,它也不会成为Enumerable
方法。 Enumerable
方法只能使用each
或其他Enumerable
方法。您使用的length
和[]
都不属于Enumerable
界面,例如,Set
不响应[]
。< / p>
这可能是一种可能的实现,使用Enumerable#inject
方法:
module Enumerable
def my_map
return enum_for(__method__) unless block_given?
inject([]) {|res, el| res << yield(el) }
end
end
[1, 2, 3, 4, 5].my_map(&2.method(:*))
# => [2, 4, 6, 8, 10]
使用each
module Enumerable
def my_map
return enum_for(__method__) unless block_given?
[].tap {|res| each {|el| res << yield(el) }}
end
end
[1, 2, 3, 4, 5].my_map(&2.method(:*))
# => [2, 4, 6, 8, 10]
请注意,除了完全错误之外,您的代码非常不恰当。那里也有死代码。
break
是死代码:方法return
位于它之前的行中,因此永远不会执行break
。你可以摆脱它。
def my_map(&block)
mod_input = []
x = -1
while x < length - 1
x = x + 1
if block == nil
return self
end
mod_input.push(block.call(self[x]))
end
return mod_input
end
现在我们已经摆脱了break
,我们可以将条件转换为一个条件的守护式语句修饰符。
def my_map(&block)
mod_input = []
x = -1
while x < length - 1
x = x + 1
return self if block == nil
mod_input.push(block.call(self[x]))
end
return mod_input
end
它在循环的中间也没有意义。它应该在方法的开头。
def my_map(&block)
return self if block == nil
mod_input = []
x = -1
while x < length - 1
x = x + 1
mod_input.push(block.call(self[x]))
end
return mod_input
end
不应将对象与nil进行比较,而应该问它是nil?
:block.nil?
def my_map(&block)
return self if block.nil?
mod_input = []
x = -1
while x < length - 1
x = x + 1
mod_input.push(block.call(self[x]))
end
return mod_input
end
Ruby是一种面向表达式的语言,在方法体中计算的最后一个表达式的值是该方法体的返回值,不需要显式的return
。 / p>
def my_map(&block)
return self if block.nil?
mod_input = []
x = -1
while x < length - 1
x = x + 1
mod_input.push(block.call(self[x]))
end
mod_input
end
x = x + 1
更具惯用性x += 1
。
def my_map(&block)
return self if block.nil?
mod_input = []
x = -1
while x < length - 1
x += 1
mod_input.push(block.call(self[x]))
end
mod_input
end
使用Array#push
代替Array#<<
而不是Proc#call
。
def my_map(&block)
return self if block.nil?
mod_input = []
x = -1
while x < length - 1
x += 1
mod_input << block.call(self[x])
end
mod_input
end
您可以使用.()
句法糖代替K Combinator。
def my_map(&block)
return self if block.nil?
mod_input = []
x = -1
while x < length - 1
x += 1
mod_input << block.(self[x])
end
mod_input
end
如果您不想存储,传递或以其他方式操纵块作为对象,则无需将其捕获为Proc
。只需使用block_given?
和yield
代替。
def my_map
return self unless block_given?
mod_input = []
x = -1
while x < length - 1
x += 1
mod_input << yield(self[x])
end
mod_input
end
这个是自以为是的。您可以将计数器递增到条件中。
def my_map
return self unless block_given?
mod_input = []
x = -1
while (x += 1) < length
mod_input << yield(self[x])
end
mod_input
end
然后使用语句修饰符表单。
def my_map
return self unless block_given?
mod_input = []
x = -1
mod_input << yield(self[x]) while (x += 1) < length
mod_input
end
此外,您的变量名称可以使用一些改进。例如,mod_input
甚至意味着什么?我只能看到它是你输出的,所以为什么它甚至有&#34;输入&#34;在它的名字?什么是x
?
def my_map
return self unless block_given?
result = []
index = -1
result << yield(self[index]) while (index += 1) < length
result
end
初始化变量,然后改变分配给该变量的对象并最后返回对象的整个序列可以通过使用Object#tap
来简化,该Array#each
在Ruby中可用Enumerator
def my_map
return self unless block_given?
[].tap {|result|
index = -1
result << yield(self[index]) while (index += 1) < length
}
end
整个while
循环没用。它只是重新实施Catamorphism,这是a)不必要因为Array#each
已经存在,并且b)意味着您的my_map
方法仅适用于Array
但不是其他Enumerable
(例如Set
或fold
or reduce
)。所以,我们只需使用each
。
def my_map
return self unless block_given?
[].tap {|result|
each {|element|
result << yield(element)
}
}
end
现在它开始看起来像Ruby代码!你以前用的东西更像是用Ruby语法编写的BASIC。
这种模式首先创建一个结果对象,然后根据集合的每个元素修改该结果对象,最后返回结果是很常见的,它甚至有一个奇特的数学名称:{{3虽然在编程世界中,我们通常将其称为Enumerable#map
。在Ruby中,它被称为Enumerable#inject
。
def my_map
return self unless block_given?
inject([]) {|result, element|
result << yield(element)
}
end
return self
很奇怪。 map
应该返回 new 对象!您没有返回新对象,而是返回相同的对象。让我们解决这个问题。
def my_map
return dup unless block_given?
inject([]) {|result, element|
result << yield(element)
}
end
实际上,map
也应该返回Array
,但您可以返回您调用map
的内容。
def my_map
return to_a unless block_given?
inject([]) {|result, element|
result << yield(element)
}
end
但真的,如果您查看Kernel#__method__
的文档,您会发现它返回Enumerator
而不是Array
时没有阻挡地叫。
def my_map
return enum_for(:my_map) unless block_given?
inject([]) {|result, element|
result << yield(element)
}
end
最后,我们可以使用{{3}}方法删除硬编码的方法名称。
def my_map
return enum_for(__method__) unless block_given?
inject([]) {|result, element|
result << yield(element)
}
end
现在,看起来好多了!
答案 1 :(得分:3)
if(request.getParameter("action")=="delete" && request.getParameter("action")!=null)
{
//delete operation
}
else
{
//update operation
}
代码本身并不是惯用的Ruby - class Array
def my_map(&block)
# your code, replacing `input` with `self`
end
end
很少用于集合上的迭代,如果你不需要在其他地方传递一个块,使用{{1}通常更简洁而不是while
(更不用说block_given?
)和block.nil?
而不是block == nil
。