2009/02/14

[scheme][Gauche]lambda記法⇒MIT記法

プログラミングGauche」P.75~76 構文の拡張とマクロ

 

 

取り合えず「quate」がまだ正式に出てきてない段階なので「quate」「'」があまりよくわからないので少し試し書き。

evalとか試してみた。引数が2つ必要みたいだけど、何を渡したらいいのか調べず、取り合えず'()を渡したら動いたので続行。

;; (define double (lambda (x)(* x x))) -> (define (double x)(* x x))
(define exp '(define double (lambda (x)(* x x))))

 

exp
;; => (define double (lambda (x)(* x x)))

 

(eval exp '())
;; => double

 

double
;; => #<closure double>

 

(double 5)
;; => 25

 

(define double 1)
double
;; => 1

 

exp
;; => (define double (lambda (x)(* x x)))


(eval exp '())
;; => double


(double 5)
;; => 25

 

'(define double (lambda (x)(* x x)))に対してのcarとcdrの動作を確認してみる。

;; (define double (lambda (x)(* x x))) -> (define (double x)(* x x))
(define exp '(define double (lambda (x)(* x x))))


(car exp)
;; => define


(car (cdr exp))
;; => double


(car (cdr (car (cdr (cdr exp)))))
;; => (x)


(cdr (cdr (car (cdr (cdr exp)))))
;; => ((* x x))

 

ようやく本題。lambda記法をmit記法に変換。コメントのために少しインデントを崩してます。

;; (define double (lambda (x)(* x x)))
;; lambda -> mit
(define (lambda->mit exp)
  (cons (car exp) ;; -> define
        (cons (cons (car (cdr exp)) ;; => double
                    (car (cdr (car (cdr (cdr exp)))))) ;; => (x)
              (cdr (cdr (car (cdr (cdr exp))))) ;; => ((* x x))
              ) ;; => ((double x) (* x x))
        ) ;; => (define (double x) (* x x))
  );; => lambda->mit

 

(lambda->mit exp)
;; => (define (double x) (* x x))

 

(define a (lambda->mit exp))
;; => a

 

(eval a '())
;; => double

 

(double 3)
;; => 9

[scheme][Gauche]MIT記法をlambda式による定義に変換する

プログラミングGauche」P.75 ~ 76 構文の拡張とマクロ

 

こうして考えるとLisp自身を使って構文を追加できそうに思えてきませんか。

思えてきます!

 

ほぼ写経ですが。手続きの名前は好みで変えました。本ではmit-form->primitive-form。

「'(define (double x)(* x x))」を「(define double (lambda (x) (* x x))」に変換するmit->lambda手続き。

(define (mit->lambda exp)
  (cons (car exp)
        (cons (car (car (cdr exp)))
              (cons (cons 'lambda
                          (cons (cdr (car (cdr exp)))
                                (cdr (cdr exp))))
                    ()))))

 

コメント付けてみた。MeadowでM-;が便利。

;; mit -> lambda
(define (mit->lambda exp)
  ;; define
  (cons (car exp)
        ;; double
        (cons (car (car (cdr exp)))
              ;; lambda
              (cons (cons 'lambda
                          ;; (x)
                          (cons (cdr (car (cdr exp)))
                                ;; ((* x x))
                                (cdr (cdr exp))))
                    ()))))

 

(mit->lambda '(define (double x)(* x x)))
;; => (define double (lambda (x) (* x x)))

 

「すべてがリスト」ってのはホンマですね。

2009/02/10

[scheme][Gauche]list-ref+追記

 

指定した位置にある要素を取得する。

(list-ref '(1 2 3 4 5) 3)
;; => 4

 

(list-ref '(1 3 4 5 6) 0)
;; => 1

 

Gaucheプログラミング(立読み版)

プログラミングとは名前付け(bind)である

 

タイトルの「プログラミングとは名前付け(bind)である」って、名言だな。

 

追記:

プログラミングとは名前付け(bind)である」のページのweekday-name手続きを自分なりに書いてみた。

(define (weekday-name index)
  (let ((day-names '("月" "火" "水" "木" "金" "土" "日"))
          (between (lambda (min n max)
                               (and (<= min n)(<= n max)))))
    (if (between 0 index 6)
        (list-ref day-names index))))


(weekday-name 0)
;; => "月"
(weekday-name -1)
;; => #<undef>
(weekday-name 7)
;; => #<undef>
(weekday-name 6)
;; => "日"

 

 

自分なりにって言っても範囲判定の部分をbetweenにして、範囲外はそのまま#<undef>が返るだけだけど。

2009/02/08

[KPF][勉強会]第一回KPF勉強会

kpf.logo.main

第一回KPF勉強会を開催しました!!
KPFでもブログ書くまでが勉強会です♪

(↑のKPFのロゴ画像はrosylillyさん作)

 

KPFとは
「熊本プログラミングフリークス」
Kumamoto Programming Freaks

WS0589 

熊本でプログラマのための勉強会及び読書会などを継続的に開催していくためのコミュニティです。
「熊本のプログラミング大好きなプログラマ集れ!!」的なコミュニティ!

詳しくはKPFのサイトをご覧ください。
メーリングリストもどうぞ。

 

 

参加者は以下の通り。

  • Rubyを内からぶっ壊す!RubyでJavaScriptっちゃう仰天16歳はRubylist。
  • 九州3傑ぷよぷよの猛者!オーバークロック大好きSilverLighter。
  • 言語の話が止まらない!寝るより食うよりコーディング!C/C++/C#er。
  • 異色の研究員プログラマ!過去と未来がフリーランスなRubylist。
  • レコード屋からWebプログラマへ転身!RubyをやりたいPHPer。
  • バイクと水槽とチャリと釣り!バイク屋からプログラマへ転身そして独立C#er。
  • 昨日辞表!独立しちゃう野心あふれる静かなC#erなRubylist。
  • 毎日がクアッドディスプレイ!独立起業のビジネスマンPHPer。

以上8名+の9名でした!
詳しくはKPFのメンバーのページをどぞ。

 

 

猛烈に熱かった!熱かったです!熊本のプログラマは熱い!
大成功だと言わざるを得ませんwすごい盛り上がりでしたw

 

勉強会も4時間近く時間があったので、時間が余るかもしれないと心配していましたが見事に足りませんでしたw勉強会後の懇親会も17:30~0:00までプログラミングの話で盛り上がりました。未だに余韻が覚めやらぬ日曜の午後、この記事を書いています。ブログを書くまでが勉強会!

 

みんな本当にプログラミングを愛しているのだと感じました><
こんな人たちが熊本にいるなんて!技術的な話、ビジネス的な話、プログラミングの話、みんなそんな話がしたくて仕方なかったんだなぁーと。私もそうです。

 

プログラミングが大好きなプログラマって、ソフトウェア開発会社で働いていても滅多にお目にかかれません。「大好きなこと」の話がしたいのに盛り上がれる同士がなかなか見つからないというのは鬱憤がたまるものです。そんなプログラミング大好きなプログラマが集った昨日の勉強会は、ダム決壊的な怒涛の白熱プログラミングトークw

 

  • 熊本のプログラマはKPFに参加すべき !!

 

まとめて面倒みてやるぜ!!なんちって♪
プログラミングが好きな人はKPFへどうぞ。
熊本県に住んでる必要はありません。
プログラミングが大好きなプログラマは取り合えずKPFへ!

 

 

昨日のKPF勉強会の流れ
・主催挨拶 (valvallow
KPFの概要と成り立ち
・発表
・ディスカッション
    ・KPFの今後の活動
    ・勉強会、読書会について
    ・その他多種多様なディスカッション

発表はrosylillyさんと私valvallowの二人が行いました。

 

rosylillyさん

Ruby + JS to Roptotype

Prototype.rb

 

valvallow

プログラミング言語Scheme

 

 

 

最後に、懇親会での「その発想はなかったわ。」をメモメモ。

 

熊本では今までプログラミングの勉強会はほぼ開催されていませんでした。
過去には開催された形跡がWeb上にちらほら

 

福岡では数十のプログラマ向け勉強会があり、毎月いくつも勉強会や読書会が開かれています。
そんな状況を見て、熊本でも勉強会を開催したいという思いでKPFを立ち上げました。この状況を見ると福岡の方が圧倒的に良い環境にも思えますが、勉強会が多いことにも弊害はあるようです。
その一つが、勉強会がたくさんあると、その分優秀な技術者が分散してしまうという状態を作り出すということです。
その点、「熊本に一つだけのKPF」は優秀/有望なプログラマが一点に集るというおもしろい状態を作り出せるのではないでしょうか。そうなれば、九州の中心にある熊本は九州のプログラマをつなげるハブのような役割をも担うことができるすばらしいコミュニティになる可能性を秘めているのでは!?
そんな壮大な話です。

 

 

他の参加者の感想はこちら
・第1回KPF(Kumamoto Programming Freaks)勉強会に参加してきました
http://d.hatena.ne.jp/shunsuk/20090207/1234012737
KPF勉強会、第一回
http://generation1991.g.hatena.ne.jp/rosylilly/20090208/1234062915
・第一回クマモトプログラミングフリークス
http://mixi.jp/view_diary.pl?id=1074721269&owner_id=5046838

 

 

次は3月末にまた「第二回KPF勉強会」を開催しますよん♪

2009/02/07

[scheme][Gauche]可変長引数、練習問題list

プログラミングGauche」P.72~

P.74 練習問題
;; list
;; MIT
(define (my-list . a) a)
;; lambda
(define my-list (lambda a a))

(my-list 1 2 3 4 5) ;; => (1 2 3 4 5)
(my-list 1) ;; => (1)
(my-list) ;; => ()

MIT記法と非MIT記法での可変長引数
;; MIT
(define (func . a) (print a))
(func 1 2 3 func + '() "aaa" 4 5 6)
;; => (1 2 3 #<closure func> #<subr +> () aaa 4 5 6)


;; lambda
(define func (lambda a (print a))
(func 1 2 3 func + '() "aaa" 4 5 6)
;; => ;; => (1 2 3 #<closure func> #<subr +> () aaa 4 5 6)

mapに複数のリストを渡してみる。
手続きも可変長引数を取れるように。
;; higher order varargs mapping
(map (lambda a (print a) a) '(1 2 3) '(1 2 3 4 5))
;; => (1 1)
;; => (2 2)
;; => (3 3)
;; => ((1 1) (2 2) (3 3))

print関数を自前で実装してみる。
;; print
;; MIT
(define (my-print . a)
  (map (lambda (s)(display s)(newline)) a))
(my-print 1 2 3)
;; => 1
;; => 2
;; => 3
;; => (#<undef> #<undef> #<undef>)



;; lambda

(define my-print
  (lambda a
    (map (lambda (s)(display s)(newline)) a)))
(my-print 1 2 3 4 5)
;; => 1
;; => 2
;; => 3
;; => 4
;; => 5
;; => (#<undef> #<undef> #<undef> #<undef> #<undef>)

プログラミングGauche

[scheme][Gauche]reversed

プログラミングGauche」P.67

 

これは、この発想はなかった。

高階プログラミングが身についてない証拠かも。

 

手続きにリストを逆順に適用する走査手続きを生成する手続き。

(define (reversed walker)
  (lambda (proc ls)
    (walker proc (reverse ls))))

 

(define (tree-walk walker proc tree)
  (walker (lambda (ele)
      (if (list? ele)
        (tree-walk walker proc ele)
        (proc ele)))
    tree))

(tree-walk for-each (lambda (n)(print n)) '(1 (2 3 (4 5)) 6 (7 8 9) 10))
(reversed for-each)
(tree-walk (reversed for-each) (lambda (n)(print n)) '(1 2 3 (4 5 6)))
(reversed map)
(tree-walk (reversed map) (lambda (n)(+ n n)) '(1 2 3 (4 5 6 (7 8 9)) 10))

[scheme][Gauche]map

プログラミングGauche」 P.66

 

map
リストの各要素に引数の手続きを適用し、結果をリストにして返す。
リスト内の順序は保持されても、引数の手続きがリストの順番通りに適用される保証はない。

 

map

;; map
(map (lambda (n) (* n n)) '(1 2 3 4 5))
;; => (1 4 9 16 25)

 

mapにprint手続きを渡してみる。

(map (lambda (n) (print n)) '(1 2 3 4 5))
;; => gosh> 1
;; => 2
;; => 3
;; => 4
;; => 5
;; => (#<undef> #<undef> #<undef> #<undef> #<undef>)

 

 

mapにlambdaを渡してみる。

(map (lambda (n) (* n 2)) '(1 2 3 4 5))
;; => (2 4 6 8 10)

 

木構造リストの末端要素(リーフ)に手続き(proc)を適用するtree-walk。

走査手続きwalkerにはfor-each手続きを渡してみる。

;; tree-walk
(define (tree-walk walker proc tree)
  (walker (lambda (ele)
      (if (list? ele)
        (tree-walk walker proc ele)
        (proc ele)))
    tree))

 

tree-walkにmapを渡してみる。

;; tree-walk with map
(tree-walk map (lambda (n) (* n n)) '((1 2) 3 (4 (5 6 (7))) 8))
;; => ((1 4) 9 (16 (25 36 (49))) 64)

 

以前も書いたがリストを逆順にするreverse手続きを使う。

;; reverse
(define (reverse ls)
  (define (rev-iter ls ret)
    (if (null? ls)
      ret
      (rev-iter (cdr ls)(cons (car ls) ret))))
  (rev-iter ls '()))

(reverse '(1 2 3 4 5));; => (5 4 3 2 1)

 

;; reverse
(define (reverse ls)
  (fold cons '() ls))

(reverse '(1 2 3 4 5)) ;; => (5 4 3 2 1)

 

逆順に手続きを適用する。

;; reverse-map
(define (reverse-map proc ls)
  (map proc (reverse ls)))

(reverse-map (lambda (n) n) '((1 2) 3 (4 (5 6 (7))) 8))
;; => (8 (4 (5 6 (7))) 3 (1 2))

(tree-walk reverse-map (lambda (n) n) '((1 2) 3 (4 (5 6 (7))) 8))
;; => (8 (((7) 6 5) 4) 3 (2 1))

[C#][WSH]メッセージボックスを自動で閉じたい

 

MessageBoxを自動で閉じたいなーと思ったら、こんな裏技(力技)が!
WSHを使って表示時間を指定したMessageBoxを表示するというテクニック(?)みたいです。

 

[.NET][C#][Code]一定時間で自動的に閉じるメッセージボックス
http://d.hatena.ne.jp/akiramei/20040921/p1

 

WshShellClassクラスを使うには参照設定でCOMから「Windows Script Host Object Model」を参照して「IWshRuntimeLibrary」をusingディレクティブに加えればOK。
詳しくはここ↓を参照。

 

[C#] ショートカットファイルの作成
http://d.hatena.ne.jp/gsf_zero1/20070419

 

ちゃんとやるんなら、自分で専用のクラスを作るべきなんでしょうかね、やっぱ。
まぁでもXP以降ならWSHはプリインストールされてるみたいだし、いいんじゃね。


WSHクイックリファレンス 第2版

2009/02/06

scheme, Gauche: let、let*、letrec

それぞれの let

let

初期値式が先に評価されて、その後、変数名に束縛される。
初期値式の中で同レベル(同一スコープ)の変数を参照しようとしても、変数は unbound(束縛されていない) variable(変数)となる。
;; let
(let ((a 2)
      (b 3))
  (* a b))
;; => 6


;; nested let
(let ((a 2)
      (b 3))
  (let ((c 4))
    (* a b c)))
;; => 24


;; let with lambda
(let ((a 2)
      (b 3)
      (c (lambda (x y) (* x y))))
  (c a b))
;; => 6


;; cに束縛しようとしているlambda式内からは変数cが見えていない。
;; let with recursion
(let ((a '(1 2 3 4 5))
      (b 2)
      (c (lambda (ls x)
           (if (pair? ls)
               (c (cdr ls) x)
               (print (* (car ls) x))))))
  (c a b))
;; => ERROR: unbound variable: c


letrec

初期値式が評価されるときに同レベル(同一スコープ)の変数が見えている。
ローカルスコープでの再帰が可能。
;; letrec recursion
(letrec ((sum (lambda (ls)
                (cond ((null? ls) 0)
                      ((number? (car ls))(+ (car ls)(sum (cdr ls))))
                      (else (sum (cdr ls)))))))
  (sum '(1 2 3 4 5 6 7 8 9 10)))

P.72 の「ローカルな相互再帰手続き」の例の写経
;; letrec odd adn even double recursion
(letrec ((even? (lambda (n)
                  (cond ((zero? 0) #t)
                        ((> n 0) (odd? (- n 1)))
                        (else (odd? (+ n 1))))))
         (odd? (lambda (n)
                 (cond ((zero? n) #f)
                       ((> n 0) (even? (- n 1)))
                       (else (even? (+ n 1)))))))
  (even? 10))

let*

;; let*
(let* ((a 2)
       (b 3)
       (c (* a a)))
  (* a b c))
;; => 24


;; let* はネストした let と同等
(let ((a 2)
      (b 3))
  (let ((c (* a a)))
    (* a b c)))

Gauche には他にもたくさんの let 系マクロがある。let1, rlet1, if-let1, match-let, let-values, let/cc などなど。


プログラミングGauche

[Regexp][正規表現]正規表現メモ

 

・[電話番号]
([0-9]{2,4}-[0-9]{2,3}-[0-9]{4})|([0-9]{8,11})

 

・[携帯電話]
([0-9]{3}-[0-9]{4}-[0-9]{4})|([0-9]{11})

 

・[郵便番号]
[0-9]{3}-[0-9]{4}

 

・[西暦(数値のみ)]
([0-9]{4})(0([1-9])|1([0-2]))(([0-2][0-9])|(3[01]))

 

・[メールアドレス]
[a-zA-Z0-9!$&*.=^`|~#%'+\/?_{}-]+@([a-zA-Z0-9_-]+\.)+[a-zA-Z]{2,4}

 

・[全角文字列]
[^ -~。-゚]*

 

・[半角文字列]
[ -~。-゚]*

 

・[数値]
([0-9]+\.[0-9]+)|([0-9]+)

 

・[「.」区切りの数字]
[0-9]+(\.[\.0-9]+)[0-9]

 

 

 

正規表現いいよねー。自分はつい先日まで正規表現使ったことありませんでした。

使ってみたら、なぜもっと早く学ばなかったのか強烈な後悔が押し寄せたものです。

 

取り合えず、「入門 正規表現」って本をザッと読んだら、少し書けるようになった。

少し書けるようになった今、もう一度読みたい。