【问题标题】:Meaning of # symbol# 符号的含义
【发布时间】:2013-07-18 18:55:05
【问题描述】:

我的代码在class_eval 部分中有一个# 符号。这对我来说很陌生,这是什么意思?

class Class
  def attr_accessor_with_history(attr_name)
    attr_name = attr_name.to_s # make sure it's a string
    attr_reader attr_name # create the attribute's getter
    attr_reader attr_name+"_history" # create bar_history getter
    class_eval %Q{
def #{attr_name}=(attr_name)
@#{attr_name} = attr_name
@#{attr_name}_history = [nil] if @#{attr_name}_history.nil?
@#{attr_name}_history << attr_name
end
}
  end
end

【问题讨论】:

    标签: ruby methods syntax


    【解决方案1】:

    为什么下一个代码在 class_eval 中有 #?

    这是字符串插值。

    一个例子:

    x = 12
    puts %Q{ the numer is #{x} }
    # >>  the numer is 12 
    

    %QHere

    当字符串中有更多引号字符时,这是双引号字符串的替代方法。而不是在它们前面放置反斜杠。

    【讨论】:

      【解决方案2】:

      此功能称为字符串插值。它的有效作用是将#{attr_name} 替换为attr_name 实际值。您发布的代码显示了一种用例 - 当您想在运行时使用具有通用名称的变量时。

      那么更常用的用例如下:

      您可以这样使用字符串:"Hello, #{name}!"#{name} 将在此处自动替换 - 这是非常方便的功能。语法糖。

      但请注意代码中的%Q - 这会将以下代码转换为字符串,然后传递给class_eval 并在那里执行。查看更多关于它的信息here。没有它,当然是行不通的。

      【讨论】:

      • 我认为%Q 正在做的事情也值得一提,因为如果遗漏了它,剩下的代码看起来就像奇怪的 Ruby,插值可以在任何地方发生,这可能是一个混淆点
      【解决方案3】:
      def #{attr_name}=(attr_name)
      @#{attr_name} = attr_name
      @#{attr_name}_history = [nil] if @#{attr_name}_history.nil?
      @#{attr_name}_history << attr_name
      end
      

      如果attr_name 变量等于"params"。这实际上会变成这样:

      def params=(attr_name)
      @params = attr_name
      @params_history = [nil] if @params_history.nil?
      @params_history << attr_name
      end
      

      为什么会这样?因为所谓的字符串插值。如果您在字符串中写入#{something}something 将在该字符串中被评估和替换。

      为什么上面的代码即使不在字符串中也能工作?

      答案是,因为它是!

      Ruby 为您提供了不同的处理方式,并且对于某些文字有另一种语法,如下所示:%w{one two three} 其中{} 可以是任何分隔符,只要您使用相同或相应的结束符一。所以它可能是%w\one two three\%w[one two three],它们都可以工作。

      %w 用于数组,%Q 用于双引号字符串。如果你想看到所有这些,我建议你看看这个:http://www.ruby-doc.org/docs/ProgrammingRuby/html/language.html

      现在,在那个代码中

      class Class
        def attr_accessor_with_history(attr_name)
          attr_name = attr_name.to_s # make sure it's a string
          attr_reader attr_name # create the attribute's getter
          attr_reader attr_name+"_history" # create bar_history getter
          class_eval %Q{ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # STRING BEGINS
      def #{attr_name}=(attr_name)
      @#{attr_name} = attr_name
      @#{attr_name}_history = [nil] if @#{attr_name}_history.nil?
      @#{attr_name}_history << attr_name
      end
      } <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< # STRING ENDS
        end
      end
      

      我们可以看到带有字符串插值的整个部分在%Q{ } 内。这意味着整个块是一个大的双引号字符串。这就是为什么字符串插值会在将字符串发送到 eval 之前成功完成它的工作。

      【讨论】:

      • 没有问题,伙计。很高兴你得到它。
      猜你喜欢
      • 2012-06-12
      • 2017-01-02
      • 1970-01-01
      • 2016-02-25
      • 2016-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-01
      相关资源
      最近更新 更多