2

より具体的には、組み込みの Scheme プロシージャの表示をオーバーロードできますか?

より一般的に言えば、Scheme でプロシージャをオーバーロードするにはどうすればよいでしょうか?

4

2 に答える 2

3

スキームには、Java/C++ のような型に基づくオーバーロードがありません。動的に型付けされるため、意味がありません。

ただし、いくつかのことができます。

引数の構造に基づいてオーバーロードできます。

(define overload1
    (case-lambda
        ((x y) (+ x y))
        ((x y z) (+ (- x y) z))))

displayただし、何があっても1つの引数しかとらないため、これは実際には役に立ちません。

(define (overload-kinda x)
    (cond
        ((list? x) (do-list x))
        ((symbol? x) (do-sym x))
        ;etc
        ))

これはハックですが、必要な場合もあります。

私の通常のアプローチは、高階関数とケース ラムダです。

(define my-display
    (case-lambda
        ((x) (display x))
        ((x f) (display (f x)))))

何かを表示するために特別な処理が必要な場合は、それをレンダリングする関数を渡します。

于 2013-04-09T06:00:53.140 に答える
0

受け入れられた答えは、関数をオーバーロードせず、同じ動作で異なる関数を定義するだけです。

通常、Scheme では bultin 関数を上書きすることが許可されているため、関数をオーバーロードするには (例: ) Monkey Patchdisplayと呼ばれるものを使用できます。

(define display (let ((orig display))
                  (lambda (x . rest)
                     (let ((port (if (null? rest)
                                     (current-output-port)
                                     (car rest))))
                       (if (number? x)
                           (orig (string-append "#<" (number->string x 16) ">") port)
                           (orig x port))))))

そして今、ディスプレイは数字で異なった働きをします。さまざまなタイプのレコードを特定の方法で表示するなど、カスタム タイプを使用することもできます。これは、元のバインドを変更できる任意の言語で bultin 関数を上書きする方法の一般的な例です。元の関数を変数に保存し、関数を再定義します。元の関数を呼び出す場合は、元の関数を保存した変数を使用します。

コードは、関数を再定義し、特定のタイプの引数でコードを実行する一般的なマクロに抽象化できるため、Java のように適切なオーバーロードになり、のような引数の数に基づくだけではありませんcase-lambda

以下はそのようなマクロの例です (lisp タイプのマクロを使用):

(define-macro (overload name-spec . body)
   (let ((name (car name-spec))
         (args (cdr name-spec)))
      `(define ,name (let ((,name ,name))
                       (lambda ,args
                          ,@body)))))

(overload (display x . rest)
   (let ((port (if (null? rest)
                   (current-output-port)
                   (car rest))))
     (if (number? x)
         (display (string-append "#<" (number->string x 16) ">") port)
         (display x port))))

(display 10)
;; ==> #<a>
(display "20")
;; ==>  20
于 2021-03-04T12:37:15.783 に答える