約1年前に全く Julia っぽくない邪道な遊びをしていたなということをふと思い出した。
微妙なメモだけは残っていたので供養しておく。
好奇心に負けて倫理的に許されないことをしてしまった気分になった。#julialang pic.twitter.com/ahmRgVFz7t
— goropikari (@goropikari_) November 5, 2018
これから紹介する方法は遊びであって本気にされると困ります。
環境
- Julia 1.3.0
getproperty
v.method
という呼び方は getproperty
が呼ばれているので、この関数をオーバーロードすると v.length()
のような他の言語では一般的だけれども、全然 Julia っぽくない書き方を一応実現することはできる。
https://docs.julialang.org/en/v1/base/base/#Base.getproperty
julia> function Base.getproperty(v::Vector, s::Symbol) s == :length && return () -> length(v) s == :reshape && return function (a,b) return reshape(v, a,b) end end julia> v = rand(10) 10-element Array{Float64,1}: 0.8267378196342272 0.6176403952129186 0.5046041927146574 0.8758407174025733 0.6085707115128745 0.9317736835188135 0.40242234842524804 0.9733691132606714 0.5724142410241722 0.568618356534722 julia> v.length() 10 julia> v.reshape(2,5) 2×5 Array{Float64,2}: 0.826738 0.504604 0.608571 0.402422 0.572414 0.61764 0.875841 0.931774 0.973369 0.568618
PyCall.jlでPyTorch使ってDeep Learningする - Qiita の記事の方法を使うとより汎用的になる。(一部走るように修正した) ただし、全体的にものすごく動作がもっさりする。
julia> function Base.getproperty(obj, s::Symbol) if isdefined(obj, s) getfield(obj, s) else eval(quote (args...) -> $(s)($obj, args...) end) end end WARNING: Method definition getproperty(Any, Symbol) in module Base at Base.jl:20 overwritten in module Main at REPL[1]:2. julia> v = rand(6) 6-element Array{Float64,1}: 0.06120994308448946 0.5256925985282832 0.9023581914503764 0.8468689107200875 0.019238205610359937 0.6605465949011493 julia> function myfunc(v::Vector, a) return v .+ a end myfunc (generic function with 1 method) julia> v.myfunc(10) 6-element Array{Float64,1}: 10.061209943084489 10.525692598528284 10.902358191450377 10.846868910720087 10.01923820561036 10.660546594901149 julia> v.size() (6,)
struct
class のある他言語のように、struct 定義時に method を生やそうと思えば一応生やせる。
julia> mutable struct Hoge v::Array length::Function size::Function reshape::Function function Hoge(v) x = new() x.v = v x.length = () -> length(x.v) x.size = () -> size(x.v) x.reshape = (a, b) -> reshape(x.v, a, b) return x end end julia> x = Hoge([1, 2, 3]) Hoge([1, 2, 3], var"#3#5"{Hoge}(Hoge(#= circular reference @-2 =#)), var"#4#6"{Hoge}(Hoge(#= circular reference @-2 =#))) julia> x.length() 3 julia> x.size() (3,) julia> x.v = rand(10, 5) 10×5 Array{Float64,2}: 0.0844862 0.842631 0.339725 0.954259 0.194565 0.470892 0.521036 0.00714723 0.846754 0.524923 0.870488 0.545857 0.545821 0.827207 0.974655 0.29028 0.876719 0.637267 0.997776 0.462824 0.925254 0.858045 0.53476 0.794868 0.330684 0.711127 0.318063 0.0518006 0.0385135 0.00460019 0.930399 0.979754 0.0512777 0.0573049 0.412405 0.627587 0.281032 0.115321 0.194771 0.87389 0.646853 0.140648 0.906595 0.0133067 0.158983 0.539785 0.133379 0.0629104 0.143179 0.659137 julia> x.length() 50 julia> x.size() (10, 5) julia> x.reshape(5, 10) 5×10 Array{Float64,2}: 0.0844862 0.711127 0.842631 0.318063 0.339725 0.0518006 0.954259 0.0385135 0.194565 0.00460019 0.470892 0.930399 0.521036 0.979754 0.00714723 0.0512777 0.846754 0.0573049 0.524923 0.412405 0.870488 0.627587 0.545857 0.281032 0.545821 0.115321 0.827207 0.194771 0.974655 0.87389 0.29028 0.646853 0.876719 0.140648 0.637267 0.906595 0.997776 0.0133067 0.462824 0.158983 0.925254 0.539785 0.858045 0.133379 0.53476 0.0629104 0.794868 0.143179 0.330684 0.659137