Ruby
オブジェクト指向
Julia
JuliaDay 9

Julia でも array.map() do ... end と書ける

More than 1 year has passed since last update.

 Julia Advent Calendar 2016 です。12月9日の記事を 12月27日に投稿しました。

 Julia でも、Ruby のようなオブジェクト指向の構文で書きたい。その要望に Lazy.jl パッケージが応えます。

(その1) 文字列置換

 文字列を置換するには replace を使います。

julia> s="123"
"123"

julia> s=replace(s,"2","b")
"1b3"

julia> s=replace(s,"3","c")
"1bc"

 replace は、元の文字列を更新しません (文字列は immutable だから)。ですので、文字列置換を複数回行うには、s=replace(s,from,to) を繰り返して適用することになります。面倒ですね。
 Ruby では、これをメソッド・チェーンできれいに書けます。一時変数も不要です。

 Ruby
"123".sub("2","b") # => "1b3"
"123".sub("2","b").sub("3","c") # => "1bc"

 Julia では、 Base.|> を使って function chain を書けますが、無名関数を書く必要があり、いまいちイケていません。(別記事へのコメント )

julia> "123" |> (x -> replace(x,"2","b")) |> (x -> replace(x,"3","c"))
"1bc"

 さて、クリスマス・プレゼントに、Lazy.jl パッケージを頂きました。
 @> マクロを使えば、Julia でも似たように書けますよ。

julia> Pkg.add("Lazy")

julia> using Lazy

julia> @> "123" replace("2","b")
"1b3"

julia> @> "123" replace("2","b") replace("3","c")
"1bc"

 繰り返し文字列置換を適用できて、大満足です。

(その2) map, foreach

 Julia の mapmap(func, collection...) という引数をとります。func を do...end ブロックで後置する構文もあります。いずれにせよ map から始まります。

julia> map(x-> sin(x), [1,2,3])
3-element Array{Float64,1}:
 0.841471
 0.909297
 0.14112

julia> map([1,2,3]) do x sin(x) end
3-element Array{Float64,1}:
 0.841471
 0.909297
 0.14112

 Ruby のmap は、配列に対する操作を簡潔に書けますね。

# Ruby
[1,2,3].map do |x| Math.sin(x); end
# => [0.8414709848078965, 0.9092974268256817, 0.1411200080598672]

 Ruby がうらやましい ?
 いやいや、@>> マクロを使えば、Julia でも似たように書けますよ。

julia> @>> [1,2,3] map() do x sin(x) end
3-element Array{Float64,1}:
 0.841471
 0.909297
 0.14112

 計算結果が不要なら foreach を使いましょう。

julia> @>> [1,2,3] foreach() do x println(sin(x)) end
0.8414709848078965
0.9092974268256817
0.1411200080598672

種明かしは初夢で

 Lazy.jl のドキュメントをどうぞ。
 https://github.com/MikeInnes/Lazy.jl#macros

(その3) map を連結できる

2017/01/03 追記

( 初夢を見ました。まだ種明かしはしませんが )

# Ruby
[1,2,3].collect{|x| Math.sin(x)}.collect{|x| x+1 }
# => [1.8414709848078965, 1.9092974268256817, 1.1411200080598671]

Julia でも map を連結できます。

julia> @>> [1,2,3] map() do x sin(x) end map() do x x+1 end
3-element Array{Float64,1}:
 1.84147
 1.9093 
 1.14112