2010/05/31

遅延評価はマクロで、多値は継続とマクロで実装できるんですって

そういえば、伝統的マクロなら継続も実装できるんでしたっけ?



The Scheme Programming Language, 4th Edition

syntax-rules: allf

便利そうだったので。
こうかなー。


On Lisp

熊本市内の本屋さんに「実用 Common Lisp」がなかった

今日、私の知る限りで最も品揃えの良い熊本市内の本屋さん2件を回ってみましたが、実用 Common Lisp (IT Architects’Archive CLASSIC MODER) は置いてませんでした・・・orz

「私の知る限り」なんて言わなくても、熊本市内で品揃えの良い2件と言ったら、三年坂のツタヤとダイエーのキクヤですね、はい。

ついでに、プログラミング言語SCHEMEビューティフルコード を立ち読んだら、欲しくなりました・・・。

後者は、scheme の syntax-case が載っている25章だけでも良いので欲しいなー。などと Twitter でつぶやいたら、PDF(英語)を教えて頂きました!ありがとうございます!

前者は、英語版が Web 上に公開されているので、チラ見してみます。

Web 上には、無料で読めるものが他にもたくさんあるしなー・・・。実用 Common Lisp (IT Architects’Archive CLASSIC MODER) は、また今度で良いかなー・・・。いや、立ち読んでみたいだけだったんだ。


ビューティフルコード実用 Common Lisp (IT Architects’Archive CLASSIC MODER)プログラミング言語SCHEMEThe Scheme Programming Language, 4th Edition

syntax-rules: let/

(let ((a #f)(b #f)(c #f)) (list a b c)) を (let #f (a b c) (list a b c)) と書ける的な。
良い名前が思い浮かびませんでした。当初 lump-init-let としていましたが、長いのでボツ。(let-with init-value ... というような意味合いを込めて、let/ ・・・。



プログラミング言語SCHEME

syntax-rules: define-syntax-rule, define-syntax-rules

こんなのもありかなー、とか。



こんなのもありかなーとか。


define-syntax-rules がそうなら、define-syntax-rule もこうかなーとか。


結局このくらいが丁度良いのかも。


プログラミングGauche

2010/05/29

2010/05/28

Emacs view-mode がステキ便利

ソースコードはもちろんですが、テキストファイルなどを Emacs で読む機会が多いです。
つい先日も、Twitter で見かけたテキストファイルをダウンロードして、Emacs で読んでいました。
実は、C-x C-q (読み取り専用)なども知らなかったため、C-n C-p で読んでいる時に文章中に n や p が紛れ込むこともしばしばです。これはテキストファイルに限らずプログラムを書いている時もそうで、わりと困っていました。

そこで、こういうものを見かけたので、試してみたら便利も便利。。。
  1. emacsでコードリーディングをするときはvi-modeがおすすめ - goinger的日記
  2. view-mode - とりあえず暇だったし何となく始めたブログ
  3. Ctrl+中指か薬指を使うキー操作が多いEmacsで指の負担を軽くする方法 - (rubikitch loves (Emacs Ruby CUI))
特に、3の rubikitch さんところで紹介されている key-chord.el と view-mode のコンボがすごく便利でした。

例えば、.emacs はよく編集しますが、編集を始めるまでに眺める時間の方が長かったりします。この際、view-mode をデフォにしてみました。

どうせなので、ファイルを開いたときはデフォルトで view-mode にすることにしました。しばらくこの状態で試してみます。


設定は、rubikitch さんのところから頂きました。
キーバインドは好みで以下のように変更しました。メモがてらさらしておきます。


入門 GNU Emacs 第3版

quack-find-file

Emacsでschemeを書く時に、quack.elを使っています。quack.elを使っていると、C-x C-f(つまり find-file)がquack-find-fileになります。
これを解除したかったので、以下のように.emacs に書き加えました。

(setq quack-remap-find-file-bindings-p nil)



入門 GNU Emacs 第3版

2010/05/27

「そのプロセスにおいて、Schemeを使うことに関する多くの勘を やしなうだろう。」

数nの階乗を計算するが、手続きの最終行で自身に再帰できるようにするた めに名前"fact"が必要であるように思える。しかし、我々はそれは必要でない ことを理解し、そのプロセスにおいて、Schemeを使うことに関する多くの勘を やしなうだろう。

これが本当かどうかは置いといて、みんなもっと Y Combinator で遊ぼうよー!

 計算論 計算可能性とラムダ計算 (コンピュータサイエンス大学講座)The Little Schemer, 4th EditionThe Seasoned Schemer

Yコンビネータ 継続編

fixed point of call/cc だそうです。
タイトルに Y Combinator と入れましたが、正確にはそうではないようです。

すごくおもしろそうだったのでプリントアウトして頑張って読んでます。印刷したら10ページありました。まだ3ページくらいしか読んでないので、残りを読んでみます。

で、一見してもよくわかりません。よくわからないので、いじくり回してみました。先日ノーマルな Y Combinator でやったことの、逆過程のようなことをやりました。
結果、理解できてないのですが、なんとなく雰囲気がつかめた気がします。気がするだけかもしれません。
以下コード。



入門Common Lisp―関数型4つの特徴とλ(ラムダ)計算計算論 計算可能性とラムダ計算 (コンピュータサイエンス大学講座)

Re: Re: syntax-rules: reverse-and-quote-list @ IronScheme

「展開した結果に...を含める」には (... ...) と書くことにR6RSではなっています。

R6RS と聞いて思い浮かんだのは、IronScheme, mosh, Ypsilon でした。
取りあえず今回は、すでにインストール済みの IronScheme で試してみました。




どうやら意図通り動いたようです。

追記

IronScheme は Emacs インターフェースもあったりします。
以前少し試したことが・・・。

Programming C# 4.0

Re: syntax-rules: reverse-and-quote-list

letrec-syntax が、なかなか思ったように動かない(書き方がわからない)という状態でした。
補助マクロやローカルマクロが思ったように動かないなら、パターンを追加すれば良いのかも?


ということで、今回の場合はこれで動いたようです。
なんかメソッドのオーバーロード(C#とか)に似ていませんか。



shiro さんにコメントを頂き、教えて頂きました。ありがとうございます!
こうやって処理系の作者の方から直接コメントを頂けるなんて、すごい世界ですね、インターネッツは・・・。
define-syntaxの直下にletrec-syntaxが来る形はGaucheではまだサポートされていません。
「展開した結果に...を含める」には (... ...) と書くことにR6RSではなっています。Gaucheでは未サポートです。
R5RS をまともに読んだことがない、というのがよくないですね・・・orz R6RS についてはほとんど何もしりません。。R5RS に比べてページ数が3倍の150ページになったらしいことと、defmacro でできることができるらしい syntax-case なる難しそうなものがある、ということくらいしか知りません。

追記

補助マクロやローカルマクロが思ったように動かないなら、パターンを追加すれば良いのかも?
でも、余計なインターフェース(?)が増えるのか・・・。うーん。

プログラミングGaucheThe Reasoned Schemer

2010/05/26

syntax-rules: amb

非決定性というやつです。よく分からないので、写経してみました。動き気持ち悪いですね。。どうなってるんですかこれ。。
確か、On Lisp や SICP (計算機プログラムの構造と解釈)にも出てくるらしいですね。

わけわかめ。

追記


On Lisp計算機プログラムの構造と解釈

syntax-rules: try

macroの方のPDFを一通り読み終えたので、continuationの方のPDFを読み始めました。
英語の方は、ほとんどわかりません。The Seasoned SchemerThe Little Schemer, 4th Editionは雰囲気と勢いで読みました。
The Seasoned Schemerに出てくる try のことを思い出しました。





The Little Schemer, 4th EditionThe Seasoned Schemer

syntax-rules: reverse-and-quote-list

取りあえず書いてみたのがこれ。微妙っぽい。

で、PDF に書いてあったのは、こういうの。

なるほどー!

これは、letrec-syntaxとやらで、rl-helperをローカルに定義できるのでは?

エラー。うーん。間違ってるのはどこだろう。。エラーメッセージもよくわからない。
letrec-syntax, let-syntax は余計に情報少ないな・・・(web)。

追記

これは動きますね。。

どういうことかよくわかりません。

プログラミングGaucheThe Reasoned Schemer

syntax-rules: shadow shadows

おー。最初見たときは、驚きました。

では、こうしたら。

おー。便利。
待てよ、これなんてlet?

展開。


プログラミングGaucheThe Reasoned Schemer

Re: syntax-rules: dotimes


プログラミングGaucheThe Reasoned Schemer

2010/05/25

syntax-rules: dotimes



プログラミングGaucheThe Reasoned Schemer

syntax-rules: implecations



追記

コメントでご指摘頂きました。
implecationsではなくimplicationsのようです。

プログラミングGaucheThe Reasoned Schemer

Re: syntax-rules: update-if-true (cond-set!)

shiroさんにご指摘頂きました。大変恐縮です。。
仰る通りですね。(そりゃそうですよね)


こうでしょうか。。


教えて頂きました。
って、ここは・・・偶然にも今日、眺め始めたページ(笑)

追記

引数2つのところはいらないかな?


プログラミングGauche

syntax-rules: quoted-append



追記

何か違う気がする。こういう意図じゃないような気がする。

プログラミングGauche

syntax-rules: update-if-true!

プログラミングGauche って、マクロの章すごく少ないですよね・・・。syntax-rules の練習問題というか例題というか、そういうのをたくさん見たい。ソース読め?



追記

コメント欄より。
cond-set!の2番目の節はおそらくやりたいことと違うのではないかと推察します。
init2だけが複数扱いになり、var2が繰り返されます。
(cond-set! a b c d e f g)

(if a (begin (set! b c) (set! d e) (set! d f) (set! d g)))
になります。(2番目以降、set!されてるのはすべてd)
修正してみました。

プログラミングGauche


syntax-rules: cond-set!

こうですか。。


追記

修正しました。


プログラミングGauche

syntax-rules: (define-syntax foo (syntax-rules () ((foo (a ...) (b ...)) '((a b) ...))))

これは意外。。


プログラミングGauche

syntax-rules: let1

こうかな。

追記

間違ってるな。


プログラミングGauche

syntax-rules: let*

こうかな。


プログラミングGauche

syntax-rules: ever

これを眺めていて(ry


until を書き直してみます。


プログラミングGauche

syntax-rules: until

これを眺めていて思いつきました。
名前付けが適切かわかりませんが、思いつかなかったので、label まで繰り返すということで until 。

プログラミングGauche

2010/05/24

月末取得

私は、今まで以下のようにしていました。
  1. 次月の頭を取得
  2. 1日減算する
例えば、2010/05 の月末を取得したい場合。
  1. 2010/06/01 を取得する
  2. 1から1日減算する
  3. 2010/05/31 が返る
今日、Gauche のリファレンスを眺めていて、この「1日減算する」というのが見当たらなくて、どうやればいいのかわかりませんでした・・・。
検索してみると、こういうのがありました。
(define (days-of-month date)
  (inexact->exact
   (- (date->modified-julian-day (next-month date))
      (date->modified-julian-day (current-month date)))))

julian というのが、たぶんユリウス暦のことだろうというのはわかったのですが、ユリウス暦というのが何なのか、実はよく知りませんでした。

Function: current-julian-day
[SRFI-19] 現在のユリウス日(Julian day)を返します。Julian dayは -4714-11-24T12:00:00Z (November 24, -4714 at noon, UTC) からの日数を 実数で表現したものです。


余談ですが。日付関連って、結構面倒です。業務アプリは日付を扱う機会が多いですよね。プログラマとして仕事を始めたばかりの頃、特に迷走したことを覚えています。

例えば、「期間と基準日を指定して基準日から見て相対的な偶/奇数週の月水金の祝日意外に予定を展開」などの条件指定ができる機能などでしょうか。過去も含めて長期間を指定された場合など、特に面倒そうですね。。まず祝日が面倒ですね。


SQL が面白くて調子に乗っていた時なども悲惨でした。担当していた業務アプリが MSSQL のみのサポートから MSSQL/MySQL サポートになった時などは吐けました。。
--int型の任意の日付から月末を取得する
SELECT
CAST(CONVERT(VARCHAR, DATEADD(DAYOFYEAR, -1, DATEADD(MONTH, 1, CONVERT(DATETIME, CONVERT(VARCHAR(6), REPLACE(STR(20080215), ' ', '')) + '01 00:00:00', 112))), 112) AS INT)
--結果:20080229

この場合、サポート DB が増えたことよりも、こういったクエリを散在させていたことが致命的だったわけです。。下級戦士どころじゃねーぞ。

そういえば JavaScript なんかも、月が0始まり(0~11)で驚きましたね。

プログラミングGauche

syntax-rules: for

結局、9LISP の宿題をやり終えていなかったので、いくつか書いていました。

for をより for らしく書き直していったつもりでしたが、do マクロに近づいて行きました。do マクロと聞くと do ~ while とか do ~ until などを連想しますが、for に近いですね。というか、for じゃないですか。
これは、for というより nfor といった感じでしょうか。


step を追加。


練習がてら do マクロで書き直し。


数値に限らないように書き直し。


再度 do マクロ。


さらに、for らしく。


この辺で、劣化 do マクロを書いている様な気がしてきたので終了。

for って自由度高いですよね


プログラミングGauche

gauche with-module

前にメモっていますが、もう一度。


プログラミングGauche

call/cc sum1-n, reverse

(call/cc identity) が、なるほど!だったので。



プログラミングGauche

2010/05/22

Emacs custom-set-faces

custom-set-faces のことを知りませんでした。お陰様で、quack.el のシンタックスハイライトを変更したかったとき、quack.el を直に修正しましたよ・・・。

.emacs 編集時(lisp-mode?)の、コメントは斜体ですよね。それを変更しました。


そこで、quack.el のことを思い出してのぞいて見たら同じことができるようだったので、そうしました。


そういえば、auto-complete.el でもやってましたね。


何か一冊くらい Emacs の本が欲しいな。。

入門 GNU Emacs 第3版

2010/05/19

Re: TSS rember1*

もっとカッコよく書けないのかなーと思いながら。



いくつか書いていれば何か思いつくかなー、と思いましたが思いつきませんでした。わかりにくくなった気がします。

しかし、ホント The Seasoned Schemer のコードときたら・・・。。

The Seasoned Schemer

t, nil, '(), #t, #f

メモっておきたかったので、勝手にまとめました。「誰でも編集可」です。

私の日本語がカオスですいませんでした・・・。

「scheme も Common Lisp みたいに、nil が偽で空リストも偽で空リストが nil 、だと良いのになー。」「(car nil) や (car '()) が nil なのも良いなー。」と思ったのでした。なんで Scheme はそうじゃないんだろう?というのが切欠です。




Chaton の方からも転載・・・。
shiro
#
@valvallow @finalfusion 括弧のざわめきに混じって俺を呼ぶ声が聞こえた、ような気がした。
#
nil問題はいくつかの要素が絡んでいるので、分けて考えると良いかと思う。
#
とりあえず返しておける値があると便利、という話と、それがリストのゼロ元である()であると便利、という話。
#
とりあえず返しておける値、というのは、例えばwhenの条件不成立時とか、findで値が見つからなかった時とか、そういう何かの不成立を示すユニバーサルな値ってこと。
#
値そのものは何でも良いんだけど、条件判断と組み合わせた時に偽と判断されるようになってると色々便利。
#
ちょっと一休み
2010/05/19 02:23:04 PDTshiro
#
一方で、主要なデータ型のゼロ元が偽になるようになっていると便利、ということがある。再帰/繰り返ししていってゼロ元に出会ったら終わり、という処理が短く書けることが多いから。
#
リストが主要なデータ型であれば、空リストが偽であると便利。
#
整数が主要なデータ型であれば、0が偽であると便利 (C言語とかね)。
#
中には、リストのゼロ元も整数のゼロ元も文字列のゼロ元も偽にしちゃおうって言語もある (Perlとか)。
#
ただ、この二つの要素、どちらもトレードオフがある。
#
不成立/不存在を示す値=偽値、という設計だと、「偽値が見つかった」という答えを返すのがちょっと困る。gethashでnilが返って来た時、値は存在しなかったのか、それともnilという値だったのか。
#
CLでは多値を使ったりしてこの問題を回避するけど、アドホックな感じは否めない。厳密にやるなら、「どんな値とも一致しない値」を使って不存在を示すしかなくて、そうすると例えばHaskellのMaybeみたいに値を一段ラップしてやることになる。
#
ゼロ元=偽、という設計についても、そのデータ型にとっては便利になるんだけど、他のデータ型にとっては便利にならないっていう非一貫性がある。CLで()が偽で便利なのは、リストばっかり使うからそう思ってるだけ。Cで書いてて0が偽で便利なのは、整数のドメインで作業することが多いから (あと、不存在を示すヌルポインタってものもあるけど)。
#
つまり、「便利」という時には、「その機能が便利になるようなコードの書き方をしているから便利なのだ」ということになってる可能性がある。
2010/05/19 02:37:09 PDTshiro
#
Schemeは前者 (不存在を示す値) については不徹底で、findで#fが返ってくる問題とかあるんだけど、後者についてはいろんなデータ型に対して中立ってことなんじゃないかと思う。
#
結局、()と#fが区別されたらそれに依存したコードを書けて、それもまた「便利」ではあるので、どういうモデルで世界を見てるかってことなんだよね。
#
あと、シンボルのnilとtを特別扱いすることに対しては私は多いに不満。プログラマから使える単語を取り上げる言語は嫌い。
2010/05/19 02:42:54 PDTvalvallow@twitter
#
すごくよくわかりました!ありがとうございました m(_ _)m
2010/05/19 02:49:49 PDTshiro
#
CLで書いてる時は確かに()=nil=偽にばりばり依存したコードを書いてるけど。たまに「シンボルかリストかで分岐したい」なんてコードを書きそうになってnilのせいできーってなることはある。
2010/05/19 03:42:36 PDT齊藤
#
そういや R6RS が出来る前に未定義値は「未定義であることを表す (比較可能な) オブジェクト」にしようみたいな話があったと思うんですが、結局は「何も期待するな」になったのは、やっぱ Scheme 的にそういう依存は好ましくないってことなんでしょうか。
2010/05/19 03:43:38 PDTshiro
#
ああ、そんな議論がありましたね。
#
私の印象では、依存が好ましくないというより、未定義値の使いどころ/位置づけがうまく決まらなかったからじゃないかなあという気がしています。「未定義値」という値として使えるってことになると、それを普通に引数に渡したり戻り値として返したり、とやることになるわけですが、それが出来て嬉しいの/何に使えるの? ってことです。
#
「使っちゃいけない値/当てに出来ない値」を示す値、というのは矛盾していて、値として存在してしまったら使えちゃうわけですから。
2010/05/19 03:51:59 PDT齊藤
#
意味が無いところは意味が無いままな方が自然ってことですね。

shiro さんありがとうございました。


そういえば、clojure は?



On LispプログラミングGauche