Programmer/Programming
-
Common Lisp으로 구현한 트리(Tree)를 중위 순회(In-order Traversal)하는 반복자(Iterator)Programmer/Programming 2016. 5. 17. 15:02
사소해 보이는 연산 뒤에 숨어있는 것 은 인턴 전화 면접에서 깨달은 내용을 담고 있다. 이 글은 인턴 면접을 소재로 하는데, 면접의 내용 중에 트리(Tree)를 중위 순회(Inorder Traversal)하는 반복자를 구현하는 것이 있다. 이 글의 필자는 C++로 구현하였다. 평소 업무에서 Common Lisp을 쓸 기회가 없어서 자꾸 잊어버린다. 도구를 갈고 닦지 않으면 녹슬기 마련이다. 간단하게 트리의 중위 순회를 Common Lisp으로 작성해봤다. 순회 순서 왼쪽의 하위 트리를 순회한다. 자신(중간) 오른쪽의 하위 트리를 순회한다. 순회할 첫번째 노드 구하기 : begin 최상위 노드의 가장 왼쪽에 있는 노드가 첫번째 노드이다. 구현은 왼쪽 하위 노드를 재귀적으로 찾는다. (defun begin ..
-
Lisp에서 클로저(closures)Programmer/Programming 2016. 2. 18. 15:57
클로저란 함수가 lexical 환경(environment)의 변수를 참조하는 것을 말한다. 예를 들면, 아래 코드를 살펴보자. (defparameter *plus-10* (let ((x 10)) (lambda (y) (+ x y)))) X와 Y를 더하는 함수 객체를 만들고, *PLUS-10*이 이를 가르키게 한다. Lexical 변수 X는 LET 구문 블럭이 생성한 환경에 갇혀서 외부에서는 접근할 수 없다. LET 구문 블럭이 종료되었다는 것은 실행 흐름이 LET이 생성한 환경에서 벗어났다는 것을 의미한다. 그럼에도 불구하고, *PLUS-10*를 호출하면 X 변수를 참조할 수 있다. CL-USER> (funcall *plus-10* 20) 30 함수 객체가 다른 곳(예제에서는 dynamic 환경의 *PL..
-
Lisp에서 lexical과 dynamic 변수 타입Programmer/Programming 2016. 2. 18. 15:43
Lisp에는 lexical과 dynamic이라는 두가지 변수(variables) 형태가 존재한다. lexical 변수는 소스 코드를 읽는 단계에서 바인딩(binding)이 결정된다. C나 Java 같은 언어에서 말하는 지역(local) 변수를 생각하면 된다. 함수의 매개변수(parameters)나 LET 구문의 변수가 이런 타입니다. 함수의 매개변수 (defun foo (x y) (+ x y)) 함수를 호출하면, 이 함수에 전달하는 인자(arguments)와 연결(binding)하는 매개변수를 생성한다. 이 변수는 함수 내로 범위가 한정된다. LET 구문의 변수 (let ((x 10) (y 20)) (+ x y)) LET 구문 역시 함수 호출과 동일한 효과를 가진다. LAMBDA로 표현하면 함수의 매개변..
-
Lisp 비교 : 암호 문자열 감추기 문제 풀이Programmer/Programming 2016. 1. 13. 18:53
"케빈 TV 12회 (상) - 느 언어엔 이런거 없지?"에 주어진 글자수만큼 '*'를 가진 문자열을 생성하는 문제가 나왔다. 여러 언어별 구현이 나왔지만, Common Lisp와 Emacs Lisp, Scheme, Clojure가 없어서 여기에 적어본다. Common Lisp: (defun hide-password (passwd) (coerce (mapcar #'(lambda (x) #\*) (coerce passwd 'list)) 'string)) Emacs Lisp: (defun hide-password (passwd) (coerce (mapcar (lambda (x) ?\*) (coerce passwd 'list)) 'string)) Scheme: (define (hide-password passw..
-
리습(Lisp)을 위한 SyntaxHighlighter 3.0 플러그인 작성Programmer/Programming 2015. 3. 17. 00:50
SyntaxHighlighter는 프로그래밍 언어의 문법에 따른 색상을 강조하는 프로그램이다. 자바스크립트(Javascript)와 CSS로 작성하였다. 블로그에 개발에 관련한 글을 쓰다보면 종종 소스 코드를 포함한다. 그럴 때마다 이 프로그램의 고마움을 많이 느꼈다. 공식 배포본에는 리습(Lisp)용 플러그인이 없다. 다행이도 누군가 리습을 위한 플러그인을 만들어서 올려놓았다. 썩 마음에 들지는 않지만, 그냥 저냥 사용하기에는 큰 무리는 없었다. 그러던 중, 눈에 거슬리는 버그 하나를 발견했다. (defun my-save (fname) (with-open-file (*standard-output* fname :direction :output :if-exists :supersede) (my-write)))..
-
초반에는 문제의 원인을 충분히 넓게 잡아라.Programmer/Programming 2014. 7. 15. 18:09
파일 읽기 플러그인에 다수의 기능을 추가했다. 추가된 기능은 원격 파일 읽기, 버퍼 읽기, 캐시 등이 있다. 원격 파일을 읽는 기능이 이전 버젼에 비해서 과도하게 CPU를 점유하고 있었다. 분석의 과정이 없이 추론에 근거하여 새로 추가된 원격 기능과 캐싱 알고리즘만을 의심했다. 그리고 내 시스템과 연동하는 HTTP 프록시 서버의 문제일 수 있다는 생각도 했다. 이전에 이런 접근 방법을 경고하는 글을 적었음에도 나란 인간은 같은 실수를 되풀이했다. 경험과 직감에만 의존한 추측과 코드 수정, 그리고 결과 보기를 반복했다. 이후 동료의 조언으로 프로파일링의 접근을 시도하였다. 이번 문제의 원인을 찾기 위한 제대로된 분석의 첫번째 시도였다. 아뿔싸! 나란 인간은 또다른 문제를 가지고 있었다. 여러번의 프로파일링..
-
리스프 개발 팁: 명령창 결과 저장하기Programmer/Programming 2014. 6. 27. 10:38
리스프에서 개발하기 가장 좋은 도구는 REPL 명령창이다. 따라서 저장할 내용을 표준 출력으로 보내면 개발이 수월할 것이다. 예를 들어, 당신은 `MY-SAVE' 함수를 개발하고 있다. 이 함수는 인자 `FNAME'으로 받은 파일명에 당신의 데이타를 저장한다. 개발 과정에서 수시로 파일을 열어서 내용을 확인해야 한다. 불편하다. REPL 명령창에 저장할 내용을 바로 확인하면 개발이 훨씬 편하겠다. 데이타를 저장할 형태로 가공하여 REPL 표준 출력하는 함수 `MY-WRITE'를 작성하자. 이 함수의 구현과 검증은 REPL을 벗어날 필요가 없다. 이제 함수 `MY-SAVE'는 단지 표준 출력을 저장할 파일에 연결한 후에 `MY-WRITE'를 호출하면 된다. (defun my-save (fname) (wit..
-
리습의 개발 방법을 배우자: 함수의 구현Programmer/Programming 2014. 6. 26. 10:37
구현이 어느정도 명확해졌으면 주로 바텀-업 방식을 사용한다. 바텀-업은 구현 결과를 눈으로 확인하며 구현하는 장점이 있다. 다소 복잡한 구현부가 있으면 스텁 함수(stub functions)로 대체한다. 스텁 함수를 사용하는 것은 이전 포스트에서 설명하였다. 스텁 함수를 예상하는 결과로 동작하도록 하드코딩 하는 것도 좋은 트릭이다. 2014/06/20 - [Programming/Functional] - 리습의 개발 방법을 배우자: 대도 웜퍼스 게임의 설계 2014/06/24 - [Programming/Functional] - 리습의 개발 방법을 배우자: 함수와 하위 함수의 설계 이번 포스트에서는 엣지 리스트를 연관 리스트(association lists, 줄여서 alist)로 변환하는 함수를 개발한다. ..