goretkin / fixargs.jl Goto Github PK
View Code? Open in Web Editor NEWLicense: Other
License: Other
This issue is used to trigger TagBot; feel free to unsubscribe.
If you haven't already, you should update your TagBot.yml
to include issue comment triggers.
Please see this post on Discourse for instructions and more details.
https://github.com/archermarx/PartialFunctions.jl
@archermarx , @MrBreadWater I wonder if you think it is worthwhile to combine the functionality of these two packages.
I really like the bind
function and would like to export it. Unfortunately its name clashes with Base.bind
:
help?> bind
search: bind binomial BigInt begin SubString bitstring disable_sigint reenable_sigint SubstitutionString AbstractString AbstractUnitRange AbstractIrrational
bind(chnl::Channel, task::Task)
...
So I think it is a good idea to rename bind
and @bind
. Some possible names: curry, fix, partial, fixargs, bindargs
Instead of carrying around args
and kw
ourselves, we can consider using
https://github.com/ararslan/FrankenTuples.jl/
e.g.
function foo(a, bargs...)
function bar(args...)
string(a, args...)
end
@fix bar(bargs...)
end
related issue: https://julialang.zulipchat.com/#narrow/stream/225542-helpdesk/topic/size.20of.20tuple.20.2F.20struct.20of.20singleton.20type
There are some cases where I want something roughly like
(@fix (@fix 1 + _) / 3)((2,))
and
(@fix (@fix _ + _) / _)((1, 2), 3)
to work.
There needs to be a mechanism to prevent this nesting (that is, to maintain the current behavior). Currently
julia> (@fix (@fix _ + _) / _)
(::Fix{typeof(/),Tuple{Some{Fix{typeof(+),Tuple{Nothing,Nothing},NamedTuple{(),Tuple{}}}},Nothing},NamedTuple{(),Tuple{}}}) (generic function with 1 method)
and so the encoding for the nesting behavior should probably just not wrap the Fix{typeof(+),...}
in Some
. That is, I desire the following:
julia> (@fix Some(@fix _ + _) / _)
(::Fix{typeof(/),Tuple{Some{Fix{typeof(+),Tuple{Nothing,Nothing},NamedTuple{(),Tuple{}}}},Nothing},NamedTuple{(),Tuple{}}}) (generic function with 1 method)
and
julia> (@fix (@fix _ + _) / _)
(::Fix{typeof(/),Tuple{Fix{typeof(+),Tuple{Nothing,Nothing},NamedTuple{(),Tuple{}}},Nothing},NamedTuple{(),Tuple{}}}) (generic function with 1 method)
julia> @fix _ .+ _
ERROR: UndefVarError: .+ not defined
because
julia> Meta.@lower(@fix _ .+ _)
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 ─ %1 = (FixArgs.fix)(.+, nothing, nothing)
└── return %1
))))
Note that
julia> Meta.@lower(1 .+ 2)
:($(Expr(:thunk, CodeInfo(
@ none within `top-level scope'
1 ─ %1 = Base.broadcasted(+, 1, 2)
│ %2 = Base.materialize(%1)
└── return %2
))))
Perhaps Base.Broadcast.Broadcasted{Nothing}(+, ())
can be used to represent .+
, or we can define new wrapper type, or better yet just use BroadcastFunction
from JuliaLang/julia#37583
After watching your JuliaCon talk, I tried to replicate what you were doing with using FixArgs
and most of it didn't work.
I looked into the reason for this, and it turns out a quite old commit is the one released to Pkg.
It's especially important to make a release since there's already something up on Pkg.
You should probably make a tag/release here too.
broadcasting: https://github.com/JuliaLang/julia/blob/d06c2a97be3f643d403c4069955e135823ff9fd0/base/broadcast.jl#L152-L173
https://docs.julialang.org/en/v1/manual/interfaces/#extending-in-place-broadcast
JuliaLang/julia@dbe1ae0
generators: https://github.com/JuliaLang/julia/blob/676ccf4eaa9b6e6c6a53f75abb4bf3e1a2457426/base/generator.jl#L3-L31
Instead of using nothing
to indicate holes, we could use
struct Hole end
const hole = Hole()
const ◻ = hole
So we don't have to think about escaping Some(nothing)
and also have more cute notation like:
@bind ◻ == 1
julia> @xquote 3 .* 3
ERROR: UndefVarError: .* not defined
Stacktrace:
[1] top-level scope
@ REPL[22]:1
reference: #8 (comment)
e.g. a macro such that
@evaltype function bounding(::Type{>:UnitRange}, _union::(@FixT union UnitRange{T} UnitRange{T})) where T <: Integer
[...]
end
expands to
function bounding(::Type{>:UnitRange}, _union::Fix{typeof(union), Tuple{Some{UnitRange{T}}, Some{UnitRange{T}}}, NamedTuple{(),Tuple{}}}) where T <: Integer
[...]
end
Could be written just as one macro on the whole function definition, but that itself is seemingly decomposable into two pieces, one of which (@evaltype
) might generally be useful outside of FixArgs.jl
.
:($(:(Complex{T})) where {T})
Types at https://github.com/JuliaReach/LazySets.jl/tree/master/src/LazyOperations could be subsumed by the referencing "eager"/"concrete" operations.
For example
struct Translation{N, VN<:AbstractVector{N}, S<:LazySet{N}} <: AbstractAffineMap{N, S}
X::S
v::VN
# [...]
end
Translation(X, v)
could be @fix LazySets.translate(X, v)
and the concretize
operation concretize(Translation(X,v))
would be translate(X, v)
? The reason it is a case study is because it's hard to reconcile whether "eager" or "lazy" is the default. One of the intentions of FixArgs.jl
is to take a system that is eager by default and allow it to be lazy.
I think it would be nice if the package was registered. I know the plan is that this lands in base, but that can take like a year until it ships with the stable julia version. Maybe Curry.jl
is not an ideal name though. What about ArgFix.jl
?
e.g. like _1
, _2
, ... https://en.cppreference.com/w/cpp/utility/functional/bind
This example came up on discord (also related to https://discourse.julialang.org/t/nested-lambda-functions-overhead-ideas-for-algebra-of-functions/47335 )
function foo(x, p)
f1 = (x;p)->x^2+p.a
f2 = (x;p)->1/(x^2+p.b^2)
f3 = (x;p) -> p.c1 * f1(x;p) + p.c2 * f2(x;p)
return f3(x; p)
end
#=
FixArgs.jl doesn't support do all the same transformations as lowering does, yet. It also does not support functions with keyword arguments (you can call functions with kwargs, but you cannot define functions with kwargs)
=#
using FixArgs: @xquote, xapply
function foo2(x, p)
f1 = @xquote (x, p) -> x^2 + getproperty(p, :a::::S)
f2 = @xquote (x, p) -> 1/(x^2+(getproperty(p, :b::::S))^2)
f3 = @xquote (x, p) -> getproperty(p, :c1::::S) * f1(x, p) + getproperty(p, :c2::::S) * f2(x, p)
return xapply(f3, (x, p))
end
# seems fine
@code_llvm foo(1.0, (a=0, b=0, c1 = 0.5, c2 = 0.5))
# less fine
@code_llvm foo2(1.0, (a=0, b=0, c1 = 0.5, c2 = 0.5))
field access doesn't appear to be the problem
function foo3(nt)
f = @xquote nt -> getproperty(nt, :a::::S)
return xapply(f, (nt,))
end
julia> @code_llvm foo3((;a=1))
; @ REPL[39]:1 within `foo3'
define i64 @julia_foo3_3334([1 x i64]* nocapture nonnull readonly align 8 dereferenceable(8) %0) {
top:
; @ REPL[39]:3 within `foo3'
; ┌ @ /Users/goretkin/projects/FixArgs.jl/src/eval.jl:95 within `xapply' @ /Users/goretkin/projects/FixArgs.jl/src/eval.jl:96
; │┌ @ /Users/goretkin/projects/FixArgs.jl/src/eval.jl:44 within `xeval'
; ││┌ @ /Users/goretkin/projects/FixArgs.jl/src/eval.jl:104 within `_xapply'
; │││┌ @ /Users/goretkin/.julia/packages/FrankenTuples/LK9o9/src/FrankenTuples.jl:405 within `ftcall'
; ││││┌ @ Base.jl:33 within `getproperty'
%1 = getelementptr inbounds [1 x i64], [1 x i64]* %0, i64 0, i64 0
; └└└└└
%2 = load i64, i64* %1, align 8
ret i64 %2
}
I am being loose, since the terms "nominative" and "structural" apply to type systems, but Rational{Int}
seems like a nominal type and Fix{typeof(/),Tuple{Some{Int},Some{Int}}}
feels like a more structural name.
julia> FixArgs.@fix +(1, _)
(::FixArgs.Fix{typeof(+),Tuple{Some{Int64},Nothing},Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}}) (generic function with 1 method)
julia> FixArgs.@fix sum([1,2]; dim=1)
(::FixArgs.Fix{typeof(sum),Tuple{Some{Array{Int64,1}}},Base.Iterators.Pairs{Symbol,Int64,Tuple{Symbol},NamedTuple{(:dim,),Tuple{Int64}}}}) (generic function with 1 method)
Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}
and
Base.Iterators.Pairs{Symbol,Int64,Tuple{Symbol},NamedTuple{(:dim,),Tuple{Int64}}}}
should ust be NamedTuple{(),Tuple{}}
and NamedTuple{(:dim,),Tuple{Int64}}
, I hope.
Perhaps it is worth making these work automatically:
@fix "not a call $(_)"
@fix (:not_a_call, _))
@fix (;a=:not_a_call, b=_)))
I think instead they should just error and provide a suggestion to rewrite like
@fix string("a call ", _)
@fix tuple(:a_call, _)
@fix NamedTuple{(:a, :b)}(@fix tuple(:a_call, _))
(the last one requires #17)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.