[英]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.