dragonteros / unsuspected-hangeul

함수형 난해한 언어 '평범한 한글'의 명세와 구현체입니다.
MIT License
56 stars 0 forks source link

재귀 중 출력 #10

Closed dhnam closed 5 years ago

dhnam commented 5 years ago

0에서 8까지 출력하는 프로그램을 만들어보려 했습니다.

ㄱ [((ㄱㅇㄱ ㅁㅈㅎㄴ ㅈㄹㅎㄴ) (ㄱㅇㄱ ㄷ ㄷㅎㄷ ㄱㅇㅎㄴ) (ㄱㅇㄱ ㄱㄴㄱ ㄴㅎㄷ) ㅎㄷ) ㅎ] ㅎㄴ

일단 8을 출력하기는 하는데, 0에서부터를 출력하는 방법이 막막합니다.

파이썬으로 바꿔 생각하면 지금 코드는

f = lambda x: print(x) if x == 8 else f(x + 1)
f(0)

이건데, 파이썬에서 중간 과정을 출력하기 위해 이런 방법을 생각해냈습니다.

f = lambda x: print(x) if x==8 else f(0 if x==print(x) else x + 1)
f(0)

조금 꼼수죠. 아무튼 0에서 8까지 출력은 잘 합니다. 이걸 평범한 한글로 옮겨봤습니다.

ㄱ [((ㄱㅇㄱ ㅁㅈㅎㄴ ㅈㄹㅎㄴ) (((ㄱ) (ㄱㅇㄱ ㄷ ㄷㅎㄷ) (ㄱ (ㄱㅇㄱ ㅁㅈㅎㄴ ㅈㄹㅎㄴ) ㄴㅎㄷ) ㅎㄷ) ㄱㅇㅎㄴ) (ㄱㅇㄱ ㄱㄴㄱ ㄴㅎㄷ) ㅎㄷ) ㅎ] ㅎㄴ

그런데 8 한번만 출력이 됩니다.

언어 명세상 그렇게 되는 건가요? 아니면 자바스크립트 구현상 오류인가요?

dragonteros commented 5 years ago

@dhnam 님, 안녕하세요? 먼저 평범한 한글에 깊은 관심을 주신 데 감사드립니다. 결론부터 말씀드리면, 명세에 따른 행동이 맞습니다.

@dhnam 님께서 '꼼수'라고 언급하신 파이썬 코드는 '부작용(side-effect)'를 사용한 방법인데요, 함수형 언어는 통상 부작용을 허용하지 않는 경향이 있고, 평범한 한글 또한 그렇습니다.

파이썬의 print(x) 표현식은 인터프리터가 평가하는대로 출력(부작용)이 이루어지는 반면, 평범한 한글의 ㄱㅇㄱ ㅁㅈㅎㄴ ㅈㄹㅎㄴ 표현식은 나중에 출력하겠다는 약속을 담은 객체일 뿐으로, 평가 당시에는 부작용을 실행하지 않는 점이 차이가 있습니다.

의도하신대로 0에서 8까지 차례로 출력하는 프로그램은 다음과 같이 짤 수 있겠습니다.

ㄱ
[ def print_and_call_this_again (x):  # Number -> IO
    {ㄱㅇㄱ ㅁㅈㅎㄴ ㅈㅀㄴ}  # Print(x)
    { def recursion_caller (unused):  # Nil -> IO
        (ㅂㄱㅎㄱ ㄳㅎㄴ)  # return Wrap(Nil())
        (ㄱㅇㄴ ㄴ ㄷㅎㄷ ㄴㅇㅎㄴ)  # return print_and_call_this_again(x+1)
        (ㄱㅇㄴ ㄱㄴㄱ ㄴㅎㄷ) ㅎㄷ  # if x == 8 ... else ...
    ㅎ}
    ㄱㅀㄷ  # return Bind(Print(x), recursion_caller)
ㅎ]
ㅎㄴ  # returns an IO Object

만약 IO 객체를 JS의 Promise처럼 생각한다면 위 코드를 다음과 같이 JS로 표현할 수 있겠습니다.

function Print (x) {
  return new Promise(function (resolve, reject) {
    console.log(x)
    resolve(null)
  })
}

function Wrap (x) {
  return Promise.resolve(x)
}

function print_and_call_this_again (x) {
  function recursion_caller(_) {
    return (x == 8) ? Wrap(null) : print_and_call_this_again(x+1)
  }
  return Print(x).then(recursion_caller)
}

print_and_call_this_again(0)
andrea9292 commented 5 years ago

아.... 지난 밤 이거 해결해보려고 머리를 싸맸는데... 역시 @dragonteros 님이 깔끔한 해답을 주셨네요. 저도 처음에 print(x) 를 저런 식으로 정의하고 시작했는데 중간에 드나듦 객체 쓰는 것이 익숙하지 못해서 코드가 마구마구 꼬여버렸습니다. 제시해주신 코드 분석하면서 또다시 평범한 한글에 푹 빠져보렵니다~ 아직까지 리커전 많이 공부해야 할 거 같아요.

dhnam commented 5 years ago

친절한 답변 감사드립니다.

andrea9292 commented 5 years ago

@dhnam 님께서 고민해주신 덕분에 저도 큰 공부가 되었습니다. 혹시 '평범한 한글'의 드나듦에 대해서 제가 쓴 글이 있는데 작으나마 도움이 되었으면 좋겠습니다. ^^

dhnam commented 5 years ago

@andrea9292 님 글 보면서 공부했습니다. 도움 많이 되었습니다.