Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 我如何构建一个基本的';英语计算器&x27;用红宝石?_Ruby_Oop_Method Chaining - Fatal编程技术网

Ruby 我如何构建一个基本的';英语计算器&x27;用红宝石?

Ruby 我如何构建一个基本的';英语计算器&x27;用红宝石?,ruby,oop,method-chaining,Ruby,Oop,Method Chaining,因此,我目前正在这个优秀的网站上进行Ruby培训,遇到了一个比我的水平略高的问题,但我觉得如果我能看看/a答案并将其在我的大脑中循环一段时间,它真的可以帮助我的代码开发。一种缺少链接类型的交易 问题是如何构建Calc类以实现以下结果: class Calc end Calc.new.one.plus.two # Should return 3 Calc.new.five.minus.six # Should return -1 Calc.new.se

因此,我目前正在这个优秀的网站上进行Ruby培训,遇到了一个比我的水平略高的问题,但我觉得如果我能看看/a答案并将其在我的大脑中循环一段时间,它真的可以帮助我的代码开发。一种缺少链接类型的交易

问题是如何构建Calc类以实现以下结果:

class Calc
end

Calc.new.one.plus.two             # Should return 3
Calc.new.five.minus.six           # Should return -1
Calc.new.seven.times.two          # Should return 14
Calc.new.nine.divided_by.three    # Should return 3
该类只需要处理单个数字输入零9和+-*/运算符,并且格式将始终是一个由3个方法组成的链,如您所见(即数字运算符编号)


我很乐意阅读你的一些解决方案,如果你不介意的话,还可以阅读你在解决问题时所经历的思考过程。谢谢

假设这些方法不会以无效方式使用:

class Calc
  def self.operand name, v
    define_method(name) do
      @operator ? @operand.send(@operator, v) : (@operand = v; self)
    end
  end
  def self.operator name, v
    define_method(name) do
      @operator = v; self
    end
  end

  operand :one, 1
  operand :two, 2
  ...
  operator :plus, :+
  operator :minus, :-
  ...
end

这里还有一个技巧:

我并没有完全实现它。但是你可以从中得到一个想法,对于你的情况。

这个怎么样

class Calc
  attr_accessor :result, :last_operator

  def initialize(result=0)
   @result = result
  end

  OPERATORS = {
    :plus => :+, :minus => :-, :times => :*, :divided_by => :/
  }

  OPERANDS = [ :zero, :one, :two, :three, :four, :five, :six, :seven, :eight, :nine, :ten, :eleven, :twelve ] 

  def method_missing(m, *args, &block)
    if OPERATORS.include?(m.to_sym)
      @last_operator = m.to_sym
      return self 
    elsif OPERANDS.include?(m.to_sym)
      if @last_operator.nil?
        @result = OPERANDS.index(m.to_sym)
        return self
      end
      @result = eval("#{@result} #{OPERATORS[@last_operator]} #{OPERANDS.index(m.to_sym)}")
      return @last_operator.nil? ? self : @result
    end

    super
  end
end


[20] pry(main)> Calc.new.three.times.seven
=> 21
[21] pry(main)> Calc.new.twelve.divided_by.two
=> 6

不是最佳解决方案,但满足以下要求:

class Calc
  ENGLISH_TO_OP = Hash[%i{zero one two three four five six seven eight nine}
    .each_with_index.to_a].merge(plus: :+, minus: :-, times: :*, divided_by: :/)

  def method_missing(m)
    if s = ENGLISH_TO_OP[m]
      (@cmd ||= []) << s
      return @cmd[0].send(*@cmd[1..2]) if @cmd.size == 3
      self
    else
      super
    end
  end
end

我不想写太多的代码,因此
method\u missing
比必须定义方法要好得多,尽管它可能会有问题,因此我倾向于避免它。散列查找适用于指定的操作数和操作,并且
每个带有\u索引的\u
都可以填充值。在条件中为s赋值就是懒惰。最后,我可以在初始化器中初始化
@cmd
,但这是较少的代码,可以防止
@cmd
稍后被另一种方法重置为零。

虽然我认为这通常是一个好问题(也是一个有趣的问题),不幸的是,Stackoverflow并不是解决这样一个相当广泛的问题的好地方。因此,更多的是具体的问题和答案;可以简明扼要地回答的事情,等等。我想你可能会在某种论坛上更幸运。或者,你可以尝试一些想法,如果你遇到一个问题或一个以前没有在这里回答过的特定问题,你肯定可以发布它。这更多的是一个讨论的请求,而不是一个可回答的问题,正如@teeg所说,这与StackOverflow的目的背道而驰我已经解决了这个关于codewars的kata,如果将整个kata作为一个问题来提问,那么根本不符合尝试kata的目的,您应该尝试kata,当您遇到问题时,发布您遇到的问题。这将打印值,而无需调用外部方法。如果希望嵌套更多调用,则必须为fixnum执行方法_missing,并且可能必须覆盖“times”(因为fixnum已经有times)。。这个解决方案完全解决了你的问题(虽然=)哈哈。。我相信你最终会做一些疯狂简单的事情!(检查下面@GarySWeaver的解决方案)他认为这些运算符都是二进制运算符。是的。。他使用了一种不同的(有趣的)方式。是的,非常简单,最后调用
val
:-)@Abdo
self
是这里的主要思想,每次方法调用后我都会返回它。:)最后一个
val
就像在计算器上按等号一样。我不认为当你不能使用
val
时,
self
是主要的想法(因为最后,你不能返回预期的输出)@Abdo这实际上是我的救命稻草……)我该如何改进它呢?哈哈:-)你必须将无休止的链接限制为三个(否则,必须使用monkeypatch Fixnum)。。。检查下面的代码=)
class Calc
  ENGLISH_TO_OP = Hash[%i{zero one two three four five six seven eight nine}
    .each_with_index.to_a].merge(plus: :+, minus: :-, times: :*, divided_by: :/)

  def method_missing(m)
    if s = ENGLISH_TO_OP[m]
      (@cmd ||= []) << s
      return @cmd[0].send(*@cmd[1..2]) if @cmd.size == 3
      self
    else
      super
    end
  end
end
2.1.0 :015 > Calc.new.seven.times.two
 => 14 
2.1.0 :016 > Calc.new.nine.divided_by.three
 => 3 
2.1.0 :017 > Calc.new.five.minus.six
 => -1 
2.1.0 :018 > Calc.new.one.plus.two
 => 3