go
Dużo widzę czytając materiał lub źródło Haskella, ale nigdy nie czułem się z tym komfortowo - (myślę, że ma to negatywne konotację „goto”). Zacząłem uczyć się języka Haskell z LYAH i wtedy wychwyciłem tendencję do używania acc
i step
pisania fałd. Skąd się wzięła konwencja pisania go
?
A co najważniejsze, co dokładnie go
ma oznaczać ta nazwa ?
haskell
naming-conventions
Dan Burton
źródło
źródło
loop
zamiast tego wzywam moją funkcję .go
w żadnym materiale Haskella, który czytałem. Czy możesz podać przykład / odniesienie?Odpowiedzi:
Hmm! Trochę archeologii!
Od około 2004 r. Używam
go
nazwy ogólnej dla ogonowych rekurencyjnych pętli roboczych podczas wykonywania transformacji pracownika / opakowania funkcji rekurencyjnej. Zacząłem go szeroko stosowaćbytestring
npfoldr :: (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 #-}
był z
bytestring
sierpnia 2005 roku.Zostało to zapisane w RWH i prawdopodobnie stamtąd zostało spopularyzowane. Ponadto Duncan Coutts i ja zaczęliśmy to często robić w bibliotece stream fusion .
Ze źródeł GHC
Idiom sięga jednak dalej.
foldr
w GHC.Base jest podana jako:foldr k z = go where go [] = z go (y:ys) = y `k` go ys
na którym prawdopodobnie podjąłem sztuczkę (myślałem, że to z pracy Andy'ego Gilla, ale nie mogę tam znaleźć żadnego zastosowania
go
). Nie jest podawany w tej formie w Gofer, więc myślę, że po raz pierwszy pojawił się w bazie kodu GHC.Do 2001 roku Simon Marlow używał
go
w niektórych kodach na poziomie systemu, więc możemy przypisać winę gdzieś w GHC, a ta wskazówka prowadzi nas do źródła GHC , gdziego
jest szeroko stosowany w funkcjach roboczych: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 i Glasgow
Odkopując stare wersje GHC, widzimy, że w GHC 0.29 ten idiom się nie pojawia, ale w serii GHC 3.02 (1998)
go
idiom pojawia się wszędzie. PrzykładNumeric.lhs
w definicjishowInt
z lat 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' }}
jest to inna implementacja niż ta przedstawiona w raporcie H98 . Zagłębiając się w implementację „Numeric.lhs” , okazuje się jednak, że nie jest to to samo, co wersja dodana do GHC 2.06 w 1997 r., A bardzo interesująca łatka od Sigbjorne Finne pojawia się w kwietniu 1998 r., Dodając
go
pętla do Numeric.lhs.Oznacza to, że przynajmniej do 1998 roku Sigbjorne dodawał
go
pętle do biblioteki „std” GHC, podczas gdy jednocześnie wiele modułów w rdzeniu kompilatora GHC miałogo
pętle. Idąc dalej, to bardzo interesujące wydanie Willa Partaina z lipca 1996 roku dodaje pętlę „go” do GHC - kod pochodzi jednak od Simona PJ!Nazywam to więc idiomem Glasgow wymyślonym przez ludzi z Glasgow, którzy pracowali nad GHC w połowie lat 90., takich jak Simon Marlow , Sigbjorn Finne , Will Partain i Simon Peyton Jones .
źródło
f
osobiście zwykle używamf'
jako nazwy dla tego rodzaju rzeczy, chociaż używaniego
jako czegoś w rodzaju idiomu zbliżonego do słowa kluczowego jest czymś, co mógłbym spróbować złapać. Ciekawe, żeshowInt
używa idiomu, aby uniknąć wielokrotnej oceny tego samego strażnika.goto
przekazania kontroli funkcji pomocniczej.loop
chyba że modyfikuję kod, który już korzysta zgo
konwencji. Zawsze myślałem, że to znaczy dosłownie „idź”, na przykład „obejdź pętlę”.Oczywiście odpowiedź Dona jest prawidłowa. Pozwólcie, że dodam tylko mały szczegół (ponieważ wydaje się, że jest to moje pismo, do którego bezpośrednio się odnosicie): go jest fajne, ponieważ składa się tylko z dwóch liter.
Aha, a powodem, dla którego książka Yesod poświęca tak dużo treści pakietowi modułu wyliczającego, jest to, że napisałem już trzyczęściowy samouczek enumeratora jako serię postów na blogu, więc zdecydowałem, że równie dobrze mogę go włączyć do książki. Pakiet modułu wyliczającego jest używany w wielu miejscach w Yesod, więc jest istotny.
źródło
Spodziewałbym się, że ten idiom będzie miał zastosowanie nie tylko do struktur liniowych (a więc „pętli”), ale także do struktur rozgałęzionych (drzewiastych).
Zastanawiam się, jak często
go
wzór odpowiada parametrom akumulacji i, bardziej ogólnie, strategiom kodowania kontynuacji, które Mitch Wand zbadał w artykule Continuation-Based Program Transformation Strategies (jednym z moich ulubionych artykułów wszechczasów). W takich przypadkachgo
funkcja ma szczególne znaczenie, które można następnie wykorzystać do wyprowadzenia wydajnego kodu z eleganckiej specyfikacji.źródło
add_x
lubconsOnto_xs
.