Ruby的隐藏特性

159

应该是社区维基 - SilentGhost
46个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
3
任何可枚举的对象(数组、哈希表等)都可以使用 each_with_index 方法吗?
myarray = ["la", "li", "lu"]
myarray.each_with_index{|v,idx| puts "#{idx} -> #{v}"}

#result:
#0 -> la
#1 -> li
#2 -> lu
也许相对于其他答案来说更为人所知,但并不是所有 Ruby 程序员都熟知 :)

6
在1.9版本中,每个Enumerator都拥有#with_index方法,也就是说可以使用myarray.each.with_index或者myarray.map.with_index这样的语法。 - Reactormonk

2
class A

  private

  def my_private_method
    puts 'private method called'
  end
end

a = A.new
a.my_private_method # Raises exception saying private method was called
a.send :my_private_method # Calls my_private_method and prints private method called'

2
私有方法的目的是将它们隐藏起来,以便在更改时不会破坏代码。如果您知道自己在做什么,请继续调用私有方法。Ruby 强制您使用看起来非常不同的调用(使用 .send),这使得这个调用很特殊。大多数动态语言都允许您规避私有方法定义,因为有时这很方便。 - rfunduk
5
大多数编程语言中的可见性规则旨在保护你免受错误而非欺诈,正如 Stroustrop 所说。 - JasonTrue
2
将此内容添加到“Ruby 最差实践”列表中。 - maček
1
针对所有讨厌这个的人:显然这是一个hack。除非作为最后的手段,你不应该使用它,就像其他所有的hack一样,但当你确实需要它时,你会很高兴它在那里,就像其他所有的hack一样。 - Matt Briggs
2
如果你只想发送到一个公共方法,可以使用 send_public。但是似乎没有私有方法或受保护方法的等效方法... - @rogerdpack - Andrew Grimm
显示剩余6条评论

2
Ruby有一个call/cc机制,允许用户自由地在堆栈中上下跳跃。 以下是一个简单的例子。这当然不是在Ruby中乘以一个序列的正确方法,但它演示了如何使用call/cc来到达堆栈顶部以绕过算法。在这种情况下,我们递归地将一组数字相乘,直到我们要么看到每个数字,要么看到零(我们知道答案的两种情况)。在零的情况下,我们可以任意深入列表并终止。
#!/usr/bin/env ruby

def rprod(k, rv, current, *nums)
  puts "#{rv} * #{current}"
  k.call(0) if current == 0 || rv == 0
  nums.empty? ? (rv * current) : rprod(k, rv * current, *nums)
end

def prod(first, *rest)
  callcc { |k| rprod(k, first, *rest) }
end

puts "Seq 1:  #{prod(1, 2, 3, 4, 5, 6)}"
puts ""
puts "Seq 2:  #{prod(1, 2, 0, 3, 4, 5, 6)}"
你可以在这里看到输出:

http://codepad.org/Oh8ddh9e

对于一个更复杂的示例,其中包含在堆栈上向另一个方向移动的 continuations,请阅读 Generator 的源代码。

4
不应使用callcc。来自Matz的书: 由于实现难度,其他Ruby实现(如基于Java的实现JRuby)无法支持continuations。因为它们不再得到良好支持,所以应该将continuations视为一种好奇心,新的Ruby代码不应使用它们。 - Marc-André Lafortune

2

我刚刚阅读了所有的答案...有一个值得注意的遗漏是解构赋值:

> (a,b),c = [[1,2],3]
=> [[1,2],3]
> a
=> 1

它还适用于块参数。当您拥有嵌套的数组并且每个元素代表不同的东西时,这将非常有用。您可以将该嵌套数组分解,并为每个元素赋予一个描述性名称,而不是编写类似“array[0][1]”的代码,这可以在一行代码中完成。


1
@user #=> nil (but I did't know)
@user.name rescue "Unknown"

-1:完全复制Fabiano PS的[答案](https://dev59.com/UHVD5IYBdhLWcg3wKoWH#2379114)。 - Andrew Grimm

1

sprintf快捷方式

我最喜欢的Ruby功能。语法是format_string % argument

"%04d"  % 1         # => "0001"
"%0.2f" % Math::PI  # => "3.14"

对于数组同样适用 (format_string % array_of_arguments)

"%.2f %.3f %.4f" % ([Math::PI]*3) 
# => "3.14 3.142 3.1416"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,