将方法转换为可枚举方法

时间:2016-02-04 05:19:19

标签: ruby oop instance-methods

我重写了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

我需要调用此代码,因为我会调用mapreverse。有谁知道它的语法?

2 个答案:

答案 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]

请注意,除了完全错误之外,您的代码非常不恰当。那里也有死代码。

  1. 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
    
  2. 现在我们已经摆脱了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
    
  3. 它在循环的中间也没有意义。它应该在方法的开头。

    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
    
  4. 不应将对象与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
    
  5. 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
    
  6. 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
    
  7. 使用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
    
  8. 您可以使用.()句法糖代替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
    
  9. 如果您不想存储,传递或以其他方式操纵块作为对象,则无需将其捕获为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
    
  10. 这个是自以为是的。您可以将计数器递增到条件中。

    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
    
  11. 然后使用语句修饰符表单。

    def my_map
      return self unless block_given?
      mod_input = []
      x = -1
      mod_input << yield(self[x]) while (x += 1) < length
      mod_input
    end
    
  12. 此外,您的变量名称可以使用一些改进。例如,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
    
  13. 初始化变量,然后改变分配给该变量的对象并最后返回对象的整个序列可以通过使用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
    
  14. 整个while循环没用。它只是重新实施Catamorphism,这是a)不必要因为Array#each已经存在,并且b)意味着您的my_map方法仅适用于Array但不是其他Enumerable(例如Setfold or reduce)。所以,我们只需使用each

    def my_map
      return self unless block_given?
      [].tap {|result| 
        each {|element|
          result << yield(element)
        }
      }
    end
    

    现在它开始看起来像Ruby代码!你以前用的东西更像是用Ruby语法编写的BASIC。

  15. 这种模式首先创建一个结果对象,然后根据集合的每个元素修改该结果对象,最后返回结果是很常见的,它甚至有一个奇特的数学名称:{{3虽然在编程世界中,我们通常将其称为Enumerable#map。在Ruby中,它被称为Enumerable#inject

    def my_map
      return self unless block_given?
      inject([]) {|result, element|
        result << yield(element)
      }
    end
    
  16. return self很奇怪。 map应该返回 new 对象!您没有返回对象,而是返回相同的对象。让我们解决这个问题。

    def my_map
      return dup unless block_given?
      inject([]) {|result, element|
        result << yield(element)
      }
    end
    
  17. 实际上,map也应该返回Array,但您可以返回您调用map的内容。

    def my_map
      return to_a unless block_given?
      inject([]) {|result, element|
        result << yield(element)
      }
    end
    
  18. 真的,如果您查看Kernel#__method__的文档,您会发现它返回Enumerator而不是Array时没有阻挡地叫。

    def my_map
      return enum_for(:my_map) unless block_given?
      inject([]) {|result, element|
        result << yield(element)
      }
    end
    
  19. 最后,我们可以使用{{3}}方法删除硬编码的方法名称。

    def my_map
      return enum_for(__method__) unless block_given?
      inject([]) {|result, element|
        result << yield(element)
      }
    end
    
  20. 现在,看起来好多了!

答案 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