For many users, this is probably a minor bike-shed thing but I wanted to dump it ;)
maybe it’s even a bug or let’s say, design flaw (see at the end), no idea.
I use function-like objects a lot in my packages and I constantly bump into this.
Given the following simple example
julia> struct Foo
buffer::Vector{Float64}
Foo() = new(Float64[])
end
julia> function (f::Foo)(arr)
resize!(f.buffer, length(arr))
# do some stuff, use the `buffer`, mutate `arr` etc.
reverse!(arr) # just that we mutate...
end
we will end up with:
julia> f = Foo()
Foo(Float64[])
julia> f([1,2,3])
3-element Vector{Int64}:
3
2
1
My problem is that there is of course no !
to indicate that f
is mutating, so the only way to make it look nicer (i.e. signal that it’s mutating) is discipline, which is a source of error in the sense that users of the package will likely name their Foo()
whatever they like and not realise that calling it will mess with the input values, so they will not even think about adding an !
.
So this is the “discipline” which is required, when creating Foo()
:
julia> f! = Foo()
Foo(Float64[])
julia> f!([2,3,4]) # add the !
3-element Vector{Int64}:
4
3
2
What I find confusing however (this is the bug or design flaw part) is that you can defeine `(f::Foo)!(arr) and will not give any error, but then nothing is callable:
julia> struct Foo
buffer::Vector{Float64}
Foo() = new(Float64[])
end
julia> function (f::Foo)!(arr)
resize!(f.buffer, length(arr))
# do some stuff, use the `buffer`, mutate `arr` etc.
reverse!(arr) # just that we mutate...
end
#16 (generic function with 1 method)
julia> f = Foo()
Foo(Float64[])
julia> f!([2,3,4])
ERROR: UndefVarError: `f!` not defined
Stacktrace:
[1] top-level scope
@ REPL[4]:1
julia> f([2,3,4])
ERROR: MethodError: objects of type Foo are not callable
Stacktrace:
[1] top-level scope
@ REPL[5]:1
So I am wondering what happens when defining (f::Foo)!(arr)
, where is the !
? ;)
To me it would make sense that however Foo()
is named later, I can call however!(arr)
when defining (f::Foo)!(arr)
.
I assume this would not be a breaking change since it did not work before, so maybe something for Julia 1.10 or 1.11, unless I am overlooking something.
Any thoughts?