manywaypark's Blog
개발, 검색, 함수

Mac OS X용 R 설치 직후에 한글을 표시하려 하면 Quartz 화면에서는 한글이 제대로 표시되지 않고 네모 상자로 표시되는 문제가 있다.
~/.Rprofile 파일(없으면 생성)에 다음 내용을 추가:
setHook(packageEvent("grDevices", "onLoad"), function(...){ if(capabilities("aqua")) grDevices::quartzFonts( sans =grDevices::quartzFont(rep("AppleGothic",4)), serif=grDevices::quartzFont(rep("AppleMyungjp",4))) grDevices::pdf.options(family="Korea1") grDevices::ps.options(family="Korea1") } ) attach(NULL, name = "KoreaEnv") assign("familyset_hook", function() { macfontdevs=c("quartz","quartz_off_screen") devname=strsplit(names(dev.cur()),":")[[1L]][1] if (capabilities("aqua") && devname %in% macfontdevs) par(family="sans") }, pos="KoreaEnv") setHook("plot.new", get("familyset_hook", pos="KoreaEnv")) setHook("persp", get("familyset_hook", pos="KoreaEnv"))
refs:
http://www.mail-archive.com/r-sig-mac@stat.math.ethz.ch/msg04538.html

happy hackin'

erlang build 하기 #2 - w/ wx

함수형 언어/Erlang 2009. 9. 16. 14:23 by manywaypark
erlang build하기 첫번째 글을 쓸 때는 erlang에 wx 같은 라이브러리가 포함되어 있지 않았다 (R13 이상부터 포함된것같다).
첫번째 글에 설명한 일반적인 설정을 기준으로 configure를 실행하면, 중간에 다음과 같은 경고가 표시된다.
configure: WARNING:
                wxWidgets must be installed on your system.

                Please check that wx-config is in path, the directory
                where wxWidgets libraries are installed (returned by
                'wx-config --libs' or 'wx-config --static --libs' command)
                is in LD_LIBRARY_PATH or equivalent variable and
                wxWidgets version is 2.8.0 or above.


configure 마지막에는 다음과 같은 메시지를 출력한다(빌드시 wx를 제외하겠다는 말).
*********************************************************************
**********************  APPLICATIONS INFORMATION  *******************
*********************************************************************
wx             : Can not link the wx driver, wx will NOT be useable

*********************************************************************
이대로 빌드하면 당연히 wx 관련 프로그램은 동작하지 않는다.

다음과 같이 관련 개발 패키지들을 설치하면 해결된다.
sudo apt-get install libwxbase2.8-dev libwxgtk2.8-dev libgl1-mesa-dev libglu1-mesa-dev libglut3-dev

NOTE: configure 설정에 cache 문제가 있는 듯하다. 필요한 패키지들이 최초의 configure를 실행하기전에 설치되어있어야한다. 그렇지 않을 경우에는 계속 wx 관련 링크못하겠다는 메시지가 뜨면서 wx를 build에서 제외하는 makefile을 만든다. 그러므로 기존 otp 디렉토리를 지우고, 원래 tar ball을 다시 압축을 풀어서 (fresh untar) 빌드해야한다.

NOTE2: configure 시에 --enable-smp-support 옵션을 꼭 줘야하고, 실행시에는 -smp 옵션을 주어야한다(erl -smp). 안 그러면 runtime에 다음과 같은 에러가 나면서 실행이 안된다.
WX ERROR: SMP emulator required** exception error: not_smp
     in function  wxe_server:start/0
     in call from wx:new/1
     in call from hello:start/0

참고:

happy hackin'

예전에 원작자인 ttyerl에게 패치를 보낸적이 있는데 적용되지 않았다. 그래서 그냥 포크했다.
또한 새로운 버그도 발견!!
davisp이 ttyerl의 원본을 좀 매끄럽게 돌게 고쳤는데 버그는 그대로였다.
그래서 davisp의 fork를 내가 fork해서 수정했다.

버그들:
  1. table_info 버그
  2. query timeout 버그

작업 내역:
  1. 상기 버그 퇴치
  2. eunit test case 추가


URL: http://github.com/mwpark/sqlite-erlang/tree/master

happy hackin'

erlyweb 빌드 하기

함수형 언어/Erlang 2009. 6. 1. 18:43 by manywaypark
erlyweb의 빌드 스크립트(make.sh)는 기본적으로 erlang의 lib 폴더(보통 /usr/local/lib/erlang/lib, code:lib_dir()로 찍어보면 나온다)에 yaws가 깔린 것으로 가정하고 만들어져있다.
즉, 다음과 같다.
#!/bin/bash

ERLIB=$(erl -noshell -eval 'io:format(code:lib_dir()).' -s erlang halt)
YAWS=$(ls $ERLIB | grep yaws)

cat >Emakefile <<EOF
{"src/erlyweb/*", [debug_info, {outdir, "ebin"},
{i,"$ERLIB/$YAWS/include"}]}.
{"src/erlydb/*", [debug_info, {outdir, "ebin"}]}.
{"src/erlsql/*", [debug_info, {outdir, "ebin"}]}.
{"src/erltl/*", [debug_info, {outdir, "ebin"}]}.
{"src/smerl/*", [debug_info, {outdir, "ebin"}]}.
{"src/erlang-mysql-driver/*", [debug_info, {outdir, "ebin"}]}.
{"src/erlang-psql-driver/*", [debug_info, strict_record_tests, {outdir,
"ebin"}]}.
EOF

ebin_dir="./ebin"
# bash check if directory exists
if [ ! -d $ebin_dir ]; then
    mkdir $ebin_dir
fi

erl -noshell -eval 'make:all(), filelib:fold_files("src/", ".+\.et$", true, fun(F, _Acc) -> erltl:compile(F, [{outdir, "ebin"}, debug_info, show_errors, show_warnings]) end, []).' -pa ebin -s erlang halt
일견 복잡해보이지만, 실제로 하는 일은 erlang의 기본 lib 폴더에서 yaws 폴더를 찾은 후에 Emakefile을 만들고 erlang 방식의 make를 돌리는 것이다.
문제는 나는 yaws를 직접 빌드해서 설치해서 다른 디렉토리(/usr/local/lib)에 있다는 것이다.
그냥 간단하게 make.sh를 다음과 같이 고쳐서 make 하면 잘된다. 나는 yaws의 기본 설정(즉, prefix 따위 설정 안한)으로 빌드했다. prefix 설정으로 설치 경로 바꾼 경우는 적절히 바꾸면 될 것이다.^^
#!/bin/bash

#ERLIB=$(erl -noshell -eval 'io:format(code:lib_dir()).' -s erlang halt)
#YAWS=$(ls $ERLIB | grep yaws)

cat >Emakefile <<EOF
{"src/erlyweb/*", [debug_info, {outdir, "ebin"},
{i,"/usr/local/lib/yaws/include"}]}.
{"src/erlydb/*", [debug_info, {outdir, "ebin"}]}.
{"src/erlsql/*", [debug_info, {outdir, "ebin"}]}.
{"src/erltl/*", [debug_info, {outdir, "ebin"}]}.
{"src/smerl/*", [debug_info, {outdir, "ebin"}]}.
{"src/erlang-mysql-driver/*", [debug_info, {outdir, "ebin"}]}.
{"src/erlang-psql-driver/*", [debug_info, strict_record_tests, {outdir,
"ebin"}]}.
EOF

ebin_dir="./ebin"
# bash check if directory exists
if [ ! -d $ebin_dir ]; then
    mkdir $ebin_dir
fi

erl -noshell -eval 'make:all(), filelib:fold_files("src/", ".+\.et$", true, fun(F, _Acc) -> erltl:compile(F, [{outdir, "ebin"}, debug_info, show_errors, show_warnings]) end, []).' -pa ebin -s erlang halt

happy hackin'

[BR] EUnit Bug Report

함수형 언어/Erlang 2008. 12. 24. 18:25 by manywaypark
맨 마지막 테스트 함수의 테스트 준비단계가 2번 실행되는 버그가 있는 것같다.
나의 test case가 성공할 때도 있고 실패할 때도 있는 이상한 상태가 되어서 내 잘못인 줄 알고 개발중인 모듈의 여기저기를 손댔다가 갑자기 느끼는 바가 있어 EUnit을 테스트하는 간단한 코드를 만들었다.

일단 공식적으로 버그 리포트는 했고,
참고를 위해 글을 남긴다.

last_test_() ->
do_some_prep(), % 요놈이 매번 두번씩 불린단 말씀.
... do some tests ...
do_some_prep()가 두번 불려지면 당혹스런(?) 테스트 실패가 나올 수 있다. disk i/o나 DB operation 처럼 side effect가 있는 경우에 특히 테스트가 통과될 때도 있고 안될때도 있는 불안정한 상태가 될 수 있다.

happy hackin'

ps. 글을 쓰고 좀더 만져 보니 조금 더 복잡하다. EUnit 사이트에 올린 케이스들 말고 테스트 케이스를 다음과 같이 하면...

twice_case1_test_() ->
    io:format("c1: prep one~n"),
    ?_assert(1 + 1 =:= 2).

twice_case2_test_() ->
    io:format("c2: prep one~n"),
    ?_assert(1 + 1 =:= 2).

twice_case3_test_() ->
    io:format("c3: prep one~n"),
    ?_assert(1 + 1 =:= 2).

결과:
(emacs@desktop)14> eunit_twice_case:test().
c3: prep one
c2: prep one
c3: prep one
c2: prep one
c1: prep one
  All 3 tests successful.
ok
마지막에 있는 두개가 두번씩 불린다.

2008-12-31 "by design" 이라는군요 Orz. side effect가 있는 함수는 준비단계에서 부르면 절대 안되겠습니다.
Erlang:
시퍼렇게 날이 선,
언제라도 목표가 포착되면 일도양단의 기세로 칼집에서 뛰쳐나올듯한 예리한 刀와 같은...

Lisp:
약간은 뭉툭한,
시간을 가지고 연마하면 그 어떤 치명적인 무기로도 바뀔 수 있는 연철(軟鐵)과 같은...

그렇다. Erlang은 Lisp을 오랜 기간 연마하여 탄생한 Joe의 치명적 무기다.

happy hackin'
제목의 용어가 정확한지 잘 모르겠다. 작업도중 필요해서 만들게 되었는데 함수형 언어의 장점(REPL의 장점)을 부각시킬 수 있는 예제가 될 수 있을 것같아서 포스팅한다.
전각 문자를 반각으로 문자열 변환하는 간단한 함수를 하나 만들었는데 좀 꼼수(?)를 동원해서 얄팍하게 재빨리 만들었다.
정확하게 하려면 몇몇 자료를 참조해야하겠지만, 필요한 상황의 테스트 케이스는 다 통과하므로 그대로 쓰기로 했다.

(emacs@desktop)1> "ABC012". % wide chars
"\357\274\241\357\274\242\357\274\243\357\274\220\357\274\221\357\274\222".
[239,188,161,239,188,162,239,188,163,239,188,144,239,188,
 145,239,188,146]
(emacs@desktop)2> "A".         % wide char
"\357\274\241".
(emacs@desktop)3> "A".          % normal char
"A"
(emacs@desktop)4> "0".         % wide char
"\357\274\220".
[239,188,144]
(emacs@desktop)5> $0.           % normal char
48

패턴이 보이는가?
[239,188] ("\357\274") 뒤의 숫자만 변한다. ^^;
자연스럽게 다음과 같은 함수가 만들어진다.
%% 96 = last("1") - $1
'wide->narrow'([239,188,C|T]) ->
    [C - 96 | 'wide->narrow'(T)];
'wide->narrow'([C|T]) ->
    [C | 'wide->narrow'(T)];
'wide->narrow'([]) ->
    [].

결과:
(emacs@desktop)8> str_util:'wide->narrow'("ABC012").
str_util:'wide->narrow'("\357\274\241\357\274\242\357\274\243\357\274\220\357\274\221\357\274\222").
"ABC012"

REPL이 지원되지 않는 언어였더라면 과연 이렇게 눈깜짝할 사이에 만들 수 있었을까?
단위 작업의 feedback이 즉시 확인되는 것은 엄청난 매력이자 장점이다.

happy hackin'
좀 복잡한 테스트 케이스를 하나 추가하고 컴파일후 mod:test()를 실행했더니,
다음과 같은 에러가 나면서 그 모듈에 대한 유닛 테스트가 아예 동작하지 않았다.
*** test module not found ***
::false

{error,{module_not_found,false}}

순간 당황했으나, 방금 추가한 테스트 케이스를 살펴보니 _assert macro에 들어가는 내용이 잘못되어 있었다. boolean expression이 들어가야하는 곳에 그냥 expression만 하나 들어있었고, _assert(very_complex_expression) =:= expected value의 형태로 되어 있었다(어제 급히 추가하고 안돌려보고 바로 퇴근한 것이 후회되는 순간이었다). 그래도 컴파일은 멀쩡히 평소처럼 잘 되고 runtime에 가서야 에러가 나는 것은 좀 불편해보인다.

간략히 축약해서 예를 들자면 다음과 같다.
%% causes runtime error (see above msg).
?_assert(1+1) =:= 2
%% runs well w/o runtime error (good)
?_assert(1+1 =:= 2)

실제 내 코드에서는 1+1부분이 많이 복잡해서 화면을 넘어가고 있었고, _assert macro가 여러 개의 리스트로 묶여져 있어서 찾는데 좀 고생했다. Orz.

happy hackin'
외부 DTD 파일에 <?xml version ... ?> 같은 XML 파일임을 나타내는 PI가 들어있으면 xmerl_scan:(file|string)에서는 다음과 같은 에러를 내면서 parsing이 안된다 (java 쪽에서는 별 문제가 없었던 DTD 파일이다).

error msg:
1066- fatal: {invalid_target_name," version=\""}
** exception exit: {fatal,{{invalid_target_name," version=\""},
                           {file,"/path/to/dtd.dtd"},
                           {line,6},
                           {col,18}}}
     in function  xmerl_scan:fatal/2
     in call from xmerl_scan:scan_ext_subset/2
     in call from xmerl_scan:scan_decl_sep/2
     in call from xmerl_scan:scan_ext_subset/2
     in call from xmerl_scan:scan_decl/2
     in call from xmerl_scan:fetch_and_parse/3
     in call from xmerl_scan:fetch_DTD/2
     in call from xmerl_scan:scan_doctype2/3

간편 해결책: DTD 들이 있는 디렉토리에서 다음을 실행해주자 (DTD 파일이 여러개일때...)
$ sed -i -r "/<\?xml .*\?>/s/.*//" *.dtd      # remove xml PI stuff.
$ sed -i '/./,/^$/!d' *.dtd                   # remove leading blank line(s).

happy hackin'
ko:
성능을 향상 시키는 방법:
  1. 메모리 사용량을 낮게 유지한다.
  2. CPU 사용률을 높게 유지한다.
  3. 한계를 넘어서지 않는 한 많은 수의 worker 를 동작시킨다. (2번을 실제 적용하는 유용한 방법중의 하나).
  4. 실행 흐름을 동기화가 필요하지 않은 방향으로 설계한다 (spawn후에 잊어버리기 전략. 3번과 일맥상통).

en:
to improve performance of concurrent program:
  1. always keep small footprint of memory usage.
  2. high CPU utilization.
  3. run workers as many as possible (of course, under limit). one of good methods for #2.
  4. design program flow to avoid synchronization. use spawn and forget strategy if possible.

happy hackin'
1 2 3 4 5 6 7 
분류 전체보기 (306)
잡담 (20)
함수형 언어 (65)
emacs (16)
java (18)
tips & tricks (154)
사랑 (1)
가사 (0)
독서 (4)
mobile (6)
비함수형 언어 (2)

공지사항

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

05-14 14:22