Hi, Inspired by Karsten Schmidt's amazing work[0], I'm thinking about porting some generative code from python to Clojure[script].
However, I would like to use the (expected) performance boost (from python turtle module) to add some animation effects. I believe my current code is quite clean and would like to avoid the second-system effect [1] I currently have some very generic fractal generators taking some geometric transforms as arguments. Those geometric transforms are composition of curryfied primitive operations (rotate, add, zoom), as in (def transfo (compose (partial rotate pi) (partial add [0. 1.]) (partial zoom (/ 1 3)))) My wish would be to be able to compute smooth animations by "scaling" smoothly the composite transformations between identity (no transformation) and the full (original) transformation (if fact I would also use the opposite transforms, the one that would compose to identity). I would do so by scaling all the parameters involved with a scaling factor in [0 …1] ([0…-1] for opposite transforms) either by multiplication (for "additive" transformations like rotate and add) or by exponentiation (for "multiplicative" transformations like zoom). "Half" of the above "transfo" would thus be : (def transfo_half (comp (partial rotate (deep_multiply 0.5 pi)) (partial add (deep_multiply 0.5 [0. 1.])) (partial zoom (Math.pow (/ 1 3) 0.5)))) with (defn deep_f [f x] (if (seq? x) (map deep_f x) (f x))) (defn deep_multiply [k x] (deep_f (partial * k) x)) to unify meutiplication because for additive functions, some params are vectors (for add) while others are scalars (for rotate). and the opposite of the original full transformation would be : (def transfo_inv (comp (partial rotate (deep_multiply -1 pi)) (partial add (deep_multiply -1 [0. 1.])) (partial zoom (Math.pow (/ 1 3) -1)))) The ideal solution for me would be to be able to write a "scale" function so that : (def transfo_half (scale 0.5 transfo)) (def transfo_inv (scale -1 transfo)) The scale function could look like (def scale [k f] (condp is f comp (apply comp (map (partial scale k) (args f))) partial (let[ [ fun bound] (args f)] (if (or (is f add) (is f rotate)) (partial f (deep_multiply k bound )) (if (is f zoom) (partial f (Math.pow bound k)) f))) f) ) But that would require some help from the values returned by comp and partial : - the ability to identify them as such (above with an "is" function) - the ability to access the bound values passed to them as arguments (above with an "args" function) Of course, I would have to shadow clojure.core/comp and clojure.core/partial to add those functionalities. I suppose I would have to create records and protocols. However, I find this a bit cumbersome and thought that there might be a simpler way to achieve my goal of keeping the transformation generation separate from the animation code that must scale those functions. Piggiebacking metadata might be easier if more hackish. Best would be to be able to write a higher order function (or macro) like: (def comp (with-is-args comp)) (def partial (with-is-args partial)) Maybe using metadata on the elementary transformation functions (rotate, add, zoom) to indicate that comp and partial should have specific results so that the generic case would not be changed. But that is getting over my clojure-foo ☹. How would you go about it ? I have a hard time to believe I'd be the first to want to modify composed and curryfied functions. Any piece of advice would be greatly appreciated ! Best Regards, b. [0] https://medium.com/@thi.ng/workshop-report-generative-design-with-clojure-7d6d8ea9a6e8#.w6te331y0 [1] https://en.wikipedia.org/wiki/Second-system_effect . -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to [email protected] Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
