考虑在柯里编程语言中实现一个名为
我会通过两个可替换的非确定性规则来直接实现它:
(因此,这里的直接性被逆转。)
在哪些情境下它可能很重要?
choose
的函数,其规范是"(choose xs)
从列表xs
中非确定性地选择一个元素"。我会通过两个可替换的非确定性规则来直接实现它:
choose :: [a] -> a
choose x:_ = x
choose _:xs = choose xs
但在来自明斯特Curry编译器的/usr/lib/curry-0.9.11/Success.curry中,它被定义为一个辅助函数:
choose (x:xs) = choosep x xs
where choosep x [] = x
choosep x (_:_) = x
choosep _ (x:xs) = choosep x xs
如果编译器提供的模块定义有什么优势(如果有的话),是不是这两个定义在所有情况下都完全等效(即使涉及到非确定性和未定义值的一些棘手情况)?那么其中一个在某些情况下是否更有效?
新增:更深入的考虑
cthom06(谢谢!)正确指出了我的定义会导致在更多情况下遇到未定义的值(因为我们会尝试每次使用空列表参数来调用此函数,并且每次“顶层”调用时使用最初的非空列表参数)。 这样做的效率较低。
但我想知道:这两种定义是否存在任何语义上的区别? 在某些棘手的上下文中差异是否重要?
我们看到,这两个定义之间的差异 - 在非空列表的情况下 - 基本上归结为两个id
的潜在定义之间的差异:
我的定义类似于将id
定义为:
id x = x
id _ = undefined
它们的定义就像正常定义id
一样:
id x = x
(因此,这里的直接性被逆转。)
在哪些情境下它可能很重要?
id x = x
或使用额外的虚假规则id x = x
和id _ = undefined
来定义id
有哪些重大差异(关于语义方面-任何棘手的情况,或关于效率方面)?我想知道:是否存在语义可能发生变化的棘手情况? - imz -- Ivan Zakharyaschevhead(a:xs)=a
的行为类似于head(x:xs)=x
,而head[] = failed
。但是我们应该如何解释“error”? - Edgar Klerks