Scheme

radikoスケジューラー

聴きたいradikoの番組を聴き逃さないために、時間になったら自動的に番組を再生してくれるプログラムを作ってみました。再生にはブラウザを使用するので、Schemeで番組表APIを叩いて検索、番組データをJSON化してブラウザに渡す、という流れになります。ブラ…

Scheme で定数定義

define がそろそろ長くて面倒になってきたので (遅いですか?)、こういうマクロを作ってみました。 (define-syntax set (syntax-rules () ((set id x) (define id x))))これならタイプするのも簡単です。Racket であれば (define-syntax set (make-rename-tr…

MPEG-4、ツリー探索、autovivification

近ごろ動画や音声データの読み書きを Scheme でしているんですが、MPEG-4 の処理が個人的にかなり楽しかったので少し書きます。MPEG-4 のデータはこのようなツリー構造になっており、お馴染みのツリー探索のテクニックが活躍しそうな雰囲気です。 (define st…

多値アクセス構文

ML(やHaskell)のプログラマがタプルを使うような文脈でSchemerは多値を使うと思うんですが、値が一つだけ欲しいという場合に多値はちょっと不便なんですよね。MLだとfstやsndというアクセサが使えるんですが、それに相当するものが無いなと思って、作ってみ…

PLT SchemeのREPLで直前の値を参照できるようにする

CLの処理系にも似たようなのがあると思いますが、HaskellのGHCiで、直前に評価された値にitでアクセスできるというのがあったので、真似してみました。 #lang scheme/base (provide it) (define it~ '()) (define eval~ (current-eval)) (define-syntax it (…

Clojure風の無名関数構文

Arcには角括弧で無名関数を作る構文があります。例: > (map [if _ (+ 1 _) 1] '(1 -1 nil)) (2 0 1)便利そうなのでマクロで模倣して喜んでいたんですが、1引数の関数しか作れないのが不便に感じることもありました。で、最近Clojureにはその多変数版みたいな…

環境を汚さないrequire

トップレベルで作業をする時に、どうしてもライブラリを利用したくなりますが、その時にrequireで幾つもロードしていると、何となくREPLを汚してしまってるような気分になります。実際それで困ることはまず無いんですが、たまに基本構文のセマンティクスが変…

Purely Functional Red-Black Tree

ちょっと思い立って作ってみました。最初はProgramming Praxisで示されている実装から出発したんですが、結果的にはHaskell版の実装に近い形に変化していきました。アルゴリズム等の解説はWikipediaに譲ることにして、ここではマクロを活用して煩雑なパター…

連想リストを適用可能にするために必要なこと

連想リストから値を検索する際に、このように lookup 関数を毎度毎度呼び出すのが面倒だなーと思うことがあります。 (let ((al '((a . 1) (b . 2) (c . 3)))) (list (lookup 'a al) (lookup 'b al) (lookup 'c al)))これを、 (al 'a)のように書けたら楽です…

ifのセマンティクスをarc風にする試み

anaphoric ifを使っていて時々感じるんですが、やはり空リストが偽として扱われない Scheme の意味論は、実用上どうしても不便なことが多いです。例えば、cdr が空でなければループを続ける (if (pair? (cdr l)) (loop (cdr l)) ...)というパターンを (aif (…

Threaded OR (in PLT Scheme)

ある必要があって、複数のリソースから最初に返答の得られたものを値として採用する、という構文を作ってみました。実装: (define-syntax spawn (syntax-rules () ((spawn . e) (thread (lambda () . e))))) ;; cf: http://scheme.com/tspl4/examples.html#.…

flet & labels in Scheme

ループ処理を書く時などに、全く同じ関数呼び出しを複数回書くことがあると思うんですが、それがどうも面倒*1なので、ローカル関数を手軽に作る構文を書いてみました。マクロ: (require "mlfun.ss") (define-syntax define-flet (syntax-rules () ((define-f…

ルート探索を用いた型変換

Scheme のような、強い型付けがされた言語でプログラミングしていると、型変換の作業が面倒になることがあると思います。あるいは、複数の型のデータが流れ込んできて、それらを統一的に扱いたいというケースもあるかも知れません。ということで、型変換の関…

ML や Haskell でよく見る ' (プライム) 記号がうらやましかった件について

数学でよく使われる記号だと思うんですが、ML系のプログラムとか論文を読んでいると、1重引用符が識別子の後に付けられているのをよく見かけます。ある関数の変種とか、ある変数に基づいて一時変数を作る時などに、いちいち新しい名前を考えなくて済むので便…

部分継続について本気出して考えてみた

以前何度か部分継続について書いたことがあるんですが、当時は表面的な振る舞いを観察して何となく分かった気になった程度の拙い説明しか出来ませんでした。その上、最近のプログラミングでもほとんど活用しておらず、改めて理解し直す必要を感じてきた次第…

もっと! ML/Haskell っぽい関数構文

ML や Haskell では、関数を定義する時に、変数だけでなくリテラルやデータ・コンストラクタなどでパターンマッチをすることができますね。PLT Scheme にも、それによく似た構文があります。 > (require scheme/match) > (match '(1 . 2) ((cons x y) (list …

Anaphoric If

Arc の aif のように、意図的な変数キャプチャ (マクロ定義の中で作られた変数をマクロユーザーが参照できるようにすること) を用いたマクロを作る時、Scheme では一般に datum->syntax という関数を使います。 (define-syntax (aif stx) (syntax-case stx (…

マクロを書くマクロで Arc の角括弧構文

Haskellっぽいカリー化関数の構文で、「Haskellっぽい」と言いながらも Arc の角括弧みたいな構文を導入しました。実際にはそれにも偽りがありまして、見た目は Arc っぽいんですが実体は SRFI-26 の cut の糖衣構文に過ぎなかったわけです (次のように変換…

Haskellっぽいカリー化関数の構文

以前作ったMLっぽいカリー化関数の構文を使って、今度はHaskellっぽいのを作ってみました。こういうことが出来るようになります。関数定義: > (add x y := (+ x y)) > (add 1 2) 3 > ((add 1) 2) 3ラムダ式: > (map (x -> (+ x 1)) '(1 2 3)) (2 3 4) > (map…

Unix シェル的なバックグラウンドでのタスク処理

bash> command &みたいに、バックグラウンドで関数を呼び出して、値が必要になった時に表に戻す、というイディオムを思い付きました。 (define (& t) (let ((c (make-channel))) (thread (lambda () (channel-put c (t)))) (lambda (k) (k (channel-get c)))…

ニコ動のコメントをREPLで

最近ニコ動に上がっている作業用BGMとか、音声だけで楽しめるものをWinampで聴く、ということをしているんですが (Scheme でローカルサーバー -> localhost:2525/?id=VIDEO_ID 的なURLをWinampで再生 -> にこさうんど or にこみみのキャッシュを探す -> mp3…

Scheme から Emacs のコマンドを実行

私はよく Scheme のプログラムを Emacs 上で実行するんですが、elscreen で裏に回していたりして *scheme* バッファが見えない時に、何かユーザーの注意や介入が必要な事態が起こっていることがあります (入力を促す、等)。そんな時、外部プログラムを起動す…

Implicit Function Currying with Automatic Partial Evaluation

関数の部分適用と部分評価を自動的に行うマクロの実装を、日本語と Scheme で示していきます。 動機 前回 fun と fn という、Standard ML ライクなカリー化関数の構文をご紹介しました。とても便利で既に多用しているんですが、一つどうしても気になるのは、…

ML っぽいカリー化関数を定義するマクロ

ML とか Haskell のコードを読む時に私がどうしても憧れてしまうのが、自動的にカリー化定義される関数です。Scheme にもカリー化関数を定義する構文自体は存在します (処理系にもよるでしょうが)。例えば、このようなラムダ式のネストで定義された関数を (d…

パーサーコンビネータの性能向上について

自前の XML パーサーやウェブ・スクレイピングなどにパーサーコンビネータ・ライブラリを使っているんですが、どうも実行速度が遅いのが気になってきたので、原因を考えてみました。で、気付いたんですが、例えばこのようなパーサーを定義した時に、 (doP (c…

パーサーコンビネータで作るインタープリタ

ふと、パーサーコンビネータでパーサーを作ると、それをそのままインタープリタとして走らせられるんじゃないか、ということを思い付きました。普通はファイルやネットワークの入力ポートを (parse p input-port)のようにして渡すことで (p はパーサー関数)…

恒等関数としての values

再び多値関連の小ネタです。PLT Scheme のあるライブラリを見ていて、こんな values の使い方を発見しました。 (filter values (list ...))一瞬 values が再定義されているのかな?と思って辺りを探したんですが何も無く、試しにやってみると > (filter valu…

多値と関数合成

PLT Scheme のレファレンス・マニュアルを読んでいてちょっと驚いたことがあるので書きます。compose 関数で合成する関数の中に、多値を返す関数を入れられるんですよ: (map (compose list split-path path->complete-path) (directory-list)) ; => ((#<path:C:\home\desktop\> #<path:onlisp.pdf> #f</path:onlisp.pdf></path:c:\home\desktop\>…

livedoor 番組表から Google Calendar へ

plagger 界隈等で話題としてはおなじみだと思うんですが、Scheme でやってみました。livedoor 番組表の RSS フィードで番組検索をし、ATOM ドキュメントに変換して Google Calendar のフィード API にポストする、というものです。 livedoor tv とりあえず、…

パーサー・コンビネーターで Web スクレイピング

パーサー・コンビネーター (parser.ss) を使って、テキスト全体の解析だけでなく、部分を抽出することも可能なんじゃないかと思い付き、実験してみました。例として、はてなダイアリーに貼り付けられているコードを抽出するパーサーを作ります。 このページ…