繁体   English   中英

Palindrome 和 Danvy 对直接风格的评论

[英]Palindrome and Danvy's remark on direct style

这是一些代码,以“直接样式”确定列表是否是 n+1 比较中的回文

pal_d1 :: Eq a => [a] -> Bool
pal_d1 l = let (r,_) = walk l l in r
        where walk l           [] = (True,l) 
              walk l       (_:[]) = (True,tail l)
              walk (x:l) (_:_:xs) = let (r, y:ys) = walk l xs
                                    in (r && x == y, ys)      

可以在几个例子上进行测试

-- >>> pal_d1 [1,2,1]
-- True

-- >>> pal_d1 [1,2,2,1]
-- True

-- >>> pal_d1 [1,2,3,4,2,1]
-- False

Danvy 在“ There and back again ”中声称,由于以下 CPS 风格解决方案中延续的非线性使用,没有控制运算符(在 4.2 之前)没有直接风格的解决方案:

pal_cps1 :: Eq a => [a] -> Bool
pal_cps1 l = walk l l (\_ -> trace "called" True) 
    where 
          walk  l          []  k = k l
          walk  l       (_:[]) k = k (tail l)
          walk (x:xs) (_:_:ys) k = walk xs ys (\(r:rs) ->  x == r && k rs)          

第一个代码如何不与此断言相矛盾?

(以及如何不线性使用延续?)

他没有声称没有控制操作员就没有解决方案。

延续不是线性使用的,因此将此程序映射回直接样式需要控制运算符。

这篇论文的背景是研究直接风格和 CPS 之间的系统转换,而那段的主张是,如果以花哨的方式使用延续,从 CPS 回归是很棘手的。

通过一些努力,您可以将其重新调整为一个不错的形状,但问题仍然存在,编译器如何自动执行此操作?

(以及如何不线性使用延续?)

在本文中,延续位于andalso ( && ) 的右侧,因此如果左侧操作数为False则将其丢弃。

在操作语义中,您可以将延续视为评估上下文,并且在该视图中丢弃延续对应于引发异常。 当然可以,但关键是这需要源语言中的额外机制。

CPS 代码(在问题的原始版本中——因为由 OP 编辑)似乎有问题。 看起来应该是

      walk (x:xs) (_:_:ys) k  =  walk xs ys (\(z:zs) -> x == z && k zs)

非 CPS 代码从中间开始比较,对长度为n的列表进行n `div` 2比较。 即使发现不匹配,它也会继续测试,因此是"linear"

在这种情况下,CPS 代码会立即退出,因为(False && undefined) == False成立; “非线性”也是如此。 两者相等,因此第一个没有说明第二个。

正如另一个答案所说,不调用延续相当于在没有延续的代码中抛出异常,该论文的作者显然称之为“直接[即非CPS(?)--wn]风格”。

(我没有读过论文)。

顺便说一句,以“直接”风格对早期退出的解决方案进行编码并不难。 我们将使用相同的海龟和兔子技巧来发现一半,同时反向构建前半部分,然后在 Haskell 或其等效的短路直接递归变体中调用and $ zipWith (==) first_half_reversed second_half second_half,使用严格的语言,例如 Scheme。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM