Question

I have those two sources:

(ns odo.IComplex)
(gen-interface
    :name odo.IComplex
    :methods [
        [getReal [] Double]
        [getImag [] Double]
        [getAbs  [] Double]
        [getArg  [] Double]

        [setReal [Double] void]
        [setImag [Double] void]
        [setAbs  [Double] void]
        [setArg  [Double] void]])

(defprotocol PolarComplex
    (abs [this] [this value])
    (arg [this] [this value]))

(defmulti polar-complex (fn([record abs arg] (class record))))

and

(ns odo.Complex
  (:gen-class
   :init init
   :state state
   :implements [odo.IComplex])
  (:use odo.IComplex))

(defrecord State [^Double imag ^Double real]
  Object (toString [self] 
           (str real (if (>= imag 0) " + " " - " ) (Math/abs imag) "j"
            " : " (abs self) " * exp[ " (arg self) " ]"))

  PolarComplex (abs [self]       (Math/sqrt (+ (* real real) (* imag imag))))
               (abs [self value] (polar-complex self value (arg self)))

               (arg [self]       (Math/atan2 real imag))
               (arg [self value] (polar-complex self (abs self)  value)))

(defmethod polar-complex PolarComplex [num abs arg]
    (assoc num :real (* abs (Math/cos arg)) :imag (* abs (Math/sin arg))))

(defn -init [] [[] (atom (State. 0. 0.))])
(defn -getImag [self] (:imag @(.state self)))
(defn -getReal [self] (:real @(.state self)))
(defn -getAbs  [self]  (abs @(.state self)))
(defn -getArg  [self]  (arg @(.state self)))

(defn -setImag [self value] (swap! (.state self) assoc  :imag  value))
(defn -setReal [self value] (swap! (.state self) assoc  :real  value))
(defn -setAbs  [self value] (swap! (.state self) abs value))
(defn -setArg  [self value] (swap! (.state self) arg value))

(defn -toString [self] (str @(.state self)))

and I'm ensured that (isa? odo.Complex.State odo.IComplex.PolarComplex) is true

but when I execute

(doto (odo.Complex.)
  (.setArg (/ Math/PI 4.)) (.setAbs (Math/sqrt 2)) (println) )

I get

java.lang.IllegalArgumentException: No method in multimethod 'polar-complex' for dispatch value: class odo.Complex.State

Can you tell me why?

Was it helpful?

Solution

I have discovered that in context of its definition var PolarComplex is bound to map containing information about protocol, not to Class. So correct implementation of multimethod will be

(defmethod polar-complex (:on-interface PolarComplex) [num abs arg]
    (assoc num :real (* abs (Math/cos arg)) :imag (* abs (Math/sin arg))))

or

(defmethod polar-complex odo.IComplex.PolarComplex [num abs arg]
    (assoc num :real (* abs (Math/cos arg)) :imag (* abs (Math/sin arg))))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top