おさかなせいざ

おさかなせいざ

プログラミングメモや日記がわりに

Clojure から Java の可変長引数をもつ関数の呼び出し

はてなブログ初めました。うおざです。
最初の記事に何を書こうか書こうかと考えていたら、いい感じに問題にあたったのでそれを書くことにしました。
それは ClojureJavafx を呼びだしてファイルダイアログを表示させる際に、拡張子でフィルタをかけるようにしていたときのことです。
Clojure で以下のようなコードを書いていました。

(let [fileChooser (FileChooser.)]
  (-> fileChooser
    .getExtensionFilters (.add (FileChooser$ExtensionFilter. "Audio Files" "*.wav" "*.mp3" "*.aac"))))

しかし、これを実行すると

java.lang.IllegalArgumentException: No matching ctor found for class javafx.stage.FileChooser$ExtensionFilter, compiling:(scoreditor/application.clj:67:34)
Exception in thread "main" java.lang.IllegalArgumentException: No matching ctor found for class javafx.stage.FileChooser$ExtensionFilter, compiling:(scoreditor/application.clj:67:34)

といったエラーがでます。

No matching ctor found for class javafx.stage.FileChooser$ExtensionFilter

クラスが見つからないようなことを言われています。
しかし、調べても Clojure でのインナークラスのコンストラクタの呼び出しは

(ClassName$InnerClass.)

で可能のはずなので不思議で不思議でした。Java で無理やり解決しましたが、やはりモヤモヤは消えず。
あまりにもわからないのでtwitterでつぶやいたら


リプライがきました。
Clojure で調べたら日本語の情報で度々目にする @_ayato_p さんです。
最初のコード送ると以下の StackOverFlow の URL がおくられてきました。ありがとうございます。
stackoverflow.com
ふんふんとわからない英語を読むと、どうやら Clojure から Java の可変長引数の関数を呼ぶにはどうすればいいかという内容でした。
Clojure から Java の可変長引数を呼ぶ際には可変長引数の部分を vector で囲んでやらんといけんとのことでした。
FileChooser$ExtensionFilter のコンストラクタを確認してみると可変長引数になっていました。
そこで以下のように直すと

(let [fileChooser (FileChooser.)]
  (-> fileChooser
    .getExtensionFilters (.add (FileChooser$ExtensionFilter. "Audio Files" ["*.wav" "*.mp3" "*.aac"]))))

エラーなく実行できました。[] で囲っただけです。とっても単純。
こういった言語のルールをしらないと今日のように半日うんうん悩むことになってしまうので、しっかりと勉強しておきます。

これからもこういった記事を書いていきますので、よければ見ていただければと思います。よろしくお願いします。