dragonteros / unsuspected-hangeul

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

값을 평가하는 순서 등에 대해서 스펙에서 명확하게 정의해야 할 것 같습니다. #7

Closed kmc7468 closed 5 years ago

kmc7468 commented 5 years ago

안녕하세요. 우선 구현체 목록에 제 C++ 구현체를 올려주신 것에 대해 감사하다는 말씀을 드리고 싶습니다. 현재 평범한 한글 스펙에는 값을 평가하는 순서에 대해 정의하고 있지 않습니다. JS, Python 레퍼런스 구현체의 경우에는 느긋한 평가를 적용하고 있고, 저의 구현체에서는 일반적인 명령형 언어에서처럼 값을 즉시 평가하는 방식을 적용하고 있습니다. 이렇게 값을 평가하는 순서가 스펙에서 정의되어 있지 않다보니 구현체에 따라 값을 평가하는 방법이 달라지기 마련이고, 이는 같은 코드의 실행 결과가 구현체마다 달라지는 결과를 낳기도 합니다.

제가 확인해 본 사례로는 팩토리얼 예제가 있습니다. 제 구현체에서는 함수를 호출하는 구문의 경우 일반적인 명령형 언어처럼 함수를 호출하기 전에 인수를 첫번째 인수부터 순서대로 평가한 후 함수를 호출하도록 구현되어 있습니다. 이 때문에 팩토리얼 예제를 제 구현체에서 실행하면 스택 오버플로우가 발생하게 되는데, 이는 중괄호 안에 있는 소괄호에 있는 값을 평가하는 과정에서 무한 루프가 발생하기 때문입니다. 그러나 레퍼런스 구현체에서는 이러한 문제가 발생하지 않습니다. 그리고 README에도 적어두셨듯이 입력을 여러 번 받는 경우 어떤 구문을 먼저 실행해야 할 지도 애매하다는 부분도 있습니다.

따라서 값을 평가하는 순서 등에 대해서 스펙에서 명확하게 정의하였으면 하는 요청을 드립니다. 감사합니다.

kmc7468 commented 5 years ago

image 추가로 제 구현체에서 함수 호출 구문의 평가 코드를 첨부합니다. 53~57번 줄에서 인수를 평가한 후 60번 줄에서 실제 함수를 호출합니다.

dragonteros commented 5 years ago

안녕하세요? 귀한 주말에 시간을 내 주셔서 기여해주시는 데 깊은 감사의 말씀을 먼저 올립니다. 본래 원칙적으로 함수형 언어는 식을 평가하는 순서가 결과에 영향을 미치지 않아야 한다는 점이 있지만, 말씀해주신대로 재귀 함수와 (부작용이 있는) 입력 함수가 걸림돌이 되고 있습니다. 한편 재귀 함수와 관련하여 언어의 구조상 느긋한 평가가 강제되다시피 한다는 점을 인정합니다. 해서 크게 두 가지 해결책이 있을텐데요,

  1. 조급한 평가를 기본으로 하고 느긋한 평가를 할 부분을 프로그래머가 명시하게 하는 방안

    • 느긋하게 평가하라는 구문을 예를 들어 기본 함수 'ㄴㄱ'에 배정한다면, 팩토리얼 예제의 대괄호 안은 [ㄴ {...} ㄴㄱㅎㄴ (...) ㅎㄷ]처럼 되겠습니다. 다만 이렇게 되면 프로그래머 쪽에서 실행 순서가 어떻게 될지 추적해야 하는 부담을 안게 됩니다.
  2. 느긋한 평가를 명시하는 방안

    • 만약 느긋한 평가를 하려고 하면, 현재 입력 함수 호출은 조급한 평가가 자연스러운 측면이 있어서 평가 순서를 정하는 데 매우 골치아픈 게 사실입니다. 그래서 느긋한 평가가 자연스러운 방식으로 행동을 변경하는 게 나을 것 같습니다. 해서, 하스켈의 IO모나드를 도입해서 평가 순서를 명시하도록 하는 것은 어떨까 생각 중입니다. 저는 이 편이 더 함수형 프로그래밍이라는 정체성에 맞지 않을까 생각합니다.
kmc7468 commented 5 years ago

답변 감사합니다. 저도 1안보다는 2안이 더 적절할 것 같다고 생각합니다.