Doge log

Abby CTO 雑賀 力王のオフィシャルサイトです

protocolを使って既存の関数の振る舞いを変える

こんにちわ、高校生です。
今回はprotocolを使った話です。

通常の場合

user=> (bit-and "生" "死")
IllegalArgumentException bit operation not supported for: class java.lang.String  clojure.lang.Numbers.bitOpsCast (Numbers.java:994)

bit-andはNumbersしか受け付けない関数なので当たり前のごとくうまくいきません。
異なる型でもいい感じに処理をして欲しい場合にはprotocolで既存関数も拡張ができます。

(defprotocol bit-protocol
  (bit-and [x y]))

(extend-protocol bit-protocol
  java.lang.String
  (bit-and [x y]
    (let [a (Character/codePointAt x 0)
          b (Character/codePointAt y 0)
          c (bit-and a b)]
      (apply str (Character/toChars c))))

  java.lang.Object
  (bit-and [x y]
    (clojure.core/bit-and x y)))

(bit-and "生" "死")

上記のように型ごとに処理が書けます。

Warning: protocol #'user/bit-protocol is overwriting function bit-and
WARNING: bit-and already refers to: #'clojure.core/bit-and in namespace: user, being replaced by: #'user/bit-and

Warningが出るものの既存の関数をoverwriteすることができます。
もちとんns上も置き換わるのでそちらの警告も出ますが。