-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Should we allow IOContext
to accept kwargs
#47396
Comments
For context, the kwargs version was deleted in #23271 as being redundant. |
This
|
@rfourquet could we also label this as performance improvement as well? |
|
I see. It seems quite natural (and performant, see the example above) to allow this sort of construction. What is the rationale behind this convention. |
For Dict, it is because it fails to generalize appropriately, since it only meaningful for Symbol keys. And because it is how the AbstractDict itself is expected to be configured (if applicable). And because NamedTuple doesn't iterate to produce pairs, but rather is an ordered container of values closer to a Tuple (that last is a bit less relevant now that kwargs are once again acting like a list of Pairs objects and not like NamedTuples) |
The benchmarks you gave are not particularly convincing because the julia> using BenchmarkTools
julia> @btime IOContext(stdout)
105.540 ns (1 allocation: 32 bytes)
IOContext(Base.TTY(RawFD(15) open, 0 bytes waiting))
julia> @btime IOContext(stdout, :compact=>true, :limit=>true, :color=>true)
430.151 ns (9 allocations: 304 bytes)
IOContext(Base.TTY(RawFD(15) open, 0 bytes waiting))
julia> Base.IOContext(io; kwargs...) = if length(kwargs) > 0
IOContext(io, kwargs...)
else
convert(IOContext, io)
end
julia> @btime IOContext(stdout)
105.931 ns (1 allocation: 32 bytes)
IOContext(Base.TTY(RawFD(15) open, 0 bytes waiting))
julia> @btime IOContext(stdout, :compact=>true, :limit=>true, :color=>true)
424.854 ns (9 allocations: 304 bytes)
IOContext(Base.TTY(RawFD(15) open, 0 bytes waiting))
julia> @btime IOContext(stdout; compact=true, limit=true, color=true)
117.416 ns (4 allocations: 128 bytes)
IOContext(Base.TTY(RawFD(15) open, 0 bytes waiting)) |
This is probably a better definition than the one I had originally @inline Base.IOContext(io; kw...) = isempty(kw) ? convert(IOContext, io) : IOContext(io, kw...) |
The docs say:
so I am not sure it is really an implementation detail. And you interact with it like a dict with |
I would not base the decision for this on whether this is faster or not, as performance comparisons might evolve; unless the current performance with pairs is deemed problematic (but I don't recall seing complaints about it) and it's believed to not be easily improvable. |
Ok, so maybe leave function sprint(f::Function, args...; context=nothing, sizehint::Integer=0)
s = IOBuffer(sizehint=sizehint)
if context isa Tuple
f(IOContext(s, context...), args...)
elseif context !== nothing
f(IOContext(s, context), args...)
else
f(s, args...)
end
String(resize!(s.data, s.size))
end It could be extended to function sprint(f::Function, args...; context=nothing, sizehint::Integer=0, kw...)
s = IOBuffer(sizehint=sizehint)
if context isa Tuple
ioc = IOContext(s, context...)
elseif context !== nothing
ioc = IOContext(s, context)
else
ioc = IOContext(s)
end
f(IOContext(ioc, kw...), args...)
String(resize!(s.data, s.size))
end |
Why not, but |
Fair point. function sprint(f::Function, args...; context=nothing, sizehint::Integer=0, func_kws = (;), kws...)
s = IOBuffer(sizehint=sizehint)
if context isa Tuple
ioc = IOContext(s, context...)
elseif context !== nothing
ioc = IOContext(s, context)
else
ioc = IOContext(s)
end
f(IOContext(ioc, kws...), args...; func_kws...)
String(resize!(s.data, s.size))
end |
Still when seeing |
|
New code here needs to be reviewed against https://docs.julialang.org/en/v1/manual/performance-tips/#Break-functions-into-multiple-definitions norm(x::Vector) = sqrt(real(dot(x, x)))
norm(A::Matrix) = maximum(svdvals(A)) is better than using LinearAlgebra
function mynorm(A)
if isa(A, Vector)
return sqrt(real(dot(A,A)))
elseif isa(A, Matrix)
return maximum(svdvals(A))
else
error("mynorm: invalid argument")
end
end BTW the couple namedtuple/kwargs gains maturity around julia v1.5 . |
@o314 Julia doesn't dispatch on keyword arguments and |
Sorry for not being clear enough. The comment doesn't apply to the function head but to the function body (as in the example of the doc), and to your defense, flaws begun before your contribution. That's fine to fix them on next round anyway function sprint(f::Function, args...; context=nothing, sizehint::Integer=0, func_kws = (;), kws...)
iobuf = IOBuffer(; sizehint)
ioctx = IOContext(iobuf, context; kws...)
f(ioctx, args...; func_kws...)
String(resize!(iobuf.data, iobuf.size))
end
IOContext(io::IO, tup::Tuple; kws...) = IOContext(io, tup..., kws...)
IOContext(io::IO, ::Nothing; kws...) = IOContext(io, kws...)
IOContext(io::IO, t::Any; kws...) = IOContext(io, t, kws...) One can now compare
That's small things but summed up, that naturally delivers a better message about what an iocontext ctor should be. |
IOContext
already acceptsVararg{Pair{Symbol}}
. The following code seems to work just fine.I can open a PR if there is interest.
The text was updated successfully, but these errors were encountered: