Как вы можете расширить протокол Clojure на другой протокол?

Предположим, у меня есть два протокола:

(defprotocol A 
  (f [this]))

(defprotocol B 
  (g [x y]))

И я хочу расширить протокол B на все экземпляры, поддерживающие протокол A:

(extend-protocol A 
  String 
    (f [this] (.length this)))

(extend-protocol B 
  user.A
    (g [x y] (* (f x) (f y))))

Основная мотивация состоит в том, чтобы избежать необходимости расширять B отдельно для всех возможных классов, до которых может быть расширен A, или даже до неизвестных будущих классов, до которых другие люди могут расширить A (например, представьте, если бы A был частью общедоступного API).

Однако это не сработает - вы получите что-то вроде следующего:

(g "abc" "abcd")
=> #<IllegalArgumentException java.lang.IllegalArgumentException: 
No implementation of method: :g of protocol: #'user/B found for 
class: java.lang.String>

Возможно ли это вообще? Если нет, есть ли разумный обходной путь для достижения той же цели?

10
задан mikera 4 November 2011 в 02:31
поделиться