2009년 2월 27일 금요일

haskell 동영상 강의

Video Lectures
Lectures (in English) by Jürgen Giesl. About 30 hours in total, and great for learning Haskell. The lectures are 2005-SS-FP.V01 through 2005-SS-FP.V26. Videos 2005-SS-FP.U01 through 2005-SS-FP.U11 are exercise answer sessions, so you probably don't want those.

우왕국. http://www.haskell.org/haskellwiki/Tutorials 에서 찾은 링크인데 잠깐 들어보니 좋네. 딴나라 말이라 좀 난감하긴 한데 독일사람이 영어하는거라 좀 들을만 하다...(발음이야 좀 이상하지만 느리게 말해주는 편. 뭐 강의 뒤쪽가면 말이 빨라지거나 하진 않겠지....)

2009년 2월 26일 목요일

웹기반 IDE bespin

http://labs.mozilla.com/projects/bespin/

당장은 이딴거 관심 밖이지만 기억은 해두자.
협업 에디팅을 지원하는 에디터들 중에는 그나마 쓸만 할것 같은데
어쩌다 가끔 필요하긴 하니까..

추가.
가입하고 잠깐 써봤는데 절라 느리네.
한글입력이 안되는거 같기도 하고
되는지 안되는지 확인이 어려울 정도로 느린걸 보니 뭔가 좀 비정상인거 같은데

emacs 기반 개발환경을 제공하는 common lisp 로그라이크 엔진

RLX: a cross-platform graphical roguelike engine

emacs 를 저렇게도 활용하네.
스샷에 보이는 cell 모드가 이 http://www.emacswiki.org/emacs/CellMode 셀모드인가 아님 따로 만든건가.. 어쨌건 셀모드 사이트는 링크가 지금 죽은 상태.

그외 걸린 링크들도 그럴싸해보이길래 적어둔다.

소스는 아직 안받아보고 스샷만 구경한 상태..
그런데 플레이어 입장으로 보면 별로 재미있어 보이는 스샷은 아니네. 낄낄

2009년 2월 24일 화요일

haskell 로 간단한 소켓 서버와 클라이언트 제작 두번째

이전글 에서는 코드가 전체적으로 Socket 기반으로 돌아가는데 뭐랄까.. 이게 그다지 좋은 방법이 아닌가보다. haskell 의 경우 입출력이 Handle 을 통해서 이루어지게 디자인 되어있어서 Socket 을 바로 입출력에 쓰기엔 제공되는 api 들이 좀 난감한 면이 있다.

그래서 이전 코드에서 세션핸들러 함수들이 Socket 을 받던것을 Handle 을 받도록 수정해봤다. 그리고 핸들(소켓) 을 닫는 책임을 세션핸들러 쪽으로 옮겨버렸다... 세션함수 작성시 클로즈를 잊지말고 해야 하는 부담이 있긴 하지만 이게 좀더 유연할거 같다.


이건 서버쪽 소스

펼쳐두기..

이건 클라이언트쪽 소스

펼쳐두기..





haskell 로 간단한 소켓 서버와 클라이언트 제작

이건 서버 소스. serveTcp 가 핵심. 이 함수에 포트번호와 소켓핸들러 함수를 넘기면 된다.

펼쳐두기..


이건 클라이언트 소스

펼쳐두기..


으음... 이건 패킷이 너무 단순해서 별 의미는 없지만 위에 withTcp 나 serveTcp 는 자주 쓰일 함수들이라 적어둔다. 다음에는 현재 Socket 기반인것을 Handle 기반으로바꾸고.. 바이너리패킷을 쏘는걸 한번 만들어보고.. 그담엔 서로 주고받는걸 만들어보자...



2009년 2월 20일 금요일

MozRepl 자바스크립트 REPL 환경

웹개발은 전혀 모르고 자바스크립트도 마찬가지지만 자바스크립트가 REPL 스타일 개발이 된다길래 적어둔다. 언젠가 공부해야 할 상황이 오면 필요하겠지.

자바스크립트는 http://www.slash7.com/articles/2006/07/26/javascript-boot-camp-tutorial 보면 대강 어떤지 이해가 가겠더라. DOM 쪽 들어가면 좀 난감해지긴 하지만 ECMA script 자체는 존나 좋군.

2009년 2월 19일 목요일

netcat

으음.
netcat.. 존재를 알고는 있지만 막상 필요할때는 항상 까먹어서 걍 스크립트질하기 때문에 지금껏 써본적이 없는 놈. socat 은 처음알았네.

기억해두고 다음엔 좀 써먹어보자.

2009년 2월 17일 화요일

haskell 로 프로젝트 오일러의 22번 문제를 풀어봤다

-- http://projecteuler.net/index.php?section=problems&id=22

import Data.List(sort)
import Data.Char(ord)

-- 으험.. 스플릿 함수가 안보이네. 직접 만들어봤는데 좀 추해보인다.
split :: Char -> String -> [String]
split c s = split' [] s
where split' acc [] = acc
split' acc s = let (tok, remains) = break (==c) s
in split' (tok:acc) (safeTail remains)
safeTail [] = []
safeTail x = tail x

-- 문자열들을 받아서 , 로 스플릿 하고 앞뒤에서 한글자씩 잘라냈다.
-- 따옴표 제거
names s = map (tail . init) $ split ',' s

nth x = (ord x) - (ord 'A') + 1 -- 'A' 에서 몇번째 문자냐
scoreName = sum . map nth -- 이름의 점수
scoreIndexedName (name,index) = (scoreName name) * index -- 점수에 인덱스 곱

solve input =
let splitted = names input -- 쪼개고
sorted = sort splitted -- 정렬하고
indexed = zip sorted [1..] -- 인덱스붙여서
scores = map scoreIndexedName indexed -- 점수내고
in sum scores --

main = do
input <- readFile "/tmp/h/names.txt"
print $ solve input

2009년 2월 13일 금요일

앵밴드 매크로 인스크립션 도움말

몇달에 한번씩 로그라이크를 하는 편인데 앵밴드는 키를 여러번 눌러야 할 일이 많아서 매크로가 필수고 이걸 자꾸 까먹길래 여기 적어둔다.

출처는 http://www.thangorodrim.net/help/inscriptions.html 이곳.

A Really Quick Guide to Magic Inscriptions..


예를 들어 현재 플레이중인 프리스트는 위 예제처럼 첫번째 마법책을 @p1!d!k!v 이라고 해놓고 매크로에서 f12 를 누르면 p1fp1gp1aR\r 를 실행하게 해서 그지역에 쓸쑤있는 탐지마법들을 뿌리고 마나 회복까지 끝내도록 해뒀다..

매크로에 리턴을 포함시키려면 \r 쓴다는거.. 나중에 다시 하려고 하면 기억 못하겠지.


2009년 2월 11일 수요일

haskell-mode 에서 ^J 가 찍혀대는 문제 해결

http://www.nabble.com/problem-with-echo-prompting-in-ghci-(visible-in-emacs)-td20451779.html

ghc 6.10.1 로 올리고 haskell-mode 도 올리고 보니 이런 문제가 생기네.
적당히 구글링해서 해결.


혹시나 내용백업해둔다.

펼쳐두기..



ghc 6.10 이 되면서 생긴 Exception 변화

흠.
먼저 6.10 을 깐 배경.
우분투는 아직 6.8 을 패키징 하고 있는데 cabal 하고 같이 쓰려니 좀 문제가 있더라.
그래서 apt 에서는 지워버리고  ghc 6.10.1 바이너리 배포본을 받아 직접 설치해줬다.

그러고 나니 6.8 에서 쓰던 코드들이 에러를 뱉어내네..
조금 검색해보니 이런글이 보였다.
http://groups.google.com/group/fa.haskell/browse_thread/thread/8c6352ed6767952d

결론.
OldException 을 임포트 하거나
타입지정을 하자??
음 타입지정 말고 좀 깔끔한 방법은 없을까? 보통 람다로 핸들러 짜는데 말이지.

http://www.haskell.org/ghc/docs/6.10.1/html/users_guide/release-6-10-1.html
는 읽어봐야 할듯?



2009년 2월 5일 목요일

텐 코드

http://en.wikipedia.org/wiki/Ten-code

양키영화 보면 10-4 등 코드로 통신하는 장면이 나오는데 텐코드라는게 있었군.
기억해두면 나중에 쓸일이 있을듯.

2009년 2월 4일 수요일

haskell 에서 랜덤값 사용하기

랜덤하나 부르는것도 힘드네. haskell 의 System.Random 문서를 보고
정리해봤다.

먼저 모든 RNG 는 RandomGen 이란 타입클래스에 속해있는
모냥이군. 음.. RandomGen 의 인스턴스라는 소리를 그 타입클래스에
속해있다.. 라고 표현하는게 맞는 건지 잘 모르겠지만.

class RandomGen g where
  next     :: g -> (Int, g)
  split    :: g -> (g,g)
  genRange :: g -> (Int,Int)

next 는 뭐 간단한 모양이군. 랜덤값 하나를 뽑아주고 이때문에 바뀐 새
상태를 같이 리턴해준다. 뭐 여기까진 이해가 되는데.

split 은 g 를 쪼개주는데.. 문서상에야 설명이 있지만 이해가 잘 안가네.

genRange 는 그냥 그 g 가 뽑아내는 랜덤값의 범위다. 내공이 부족하여
처음에 이 함수 모양만 가지곤 뭐하는지 추측이 안되더군. 단순히 getter
였을줄이야.


위는 타입클래스라.. 실제로 뭔가 돌아가는놈은 위 타입클래스의 인스턴스
일테고 haskell 은 표준으로 StdGen 이란놈을 가지고 있구나.

*Main> :info StdGen
data StdGen = System.Random.StdGen GHC.Int.Int32 GHC.Int.Int32
      -- Defined in System.Random
instance Read StdGen -- Defined in System.Random
instance Show StdGen -- Defined in System.Random
instance RandomGen StdGen -- Defined in System.Random

StdGen 은 밸류 컨트스럭터가 노출이 안되어있고 mkStdGen 이란 함수를
통해서 값을 만들수 있다. 이 함수가 받는 인자는 seed 로 쓰이는
놈이겠지.

자.. 이제 직접 랜덤값을 뽑아낼정도로 함수들을 알게됐으니 일단 불러보자.

*Main> next (mkStdGen 0)
(2147482884,40014 40692)
*Main> genRange (mkStdGen 0)
(0,2147483562)

우왕ㅋ굳ㅋ mkStdGen 0 으로 제네레이터를 만들고 next 로 랜덤값과 새
제네레이터를 뽑아냈다. 여러값을 불러야 하면 새 상태를 적절히 체이닝
해야겠지. 랜덤을 뽑는 행위에 사이드이펙트가 없다는게.. 뭐랄까 응용할
꺼리가 많겠군.


음 그런데 전역상태에 의존해서 랜덤을 생각없이 쓰다가 이렇게 매번 상태를
관리하는 랜덤을 쓰는건 정말 괴롭겠지. 다행히도 haskell 에 IO 모나드에
속한(전역인) StdGen 이 있다. 한마디로 말해 다른 언어에서 랜덤 쓰던것과
동일하게 쓸수 있다. 굳이 새상태를 들고다니는 짓을 안해도 된단말이지.

getStdRandom :: (StdGen -> (a, StdGen)) -> IO a
getStdGen    :: IO StdGen
setStdGen    :: StdGen -> IO ()
newStdGen    :: IO StdGen

getStdGen 와 setStdGen 은 간단한 엑세서 함수다.

무식하게 쓰려면 꺼내서 next 로 새값과 새상태 만들고 새 상태를
setStdGen 으로 박아넣는 식으로 돌아가겠지. 이게 아주 뻔한 작업이 될테니
getStdRandom 함수를 제공해준다. 타입만 봐도 어느정도 돌아가는 모양이
예측이 가능하네.. 하지만 실제 이 소스를 보면 IORef 등 더 공부할게
튀어나온다. 더 깊이는 안보고 넘어가야지..

아 실제로 쓰는건 요리 쓰면 된다.

*Main> getStdRandom next
501819957
*Main> getStdRandom next
557655835
*Main> getStdRandom next
1527018794
*Main> getStdRandom next
1881200278

매번 부를때마다 새로운 값이 튀어나오는게 확인된다.


음 그런데 이렇게 next 를 통해서 값을 가져오면 내가 원하는 모양으로 다시
가공을 해야 하는데(적정 범위안으로 구겨넣는다던지, 이 값을 인덱스로
해서 리스트로부터 랜덤하게 엘리먼트를 뽑는다던지..) 상당히
불편하지... 뭐 불편하다고는 하지만 이미 이렇게 잘 써왔지만.

어쨌거나 haskell 은 위와 같은 가공을 개발자한테 알아서 하라고 그냥 둔게
아니고 적절한 유틸리티 함수들을 제공을 하고 이 함수들을 Random 이란
클래스로 묶어뒀다. 사실 이제까지 내용은 그냥 haskell 은 이러하다.. 란
식이라 머리쓸일이 없었는데 이 Random 클래스는 음.. 좀 어렵군.

class Random a where
  randomR  :: RandomGen g => (a,a) -> g -> (a,g)
  random   :: RandomGen g => g -> (a,g)
  randomRs :: RandomGen g => (a,a) -> g -> [a]
  randoms  :: RandomGen g => g -> [a]
  randomIO :: IO a

먼저 randomR 은 모양만 봐도 next 한 값을 주어진 범위 안으로 구겨넣는
놈이라는걸 알수있다.

*Main> getStdRandom (randomR (0,10))
10
*Main> getStdRandom (randomR (0,10))
9
*Main> getStdRandom (randomR (0,10))
5
*Main> getStdRandom (randomR (0,10))
8

haskell 의 특징인 currying 때문에 위 예제에서 쓰인 randomR (0,10) 의
타입은 정확히 next 와 일치하고 따라서 getStdRandom 의 인자로 사용이
가능하다.. 이런식의 currying 사용은 빨리 익숙해져야 할텐데.

random 은 randomR 의 범위에 리턴받을 타입의 유효범위를
지정해준것. 위에서 봤다시피 그냥 next 의 범위는 genRange 를 불러보면
알겠지만 리턴받을(생성할) 타입의 값과는 무관하다. 따라서 이걸 적절히
바꿔줄 놈이 필요한데 이 함수가 그짓을 해준다.

*Main> getStdRandom random
-864292929

randoms 는 후럴... 희한한 놈이네. 새상태는 리턴해주지 않고 무한히
랜덤값을 찍어내주는 놈이다. 일단 randoms 부르면 함수 안쪽에서 새값을
유지하면서 루프(리커젼)을 돌테니 굳이 새상태를 리턴받지
않는것이겠지.. 음.. 이 무한이란 개념도 내가 지금껏 다뤄오던 언어들에선
접하기 힘든거라 randoms 타입만 봐서는 뭐하는놈인지 정말 애매했다. 만약
내가 이런류의 함수를 만든다면 몇개의 엘리먼트를 뽑을지 인자로 받을텐데
haskell 에서는 그냥 무한리스트를 주고 필요한쪽에서 필요한만큼 가져다
쓰는 방식히 선호되는듯 하다( lazy 하니까 ) 이런 스타일이 어여 손에
익어야 할텐데. (좀더 자세히 말해서 무한리스트를 준다는 표현은
잘못된거지. lazy 하다는 특성때문에 randoms 함수가 불리는 순간에 값이
만들어 지는게 아니니까. 무한리스트를 준다 라는 표현보다는 나중에
필요할때 값을 만들어낼 방법을 미리 정의만 해둔다.. 정도가 맞겠지.)


*Main> take 5 $ (randoms (mkStdGen 0)) :: [Int]
[2092838931,-2143208520,2034827062,-1587933427,-1272503422]

randoms 의 타입을 보면 알겠지만 getStdRandom 하고는 잘 안섞인다(이글을
쓰는 현재 같이 섞어 부르는 방법을 모르겠다. 아마 없을거 같은데)

randomRIO 는 흠. getStdRandom 을 내포한 놈인거 같군. 위 적은 코드중에
getStdRandom 하고 randomR 을 쓴게 있었는데 randomRIO 를 쓰면 한방이구나

*Main> randomRIO (1,10)
6
*Main> randomRIO (1,10)
2
*Main> randomRIO (1,10)
1

randomIO 는 getStdRandom 하고 random 을 섞은놈이구먼.
                                           
*Main> randomIO
-795885308


마지막으로..  Random 이 타입클래스로 빠져있는게 아주 오묘하구나. 내가
랜덤생성을 원하는 타입에 따라 다른 동작을 해준다는 건데 음... 뭔가
느껴지긴 하는데 글로적기는 힘들군. 타입클래스 사용도 좀더 구경하다 보면
감 잡겠지.