• ベストアンサー

schemeのプログラミング

http://codepad.org/arrsvMiU 上記のページに書かれているschemeのコードなのですが、 letとset!を使わないで同じ動作をするプログラムを書くことは出来るでしょうか? 同じ動作で上二つの関数を使わなければ、中身がガラッと変わっても構いません。 どなたかお願いします このプログラム自体は与えられた式の変数に対して、それぞれのレキシカルアドレス、ポジションを求めてそれを加えて式を返す というものです。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.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))))

janjan2224
質問者

お礼

わざわざ新たな回答ありがとうございます。 let<->lambdaの変換は自分でも出来るようにがんばります。 おかげで解くことが出来そうです

その他の回答 (1)

回答No.1

;;; あくまで該当箇所は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)))

janjan2224
質問者

お礼

回答ありがとうございます。 お答えしてもらったのに申し訳ないのですが、 letrecも使わないで書くことは出来ないのでしょうか? またformat-variableでもletが使われいると思うのですが、そちらもどうにかなりませんでしょうか?

関連するQ&A