[질문] Scheme에서 수식 표현방법
글쓴이: 김영재 / 작성시간: 목, 2005/03/10 - 12:51오전
(* (+ 2 (* 4 6))
(+ 3 5 7))
위와 같은 수식은 Scheme언어에서 사용하는 표현방법입니다.
영어에서는 위와 같은 표현이 자연스러울지도 모르겠습니다.(이점에서 약간의 의문이 생기기도 하는 것은 한단계 정도의 수식 예를 들면 (* 4 6) 정도야 영어에서의 표현과 완전히 일치하는 흐름으로 이루어 진다 하더라도 이와같이 여러 단계의 수식을 과연 영어의 사고 흐름에서 자연스럽게 표현될 수 있는 것인가 하는것 이구요)
하지만 한국어에서는 지극히 부자연스런 표현 방법인데 이걸 극복하는 방법이 없을까요?
Forums:
영어에서 어떻게 (* 4 6)이 자연스러운 표현인지는 잘 모르겠습니다만,
영어에서 어떻게 (* 4 6)이 자연스러운 표현인지는 잘 모르겠습니다만, 일단 연산자가 먼저 오는 방식의 표현법은 이미 너무나 친숙한 표현입니다.
if <cond> then <tclause> else <fclause>
와 같은 형식이라던지, 각종 함수들을 쓰는 방법이 전부 그런 방식이지요.
scheme에서는 그런 개념을 사칙연산에 까지 극단적으로 적용한 경우입니다.
그리고 어떤 것이 읽기가 편한가는 사실 논란의 여지가 많습니다.
참고로 scheme코드를 제대로 쓰는 방법은 layout을 잘 활용하는 방법으로,
괄호를 될 수 있으면 없다고 생각하고 코드를 읽으시면 편리합니다.
[quote="정재윤"]영어에서 어떻게 (* 4 6)이 자연스러운 표현인
음... 영어에서 자연스러운 표현이라고 한 것은 제가 SICP를 쓴
Sussman(?)의 강의를 다운받아서 들어봤는데 (* 4 6)을 쓰면서
sum of four and six라고 말하더군요. 그래서 자연스럽다고 글을 쓴 것입니다. 일반적으로 영미인들이 이렇게 읽는지는 모르겠구요.
layout을 활용하라는 말씀이 어떤 것인지 좀 상세히 말씀해 주실 수 없으세요? 괄호가 없다고 생각하고 읽으니 수식을 도당체 읽지를 못하겠네요.ㅠㅠ
수식의 언어적 표현 측면보다는 데이터 구조적인 면을 생각해야할듯하군요.
수식의 언어적 표현 측면보다는 데이터 구조적인 면을 생각해야할듯하군요.
언급하신 것은 수식을 읽는 방법이고요.
간단히 말해서... 스택에 prefix 수식을 그대로 집어넣은 후에, 하나씩 꺼내면서 수식을 평가한다고 생각해보세요.
연산자를 만나면 일단 수식을 평가하면서 스택이 비워질때까지 계속하면 수식의 평가가 끝나는거죠.
-----
오늘 나의 취미는 끝없는, 끝없는 인내다. 1973 法頂
스택에 집어넣었다 빼가면서 평가하는 것은 컴퓨터가 수식을 계산할 때 다
스택에 집어넣었다 빼가면서 평가하는 것은 컴퓨터가 수식을 계산할 때 다 하는 방식인 것으로 알고 있습니다. 그렇게 생각하는 것은 뭐, 많이 알려져 있으니까요.
한데 제가 말하고 싶은 것은 이렇게 prefix형으로 표현할 경우 코딩할 때 불편하다는 것이죠. 예를 들어 수식으로 2+4*5-2/2-2
라고 써야할 때 C 같으면 우선순위에 자신이 없으면 그냥 괄호만 잔뜩 쳐주면 될텐데 이걸 Scheme처럼 prefix로 표현할려면 한참 생각해서 바꾸어 주어야 할 텐데 이걸 그냥 중위형으로 쓰듯 좀 자연스럽게 할 수 없겠는가 하는 게 궁금한거죠.
다른 언어를 하세요 :D연산자를 앞에 쓰는건 Scheme의 규칙입니다
다른 언어를 하세요 :D
연산자를 앞에 쓰는건 Scheme의 규칙입니다. 어쩔 수 없답니다.
추가: 언어를 바꿀 여건이 안된다면, 익숙해지는 수 밖에 없습니다. 제가 했었을 때는 3개월쯤 부터는 손에 익어서 수식 보는대로 옮길 수 있었습니다. :evil:
[quote="김영재"]한데 제가 말하고 싶은 것은 이렇게 prefi
흠.. 정 그러시다면, 간단히 infix -> prefix변환을 해주는 프로그램을 만들어서 쓰세요. 내공이 쌓이시면 macro를 사용해서 만들면 됩니다. 실제로 그런 것들이 나와 있는 것도 있구요.
앞에 얘기한데로 function call은 prefix notation으로 잘 쓰면서도 수식에서만 유독 infix를 쓰는게 과연 더 직관적인가 하는 것도 생각해 볼만한데요. 대부분의 경우에 수식에 대해서 만큼은 infix가 더 익숙한 관계로 언어들이 그걸 포함해서 만들게 되지만, scheme은 길어야 몇 시간이면 일단 못 읽을 코드가 없을 만큼 단순한 문법구조를 고려한 구조임을 생각하시고 받으들이세요 :)
layout은 음 여기서 설명할려고 해도 indent가 맘대로 변해서 설명하기 쉽지 않네요. 코드 자체를 괄호를 사용해서 syntax tree를 써 놓은 것이라고 생각해 보세요. 그 tree구조를 한눈에 파악할 수 있도록 평면상에 코드를 펼쳐 놓는 방법이라고 생각하시면 됩니다. 보통 제대로 짜진 Lisp계열 코드들은 다 그렇게 되어 있습니다. SICP의 코드들도 물론이고요. 편집기들도 이런 tree구조(흔히 s-expression이라고 합니다.)단위로 조작을 할수 있도록 합니다. 상위 노드로 이동, 같은 레벨의 다음/이전으로 이동, 새 노드 만들기, 현재 tree이하를 짤라서 다른 곳으로 이동 등등... 여튼 실제 프로그램을 할때는 괄호에 연연하지 않게 되고, 코드의 들여쓰기가 얼마나 잘 되어 있는가가 코드를 읽기가 얼마나 쉬운지를 결정하게 됩니다. 가끔 괄호를 제멋대로 쓰는 코드에 대해서 감점을 하는 경우가 있는 경우도 이 때문입니다. 많은 사람들이 이런 부분에 대해서 교육받지 못하고, 그 결과 괄호가 반쯤되는 미친언어를 도대체 왜 만들고 쓰는지 이해를 못 하게 되죠.
C/Java등에서도 같은 개념을 사용하면 비슷하게 편리하게 코드를 작성할 수 있습니다. emacs는 모든 프로그램 모드들이 sexp단위 조작을 기본으로 하는 명령어들 가령 M-(, M-), C-M-u, C-M-d, C-M-n, C-M-p, C-M-k등등을 제공합니다. Eclipse같은 데서도 Alt + Shift + [up|left|right] 등이 비슷한 방식으로 코드를 조작할 수 있도록 하고 있죠. 편집을 할 때, 생각하는 단위가 코드의 의미 있는 한 단위 (문장, 블럭, 함수 전체, 등등..)로 생각을 하고 이 단위로 조작을 하는 경우가 대부분이지만, 막상 편집을 할 때는 shift-left, ...., C-x, up, left, ...., C-v 이런 식으로 편집을 하시는 분들이라면 한번쯤 생각을 해보시면 도움이 되실 겁니다.
lisp계열 프로그래머 들은 괄호가 없는 것 처럼 코드를 읽습니다. SICP 아무대나 있는 코드를 하나 가져다가, 에디터가 기능을 지원한다면 괄호를 연하게 만들거나 아니면 아예 괄호를 지워보시면 어디서 많이 보던 코드와 아주 흡사함을 아실 겁니다. 바로 python 이죠. :p
@에구 아침부터 잡설이 길었네요. 그럼 좋은 하루 되세요~
Re: [질문] Scheme에서 수식 표현방법
수식만 보자면 영어라고 자유로운 표기법일까요?
1 + 3이 있다면 한국어로 한다면 1 더하기 3 혹은 1과 3의 합이라고도 할 수 있을 것입니다. 얼마나 많은 사람들이 저 식을 보고 후자를 생각할까요? LISP이나 SCHEME의 표현은 문법적인 일관성을 위해서 희생한 것이겠죠. algol-like언어에서 1 + 3이라고 표현하는 것이 오히려 영미권 사람들에게도 자연스러울 겁니다. (그래서 연산자 만이 다른 키워드, 함수 호출과 다른 문법을 가지게 된 것일겁니다.)
이렇게 생각해 볼수 도 있습니다.
1 + 2 * 3 + 4
에서 왜 2 * 3을 먼저 해야하죠? 사람이나 algol-like 언어에서는 우선순위를 두고 생각하고 있습니다.
사람에게 자유로운 표현을 희생하면 아래와 같이 쓸수 있습니다.
++1*234
이건 언어 전체 문법의 일관됨을 보장하며 우선순위와 같이 새롭게 추가되는 규칙이 없습니다.
K.I.S.S만을 생각한다면 Lisp-like language의 문법이 더 진리에 가까울 것입니다.
하지만 나는 Scheme에 손을 들어주지는 않을 것 같습니다. 프로그래머가 원한다면 1 + 2 * 3 + 4를 쓸 수 있어야 한다고 생각합니다. (그런 면에서 프로그래머의 자유를 구속하는 j모 언어에 대해서도 그렇게 긍정적이지 않습니다.)
- 죠커's blog / HanIRC:#CN
> 하지만 나는 Scheme에
> 하지만 나는 Scheme에 손을 들어주지는 않을 것 같습니다. 프로그래머가 원한다면 1 + 2 * 3 + 4를 쓸 수 있어야 한다고 생각합니다.
Lisp류에서는 실제로 그렇게 합니다. Lisp 프로그래머라면 prefix가 더 수월한 것이 사실이지만, 만일 어떤 소프트웨어 툴이 embedded language를 갖고 Lisp 프로그래머가 아닌 이들이 최종 사용자이며, 그 언어를 Lisp류로 작성한다면 infix기능을 추가하기도 합니다. 이렇게 추가된 놈은 그 embedded language에서도 사용할 수 있지만, 개발언어인 Lisp류의 언어에서도 사용할 수 있게 되는 겁니다.
프로그래밍 언어는 약속이죠. 인간의 언어에 가까울수록 컴파일러 작
프로그래밍 언어는 약속이죠.
인간의 언어에 가까울수록 컴파일러 작성에 어렵고
컴파일러한테 쉬울수록 인간의 사고는 경직되게 하죠.
지향하는 도메인에 따라 적절한걸 쓰는게 좋을거 같습니다.
---------
간디가 말한 우리를 파괴시키는 7가지 요소
첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스
이익추구를 위해서라면..
다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치
[quote="IsExist"]인간의 언어에 가까울수록 컴파일러 작성에
동의하지 않습니다.
표현력이 뛰어난 언어들은 대개 간결한 문법들을 가지고 있습니다. 간결한 문법은 간결한 컴파일러를 만듭니다.
인간의 언어에 가까울 수록 인간의 사고의 폭이 넓어진다고는 생각하지 않습니다. 화성을 들어본 적 없는 모짜르트는 영원히 화성음악을 할 수 없다고 합니다.
패러다임의 공부가 중요한 것입니다. 다른 패러다임이 다른 사고를 하게 합니다.
- 죠커's blog / HanIRC:#CN
모짜르트의 이야기가 사실인가요?
주제와는 상관없습니다만 대위법은 모짜르트 전시대인 바흐가 완성했다고 들었고,
모짜르트는 지식도 감각 못지않게 뛰어났다고 아는데요.
ALGOL류 언어들에서는
ALGOL류 언어들에서는 연산자 우선순위를 염두해야 합니다.
1 + 2 + 3 * 4 / 5 - 6
괄호로 묶이는 LISP류 언어들에서는 그런게 없어서 편했습니다.
(- (+ 1 2 (/ (* 3 4) 5)) 6)
괄호만 쓴다면
괄호로 묶으면 ALGOL이 아니라 ALGOL 할아버지가 와도 연산자 우선순위를 염두에 둘 필요가 있겠습니까.
제대로 비교하기 위해서는
1 + 2 + 3 * 4 / 5 - 6
- + 1 2 / * 3 4 5 6
이 둘을 비교하거나
(1 + 2 + ((3 * 4) / 5)) - 6
(- (+ 1 2 (/ (* 3 4) 5)) 6)
이 둘을 비교해서 어떤게 이해하기 쉬운지를 논해야 공평하지 않을까요.
-----
http://monpetit.posterous.com/
http://monpetit.tistory.com/
Lisp류는 괄호가
Lisp류는 괄호가 강제이고 다른 류는 그렇지 않다는 것이죠. 즉, Lisp 에서 (- (+ 1 2 (/ (* 3 4) 5)) 6) 를 표현하는 방법은 오직 그방법 밖에는 없다는 겁니다. 고민할 필요가 없는 것이죠.
Lisp 류에서는 때때로 코드를 데이터로 보고 처리하기 때문에 해보면 prefix 스타일이 의외로 잇점이 많습니다 - 오퍼레이션은 괄호 바로 다음 것, 나머지는 인자로 생각하고 처리하면 되기 때문이죠. 다른 프로그래밍 언어에서는 대체로 코드는 코드, 데이터는 데이터로만 사용하는 경우가 많기 때문에 prefix가 불편할 수 있죠.
요약하면, Lisp류에서 prefix는 프로그래머가 큰 힘을 발휘하게 해준다. 다른 류의 언어에서는 prefix는 골치덩어리다.
중위표기가 오히려 tree 에 가까워 보이지 않나요?
통상 이항 tree 를 표현할 때 부모는 위에 놓는 것만이 아닌 좌측 자식과 우측 자식의 가운데에 그립니다.
단지 layer 적인 개념만이 아니라 두개의 자식과 동등한 관계를 맺는 사이의 그 무엇이라고 할 수 있죠.
즉 관계개념으로 본다면 중위표기가 전위표기나 후위표기보다 직관적인 구조를 보여줍니다.
왜 중위표기를 괄호를 써가면서까지 쓰는 것이 이해하기 편한가하는 것은 저 역시 사람들이 익숙하기 때문이라는 것이
가장 큰 이유라고 생각하지만 전체를 구조로 이해하기 위한 의도에서 비롯되었다고 생각합니다.
달리 말하면 전위표기나 후위표기 역시 사회적으로 약속하고 훈련하면 분명 중위표기보다 이해하기 편해하겠지만
분명 중위표기에는 장점이 있다고 봅니다.
왜 전위표기나 후위표기를 이해하기 어려운 학생들이 parse tree 를 그려주면 이해하기 편해할까요?
단지 수식이 갖고 있는 가치가 연산과정만이 아니라 구조의 표현에 있기 때문이 아닐까요?
만일 전위표기나 후위표기가 사회적 약속이라면 parse tree 를 보고 이해하기가 쉬울까요?
비록 중첩구조에 있어 중위표기는 괄호를 쓰지 않으면 안되지만 명확한 괄호를 통해 보는 중위표기가 구조적 이해에 가장 좋다고 봅니다.
차원문제랄까요? 2차원인 수식구조 및 연산과정을 1차원으로 표현할 때 어떻게 하는 것이 좋은가라는 문제말입니다.
연산이 2차원모델인 전위표기및 후위표기를 쓸 것인가, 아니면 표현이 2차원과 유사한 중위표기를 쓸 것인가?...
수학을 잘하는 사람들은 구조와 pattern 을 잘 찾아내고 이해하는 사람들이라고 들었습니다.
이것을 모든 사람들에게 명확히 보여주기 위하여 어떤 표현을 쓰는 것이 좋았을까요?
현재의 compiler 는 text token 들을 선형적으로 받아서 처리하는데 만일 그림형태의 prgram 이 있다면 어떨까하는 생각이 드는군요.
순서도의 가치가 재평가되지 않을까요?
제가 보기에는
간단한 수식인 경우 전위 표기, 후위 표기가 익숙해지면 일반적인 중위 표기보다 편할 수도 있다고 보입니다.
(+ 3 4) 구문을 sum( 3, 4) 이렇게 이해한다면 크게 어려움이 없다고 보입니다.
(물론 ()가 계속 중첩하기 시작하면 이야기가 달라지겠죠.-_-;)
별도로 전위 표기 사용하는 scheme같은 언어가 개념적으로 간단하고 여러가지 장점이 있음에도 대중적인 성공을 거두지 못한 이유에는 집중의 문제가 있는 것 같습니다.
scheme에서 어떤 기능을 이해하려면 (의 시작과 )끝 부분 안에 있는 내용 전체를 파악해야 어려움이 있습니다.
상대적으로 일반 절차형 언어는 사용자가 이해하려는 영역을 의도적으로 끊고 집중하기가 쉬워서 코드 크기가 좀 길어지면 생산성 차이가 발생하는 것이 아닐까 생각됩니다.
> scheme에서 어떤
> scheme에서 어떤 기능을 이해하려면 (의 시작과 )끝 부분 안에 있는 내용 전체를 파악해야 어려움이 있습니다.
처음 듣는 이야기인데, Lisp류의 프로그래밍 언어 사용하시는 분중 이러한 어려움 겪는 분 있나 궁금합니다.
> 상대적으로 일반 절차형 언어는 사용자가 이해하려는 영역을 의도적으로 끊고 집중하기가 쉬워서 코드 크기가 좀 길어지면 생산성 차이가 발생하는 것이 아닐까 생각됩니다.
코드가 길어지면 Lisp류의 프로그래밍 언어가 생산성이 떨어진다는 의미라면 객관적 근거가 있는 지 알고 싶네요. Lisp류 프로그래밍 언어 사용해보신 적은 있으신가요?( Elisp, AutoLisp, Scheme, Common Lisp, ...)
특정 언어를 비하하려는 것은 아닙니다.
개인적인 생각이라고 단서를 달 것을 객관적인 것처럼 그렸군요.
emacs를 쓰다보니 lisp에 관심 있어서 현재 공부하고 있습니다.
언어적으로 우아하게 느껴짐에도 아직 제가 미숙해서인지 구조 파악에 어려움을 겪으면서 느낀 점입니다.
간혹 ()가 10줄 정도 이상 걸쳐 있게 되면 쉽게 집중할 수 없더군요.
elsip보다 sbcl+ slime으로 common lisp을 보고 있습니다.
저 같은 경우, (a (b (c
저 같은 경우,
(a (b (c (d 123))))
보다는
123.d().c().b().a()
와 같이 이어진 것이 더 읽기 편하더군요. 조금 다른 경우이긴 한데…
주제와는 별로 관련이 없지만...
스킴으로 다항식을 "적당히 처리"(?)하는 프로그램을 만든 적이 있는데, 연산자가 리스트의 맨 앞에 오는 것 덕분에 식을 처리하는 것(입력 받은 식이 다른 식들의 덧셈으로 이루어져 있는지, 곱셈으로 이루어져 있는지 구분하는 것)을 쉽게 할 수 있었습니다.
그러나 스킴으로 프로그램을 만드는 것이 이런 점에서는 불편했습니다. 예를 들어 (+ (- 3) (- 5) 7 4)를 (+ 3 5 7 4)로 바꾸려면 식안의 -를 제거하면서 -가 몇 개인지 세야 하는데, -를 세는 함수와 -를 제거하는 함수를 따로 만드는 방법 말고는 방법이 안 보였습니다. C언어에서는 -가 나올 때마다 count++를 해주면 될텐데, 스킴에서는 너무 돌아가면서 코딩하는 기분이 들었습니다.
스킴 코드를 gvim에서 열어 보면 괄호가 빨간 색으로 표시되어 나옵니다. (분명 괄호의 짝은 맞습니다.). 커서를 움직여 주어야 빨간 색이 사라집니다. 괄호가 너무 많아서 그런 것 아닐까요? (스킴과 관련된 조삼모사 중에 "괄호만 봐도 토나와~"라는 대사도 있습니다.) 어쨌튼 괄호가 많아서 타이핑하기도 힘들고 코드를 읽는 것도 헷갈립니다.
begin{signature}
THIS IS SPARTA!!!!!n.
end{signature}
> 예를 들어 (+ (- 3) (-
> 예를 들어 (+ (- 3) (- 5) 7 4)를 (+ 3 5 7 4)로 바꾸려면 식안의 -를 제거하면서
(+ (- 3) (- 5) 7 4) 가 아니라 (* (- 3) (- 5) 7 4)를 (* 3 5 7 4)로 바꾸는 문제겠죠?
> -가 몇 개인지 세야 하는데, -를 세는 함수와 -를 제거하는 함수를 따로 만드는 방법 말고는 방법이 안 보였습니다.
> C언어에서는 -가 나올 때마다 count++를 해주면 될텐데, 스킴에서는 너무 돌아가면서 코딩하는 기분이 들었습니다.
글쎄요. 그 방법은 C 같은 언어에 중독되었기 때문에 일어나는 일이 아닌가 합니다. 실제로 머리 속에서 그러한 일을 어떻게 하는가 생각해 보세요. 아마 다음과 비슷하지 않을까 합니다.
1. * 연산인 경우 다음을 고려한다.
2. 인자가 "(- x)" 와 같은 형태인 경우 '홀수' 와 '짝수' 사이를 왔다갔다 하도록 하면서 "x"만을 수집한다.
3. 마지막에 짝수이면 이제까지 수집한 것을 "(* ...)" 형태로 나열한다. 홀수이면 "(- (* ...))" 형태로 나열한다.
4. 위의 내용을 재귀적으로 프로그래밍 한다 (모든 임의의 수식에 대해 처리)
Scheme으로는 아마 3분내로 그런 코딩을 마칠 수 있을 겁니다.
아 그렇군요.
합치는 방법을 몰라서 그런 것은 아니고, 어제 정신이 없어서 착각했습니다.
p.s. C언어(또는 그 비슷한 언어)에 중독되지 않았어요.
begin{signature}
THIS IS SPARTA!!!!!n.
end{signature}
> p.s. C언어(또는 그
> p.s. C언어(또는 그 비슷한 언어)에 중독되지 않았어요.
다행이군요. 그런데 왜 그렇게 처리하는 것이 C보다 어렵다고 했는지는 아직도 의문입니다.
한번 C와 Scheme 으로 각각 C와 Scheme 의 임의의 사칙연산을 입력으로 받아 결과를 출력하는 인터프리터를 만들어보세요. C용 입력은 C에서 문법에 맞는 임의의 식이 되어야 하며, Scheme용은 Scheme 문법에 맞는 임의의 식이 되어야 합니다. 각각 프로그램을 작성해 보고 차이가 있는지 도대체 어디서 그런 차이를 보이게 되었는지 생각해 보세요. '토할것 같은 괄호'와 Prefix가 그 차이에 대부분을 기여한 것을 깨닫게 될겁니다. :)
댓글 달기