Hmm! Alguma arqueologia!
Desde cerca de 2004, usei go
como nome genérico para loops de trabalho recursivos de cauda, ao fazer uma transformação de trabalhador / wrapper de uma função recursiva. Comecei a usá-lo amplamente em bytestring
, por exemplo
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
{-# INLINE foldr #-}
era de bytestring
agosto de 2005.
Isso foi escrito no RWH e provavelmente foi popularizado a partir daí. Além disso, na biblioteca de fusão de fluxo , Duncan Coutts e eu começamos a fazer muito isso.
Das fontes GHC
O idioma é mais antigo. foldr
em GHC.Base é dado como:
foldr k z = go
where
go [] = z
go (y:ys) = y `k` go ys
que foi provavelmente onde aprendi o truque (pensei que fosse da tese de Andy Gill, mas não consigo encontrar nenhuma utilidade go
nela). Não é fornecido nesta forma no Gofer, então acho que apareceu pela primeira vez na base de código do GHC.
Em 2001, Simon Marlow estava usando go
em alguns dos códigos de nível de sistema, então podemos colocar a culpa em algum lugar no GHC, e essa pista nos leva à fonte do GHC , onde go
é amplamente usado nas funções de trabalho:
myCollectBinders expr
= go [] expr
where
go bs (Lam b e) = go (b:bs) e
go bs e@(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 e Glasgow
Desenterrando versões antigas do GHC, vemos que no GHC 0.29 esse idioma não aparece, mas pela série GHC 3.02 (1998), o go
idioma aparece em todos os lugares. Um exemplo, em Numeric.lhs
, na definição de showInt
, datado de 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# ->
let
r' = C# c# : r
in
if n' == 0 then r' else go n' r'
}}
esta é uma implementação diferente daquela fornecida no relatório H98 . Explorando a implementação de "Numeric.lhs" , no entanto, descobrimos que não é o mesmo que a versão que foi adicionada ao GHC 2.06 em 1997, e um patch muito interessante de Sigbjorne Finne aparece, em abril de 1998, adicionando um go
loop para Numeric.lhs.
Isso diz que pelo menos em 1998, Sigbjorne estava adicionando go
loops à biblioteca "std" do GHC, enquanto, simultaneamente, muitos módulos no núcleo do compilador GHC tinham go
loops. Indo mais longe, este commit muito interessante de Will Partain em julho de 1996 adiciona um loop "go" no GHC - o código vem de Simon PJ embora!
Então, vou chamar isso de uma expressão idiomática de Glasgow inventada por pessoas em Glasgow que trabalharam com GHC em meados dos anos 90, como Simon Marlow , Sigbjorn Finne , Will Partain e Simon Peyton Jones .
loop
vez disso, geralmente chamo minha função .