如果我写这个:
case v
when String
puts :String
else
puts :other
end
如果我将v
设置为"some string"
,我会收到'字符串'。
如果我将v
设置为String
,我会得到'其他'。
我应该怎样'切换'包含多个类对象之一的变量?
这是如何尊重'最少惊喜'的成熟计算原理的?
请不要告诉我修补“班级”课程。
答案 0 :(得分:3)
它通常被称为“案例相等运算符”,但===
既不是reflexive nor symmetric nor transitive,所以它根本不像是一个相等的行为:
String === "test"
# true
"test" === String
# false
String === String
# false
String === Class
# false
Class === String
# true
Class === Class
# true
我读过a === b
的最佳说明来自@JörgWMittag的answer:
“如果我有一个标有a
标签的抽屉,将b
放入抽屉是否合理?”
对于你的问题,你可以写:
v = String
case v
when Class
puts "#{v} is a Class, let's investigate some more"
# another case, if statements or hash lookup...
else
puts :other
end
答案 1 :(得分:1)
我应该怎样'切换'包含多个类对象之一的变量?
使用Module#<=
:
case v
when String then "instance of string"
when ->(c) { c <= String } then "class derived from String"
end
这是如何尊重'最少惊喜'的成熟计算原理的?
完美。
答案 2 :(得分:1)
您可以在没有对象的情况下使用case
:
case
when v == String
puts 'v is String class'
when v.is_a?(String)
puts 'v is an instance of String'
else
puts 'v is something else'
end
这类似于if
- elsif
- else
表达式。
答案 3 :(得分:1)
ruby和其他一些函数式语言中的case表达式与命令式switch语句cousins完全不同。
正如其他人所提到的,case表达式使用===
方法,这是一种模式定义方法。在a === b
范例中,a
是一种描述可能实例集合的模式。 b
是一个可能适合该模式/集合的实例。将a === b
视为:
做'a'描述'b'?
或
'a'包含'b'?
一旦理解了这一点,String === String #=> false
并不令人惊讶,因为String
是Class
的一个实例,因此它符合Class
模式。
case表达式和switch语句之间的另一个独特区别是case表达式只是:表达式。这意味着你可以做这样的酷事:
puts case v.name
when "String"
:String
else
:other
end if v.is_a? Class
此代码仅在v
为类时执行,然后根据类的名称启用v.name
和puts
。
由于ruby作为鸭子类型语言的本质,在变量中有一个类并且需要打开它是极其罕见的。如果你感到沮丧case
并不像你希望的那样优雅,请给我们更多关于你的目标的背景信息,我们也许能够提出一个优雅的解决方案,避免一起切换。