- ベストアンサー
schemeのプログラミング
http://codepad.org/arrsvMiU 上記のページに書かれているschemeのコードなのですが、 letとset!を使わないで同じ動作をするプログラムを書くことは出来るでしょうか? 同じ動作で上二つの関数を使わなければ、中身がガラッと変わっても構いません。 どなたかお願いします このプログラム自体は与えられた式の変数に対して、それぞれのレキシカルアドレス、ポジションを求めてそれを加えて式を返す というものです。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
;;; 最近のSchemeじゃ推奨されないけど、letrecが嫌だ、と言う場合はinternal defineを使うのがセオリー。 ;;; 手続き内に手続きをぶち込んで外部から保護したレキシカル環境を作るのがポイント。 ;;; Common Lispと違ってSchemeだと名前空間の制限が(比較的)厳しいので、名前を保護出来るところはした方が良いです。 (define (make-frame depth lst) (define (loop ls0 ls1 n) (if (null? ls0) (reverse ls1) (loop (cdr ls0) (cons (cons (car ls0) (cons depth (+ n 1))) ls1) (+ n 1)))) (loop lst '() -1)) ;;; let <-> lamda式の変換は覚えておきましょう。letはlambda式の糖衣構文なんで、letは必ずlambda式に置き換え可能です。 ;;; 基本的には (let ((x v)) 本体) は ((lambda (x) 本体) v) に機械的に置き換えられます。 ;;; 理論的にはLisp系言語は内部で実際にこの処理を行って(いるものとされて)います。 (define (format-variable v depth frames) ((lambda (result-variable-list) (if (null? result-variable-list) v ((lambda (var) (list (var-name var) ': (- depth (var-depth var)) (var-num var))) (caar result-variable-list)))) (filter (lambda (item) (not (null? item))) (map (lambda (frame) (filter (lambda (var) (eq? v (var-name var))) frame)) frames))))
その他の回答 (1)
- cametan_42
- ベストアンサー率62% (162/261)
;;; あくまで該当箇所はmake-frame一箇所だけ。 ;;; letを使わない、と言う条件をマトモに受けると、例えば以下のような感じ。 (define (make-frame depth lst) (letrec ((iter (lambda (ls0 ls1 n) (if (null? ls0) (reverse ls1) (iter (cdr ls0) (cons (cons (car ls0) (cons depth (+ n 1))) ls1) (+ n 1)))))) (iter lst '() -1)))
お礼
回答ありがとうございます。 お答えしてもらったのに申し訳ないのですが、 letrecも使わないで書くことは出来ないのでしょうか? またformat-variableでもletが使われいると思うのですが、そちらもどうにかなりませんでしょうか?
お礼
わざわざ新たな回答ありがとうございます。 let<->lambdaの変換は自分でも出来るようにがんばります。 おかげで解くことが出来そうです