我经历了Write Yourself a Scheme in 48 Hours,在其中我遇到了一些看似冗余的代码;他们使用@ -patterns然后返回值本身,让我解释一下。
以下是相关代码:
data LispVal = Atom String
| List [LispVal]
| DottedList [LispVal] LispVal
| Number Integer
| String String
| Bool Bool
eval :: LispVal -> LispVal -- code in question starts here
eval val@(String _) = val
eval val@(Number _) = val
eval val@(Bool _) = val
eval (List [Atom "quote", val]) = val
在我看来,整个eval函数可以很容易地重写为
eval :: LispVal -> LispVal
eval (List [Atom "quote", val]) = val
eval val = val
并在原始代码中使用所有@ -patterns的底部案例帐户。
我是否错误地想到了这一点,并且按照他们的方式做到这一点是否有实际好处?或者另一种方式更简洁?
答案 0 :(得分:11)
一个区别是对于使用Atom
构造的值,原始代码未定义,即没有行
eval val@(Atom _) = val
无论这是否是一个'复制'错误,它突出了风格的重要区别:
第一种风格鼓励你单独思考每个值,明确断言“这是正确的方程式”。如果稍后在LispVal
类型中添加更多构造函数,则会出现运行时错误(或编译器警告-fwarn-incomplete-patterns
,这是一种很好的做法)。
第二种风格断言:eval
只需要查看List
值,而其他所有值都可以单独处理。特别是,稍后添加到数据类型也应该可以正常工作,并且您不希望对此函数感到困扰。
在操作上,它们是等效的。