0

私は現在、いくつかの探索的プログラミングのエディターとして DrRacket でラケット スキームを使用しています。関数を再定義しようとすると、次のメッセージが表示されます。

define-values: cannot re-define a constant: png->byte-list

今、私はこれが言語の特性であることを受け入れ、それに不満を感じていましたが、それを受け入れました. DrSchemeで定数識別子を再定義するにはどうすればよいですか? 必ずしもこの制限を受け入れる必要がないことがわかります。

私の質問は次のとおりです。

  1. この機能は R5RS 言語でのみ利用できますか? 任意の言語でこの機能をオフにする方法はありますか?
  2. または、R5RS の言語を切り替えると、現在使用しているモジュールを使用する際に影響がありますか?racket/gui/base および web-server/insta?
4

3 に答える 3

4

このような再定義は#lang racket、定義ウィンドウで行うと可能です。覚えておくべきことは、これは一種の突然変異ではないということです(これは、R5RS実装で一般的です)。たとえば、次のようになります。

#lang racket
(define orig-+ +)
(define + whatever)

orig-+実際の加算関数にバインドされていません。このモジュールがコンパイルされるとき、Racket+はそれがあなたが定義するものであることを(静的に)知っているので、それへの参照はすべてあなた自身の定義への参照です-したがって、上記のコードはorig-+の「初期化されていない」値にバインドされます+。あなたが本当にそのようなことをしたいのなら、あなたは+別の名前でオリジナルを要求することができます:

#lang racket
(require (rename-in racket [+ orig-+]))
(define + whatever)

その上、モジュールがコンパイルされるときに発生するインライン化があります。これは別の問題です。通常、Racketは、コード内で変更されないバインディングへの参照をインライン化する必要があるため、最後のコードを試してみると+、REPLでさらに再定義することはできません。これは、2つの方法のいずれかで処理できます。1つは、バインディングを明示的に変更することです。

#lang racket
(require (rename-in racket [+ orig-+]))
(define + #f)
(set! + whatever)

これにより、コンパイラはインライン化を回避します。もう1つのオプションは、すべてのインライン化を回避するコンパイラフラグをオンにするDrRacketフラグです。これに対する速度のペナルティは重大である可能性があることに注意してください。

于 2011-01-14T14:10:44.483 に答える
0

1-私はSchemeのプロではありませんが、乗算関数(*)を再定義しようとしました。「初期バインディングの再定義を禁止する」では機能しません。ただし、チェックを外すと、機能します。

Welcome to DrRacket, version 5.0.2 [3m].
Language: R5RS [custom]; memory limit: 128 MB.
> (* 2 2)
4
> (define (* a b) a)
> (* 2 2)
2
>

ただし、エラーを取得できませんでした(define-values:定数を再定義できません:...)既存の関数を再定義すると(define-values:定数変数を変更できません:...)

2-モジュールに言語を明示的に指定する#langディレクティブがある場合、問題はないはずです(私は推測します)。

于 2011-01-14T11:26:16.880 に答える