如何使用符号来标识 ruby​​ 方法中的参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8021628/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 02:18:04  来源:igfitidea点击:

How are symbols used to identify arguments in ruby methods

ruby-on-railsrubysymbolshash

提问by Amit Erandole

I am learning rails and going back to ruby to understand how methods in rails (and ruby really work). When I see method calls like:

我正在学习 rails 并回到 ruby​​ 以了解 rails 中的方法(和 ruby​​ 真正的工作原理)。当我看到如下方法调用时:

validates validates :first_name, :presence => true

I get confused. How do you write methods in ruby that accept symbols or hashes. The source code for the validates method is confusing too. Could someone please simplify this topic of using symbols as arguments in ruby class and instance methods for me?

我有点迷惑不解了。你如何在 ruby​​ 中编写接受符号或散列的方法。validates 方法的源代码也令人困惑。有人可以为我简化在 ruby​​ 类和实例方法中使用符号作为参数的主题吗?

UPDATE:

更新:

Good one @Dave! But What I was trying out was something like:

好一个@Dave!但我尝试的是这样的:

def full_name (:first_name, :last_name)
  @first_name = :first_name
  @last_name = :last_name
  p "#{@first_name} #{last_name}"
end

full_name("Breta", "Von Sustern")

Which obviously raises errors. I am trying to understand: Why is passing symbols like this as arguments wrong if symbols are just like any other value?

这显然会引发错误。我试图理解:如果符号与任何其他值一样,为什么将这样的符号作为参数传递是错误的?

回答by Dave Newton

Symbols and hashes are values like any other, and can be passed like any other value type.

符号和哈希值与其他任何值一样,可以像任何其他值类型一样传递。

Recall that ActiveRecord models accept a hash as an argument; it ends up being similar to this (it's not this simple, but it's the same idea in the end):

回想一下 ActiveRecord 模型接受散列作为参数;它最终与此类似(它不是那么简单,但最终是相同的想法):

class User
  attr_accessor :fname, :lname

  def initialize(args)
    @fname = args[:fname] if args[:fname]
    @lname = args[:lname] if args[:lname]
  end
end

u = User.new(:fname => 'Joe', :lname => 'Hacker')

This takes advantage of not having to put the hash in curly-brackets {}unless you need to disambiguate parameters (and there's a block parsing issue as well when you skip the parens).

这利用了不必将散列放在大括号中的优势,{}除非您需要消除参数的歧义(并且当您跳过括号时也存在块解析问题)。

Similarly:

相似地:

class TestItOut
  attr_accessor :field_name, :validations

  def initialize(field_name, validations)
    @field_name = field_name
    @validations = validations
  end

  def show_validations
    puts "Validating field '#{field_name}' with:"
    validations.each do |type, args|
      puts "  validator '#{type}' with args '#{args}'"
    end
  end
end

t = TestItOut.new(:name, presence: true, length: { min: 2, max: 10 })
t.show_validations

This outputs:

这输出:

Validating field 'name' with:
  validator 'presence' with args 'true'
  validator 'length' with args '{min: 2, max: 10}'

From there you can start to see how things like this work.

从那里你可以开始看到这样的事情是如何工作的。

回答by Hless

I thought I'd add an update for Ruby 2+ since this is the first result I found for 'symbols as arguments'.

我想我会为 Ruby 2+ 添加一个更新,因为这是我为“符号作为参数”找到的第一个结果。

Since Ruby 2.0.0 you can also use symbols when defining a method. When calling the method these symbols will then act almost the same as named optional parameters in other languages. See example below:

从 Ruby 2.0.0 开始,您还可以在定义方法时使用符号。当调用该方法时,这些符号的行为与其他语言中命名的可选参数几乎相同。请参阅下面的示例:

def variable_symbol_method(arg, arg_two: "two", arg_three: "three")
  [arg, arg_two, arg_three]
end

result = variable_symbol_method :custom_symbol, arg_three: "Modified symbol arg"

# result is now equal to:
[:custom_symbol, "two", "Modified symbol arg"]

As shown in the example, we omit arg_two:when calling the method and in the method body we can still access it as variable arg_two. Also note that the variable arg_threeis indeed altered by the function call.

如示例所示,我们arg_two:在调用方法时省略,在方法体中我们仍然可以将其作为变量访问arg_two。还要注意,变量arg_three确实被函数调用改变了。

回答by millimoose

In Ruby, if you call a method with a bunch of name => valuepairs at the end of the argument list, these get automatically wrapped in a Hashand passed to your method as the last argument:

在 Ruby 中,如果您name => value在参数列表末尾使用一堆对调用一个方法,它们会自动包装在 a 中Hash并作为最后一个参数传递给您的方法:

def foo(kwargs)
  p kwargs
end

>> foo(:abc=>"def", 123=>456)
{:abc=>"def", 123=>456}

>> foo("cabbage")
"cabbage"

>> foo(:fluff)
:fluff

There's nothing "special" about how you write the method, it's how you call it. It would be perfectly legal to just pass a regular Hash object as the kwargsparameter. This syntactic shortcut is used to implement named parametersin an API.

您如何编写方法并没有什么“特别”之处,而是您如何调用它。只传递一个普通的 Hash 对象作为kwargs参数是完全合法的。此语法快捷方式用于在 API 中实现命名参数

A Ruby symbol is just a value as any other, so in your example, :first_nameis just a regular positional argument. :presenceis a symbol used as a Hash key – any type can be used as a Hash key, but symbols are a common choice because they're immutable values.

Ruby 符号只是一个值,因此在您的示例中,:first_name它只是一个常规的位置参数。:presence是用作哈希键的符号——任何类型都可以用作哈希键,但符号是常见的选择,因为它们是不可变的值。

回答by sevgun

I think all replies have missed the point of question; and the fact it is asked by someone who is - I guess - not clear on what a symbol is ?

我认为所有的回复都没有抓住问题的重点;事实上,有人问过这个问题——我猜——不清楚符号是什么?

As a newcomer to Ruby I had similar confusions and to me an answer like following would have made more sense

作为 Ruby 的新手,我也有类似的困惑,对我来说,像下面这样的答案会更有意义

Method Arguments are local variables populated by passed in values.

方法参数是由传入的值填充的局部变量。

You cant use symbols as Arguments by themselves, as you cant change value of a symbol.

您不能单独使用符号作为参数,因为您不能更改符号的值。

回答by DGM

Symbols are not limited to hashes. They are identifiers, without the extra storage space of a string. It's just a way to say "this is ...."

符号不限于哈希。它们是标识符,没有字符串的额外存储空间。这只是说“这是……”的一种方式

A possible function definition for the validates call could be (just to simplify, I don't know off the top of my head what it really is):

validates 调用的一个可能的函数定义可能是(只是为了简化,我不知道它到底是什么):

def validates(column, options)
   puts column.to_s
   if options[:presence]
     puts "Found a presence option"
   end
 end

Notice how the first symbol is a parameter all of its own, and the rest is the hash.

请注意第一个符号是如何自己成为参数的,而其余的则是散列。