Scheme

フィボナッチで各種言語をベンチマーク

AWK、Ada、Bash、Boo、C、C#、C++、Clojure、D、Erlang、Forth、Fortran、Go、Groovy、Haskell、Io、Java、JavaScript、Lisp、Lua、OCaml、Objective-C、PHP、Pascal、Perl、Pike、Prolog、Python、R、Ruby、Scala、Scheme、Smalltalk、Tcl でフィボナッチ数…

Scheme で read

Scheme の入出力ライブラリ関数の中でも read は異彩を放っている。read-char がテキストを一文字ずつ読み込むのに対し、read は S 式をひとつずつ読み込む。以下は指定したファイルから S 式を読み込む関数。 (define extract-sexp (lambda (filename) (wit…

Scheme の手続きを動的に #2

今日はふたつ賢くなった。ひとつはScheme の #() と '#() が違うものだということを前回のエントリのコメントで教えていただいた。いくつかの処理系で #() を評価させて試してみたところ、以下のようになった。 Ypsilon 0.9.6-update3 (R6RS) > #() error: i…

Scheme の手続きを動的に

やりたいことはすごい簡単なんだけど、やり方がわからない。 (define op #(+ - * /)) (define calc (lambda (kind lhs rhs) ((vector-ref op kind) lhs rhs))) (calc 0 1 2) 手続きをベクタとかリストに持っておいて、それを取り出して実行したい。Gauche だ…

Scheme、ミニマリストすぎるのも困り者

こーゆーのは、例えばRubyなんかではsleepコマンドを出力の間に入れて簡単に出来るんですが、一方、Scheme のR5RSひっくり返して調べてみても、こう言う「表現」をやる方法は無いんですよね。一切無い。 http://www.shido.info/gb/guestbook.php?id=2082 こ…

Scheme の SRFI の使い方

Gauche だと (use srfi-27) で良いんだけど、Racket の R5RS だと (cond-expand (srfi-27 ;; ... )) で cond-expand が原因で「reference to undefined identifier: cond-expand」というエラーが出てしまう。SRFI-62 の S 式コメントは普通に使えるので、な…

Scheme でやりたいこと

Scheme は予約語がなかったり構文拡張ができたりするので、自分で言語をデザインできるのが魅力だ。やりたいことをまとめておこう。 ジェネリック関数 length、string-length、vector-length を length に、write、write-char を write に統合。これはそんな…

DrRacket を試してみた

DrRacket でデバッグでステップ実行をしているところ。ガリガリ書くためのエディタとしては機能は足りていないんだけど、実行環境としてはこの上なくわかりやすい。特にステップ実行で変数の内容が確認できるのはすばらしい。任意の S 式でブレイクポイント…

vector-append を実装してみた

R5RS では (length list) (string-length string) (vector-length vector)のようにデータ構造によって手続きが分かれている。これが気に入らない。Haskell の length や Python の len のように「長さを求める」という抽象化された手続きがひとつにまとまっ…

Scheme で append 手続きを再実装(復習)

Scheme で append 手続きを再実装(完成) - satosystemsの日記で、コメントで教えてもらった append の実装を解析。 (define append (lambda args (let f ((ls '()) (args args)) (if (null? args) ls (let g ((ls ls)) (if (null? ls) (f (car args) (cdr …

Scheme で append 手続きを再実装(完成)

手続き list-append がようやく完成した。 (define list-append (lambda (a . b) (define add (lambda (x y) (reverse (cons y (reverse x))))) (define end (lambda (x y) (if (null? x) y (end (reverse (cdr (reverse x))) (cons (car (reverse x)) y))))…

if じゃなくて cond を使おう

Scheme の if 式は (if <test> <then> <else>) という感じなので、 if (a == 1) { printf("a is 1"); } else if (a == 2) { printf("a is 2"); } else if (a == 3) { printf("a is 3"); } else if (a == 4) { printf("a is 4"); } else { printf("unknown"); } という条件分岐</else></then></test>…

リスト操作の罪悪感

Scheme をやっていて感じる罪悪感は、リスト操作の愚直性だ。例えば、リストの長さを得る手続き list-length は (define list-length (lambda (a) (let loop ((x a) (len 0)) (if (null? x) len (loop (cdr x) (+ len 1)))))) こんな感じなんだけど、これを …

null?、pair?、list? 手続き

Scheme にはリストの種類を判別するための手続きは、3 つある。 null? (null? '()) ; => #t (null? (list)) ; => #t (null? '(a)) ; => #f (null? 'a) ; => #f null? 手続きは、とにかく空リストだった場合は #t を返す。 pair? (pair? '()) ; => #f (pair? …

Scheme で null? 手続きを再実装

こんな感じかな。 (define null? (lambda (a) (eq? '() a))) Scheme には等価性検証に eq?、eqv?、equal? が用意されているけど、 eq? は同一性 eqv? は甘めの同一性 equal? 同値性 という風に使い分ける。Java で言うと、eq? は ==、equal? は equals(Objec…

Scheme で append 手続きを再定義(未完成)

append 手続きも再定義してみた。 (define list-append (lambda (a . b) (let loop ((a a) (b b)) (if (null? b) a ; b が空リストなら a を返す (if (null? a) ; b が空リストじゃなくて (loop (car b) (cdr b)) ; a が空リストなら b の car と cdr で再帰…

Scheme で length 手続きを再実装

久しぶりに Scheme の勉強。R5RS を読んでいて気になるのが、list と vector と string に対して、それぞれ似たような、だけど専用の名前の関数が用意されていること。その中でも極めつけが length 関数。Python だと len 関数、Haskell だと length 関数に…

Haskell と Scheme の共通点

Haskell の本を再度読み始めてみて、すっかり忘れていたいろいろを改めて認識した。同じ関数型言語だけあって Scheme と同じ考え方が多い。 リストの扱い Haskell も Scheme もリストが超重要なデータ構造なんだけど、どちらも以下のような特徴がある リンク…

Windows の Gauche(と Ypsilon)のコンソールで UTF-8 対応 #4

Windows コンソールで多言語対応ができるようになりました(Ypsilon ですが)。前回と同じ以下を実行したものです。 (integer->char 955) (integer->char #x3042) 'こんにちは '你好 '안녕하세요 上図は対応前のものです。 Ypsilon はコンソールから読み込む…

Windows の Gauche コンソールで UTF-8 対応 #3

注意:この記事は書きかけのまま、本業等が忙しく、何週間も経ってしまったため、何を書いていたのか自分でもわからなくなったので、未完という形にすることにしました。調査中にわかったことがいくつかあるので、それはまた次回の記事で記したいと思います…

Windows の Gauche コンソールで UTF-8 対応 #2

ただ、まだ入力の方に対応できていないので、茨の道はまだまだ続くのであった。 Windows の Gauche コンソールで UTF-8 対応 - satosystemsの日記 これはホントに茨の道だ。なんだかまだよくわかってないし解決してないけどまとめておこう。 そもそも何で UT…

Windows の Gauche コンソールで UTF-8 対応

Gauche のコンソールで日本語が扱えないのは前から気がついていたんだけど、どうやらこんな感じのようだ。 どうしてもコンソールで日本語を常用したければ、入出力をshift_jisで行うようなラッパースクリプトを書いてREPLを走らせることはできるかもしれませ…

ファイル読み込み #2

R5RS を読んでいたら、append は 結果のリストは、最後のリスト引数と構造を共有する場合を除いて、必ず新しく割り当てられる。 Revised(5) Report on the Algorithmic Language Scheme ということだった。実は昨日改善したつもりだった readfile2 は改悪な…

ファイル読み込み

Scheme で指定したファイルを読み込む方法を考えてみた。 (define (readfile filepath) (let ((port (open-input-file filepath))) (let loop ((contents "") (c (read-char port))) (if (eof-object? c) (begin (close-input-port port) contents) (loop (s…

リストの最後にアトムを追加したい

リストにアトムを追加したい場合: gosh> (cons 1 '(2 3)) (1 2 3) という感じにできるんだけど、やりたいのは std::vector で言うところの: std::vector<int> v; v.push_back(2); v.push_back(3); v.push_back(1); // [2, 3, 1] という順序 であり、java.util.V</int>…

秀丸で Scheme を効率よく開発したい

Scheme で快適に開発するには Emacs が最適だというのは承知しているけど、どうしてもなじめない。こればっかりは仕方がない。なので、快適に開発を行うためにはまず快適環境から作らなければならない。僕の場合、手になじむエディタは秀丸なので、秀丸で Sc…

Scheme でローン計算

勉強のために Scheme でローン計算する関数を作ってみました。 (define (fukuri moto riritu hensai c) (let ((tuki (/ riritu 12))) (if (> (* tuki moto) hensai) 'oops! (if (< 0 (- moto hensai)) (fukuri (* (- moto hensai) (+ 1 tuki)) riritu hensai…

(cons 0 ()) と (cons 0 '()) と (cons '0 '()) の違い

(cons 0 ()) と (cons 0 '()) と (cons '0 '()) は評価するとどれも (0) となるんだけど、(cons 0 ()) ⇒ (0)、(cons 0 '()) ⇒ '(0) まではわかるけど、最後の (cons '0 '()) がわからない。

gosh でスタックが出た後のリカバリー方法がわからない

gosh で不正な処理を入力してしまうと gosh> *** ERROR unbound variable: ??? Stack Trace: _______________________________________と出て、プロンプトに戻らないことがあるんだけど、これは起動しなおしが必要だということなのかな?Gauche 本にも FAQ …

Lisp プログラマの考え方がわからない

リストの 2 番目の要素がほしい場合、C プログラマならインデックスでアクセスするんだけど、Scheme にはそんな便利?な機能はないので、 cdr で先頭を除いたリストを取得し car でその先頭を取得する という風に考えるんだと思うんだけど、たとえばリスト l…