我目前正在学习Haskell,突然遇到了这个表达式。
statement
case 1 ´div´ 0 of _ -> 42
我的直觉是,由于用0除法,这将导致运行时错误,但从测试来看,情况并非如此。
我的结论是,这一定是由于Haskell内部的懒惰评估。因为_
匹配任何东西,所以它不会检查它与什么比较?
所以,如果有人能告诉我这个评估是否正确,如果不正确,为什么。另外,请详细说明在不实际查看表达式的情况下,案例行可以匹配的前提。
我的结论是,这一定是由于Haskell内部的懒惰评估。因为_
匹配任何东西,所以它不会检查它与什么比较?
是的,没错!
在模式匹配过程中,仅在需要匹配模式中的构造函数(和数字/字符文本)时执行求值。如果模式是变量或通配符,则无需计算。
case undefined of _ -> () -- OK
case undefined of True -> () -- crash
case undefined of (_,_) -> () -- crash
case (undefined, 4) of (_,x) -> x+1 -- OK
此外,模式匹配从左到右、从上到下进行:
case (4, undefined) of
(3, True) -> 1
(4, _) -> 2
计算结果为<代码>2--我们首先将<代码>4与<代码>3进行匹配,但在尝试将<代码>未定义的与<代码>真的进行匹配之前失败。这样我们就避免了崩溃,第二种模式成功了。
(详尽地说:这实际上有一个例外。如果您对一个新类型的构造函数进行模式匹配,则不会进行任何计算。您可以暂时忽略这种情况,因为您正在学习——这并不常见。)
你的分析是准确的,但这实际上是非常繁琐的。它不复杂,但它需要仔细考虑非常精确的问题。
大小写表达式具有一般形式
case exp0 of {pat1 -> exp1 ; ...}
计算case表达式时,将对exp0进行足够的计算,以确定它是否与pat1匹配。如果是,case表达式将使用为其创建的任何附加绑定对其求值。如果不匹配,则会切换到下一个模式或后卫并重复。(如果没有匹配项,则计算为异常。)
值得注意的是,您的第一个替代方案匹配所有内容,而无需任何评估。因此不执行div 1 0
的评估。该模式不绑定任何内容,然后case表达式的评估结果为42。
这与你做的不同:
case 1 `div` 0 of
0 -> 42
_ -> 42
在这种情况下,必须计算div表达式,以查看它是否等于0。这将导致一个异常,该异常将成为整个case表达式的结果。即使两个分支具有相同的值,这也是事实。模式的内容对于确定与严格相关的行为非常重要。
到目前为止,GHC Haskell编译器是最常见的编译器,它有一个称为“core”的中间表示形式,看起来与Haskell相似,但类型类和大多数语法糖都已完全去除。Core的语义也与Haskell略有不同,尤其是在case构造方面。在core中,case总是导致对顶级构造函数的评估。使用嵌套重写模式,以匹配原始Haskellhtml" target="_blank">代码的模式语义。
本节只是一个旁白,但是如果你研究优化Haskell代码,你会遇到core,知道有区别是很有用的。
我正在练习计算let表达式的问题,但我不理解这个表达式的输出。 下面是一个表达: 输出应该是[1,2,4,8]。有人能一步一步地解释为什么这是输出吗
问题内容: 我正在尝试创建一个switch语句,但似乎无法使用被求值的表达式(而不是设置的字符串/整数)。我可以轻松地使用if语句来执行此操作,但希望大小写应该更快。 我正在尝试以下 我缺少明显的东西吗?Google在这种情况下并不友好。 任何帮助/指针表示赞赏 问题答案: 你总是可以做 它之所以有效是因为它是一个常量,因此将执行第一个case语句下带有计算结果为true的表达式的代码。 我猜这有
本文向大家介绍Ruby中case表达式详解,包括了Ruby中case表达式详解的使用技巧和注意事项,需要的朋友参考一下 Ruby的case表达式有两种形式: 第一种形式接近于一组连续的if语句:它让你列出一组条件,并执行第一个为真的条件表达式所对应的语句。 第二种形式,在case语句的顶部指定一个目标,而每个when从句列出一个或者多个比较条件 和if一样,case返回执行的最后一个表达式的值;而
问题内容: 我有以下代码片段: 我知道在C ++中,您被教导不要依赖子表达式的求值顺序,因为它不能保证完全是任何顺序。因此,此代码将是错误的,并且不能保证条件中表达式所产生的布尔值是真实的(例如,可以在第一次等式测试中对y进行递增运算)。由于我是在Java认证书中阅读此代码的,因此我认为Java并非如此。.我的意思是,我是否保证Java的评估顺序始终是从左到右?因此,以上表达式应始终为true。
我有以下代码片段: 我知道在C++中,你被教导不要依赖子表达式的求值顺序,因为它不能保证是任何顺序。因此这段代码是错误的,并且条件中的表达式所产生的布尔值不能保证为真(例如,在第一个相等性测试中计算y之前,可以增加y)。因为我是在Java认证书上读到这段代码的,所以我假设Java不是这样的。我的意思是,我能保证Java的计算顺序总是从左到右吗?所以上面的表达式应该总是产生true。
问题内容: 我的转换案例声明昨天运行良好。但是,当我今天早些时候运行代码时,eclipse给我一个错误,强调了红色的case语句,并说:case表达式必须是常量表达式,它是常量,我不知道发生了什么。这是我的代码如下: 所有R.id.int都用红色下划线。 问题答案: 在常规的Android项目中,资源R类中的常量声明如下: 但是,从ADT 14开始,在图书馆项目中,它们将这样声明: 换句话说,常数