Veo go
mucho cuando leo material o fuente de Haskell, pero nunca me he sentido realmente cómodo con eso (supongo que tiene la connotación negativa de "goto" en mi mente). Empecé a aprender Haskell con LYAH, y ahí fue donde adquirí la tendencia al uso acc
y step
al escribir pliegues. ¿De dónde go
viene la convención para la escritura ?
Más importante aún, ¿qué se go
supone que implica exactamente el nombre ?
haskell
naming-conventions
Dan Burton
fuente
fuente
loop
.go
en ningún material de Haskell que leí. ¿Puede dar un ejemplo / referencia?Respuestas:
¡Hmm! ¡Un poco de arqueología!
Desde alrededor de 2004 lo he usado
go
como nombre genérico para los bucles de trabajo recursivos de cola, cuando hago una transformación de trabajador / contenedor de una función recursiva. Empecé a usarlo ampliamente enbytestring
, por ejemplofoldr :: (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 #-}
era de
bytestring
agosto de 2005.Esto se escribió en RWH y probablemente se popularizó a partir de ahí. Además, en la biblioteca de stream fusion , Duncan Coutts y yo comenzamos a hacerlo mucho.
De las fuentes de GHC
Sin embargo, el idioma se remonta más atrás.
foldr
en GHC.Base se da como:foldr k z = go where go [] = z go (y:ys) = y `k` go ys
que es probablemente donde aprendí el truco (pensé que esto era de la tesis de Andy Gill, pero no puedo encontrar ningún uso
go
allí). No se da de esta forma en Gofer, así que creo que apareció por primera vez en la base de código de GHC.Para 2001, Simon Marlow estaba usando
go
algunos de los códigos a nivel de sistemas, por lo que podríamos echar la culpa en algún lugar de GHC, y esta pista nos lleva a la fuente de GHC , dondego
se usa ampliamente en funciones de trabajador: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 y Glasgow
Al desenterrar versiones antiguas de GHC, vemos que en GHC 0.29 este idioma no aparece, pero en la serie GHC 3.02 (1998), el
go
idioma aparece en todas partes. Un ejemplo, enNumeric.lhs
la definición deshowInt
, con fecha 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# -> -- stricter than necessary let r' = C# c# : r in if n' == 0 then r' else go n' r' }}
esta es una implementación diferente a la dada en el informe H98 . Sin embargo, al profundizar en la implementación de "Numeric.lhs" , encontramos que no es la misma que la versión que se agregó a GHC 2.06 en 1997, y aparece un parche muy interesante de Sigbjorne Finne, en abril de 1998, que agrega un
go
bucle a Numeric.lhs.Esto dice que al menos en 1998, Sigbjorne estaba agregando
go
bucles a la biblioteca "std" de GHC, mientras que simultáneamente, muchos módulos en el núcleo del compilador de GHC teníango
bucles. Profundizando más, esta confirmación muy interesante de Will Partain en julio de 1996 agrega un bucle "go" en GHC , ¡aunque el código proviene de Simon PJ!Así que voy a llamar a esto como un idioma de Glasgow inventado por personas en Glasgow que trabajaron en GHC a mediados de los 90, como Simon Marlow , Sigbjorn Finne , Will Partain y Simon Peyton Jones .
fuente
f
, personalmente la usaréf'
como el nombre de este tipo de cosas, aunque usarlago
como una especie de modismo cercano a una palabra clave es algo que podría intentar captar. Es interesante notar queshowInt
usa el modismo para evitar evaluar al mismo guardia varias veces.goto
y entrega el control a una función de ayuda.loop
menos que esté modificando un código que ya usa lago
convención. Siempre pensé que tenía la intención de significar literalmente "ir", como en "dar la vuelta al circuito".Obviamente, la respuesta de Don es la correcta. Permítanme agregar un pequeño detalle (ya que parece ser mi escritura a la que se refiere directamente): ir es bueno porque solo tiene dos letras.
Ah, y la razón por la que el libro de Yesod dedica tanto contenido al paquete del enumerador es porque ya había escrito el tutorial de tres partes del enumerador como una serie de publicaciones de blog, así que decidí que también podría incluirlo en el libro. El paquete de enumeradores se utiliza en varios lugares de Yesod, por lo que es relevante.
fuente
Espero que este idioma sea aplicable no solo a estructuras lineales (y por lo tanto "bucles"), sino también a estructuras ramificadas (en forma de árbol).
Me pregunto con qué frecuencia el
go
patrón se corresponde con los parámetros de acumulación y, en general, con las estrategias de codificación de continuación que Mitch Wand exploró en el artículo Estrategias de transformación de programas basados en la continuación (uno de mis artículos favoritos de todos los tiempos). En estos casos, lago
función tiene un significado particular, que luego puede usarse para derivar un código eficiente a partir de una especificación elegante.fuente
add_x
oconsOnto_xs
.