상세 컨텐츠

본문 제목

3. LISP의 기초 및 필수 기본 함수 설명과 예제 2부

IT & Programming/LISP 공부

by 그림아이 2022. 1. 25. 08:00

본문

반응형

이전 시간에 이어 LISP의 기초 및 필수 기본 함수 설명과 예제를 진행합니다.

 

가장 좋은 방법은 손으로 직접 그려보는 것이다. 지금은 직접 태극 무늬 하나를 AutoCAD 이용해서 그려보는 방법을 택했다.

 

원 작도 예제-1

일단 모양을 만든 위와 같이 point들의 위치를 지정하고, 원의 지름을 적어둔다. 그리고 아직 끝난 것이 아니다. P4 P5 위치를 지정하려면 거리와 각도가 필요하다.

 

원 작도 예제-2

 

AutoCAD의 좌표계와 같이 오른쪽 방향이 0도 이므로 P5는 P1을 기준으로 45도 각도와 30.5521 거리만큼 떨어져 있다. P4는 P5와 거리는 같고 각도는 45+180, 즉 225도만큼 떨어져 있다. 그런데 여기서 가장 중요한 사실은, LISP에서의 각도는 Radian 값이라는 것이다.


그리고, 여기서도 프로그래머들의 특징들이 보여지는 증거로 소수점 개수를 들 수 있다. 일단 손 가는 대로 그냥 그린 그림이라지만 소수점 개수를 굳이 4자리까지 할 필요는 없다. 하지만 저자 본인의 정확하게 하고 싶은 욕심 또는 습관이므로 이해해주길 바란다.


그럼 이제 프로그램을 본격적으로 만들어보자. 우선 초보 여러분들은 눈으로 보기만 해도 된다.

 

(defun c:tg (/ p1 p2 p3 p4 p5)
  (setvar “osmode” 0)
  (setvar “cmdecho” 0)
  (setvar "blipmode" 0)
  (if nil (tblsearch "layer" "taeguk")
       (command "layer" "m" "taeguk" "c" "7" "" "")
  ) ; end of if
  (setq p1 (getpoint "\nPick the center point of TAEGUK : "))
  (setq p2 (polar p1 (dtr 180.0) 43.2072))
  (setq p3 (polar p1 (dtr 0.0) 43.2072))
  (setq p4 (polar p1 (dtr 225.0) 30.5521))
  (setq p5 (polar p1 (dtr 45.0) 30.5521))
  (command “circle” p1 43.2072)
  (command “arc” p2 p4 p1)
  (command “arc” p1 p5 p3)
  (setvar “cmdecho” 0)
  (prompt “\nProgram has been completed!!!”)
  (princ)
) ; end of defun

(defun dtr (a) (* (/ a 180.0) pi))

설명은 잠시 뒤로 미루고 루틴 전체를 복사해서 vlisp editor 옮긴 , 위에서 배운 것처럼 ctrl + alt + E load 해보자. 그리고 명령어인 tg command 창에 입력 마우스로 아무 곳이나 선택해 보자. 만약 error 없이 실행이 되었다면 “Program has been completed!!!” 라는 메시지와 함께 도면 상에 태극 무늬가 생성되었을 것이다. 반복해서 명령을 실행하여 아래와 같이 여러 개를 생성해 보자.

 

원 작도 예제-3

바로 우리가 LISP을 공부하는 이유가 여기에 있다. 대량 생산, 시간 및 투입 인원 절약, 정확성, 이 세가지가 LISP을 포함한 프로그램 언어의 목적이자 지향하는 바이다.

그럼 이제 위에서 만든 프로그램을 분해해 보자.

 

(defun c:tg  (/ p1 p2 p3 p4 p5)  → 프로그램 시작
(setvar “osmode” 0) → osnap 설정 off, 구문 자체를 눈에 익혀둘 것.
(setvar “cmdecho” 0) → command 창에 프로그램이 돌아가는 모습을 감춤
                       command echo의 약자이고, 역시 구문 자체를 눈에 익혀둘 것.
(setvar "blipmode" 0) → AutoCAD 화면 상에 + 표시가 나타나지 않도록 설정. 익혀둘 것.
                        이 값을 1로 해서 실행해 보고, 0으로 실행해봐서 그 차이점을 확인할 것.
(if nil (tblsearch "layer" "taeguk")
  (command "layer" "m" "taeguk" "c" "7" "" "")
) ; end of if → 자주 쓰이면서도 고급 기능임. taeguk이란 layer를 찾아보고 있다면 그냥 두고
                없다면 새롭게 만들어서 그 색깔을 7번 (white)으로 하겠다는 구문.
                현재 layer도 역시 새롭게 생성된 layer로 자동 설정됨.
                구문 자체를 익혀두고, command 상태에서 –layer 명령어를 이용해서 확인해 보면
                따옴표(“”)가 왜 끝에 두 번인지 알 수 있을 것임.
(setq p1 (getpoint "\nPick the center point of TAEGUK : ")) → 첫 번째 점인 p1 변수를 사용자로부터
                                                              좌표를 입력 받아 저장함.
(setq p2 (polar p1 (dtr 180.0) 43.2072)) → p2의 위치를 p1으로부터 거리와 각도를 이용해 정의함.
                                           이 역시 가장 많이 쓰이는 구문으로 익혀두어야 함.
                                           여기서 dtr이란 사용자 함수는 아래에서 다시 설명할 것임.
(setq p3 (polar p1 (dtr 0.0) 43.2072)) → p3 위치 지정.
(setq p4 (polar p1 (dtr 225.0) 30.5521)) → p4 위치 지정.
(setq p5 (polar p1 (dtr 45.0) 30.5521)) → p5 위치 지정.
(command “circle” p1 43.2072) → 기본적인 circle 명령어 수행문으로 중심점과 반지름만을 
                                이용해서 circle을 생성하는 구문임.
(command “arc” p2 p4 p1) → 세 점을 이용해서 arc를 생성하는 기본적인 구문임.
                           미리 sketch해둔 그림을 참고하면 이해가 쉬움.
(command “arc” p1 p5 p3) → 상동
(setvar “cmdecho” 1) → 프로그램 처음에 설정했던 값을 원래대로 돌려줌.
(prompt “\nProgram has been completed!!!”) → 프로그램이 error 없이 실행되었다는 것을 알리는 메시지
(princ) → 프로그램 종료 후 불필요한 메시지를 지워줌.
) ; end of defun → 프로그램 종료
(defun dtr (a) (* (/ a 180.0) pi)) → 외부 사용자 함수로 degree 각도를 radian 각도로 변환해줌.
                                     이 구문 역시 자주 쓰이는 구문이므로 구문 자체를 익혀둘 것.
                                     외부 변수인 a를 받아들여 180으로 나누고 파이(π)를 곱한다.
                                     사용법은 위의 p2, p3, p4, p5를 정의하는 구문과 같이 사용한다.
                                     즉, (dtr 45.0) = 45.0 / 180.0 X 3.14 = 0.785 의 계산식을 단순화.

 

위의 해석이 금방 이해되기는 힘들 것이다. 하지만 사용 빈도가 매우 높은 구문들이 꽤 포함되어 있어서 자주 접하면 금방 눈에 익혀질 것이다. Layer를 설정하는 구문, 시스템 변수 – osmode, cmdecho, blipmode 등 – 들을 설정하는 구문들, 각도 변환하는 외부 사용자 함수, 거리와 각도로 point를 설정해주는 구문들은 어떤 프로그램이던지 항상 따라다닌다. 


이 예제 프로그램을 보고 응용할 수 있는 것들은 무한하다. 이리 저리 고쳐보고 다른 구문들을 추가해 보고, 또는 한 구문을 지워보고 error 메시지들을 익혀보고, 지역변수 (/ p1 p2 p3 p4 p5)를 ()로 광역변수로 바꾼 후 !p1, !p2, !p3등과 같이 변수의 값을 확인해 볼 수도 있다.


다른 프로그램을 개발할 때는 어렵게 키보드로 치지 않고 이런 종류의 예제들에게서 복사해서 쓰면 훨씬 속도도 빠르고 편하다. 단, 영문 타자 속도가 느린 초보 프로그래머들은 영타 연습도 또한 필수적이다. 시간을 일부러 내서 연습하지 말고 조금 귀찮더라도 복사보다는 직접 입력하는 연습을 해두는 것도 역시 괜찮은 방법일 수 있다. 그것은 사용자의 개인 판단에 따른 문제이므로 저자가 왈가왈부하기 힘든 문제이다.


그리고, 또 한가지 권하고 싶은 것은 위의 프로그램처럼 단순한 프로그램을 하나 택해서 sketch만 보고 손으로 연습장에 직접 써보거나, 메모장에 직접 타이핑하면서 직접 프로그래밍하는 연습을 해두는 것 또한 필요하다. 이 방법은 sketch만 보면서 하기 때문에 상상력이 좋아지고, 알고리즘과 같이 프로그램이 흘러가는 순서도 또한 익힐 수 있다. 그리고 사용 빈도가 높은 구문들을 눈에 익혀둠으로써 함수의 사용법을 완벽히 이해할 수 있다.


8. 필수 기본 함수

시작하기 전에 아래 그림을 먼저 보자.

 

LISP 도움말

앞의 그림은 AutoCAD내의 도움말 화면이다. 번째 강좌에서도 잠시 언급했지만 세상 어떤 책보다도 함수에 대한 설명이 자세하고 일목요연하게 알파벳 순으로 정리되어 있다. 앞으로 화면을 수백 , 수천 번을 봐야 한다. 다음에 소개할 함수들은 사용 빈도가 매우 높은 것들만을 소개하겠다.

 

함수들의 예제를 보고 command 창에 직접 입력해서 연습해 보길 바란다.

 

* Operators (연산 함수)

(+ <NUMBER> <NUMBER> ...)

+ 기호 뒤에 나오는 모든 숫자들을 더한다.

예 : (+ 1 2)                   returns  3 
(+ 1 2 3 4.5)             returns  10.5
(+ 1 2 3 4.0)             returns  10.0

(- <NUMBER> <NUMBER> ...)

- 기호 뒤에 나오는 모든 숫자들을 차례로 뺀다.

예 : (- 50 40)                 returns  10
(- 50 40.0)               returns  10.0
(- 50 40.0 2.5)           returns  7.5
(- 8)                     returns  -8

(* <NUMBER> <NUMBER> ...)

* 기호 뒤에 오는 숫자들을 모두 곱한다.

예 : (* 2 3)                   returns  6 
(* 2 3.0)                 returns  6.0 
(* 2 3 4.0)               returns  24.0 
(* 3 -4.5)                returns  -13.5
(* 3)                     returns  3

(/ <NUMBER> <NUMBER> ...)

/ 기호 뒤에 오는 숫자들을 모두 차례로 나눈다.

예 : (/ 100 2)                 returns  50 
(/ 100 2.0)               returns  50.0 
(/ 100 20.0 2)            returns  2.5 
(/ 100 20 2)              returns  2 
(/ 4)                     returns  4

 

(= <NUMBER> <NUMBER> ...)

= 기호 뒤에 나오는 값들이 같으면 T, 그렇지 않으면 nil return한다.

예 : (= 4 4.0)                 returns  T 
(= 20 388)                returns  nil
(= 2.4 2.4 2.4)           returns  T 
(= 499 499 500)           returns  nil 
(= "me" "me")             returns  T 
(= "me" "you")            returns  nil

(/= <NUMB1> <NUMB2>)

= 기호 뒤에 나오는 값들이 같으면 nil, 그렇지 않으면 T return한다.

예 : (/= 10 20)                returns  T 
(/= "you" "you")          returns  nil
(/= 5.43 5.44)            returns  T
(/= 10 20 10 20 20)       returns  nil
(/= 10 20 10 20)          returns  T

(< <NUMB1> <NUMB2>)

<NUMB1> <NUMB2>보다 작으면 T, 그렇지 않으면 nil.

예 : (< 10 20)                 returns  T 
(< "b" "c")               returns  T 
(< 357 33.2)              returns  nil 
(< 2 3 88)                returns  T 
(< 2 3 4 4)               returns  nil

(<= <NUMB1> <NUMB2>)

<NUMB1> <NUMB2>보다 작거나 같으면 T, 그렇지 않으면 nil.

예 : (<= 10 20)                returns  T 
(<= "b" "b")              returns  T 
(<= 357 33.2)             returns  nil 
(<= 2 9 9)                returns  T 
(<= 2 9 4 5)              returns  nil

(> <NUMB1> <NUMB2>)

<NUMB1> <NUMB2>보다 크면 T, 그렇지 않으면 nil.

예 : (> 120 17)                returns  T 
(> "c" "b")               returns  T 
(> 3.5 1792)              returns  nil 
(> 77 4 2)                returns  T 
(> 77 4 4)                returns  nil

(>= <NUMB1> <NUMB2>)

<NUMB1> <NUMB2>보다 크거나 같으면 T, 그렇지 않으면 nil.

예 : (>= 120 17)               returns  T 
(>= "c" "c")              returns  T 
(>= 3.5 1792)             returns  nil 
(>= 77 4 4)               returns  T 
(>= 77 4 9)               returns  nil

(1+ <NUMBER>)

숫자에 1 더하는 함수.

예 : (1+ 5)                    returns   6
(1+ -17.5)                returns  -16.5

(1- <NUMBER>)

숫자에 1 빼는 함수.

예 : (1- 5)                    returns   4 
(1- -17.5)                returns  -18.5

 

 

* 함수 사전 (알파벳 순으로 정렬)

 

(abs <NUMBER>)

절대값을 return.

예 : (abs 100)                 returns  100 
(abs -100)                returns  100 
(abs -99.25)              returns  99.25

(and <EXPR> ...)

and 함수 뒤에 오는 논리식이 반드시 모두 T이어야만 T를 return. 단 한가지라도 nil이면 nil을 return.
예 : Command: (setq a 103 b nil c "string") 
"string" 
Command: (and 1.4 a c) 
T 
Command: (and 1.4 a b c) 
nil 

(angle <PT1> <PT2>)

두 점 사이의 각도를 radian으로 return.
예 : Command: (angle '(1.0 1.0) '(1.0 4.0)) 
1.5708 
Command: (angle '(5.0 1.33) '(2.4 1.33)) 
3.14159 

(angtos <ANGLE>[<MODE><PRECIS.>])

각도를 mode를 이용해 문자열로 변환해 준다.
Mode 0=Degrees,
1=Deg Min Sec
2=Grads,
3=Radians,
4=Surveyor
예 : Command: (angtos 0.785398 0 4) 
"45.0000"
Command: (angtos -0.785398 0 4) 
"315.0000"
Command: (angtos -0.785398 4) 
"S 45d E"

(append <EXPR> ....)

list와 list를 합쳐서 하나의 list로 return 한다.
예 : Command: (append '(a b) '(c d)) = (append (list a b) (list c d))
(A B C D) 
Command: (append '((a)(b)) '((c)(d))) = (append (list (a) (b)) (list (c) (d)))
((A) (B) (C) (D))

(apply <FUNCTION> <LIST>)

함수를 list의 각각의 원소들에 일률적으로 적용한다.
예 : Command: (apply '+ '(1 2 3)) = (+ 1 2 3)
6 
Command: (apply 'strcat '("a" "b" "c")) = (strcat “a” “b” “c”)
"abc" 

(ascii <STRING>)

문자열의 첫 번째 글자를 ascii 값으로 변환해 줌.
예 : Command: (ascii "A") 
65 
Command: (ascii "a") 
97 
Command: (ascii "BIG") 
66
Command: (ascii "B") 
66

 

다음 편에서 이어집니다.

 

 

 

728x90
반응형

관련글 더보기

댓글 영역