为什么我不能从另一个模块调用实例方法来初始化ruby中的lambda?

时间:2016-09-14 09:08:12

标签: ruby module

我正在尝试重构现有代码以简化。最初我在java中调用模块方法就像一个静态实用程序方法。

这是新代码:

module Module1
  def mod1() 1; end
end

module Module2
  include Module1
  def mod2
    puts mod1()
    puts 2
  end
  Constant = lambda { mod1() }  # This line fails
end

class Sample
  include Module2
  def go
    mod2
    Constant.call  #  <module:Module2>': undefined method `mod1' for Module2:Module (NoMethodError)
  end
end

Sample.new.go

如果简单地将Module1中的代码复制到Module2中,我就可以使用它。有更好的解决方案吗?

编辑:此外,我应该能够从直接包含它的类中调用Module1中的方法。例如:

class Sample2
  include Module1
  def go
    puts mod1()
  end
end
Sample2.new.go

实际模块1:

module HtmlUtils
  def wrap(tag = :span, class_names, text)
    %(<#{ tag } class="#{ class_names }">#{ text }</#{ tag }>)
  end
end

实际模块2 问题是上一代码中第3个重复的代码。它可以用HtmlUtils #wrap方法替换。

module Markdown
  include HtmlUtils
  BOLD = {
    regexp: /(_{2}|\*{2})(.*?)\1/,
    lambda: ->(token, regexp) { "<b>#{ token[regexp, 2] }</b>" }
  }
  NUMBER = {               
    regexp: /(?<=\s|\()[+-]?(?:[1-9]\d*|0)(?:\.\d+)?(?!-|\.|\d|,\d)/,
    lambda: ->(token, regexp) { %(<span class="num">#{ token }</span>) }  # Redundant Code
  }
end

Client1包括Markdown,实际上是HtmlUtils。

@parser.regexter('bold', BOLD[:regexp], BOLD[:lambda]);
@parser.regexter('numbers', NUMBER[:regexp], NUMBER[:lambda])
puts @parser.parse('some **string** 1')  # => some <b>string</b> <span class="num">1</span>

Client2包含HtmlUtils

@parser.regexter('quote', /(?<=)((["']).*?\2)/, ->(token, regexp) { wrap(:quote, token));
puts @parser.parse('s="Hello"')  # => s=<span class="quote">"Hello"</span>

1 个答案:

答案 0 :(得分:1)

注意尝试回答原始问题(在发布实际代码之前)。

嗯,这取决于。如果模块发送了他们自己需要的所有东西,你可以使mod1成为一个模块函数并明确地调用它(然后不需要包含模块)。但我担心你确实需要上下文。

module Module1
  def self.mod1() 1; end
end

module Module2
  def mod2
    puts Module1.mod1()
    puts 2
  end
  Constant = lambda { puts Module1.mod1() }  
end

class Sample
  include Module2
  def go
    mod2
    Constant.call  
  end
end

Sample.new.go

输出

#=>
1
2
1

否则你可以无法解释lambda:

module Module1
  def mod1() inmod2 ; end
end

module Module2
  include Module1

  def inmod2
    1
  end

  def mod2
    puts mod1()
    puts 2
  end
  def constant
    lambda { puts self.mod1() }
  end
end

class Sample
  include Module2
  def go
    mod2
    constant.call
  end
end

Sample.new.go

哪个有效(相同的输出)。不幸的是,我无法解释你为什么。很高兴阅读包含解释的答案(随意复制我的代码)。