Haskell : 왜 도우미 함수의 이름을 "go"로 지정하는 규칙이 있습니까?


83

내가 볼 go하스켈 재료 나 소스를 읽을 때 많은,하지만 난 그것에 대해 정말 편안 적이 없습니다 - (나는 내 마음에 "고토"의 부정적인 내포를 가지고 추측). 나는 LYAH와 함께 Haskell을 배우기 시작했고, 그것이 내가 사용하는 경향 accstep접는 부분을 쓸 때 알게 된 곳 입니다. 글쓰기 관습은 어디 go에서 왔습니까?

가장 중요한 것은 이름이 정확히 무엇 go을 의미해야 하는가?


4
나는 보통 loop대신 내 함수 를 호출 합니다.
augustss

2
go내가 읽은 Haskell 자료에서는 본 적이 없습니다. 예 / 참조를 줄 수 있습니까?
Ionuț G. Stan

@ Ionuț 예를 들어 Yesod 책의 Enumerator 패키지에 대한 설명입니다 . (예 소드 책이 내가 모르는 주제에 너무 많은 자료를 바치는 이유는 무엇입니까?)
Dan Burton

더 나은 이름을 생각할 수 없을 때 헬퍼 함수의 이름을 "go"라고하는 C / C ++ 프로그래머를 많이 보았습니다.
ShreevatsaR

FWIW, 명시 적 꼬리 재귀 난독 화 가능성을 포함하여 여러면에서 goto의 기능적 버전입니다. 하지만 정적 입력 및 범위 지정 규칙은 혼란을 최소화하는 데 도움이됩니다. 이름 선택에 관해서는 길이와 적합성에 대한 @Michael Snoyman의 답변이 마음에 듭니다. 또한 도우미 함수가 하나만있을 때 그 이름은 크게 관련이 없어 보이 므로 일반적으로 'go'또는 'loop'중 하나를 선택 합니다 . 게으른 루프에는 'go'를, 엄격한 루프에는 "loop"를 선호합니다.
mokus

답변:


137

흠! 일부 고고학!

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 #-}

출신 bytestring2005 년 8 월.

이것은 RWH로 작성 되었고 아마도 거기에서 대중화되었을 것입니다. 또한 스트림 퓨전 라이브러리에서 Duncan Coutts와 저는 많은 일을 시작했습니다.

GHC 소스에서

관용구는 더 멀리 돌아갑니다. foldrGHC에서 Base 는 다음과 같이 제공됩니다.

foldr k z = go
      where
         go []     = z
         go (y:ys) = y `k` go ys

아마도 내가 트릭을 집어 들었던 곳일 것입니다 (나는 이것이 Andy Gill의 논문에서 나온 것이라고 생각했지만 go거기에서 어떤 용도도 찾을 수 없습니다 ). 그것은 하지 않습니다 나는이 처음 GHC 코드베이스에 등장 생각, 그래서 레이터에서이 형태로 주어진다.

2001 년, 사이먼 말로우는 사용했다 go우리는 GHC에서 비난 곳, 그리고이 단서 리드 우리 둘 수 있도록 시스템 수준 코드의 일부 GHC 소스 , go널리 작업자 기능에 사용됩니다 :

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 및 글래스고

GHC의 이전 버전을 파헤쳐 보면 GHC 0.29에서는이 관용구가 나타나지 않지만 GHC 3.02 시리즈 (1998)에서는 go관용구가 모든 곳에 나타납니다. 의 Numeric.lhs정의에있는 showInt1996-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" 구현을 살펴보면 1997 년에 GHC 2.06에 추가 된 버전과 동일하지 않으며 Sigbjorne Finne의 매우 흥미로운 패치가 1998 년 4 월에 나타납니다 . goNumeric.lhs로 루프합니다.

이는 1998 년 적어도 Sigbjorne가 추가 것을 말한다 go동시에, 많은 동안 GHC에 루프하는, 라이브러리를 "STD" GHC 컴파일러 코어 모듈은go루프를. 더 자세히 살펴보면 1996 년 7 월 Will Partain 의이 매우 흥미로운 커밋은 GHC에 "go"루프를 추가합니다 . 코드는 Simon PJ에서 가져온 것입니다!

그래서 저는 이것을 글래스고의 사람들이 발명 한 글래스고 관용구 라고 부를 것입니다. 그는 Simon Marlow , Sigbjorn Finne , Will Partain , Simon Peyton Jones 와 같이 90 년대 중반 GHC에서 일했습니다 .


4
+1은 내가 본 대부분의 용도에 일반적으로 적용되는 "꼬리 재귀 작업자 루프의 일반 이름"입니다. 함수의 경우 f, 나는 개인적으로 f'이런 종류의 이름 으로 사용 하지만 go, 일종의 키워드에 가까운 관용구로 사용하는 것은 내가 선택하려고 할 수있는 것입니다. showInt동일한 가드를 여러 번 평가하는 것을 피하기 위해 관용구를 사용 한다는 점이 흥미 롭습니다.
Dan Burton

1
BTW, "정확히 이름이 의미하는 것은 무엇입니까?" 나는 그것이 힌트라고 말하고 goto, 헬퍼 기능에 제어권을 넘겨줍니다.
Don Stewart

25
내 모호한 기억은 이것이 사이먼 PJ주의라는 것입니다. loop이미 go규칙을 사용하는 코드를 수정하지 않는 한 사용하는 경향이 있습니다 . 나는 항상 "고리를 돌다"에서와 같이 문자 그대로 "가다"를 의미한다고 생각했습니다.
Simon Marlow

5
저는 항상 "go"를 작업자 함수에 대한 더러운 재귀 노동을 시작하라는 명령으로 생각했습니다. 어쨌든 개인적으로 함수 이름에 틱을 추가하면 항상 틱을 잊을 수 있다는 문제가 있었기 때문에 스트림 퓨전 슬라이드 중 하나에서 선택했습니다.
Heinrich Apfelmus

4
나는 그것이 Haskell 이전의 기원을 가지고 있다고 믿습니다. go는 이름이 지정된
let

17

당연히 Don의 대답이 맞습니다. (당신이 직접 언급하고있는 제 글인 것 같기 때문에) 약간의 세부 사항을 추가하겠습니다. go는 두 글자 밖에 없기 때문에 좋습니다.

아, 그리고 Yesod 책이 열거 자 패키지에 너무 많은 내용을 바친 이유는 이미 블로그 포스트 시리즈로 열거 자에 대한 3 부로 구성된 자습서를 작성했기 때문에 책에 포함시키는 것이 좋습니다. 열거 자 패키지는 Yesod의 여러 곳에서 사용되므로 관련이 있습니다.


6
+1 "go"는 2 글자 (그리고 여전히 의미 있음)에 불과하다는 사실은 과소 평가하기 쉬운 사실입니다. Yesod 책의 "go"사용에 대해 언급하는 동안 (예제 imho에 대한 탁월한 이름 선택) 실제로 질문을해야한다고 느꼈을 때 "go"를 사용한 StackOverflow 답변 을 읽고있었습니다 . 그래도 기억에 남을만한 Yesod 책의 예를 즉시 기억했습니다. 좋은 물건!
Dan Burton

11

이 관용구는 선형 구조 (따라서 "루프")뿐만 아니라 분기 (나무와 같은) 구조에도 적용 할 수있을 것으로 기대합니다.

go패턴이 얼마나 자주 축적 매개 변수에 해당 하는지 ,보다 일반적으로 Mitch Wand가 논문 Continuation-Based Program Transformation Strategies (내가 가장 좋아하는 논문 중 하나) 에서 탐색 한 연속 인코딩 전략과 일치 하는지 궁금합니다 . 이 경우 go함수는 특별한 의미를 가지며, 우아한 사양에서 효율적인 코드를 도출하는 데 사용할 수 있습니다.


이러한 함수는 일반적으로 둘러싸는 범위의 변수를 참조하므로 실제로 완전하지 않기 때문에 이러한 함수에 대한 좋은 이름을 찾는 것이 종종 어렵다는 것을 언급 할 수 있다고 생각합니다. 설명이 포함 된 이름은 어리석게 보일 수 있습니다. add_x또는 consOnto_xs.
dfeuer 2014-07-27
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.