【问题标题】:How do I set a keyword arg to default to undefined in Ruby如何在 Ruby 中将关键字 arg 设置为默认为 undefined
【发布时间】:2017-12-14 20:34:57
【问题描述】:

我有以下代码

def thing(item: "yeah")
  puts item == nil
end  
def thing2(item: nil)
  thing(item: item)
end
thing2()

我希望看到false,因为我希望传递给thingnil 被视为未定义的item 参数,但是,我看到true。我怀疑这是因为像 JS 一样,ruby 将 nilundefined 分开。那么有没有办法可以将值默认为undefined 而不是nil

我目前基于接受的答案的最终版本看起来像这样......

def default_item 
  "yeah" 
end
def default_other 
  "other" 
end

def thing(item: default_item(), other: default_other())
  puts item + " " + other
end  
def thing1(other: default_other())
  thing(other: other)
end  
def thing2(item: default_item())
  thing(item: item)
end
thing1()
thing2()
thing1(other:"Is Other")
thing2(item:"Is Item")
# fail with argument exception
# thing1(item:"Not Item")
# thing2(other:"Not Other")

Code Example

(返回值的方法更多是基于它需要实际返回一个实例值)

我仍然不喜欢到处都是item: default_item(),所以我愿意接受更好的解决方案。

【问题讨论】:

  • “我希望 nil 传递给 thing 并看到 false” – 嗯?如果nil 作为参数传递给thing,为什么你会期望它打印“false”?你字面意思检查你是否通过nil,所以它当然会打印“true”。
  • 因为我希望方法调用中的关键字 param 设置它,因为它为空。所以我猜这不会发生,因为它只设置未定义且 null != undefined 的值。那么我该如何声明它,而不是 nil 它将是未定义的
  • @JörgWMittag 他希望thing 看到itemnil,并将其解释为item 未设置,因此默认item"yeah"
  • @River 谢谢,是的,所以我有点理解为什么它没有,但现在我需要知道如何让它工作。我不想在所有调用 thing 方法的地方重新声明默认值。
  • 让我们非常清楚 ruby​​ 不是 javascript 并且“未定义”是一个运行时错误 (NameError)。如果您考虑这种分离,那么我想是的,红宝石可以分离这些东西。如果您想要 nil 的默认值,那么在 thing 方法中这将是 item ||= "yeah"

标签: ruby optional-parameters


【解决方案1】:

在 Ruby 中,nil 和缺席是两件截然不同的事情。

thing2item=nil 调用thing 时,thing 意识到item 存在,但以nil 作为其值。因此检查item==nil 返回true

我认为您的两个最佳选择是手动检查 nil,并且只使用与您的其他方法相同的默认值:

选项 1:

def thing(item: "yeah")
  puts item == nil
end  
def thing2(item: nil)
  if item!=nil
      thing(item: item)
  else
      thing()
  end
end
thing2()

选项 2:

$DEFAULT = "yeah"
def thing(item: $DEFAULT)
  puts item == nil
end  
def thing2(item: $DEFAULT)
  thing(item: item)
end
thing2()

【讨论】:

  • 选项 2 现在看起来是最体面的。有没有办法可以用实例级别而不是全局级别 var 来做到这一点?我试过 def initialize @default = "blah" end 但没用
  • @Jackie 是的,如果你只是在initialize 中初始化实例变量,它应该可以工作。很高兴它有帮助
  • 接受答案,直到有人提出更好的答案 :-) 我仍然不希望到处都有item: DEFAULT
【解决方案2】:

您调用thing2(),因此thing2 中的item 获取其默认值nil。然后将其提供给thing。所以item 中的thing 也是nil。如果您希望它改为"yeah",那么您需要调用thing 真正没有item 的值。不是nil 值。

一种方法是使用散列参数而不是关键字参数:

def thing(item: "yeah")
  puts item == nil
end  
def thing2(options = {})
  thing(options)
end
thing2()
thing2(item: nil)

thing2() 打印false,因为thing2 没有得到item 值,因此没有给item 值提供thing。所以thing 使用默认的"yeah"

它为thing2(item: nil) 打印true,因为thing2 确实获得了item 值并将其转发给thing,它是nil

不确定这是否是个好主意,我想这取决于您的实际用例。

编辑:正如@SergioTulentsev 评论的那样,您仍然可以使用关键字参数:

def thing(item: "yeah")
  puts item == nil
end  
def thing2(**kwargs)
  thing(**kwargs)
end
thing2()
thing2(item: nil)

这可能会更好,始终在任何地方使用关键字参数。

【讨论】:

  • 处理从未想过使用“假”默认值的有趣方式。
  • 您仍然可以使用关键字参数。 def thing2(**kwargs)。但是,是的,它下面的哈希值基本相同。
  • @Jackie 你是什么意思?这里没有什么是假的。我最近写了一个answer about different parameter styles,也许这有助于澄清这一点。
  • @SergioTulentsev 是的,使用不同的风格来接受和传递参数感觉是错误的。谢谢,添加到答案中。
  • @Jackie:“不工作”是什么意思?据我了解您的规格,它可以按您的意愿工作。
猜你喜欢
  • 1970-01-01
  • 2016-05-04
  • 2021-06-09
  • 1970-01-01
  • 2013-03-25
  • 2016-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多