Island Life

< ピアノレッスン18回目 | らむ太と言葉 >

2011/10/14

runonce

『プログラミングClojure』に、マルチスレッド環境でも 与えた関数を一度だけ実行するrunonceという仕組みを作る例が出てくる。 似たようなことをGaucheでやる必要が出てきたのでちょいと書いてみた。

runonceは関数を引数に取り、

  • その関数が既に実行されたかどうかを調べる関数 (has-run?)
  • 初期状態に戻す関数 (reset)
  • 引数を与えてその関数を実際に実行する関数。但し、既に実行されていた場合は実行せずに前の結果を返す。(once)

という3つの関数を返す関数だ。

Gauche風に書くとこんな感じになるかなあ。

atom は名前をClojureから取ったんだけど、使い勝手はかなり違うので注意。 Gaucheにトランザクションはないので、atomicな領域で副作用を起こして構わない。

gosh> (define-values [print-has-run? print-reset print-once] (runonce print))
#<undef>
gosh> (print-has-run?)
#f
gosh> (print-once "Aloha")
Aloha
#<undef>
gosh> (print-has-run?)
#t
gosh> (print-once "Mahalo")
#<undef>
gosh> (print-reset)
#f
gosh> (print-once "Mahalo")
Mahalo
#<undef>

なお、fnが引数を取らず、resetとかhas-run?が不要で 「引数なしの関数を一度だけ走らせれば良い」ということなら、単にdelayを使えば済むのだけれど。 (但し、0.9.2までのforceはスレッドセーフになっていないので注意。 開発版は安全。)

Tags: Programming, Gauche, Clojure

Post a comment

Name: