Closed alexgian closed 4 months ago
Can you show what you're trying to do?
I am using mafs trying to plot a slope-field as a background to a future ODE solver demo.
The functions that will determine the gradient at each point will be supplied by the user, so they are not known beforehand.
I tried to pass them using ev/with-params
but this was not accepted.
(def fx1 (fn [x y] 1))
(def fx2 (fn [x y] (* 2 x)))
(ev/with-let [!fns [fx1 fx2]]
(mafs/mafs
{:zoom {:min 1 :max 5}}
(mafs/cartesian {:subdivisions 5})
(mafs/vector-field
{:step 0.2
:xy (ev/with-params {:atom !fns :params [0 1]}
(fn [af1 af2]
(fn [[x y]]
(let [x1 (af1 x y) x2 (af2 x y)
; (let [x1 1 x2 (* 2 x)
h (sqrt (+ (square x1) (square x2)))]
[(/ x1 h) (/ x2 h)]
))))
:xy-opacity (constantly 0.4)})))
2024-05-26T22:56:41.197Z alex-HP-2570p INFO [emmy.expression.compile:661] - compiled function in 796.963 μs
Clerk evaluated 'src/demo.clj' in 257.761635ms.
Execution error (ExceptionInfo) at taoensso.nippy/throw-unfreezable (nippy.clj:1005).
Unfreezable type: class demo$fx1
OK, I worked it out, I was overcomplicating it my mind
I didn't have to use 'ev/with-params', as there are no params, only the x and y, which are supplied by the system through the :xy
key.
So the function can be defined outside the mafs/vector-field
call!
This is all I had to do in the end
(defn fx [[x y]]
(let [x1 1 x2 (* 2 x)
h (sqrt (+ (square x1) (square x2)))]
[(/ x1 h) (/ x2 h)]))
(mafs/mafs
{:zoom {:min 1 :max 5}}
(mafs/cartesian {:subdivisions 5})
(mafs/vector-field
{:step 0.2
:xy fx
:xy-opacity (constantly 0.4)
}))
Issue can be closed now.
ev/with-params
seems unable to process parameters that are actually functions, rather than just fixed values. I appreciate that this is due to the serialization that clerk has to perform, but is there a workaround?One example where this becomes relevant when you need to plot a number of points with an emmy-viewer in a way that is determined by a function that might only be specified at run time.