. Clojure , , / . , . , Haskell ML, Julia , {foo with y = 1} , .
Clojure - ; , . fieldnames "" (, [:x, :y]), getfield(foo, :x) :
immutable Foo
x
y
z
end
x = Foo(1,2,3)
with_slow(x, p) =
typeof(x)(((f == p.first ? p.second : getfield(x, f)) for f in fieldnames(x))...)
with_slow(x, ps...) = reduce(with_slow, x, ps)
with_slow(x, :y => 4, :z => 6) == Foo(1,4,6)
, with_slow. - , , withy(foo::Foo, y) = Foo(foo.x, y, foo.z). Foo (, Foo{T} y::T), , withy(foo, 1.) a Foo{Float64}, with_slow. , crab.
, ML co, - , . , !
type Field{K} end
Base.convert{K}(::Type{Symbol}, ::Field{K}) = K
Base.convert(::Type{Field}, s::Symbol) = Field{s}()
macro f_str(s)
:(Field{$(Expr(:quote, symbol(s)))}())
end
typealias FieldPair{F<:Field, T} Pair{F, T}
for nargs = 1:5
args = [symbol("p$i") for i = 1:nargs]
@eval with(x, $([:($p::FieldPair) for p = args]...), p::FieldPair) =
with(with(x, $(args...)), p)
end
@generated function with{F, T}(x, p::Pair{Field{F}, T})
:($(x.name.primary)($([name == F ? :(p.second) : :(x.$name)
for name in fieldnames(x)]...)))
end
- , f"foo", . , , ; Foo , . , Julia , Foo:
@code_typed with(x, f"y" => 4., f"z" => "hello")
( for nargs - , .)
, , , , . , , () , ; API. , , , .