-
Notifications
You must be signed in to change notification settings - Fork 28
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
Added @materialize convenience DSL #91
base: master
Are you sure you want to change the base?
Conversation
Codecov Report
@@ Coverage Diff @@
## master #91 +/- ##
==========================================
+ Coverage 77.81% 78.54% +0.73%
==========================================
Files 14 15 +1
Lines 1172 1212 +40
==========================================
+ Hits 912 952 +40
Misses 260 260
Continue to review full report at Codecov.
|
I assume the intermittent CI failures (e.g. https://travis-ci.org/JuliaArrays/LazyArrays.jl/jobs/633648027#L305) are related to #90 (comment)? |
I think this was fixed in master though perhaps I missed some? |
What do you think about the idea? @tkf any input? |
My initial thought was "can this be done without a macro?" but I can't think of any idea. I guess I can see that a macro like this could be handy. Regarding DSL syntax, I'd probably try to be slightly more verbose, something like @materialize function *(Ac::Adjoint{<:Any,<:AbstractMatrix},
O::MyOperator,
B::AbstractMatrix)
ApplyStyle(_, _) = MyApplyStyle()
function similar(_, T)
A = parent(Ac)
if O.kind == :diagonal
Diagonal(Vector{T}(undef, O.n))
else
Tridiagonal(Vector{T}(undef, O.n-1),
Vector{T}(undef, O.n),
Vector{T}(undef, O.n-1))
end
end
function copyto!(dest::Diagonal, _)
dest.diag .= 1
end
function copyto!(dest::Tridiagonal, _)
dest.dl .= -2
dest.d .= 1
dest.du .= 3
end
end so that you can kind of guess the meaning a bit more without reading what macro does. Another idea is to make it super generic and replace @materialize function *(Ac::Adjoint{<:Any,<:AbstractMatrix},
O::MyOperator,
B::AbstractMatrix)
LazyArrays.ApplyStyle(__op__, typeof(__applied__)) = MyApplyStyle()
function Base.similar(__applied__, T)
...
end
function Base.copyto!(dest::Diagonal, __applied__)
...
end
function Base.copyto!(dest::Tridiagonal, __applied__)
...
end
Broadcast.materialize(__applied__) =
copyto!(similar(__applied__, eltype(__applied__)), __applied__)
end Also, I wonder if there is a better name for this. Maybe |
Thanks @tkf for your input! Sorry for not responding earlier, I was preoccupied preparing a talk. I agree that I also agree it's better to be a bit verbose and less magical, but I don't like the underscores, nor the @defmaterialize function *(Ac::Adjoint{<:Any,<:AbstractMatrix},
O::MyOperator,
B::AbstractMatrix)
ApplyStyle = MyApplyStyle()
function similar(T) # or perhaps even `similar where T`?
A = parent(Ac)
if O.kind == :diagonal
Diagonal(Vector{T}(undef, O.n))
else
Tridiagonal(Vector{T}(undef, O.n-1),
Vector{T}(undef, O.n),
Vector{T}(undef, O.n-1))
end
end
function copyto!(dest::Diagonal)
dest.diag .= 1
end
function copyto!(dest::Tridiagonal)
dest.dl .= -2
dest.d .= 1
dest.du .= 3
end
end I specifically don't want to write Broadcast.materialize(__applied__) =
copyto!(similar(__applied__, eltype(__applied__)), __applied__) since it's going to be the same every time. |
I think this is an indication that macro-based solution is not quite right for defining Broadcast.materialize(A::Applied{<:CopyToApplyStyle}) =
copyto!(similar(A, eltype(A)), A) This way, you can just write struct MyApplyStyle <: CopyToApplyStyle end
@materialize function *(Ac::Adjoint{<:Any,<:AbstractMatrix},
O::MyOperator,
B::AbstractMatrix)
LazyArrays.ApplyStyle(__op__, typeof(__applied__)) = MyApplyStyle()
...
# no `materialize` here
end
It means that users need to know exactly what functions are supported by the macro. Documenting everything accurately is cumbersome and reading everything to understand is hard for users. It is burdensome to do this for every API update. I think the generic macro I suggested is better because there are very few concepts to explain.
I think you should at least get the arity correct because |
Fair enough, that makes sense.
Again, makes sense, but the @materialize function *(Ac::Adjoint{<:Any,<:AbstractMatrix},
O::MyOperator,
B::AbstractMatrix)
LazyArrays.ApplyStyle(__op__, typeof(__applied__)) = MyApplyStyle()
function Base.similar(__applied__, T)
...
end
function Base.copyto!(dest::Diagonal, __applied__)
axes(dest) == axes(__applied__) || throw(DimensionMismatch("axes must be same"))
Ac,O,B = __applied__.args
dest.diag .= -1 # Actually only required line
dest
end
end
# Generation result
function Base.copyto!(dest::Diagonal, __applied__::Applied{...})
# Boilerplate
axes(dest) == axes(__applied__) || throw(DimensionMismatch("axes must be same"))
Ac,O,B = __applied__.args
# Boilerplate ends, user code
axes(dest) == axes(__applied__) || throw(DimensionMismatch("axes must be same"))
Ac,O,B = __applied__.args
dest.diag .= -1
dest
# User code ends, boilerplate resumes
dest
end Gist of the idea: good to be general, but is it fine to be magical for
Also fair enough. |
I think making the destructuring automatic for functions taking The size-checking is a bit of problem though. If taking the idea "do less with macros as much as possible" very seriously, it makes sense to add function unsafe_copyto! end
function Base.copyto!(dest, A::Applied{<:CopyToApplyStyle})
axes(dest) == axes(A) || throw(DimensionMismatch("axes must be same"))
return unsafe_copyto!(dest, A)
end in LazyArrays.jl so that users can do struct MyApplyStyle <: CopyToApplyStyle end
@materialize function *(Ac::Adjoint{<:Any,<:AbstractMatrix},
O::MyOperator,
B::AbstractMatrix)
LazyArrays.ApplyStyle(__op__, typeof(__applied__)) = MyApplyStyle()
function LazyArrays.unsafe_copyto!(dest::Diagonal, __applied__)
...code touching dest, Ac, O, and B...
end
...
end
I still think it's a bit too DWIM (the size-checking part). At the same time, one can ask if adding But at least I like the fact that |
I think I actually like that approach; we don't have to add I will implement a new version of the macro along these lines soonish. |
Right, I agree.
Sounds great 👍 @dlfivefifty Are you OK with this approach? i.e., the second approach (with |
I have no strong opinions so once you both agree feel free to merge |
Note to self: don't forget to add |
As sketched in JuliaApproximation/ContinuumArrays.jl#37