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.

Reply via email to