oschulz / FunctionChains.jl

Function chains in Julia
Other
4 stars 0 forks source link

Specialized support for combination of property functions #11

Open oschulz opened 10 months ago

oschulz commented 10 months ago

Should specialize the proposed FunctionChains.fcoll (oschulz/FunctionChains.jl#7) for PropertyFunctions, so that

f1 = @pf(...)
f2 = @pf(...)
f = fcoll(f1, f2)

returns a new PropertyFunction that accesses the (possibly overlapping) input properties/columns of f1 and f2.

aplavin commented 8 months ago

Also see AccessorsExtra!

julia> using StructArrays, AccessorsExtra, FlexiMaps

# to be sure we don't access y ever
julia> A = StructArray(x=[1,2,3], y=mapview(_ -> error(), 1:3), z=[10,20,30]);

julia> f1 = @o _.x + 1

julia> f2 = @o _.x + _.z

julia> f = @optic₊ (a=f1(_), b=f2(_))   # or non-macro ContainerOptic

# f is not exactly a PropertyFunction, but behavior is consistent:
julia> map(f, A)
3-element StructArray(::Vector{Int64}, ::Vector{Int64}) with eltype NamedTuple{(:a, :b), Tuple{Int64, Int64}}:
 (a = 2, b = 11)
 (a = 3, b = 22)
 (a = 4, b = 33)
oschulz commented 8 months ago

Thanks for the pointer, @aplavin !

oschulz commented 8 months ago

Also, a simple

f1 = @pf(...)
f2 = @pf(...)
f = fcoll(f1, f2)

may not be a great idea anyway, since it's not clear if the user actually to merge the properties or make a tuple of them. We have stuff in the works to generalize MeasureBase.bind and product in a way that allows for passing a combinator function. Maybe a similar approach would work here.

aplavin commented 8 months ago

If I understand your design for fcoll (#7) correctly, this operation is well-defined (assuming fcoll(f1, f2) === fcoll((f1, f2))). fcoll(tuple-of-functions) = function-returning-tuple-of-values has clear semantics. Those PropertyFunction stuff is just an optimization so that only relevant properties are extracted when applying it.

Merging results of f1 and f2 is a different operation that you call fcombine in #7.

oschulz commented 8 months ago

Those PropertyFunction stuff is just an optimization so that only relevant properties are extracted when applying it

Indeed, that should be pretty much transparent to the user, it would purely be an optimization.