【问题标题】:Invalid function in ruby红宝石中的无效功能
【发布时间】:2013-08-25 20:03:47
【问题描述】:

为什么这个功能无效?

def request(method='get',resource, meta={}, strip=true)

end

unexcpected ')' 期待keyword_end

谢谢!

【问题讨论】:

  • 这不是一个函数。这是一种方法。

标签: ruby function methods syntax-error


【解决方案1】:

在 Ruby 中,您不能用可选参数包围必需参数。使用

def request(resource, method='get', strip=true, meta={})
end

会解决问题。

作为一个思想实验,考虑原始函数

def request(method='get',resource, meta={}, strip=true)
end

如果我将该方法称为request(object),则所需的行为相当明显——使用object 作为resource 参数调用该方法。但是如果我称它为request('post', object) 呢? Ruby 需要了解method 的语义来确定'post'method 还是resource,以及objectresource 还是meta。这超出了 Ruby 解析器的范围,所以它只会抛出一个无效函数错误。

一些额外的提示:

我还将 meta 参数放在最后,它允许您在不使用花括号的情况下传递哈希选项,例如:

request(object, 'get', true, foo: 'bar', bing: 'bang')

正如 Andy Hayden 在 cmets 中指出的,以下函数有效:

def f(aa, a='get', b, c); end

将所有可选参数放在函数的末尾通常是一种很好的做法,以避免在调用此类函数时进行心理操。

【讨论】:

  • 除了你可以,def f(aa, a='get', b, c); end ...?
  • 哎呀——看起来实际上只是您不能将必需参数夹在非必需参数之间。我猜 Ruby 解析器不知道如何处理这种情况。更新我的答案。
  • @AndyHayden,我添加了一些额外的说明,希望能更有效地解释原始方法失败的原因。
  • @Kyle 感谢更新 :) 我有点震惊,这是允许的!
  • @Kyle 是你的思想实验,我不同意,我认为 request(object) 不应该工作(这似乎使夹在中间的默认参数变得多余......你应该能够为它添加关键字 request(resource=object) (但我认为你不能用红宝石):(
【解决方案2】:

参数列表中只能有一组可选参数。

Ruby 中参数列表的伪正则表达式是这样的:

mand* opt* splat? mand* (mand_kw | opt_kw)* kwsplat? block?

这是一个例子:

def foo(m1, m2, o1=:o1, o2=:o2, *splat, m3, m4, 
          ok1: :ok1, mk1:, mk2:, ok2: :ok2, **ksplat, &blk)
  Hash[local_variables.map {|var| [var, eval(var.to_s)] }]
end

method(:foo).arity
# => -5

method(:foo).parameters
# => [[:req, :m1], [:req, :m2], [:opt, :o1], [:opt, :o2], [:rest, :splat], 
#     [:req, :m3], [:req, :m4], [:keyreq, :mk1], [:keyreq, :mk2], 
#     [:key, :ok1], [:key, :ok2], [:keyrest, :ksplat], [:block, :blk]]

foo(1, 2, 3, 4)
# ArgumentError: missing keywords: mk1, mk2

foo(1, 2, 3, mk1: 4, mk2: 5)
# ArgumentError: wrong number of arguments (3 for 4+)

foo(1, 2, 3, 4, mk1: 5, mk2: 6)
# => { m1: 1, m2: 2, o1: :o1, o2: :o2, splat: [], m3: 3, m4: 4, 
#      ok1: :ok1, mk1: 5, mk2: 6, ok2: :ok2, ksplat: {}, 
#      blk: nil }

foo(1, 2, 3, 4, 5, mk1: 6, mk2: 7)
# => { m1: 1, m2: 2, o1: 3, o2: :o2, splat: [], m3: 4, m4: 5, 
#      ok1: :ok1, mk1: 6, mk2: 7, ok2: :ok2, ksplat: {}, 
#      blk: nil }

foo(1, 2, 3, 4, 5, 6, mk1: 7, mk2: 8)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [], m3: 5, m4: 6, 
#      ok1: :ok1, mk1: 7, mk2: 8, ok2: :ok2, ksplat: {}, 
#      blk: nil }

foo(1, 2, 3, 4, 5, 6, 7, mk1: 8, mk2: 9)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5], m3: 6, m4: 7, 
#      ok1: :ok1, mk1: 8, mk2: 9, ok2: :ok2, ksplat: {}, 
#      blk: nil }

foo(1, 2, 3, 4, 5, 6, 7, 8, mk1: 9, mk2: 10)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8, 
#      ok1: :ok1, mk1: 9, mk2: 10, ok2: :ok2, ksplat: {}, 
#      blk: nil }

foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, mk1: 10, mk2: 11)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8, 
#      ok1: 9, mk1: 10, mk2: 11, ok2: :ok2, ksplat: {}, 
#      blk: nil }

foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, mk1: 10, mk2: 11, ok2: 12)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8, 
#      ok1: 9, mk1: 10, mk2: 11, ok2: 12, ksplat: {}, 
#      blk: nil }

foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, mk1: 10, mk2: 11, ok2: 12, k3: 13)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8, 
#      ok1: 9, mk1: 10, mk2: 11, ok2: 12, ksplat: {k3: 13}, 
#      blk: nil }

foo(1, 2, 3, 4, 5, 6, 7, 8, ok1: 9, mk1: 10, mk2: 11, ok2: 12, k3: 13, k4: 14)
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8, 
#      ok1: 9, mk1: 10, mk2: 11, ok2: 12, ksplat: {k3: 13, k4: 14}, 
#      blk: nil }

foo(1, 2, 3, 4, 5, 6, 7, 8, 
      ok1: 9, ok2: 10, mk1: 11, mk2: 12, k3: 13, k4: 14) do 15 end
# => { m1: 1, m2: 2, o1: 3, o2: 4, splat: [5, 6], m3: 7, m4: 8, 
#      ok1: 9, mk1: 10, mk2: 11, ok2: 12, ksplat: {k3: 13, k4: 14}, 
#      blk: #<Proc:0xdeadbeefc00l42@(irb):15> }

[注意:Ruby 2.1 将引入强制关键字参数,其余的都已经工作了。]

【讨论】:

    【解决方案3】:

    尝试重新排序您的参数:

    def Request(resource,strip=true,method='get',meta={})
    end
    

    【讨论】:

    • 谢谢,它可以工作,但是为什么,实际上我需要按顺序输入这些变量
    猜你喜欢
    • 2015-05-02
    • 2019-05-16
    • 2016-02-15
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    • 2023-04-11
    • 2014-12-21
    • 1970-01-01
    相关资源
    最近更新 更多