ひと筆書きをリファクタリング

きのう書いたclojure x p5のスクリプトのなかで、激遅だったピクセル置き換えの部分がどーにもこーにも気にいらなかったので書きなおしてみた。
clojureは該当する処理部分を(time (...))みたいにしてあげればベンチがとれるのでべんりですね。


(dotimes [w width] 
  (dotimes [h height] 
    (if (= (.get app w h) @black) 
      (do 
        ;(println (aget (.pixels @pic) (+ (* h width) w)))
        (.set app w h (aget (.pixels @pic) (+ (* h width) w)))))))

;; => Elapsed time: 23393.167 msecs


letで束縛

(dotimes [w width] 
  (dotimes [h height] 
    (if (= (.get app w h) @black) 
      (do 
        ;(println (aget (.pixels @pic) (+ (* h width) w)))
        (.set app w h (let [px (.pixels @pic) pos (+ (* h width) w)] (aget px pos)))))))

;; => Elapsed time: 19721.689 msecs


let+束縛時にtype hintつける

(dotimes [w width] 
  (dotimes [h height] 
    (if (= (.get app w h) @black) 
      (do 
        ;(println (aget (.pixels @pic) (+ (* h width) w)))
        (.set app w h (let [px #^floats (.pixels @pic) 
                                     pos (+ (* h width) w)] 
                                (aget px (int pos))))

;; => Elapsed time: 16063.717 msecs


let+とにかくtype hint

(dotimes [w width] 
  (dotimes [h height] 
    (if (= (.get app w h) @black) 
      (do 
        ;(println (aget (.pixels @pic) (+ (* h width) w)))
        (let [px (aget (.pixels @pic) (+ (* (int h) width) (int w)))]
                               (.set app (int w) (int h) (int px)))))))))

;; => Elapsed time: 4367.942 msecs


びっくり! というよりもまず笑ったw


とこんなわけで、いかにclojureを書くうえで「letでくるんであげること」「type hintつけること」はひじょーに大切。
おそらくjvm上でうごく言語はどれもそうだと思うのですが「javaにおまかせするところ」と「そのjvmでうごく言語のいいところ」を切りわけて書くってことが大事かってことですよね… 精進します。


それとリファクタしようと思ったらgroovyのほうも気になったので、こんなかんじでどーでしょうかみたいな…


def mask = {
    background(255)
    smooth()
    
    30.times{i->
      def(x1,y1,x2,y2,x3,y3) = [random(width),random(height),random(width)/2,random(height)/2,random(width)/3,random(height)/3]
      noStroke()
      fill(black)
      triangle(x1 as Float,y1 as Float,x2 as Float,y2 as Float,x3 as Float,y3 as Float)
    }
}


よりgroovyに!

def mask = {
    background(255)
    smooth()
    
    30.times{i->
      def(x1,y1,x2,y2,x3,y3) = ([width,height]*3).collect(){random(it) as Float}
      noStroke()
      fill(black)
      triangle(x1, y1, x2/2, y2/2, x3/3, y3/3)
    }
}


うごかしてないから分からないのですが、そのままの値を引数として使うならいいんだけど2とか3で割り算した引数はp5に怒られるはず。groovyはDoubleを返すはずだもんね…

p5はintegerとfloatだけ使うので、groovyでp5やるとなにかっちゃあintegerにしたりfloatにしたりがとにかくメンドー。
このあたりをキレイにできるといいのになー