Ruby函数可以检测请求的返回值的数量吗?

时间:2011-11-20 03:04:01

标签: ruby

在Ruby中,函数可以返回多个*值。 Ruby函数是否可以确定其调用代码所期望的返回值的数量?

例如:

a = f()                  # caller expects one return value
a, b = f()               # caller expects two return values
a, b, c = f()            # caller expects three return values

如果我们让r为预期返回值的数量,是否可以编写函数f以便找到r

具体来说,我们如何更改下面rcount的定义,以便通过以下测试:

a, b = rcount()
puts "#{a},#{b}"           # FAIL, DESIRED: "2,1"      ACTUAL: "1,"
a, b, c = rcount()
puts "#{a},#{b},#{c}"      # FAIL, DESIRED: "3,2,1"    ACTUAL: "1,,"
a, b, c, d = rcount()
puts "#{a},#{b},#{c},#{d}" # FAIL, DESIRED: "4,3,2,1"  ACTUAL: "1,,,"

rcount的定义如下:

def rcount()
  ret = []
  r = nil                  # <== Q. IS IT POSSIBLE TO GET r PROGRAMMATICALLY?
  r ||= 1
  last = r - 1
  (0..last).each do |i|
    ret[i] = r - i
  end
  ret
end

*实际上多个返回值是语法糖,实际返回值是单个数组。所有Ruby函数都只返回一个值。

3 个答案:

答案 0 :(得分:8)

Ruby函数总是只有一个返回值。你使用的是ruby的一个相当漂亮的功能,它允许使用逗号运算符来构造数组。这类似于splat(星号)运算符,可以用作反向运算符。

考虑这个例子

def rcount(number)
  # this returns an array containing the 1 till number
  (1..number).to_a
end

array = rcount(3)
# array is set to [1, 2, 3]

a, b, c = rcount(3)
# a is set to 1
# b is set to 2
# c is set to 3

x, y = rcount(3)
# x is set to 1
# y is set to 2
# the last value is thrown away

r, t, z = rcount(2)
# r is set to 1
# t is set to 2
# z is set to nil

基本上,没有必要检查返回数组中的数字或元素,至少在语法正确性方面是这样。如果您需要依赖于总是具有完全匹配数量的数组元素的事实,则应该使用测试来检查它。

请记住,你实际上是在这里处理数组。由于数组的解构是在函数返回数组之后完成的,因此无法知道之后对该值做了什么。这完全独立于函数调用。

作为最后的建议,如果你真的需要在一个生产软件中使用这样的东西,你应该认真地重新考虑你的设计,因为这样的东西引入了重要的功能耦合。鸭子打字是一种礼物。慷慨地使用它。

答案 1 :(得分:3)

没有。 Ruby环境不会为您提供该信息。您可以使用异常和ParseTree来查找调用代码的外观,但这样做太过分了:)

答案 2 :(得分:-1)

使用来电者获取文件和行号。 然后,您可以读取代码行以查看函数的调用方式:

def get_line(f,n)
  File.open(f,'r') do |fh|
    i = 0
    fh.each_line do |ln|
      i+=1
      return ln if i==n
    end
  end
end

def f()
  if caller.first=~/([^:]+):(\d+)/
    f,n = $1,$2.to_i
    line = get_line(f,n)
    case line
    when /\w+,\s*\w+\s*=\s*f\(/
      return [2, 3]
    when /=\s*f\(/
      return 1
    else
       puts 0
     end
  end
end

f()
a = f()
puts "a = #{a}"
b,c = f()
puts "b,c = #{b},#{c}"

输出结果为:

0
a = 1
b,c = 2,3

但是,是的...... 此上下文不是Ruby语言的一部分: