ChainedFixes.jl
provides useful tools for interacting with functions where arguments are fixed to them.
Some simple functionality available form this package is chaining any fixed function.
julia> using ChainedFixes
julia> gt_or_lt = or(>(10), <(5))
or(>(10), <(5))
julia> gt_or_lt(2)
true
julia> gt_or_lt(6)
false
julia> gt_and_lt = and(>(1), <(5))
and(>(1), <(5))
julia> gt_and_lt(2)
true
julia> gt_and_lt(0)
false
There's more convenient syntax for these available in the Julia REPL.
julia> gt_or_lt = >(10) ⩔ <(5); # \Or<TAB>
julia> gt_or_lt(2)
true
julia> gt_or_lt(6)
false
julia> gt_and_lt = >(1) ⩓ <(5); # \And<TAB>
julia> gt_and_lt(2)
true
julia> gt_and_lt(0)
false
Any function can have methods fixed to it with @nfix
.
julia> fxn1(x::Integer, y::AbstractFloat, z::AbstractString) = Val(1);
julia> fxn1(x::Integer, y::AbstractString, z::AbstractFloat) = Val(2);
julia> fxn1(x::AbstractFloat, y::Integer, z::AbstractString) = Val(3);
julia> fxn2(; x, y, z) = fxn1(x, y, z);
julia> fxn3(args...; kwargs...) = (fxn1(args...), fxn2(; kwargs...));
julia> f = @nfix fxn1(1, 2.0, _)
fxn1(1, 2.0, _1)
julia> f("a")
Val{1}()
julia> f = @nfix fxn1(1, _, 2.0)
fxn1(1, _1, 2.0)
julia> f("a")
Val{2}()
julia> f = @nfix fxn1(1.0, _, "")
fxn1(1.0, _1, "")
julia> f(2)
Val{3}()
julia> f = @nfix fxn2(x=1, y=2.0)
fxn2(; x = 1, y = 2.0)
julia> f(z = "a")
Val{1}()
julia> f = @nfix fxn2(x=1, z=2.0)
fxn2(; x = 1, z = 2.0)
julia> f(y = "a")
Val{2}()
julia> f = @nfix fxn3(1, 2.0, _; x = 1.0, z= "")
fxn3(1, 2.0, _1; x = 1.0, z = "")
julia> f(""; y = 1)
(Val{1}(), Val{3}())
If we specify the underscore suffix we arguments can be repeated within a single function.
julia> f = @nfix *(_1, _1)
*(_1, _1)
julia> f(2)
4
We can create a chain a functions that act like an uncalled pipe (e.g., |>
).
A chain of fixed functions can be chained together via pipe_chain
.
julia> f = pipe_chain(@nfix(_ * "is "), @nfix(_ * "a "), @nfix(_ * "sentence."))
|> *(_1, "is ") |> *(_1, "a ") |> *(_1, "sentence.")
julia> f("This ")
"This is a sentence."
julia> f2 = pipe_chain(f, endswith("sentence."))
|> *(_1, "is ") |> *(_1, "a ") |> *(_1, "sentence.") |> endswith("sentence.")
julia> f2("This ")
true
julia> f2 = pipe_chain(f, startswith("This"))
|> *(_1, "is ") |> *(_1, "a ") |> *(_1, "sentence.") |> startswith("This")
julia> f2("This ")
true
julia> f = pipe_chain(and(<=(3), !=(2)), ==(true), in(trues(2)), !in(falses(2)), >=(true))
|> and(<=(3), !=(2)) |> ==(true) |> in(Bool[1, 1]) |> !in(Bool[0, 0]) |> >=(true)
julia> f(1)
true
julia> f = pipe_chain(isapprox(0.1), !isapprox(0.2))
|> ≈(0.1) |> !≈(0.2)
julia> f(0.1 - 1e-10)
true
Internally, this includes support for those found in Julia's Base
module (Base.Fix1
, Base.Fix2
) and from ChainedFixes
(ChainedFix
and NFix
).
The constants on the right sight of the following table may be exported and accessed via using ChainedFixes.ChainedCore
The syntax corresponding to each constant is on the left.
Syntax | Type Constant |
---|---|
pipe_chain(f1, f2) |
PipeChain{F1,F2} |
and(f1::F1, f1::F2) /⩓(f1::F1, f1::F2) |
And{F1,F2} |
or(f1::F1, f1::F2) /⩔(f1::F1, f1::F2) |
Or{F1,F2} |
isapprox(x::T; kwargs::Kwargs) |
Approx{T,Kwargs} |
!isapprox(x::T; kwargs::Kwargs) |
NotApprox{T,Kwargs} |
in(x::T) |
In{T} |
!in(x::T) |
NotIn{T} |
<(x::T) |
Less{T} |
<=(x::T) |
LessThanOrEqual{T} |
>(x::T) |
Greater{T} |
>=(x::T) |
GreaterThanOrEqual{T} |
==(x::T) |
Equal{T} |
isequal(x::T) |
Equal{T} |
!=(x::T) |
NotEqual{T} |
startswith(x::T) |
StartsWith{T} |
endswith(x::T) |
EndsWith{T} |
The real utility of ChainedFixes
is when combining fixed methods in creative ways
julia> splat_pipe(op, args::Tuple) = op(args...);
julia> splat_pipe(op) = @nfix splat_pipe(op, _...);
julia> f = pipe_chain(extrema, splat_pipe(+))
|> extrema |> splat_pipe(+, _...)
julia> f([1 2; 3 4])
5