Ответ 1
Хм! Некоторая археология!
С 2004 года я использовал go
как общее имя для хвостовых рекурсивных циклов рабочих, когда выполнял преобразование рабочего/обертки рекурсивной функции. Я начал широко использовать его в bytestring
, например.
foldr :: (Word8 -> a -> a) -> a -> ByteString -> a
foldr k v (PS x s l) = inlinePerformIO $ withForeignPtr x $ \ptr ->
go v (ptr `plusPtr` (s+l-1)) (ptr `plusPtr` (s-1))
where
STRICT3(go)
go z p q | p == q = return z
| otherwise = do c <- peek p
go (c `k` z) (p `plusPtr` (-1)) q -- tail recursive
{-# INLINE foldr #-}
был от bytestring
в августе 2005 года.
Это записано в RWH и, вероятно, было популяризировано оттуда. Кроме того, в библиотеке слияния потоков, Duncan Coutts и я начали делать это много.
Из источников GHC
Идиома возвращается еще дальше. foldr
в GHC.Base дается как:
foldr k z = go
where
go [] = z
go (y:ys) = y `k` go ys
который, вероятно, там, где я подхватил трюк (я думал, что это было из тезиса Энди Гилла, но не может найти никакого использования go
там). Он не указан в этой форме в Gofer, поэтому я думаю, что это впервые появилось в базе кода GHC.
К 2001 году Саймон Марло использовал код go
в некотором коде системного уровня, поэтому мы могли бы поместить его в GHC, и этот ключ ведет нас к источник GHC, где go
широко используется в рабочих функциях:
myCollectBinders expr
= go [] expr
where
go bs (Lam b e) = go (b:bs) e
go bs [email protected](Note (SCC _) _) = (reverse bs, e)
go bs (Cast e _) = go bs e
go bs (Note _ e) = go bs e
go bs e = (reverse bs, e)
GHC 3.02 и Глазго
Выкапывая старые версии GHC, мы видим, что в GHC 0.29 эта идиома не появляется, но серия GHC 3.02 (1998), идиома go
появляется везде. Например, в Numeric.lhs
, в определении showInt
, датированном 1996-1997 гг.:
showInt n r
| n < 0 = error "Numeric.showInt: can't show negative numbers"
| otherwise = go n r
where
go n r =
case quotRem n 10 of { (n', d) ->
case chr (ord_0 + fromIntegral d) of { C# c# -> -- stricter than necessary
let
r' = C# c# : r
in
if n' == 0 then r' else go n' r'
}}
это другая реализация для приведенная в отчете H98. Однако, копаясь в реализации "Numeric.lhs" , мы обнаруживаем, что это не то же самое, что версия, добавленная в GHC 2.06 в 1997 году, и очень интересный патч от Sigbjorne Finne появляется в апреле 1998 года добавление цикла go
к Numeric.lhs.
Это говорит о том, что, по крайней мере, к 1998 году Sigbjorne добавлял циклы go
в библиотеку "std" GHC, а одновременно, многие модули в компиляторе GHC ядро имели циклы go
. Копаясь дальше, этот очень интересный коммит от Will Partain в июле 1996 года добавляет цикл "go" в GHC - код исходит от Саймона PJ, хотя!
Итак, я собираюсь назвать это идиомой Глазго, изобретенной людьми из Глазго, которые работали в GHC в середине 90-х, например Саймон Марлоу, Sigbjorn Finne, Будет ли Partain и Саймон Пейтон Джонс.