For example we have a struct
struct Daggered
block::Matrix
end
For any function trait(m::Matrix, args...)
, can we define
trait(m::Daggered, args...) = trait(m.block, args...)
automatically to make Daggered look like a real matrix?
For example we have a struct
struct Daggered
block::Matrix
end
For any function trait(m::Matrix, args...)
, can we define
trait(m::Daggered, args...) = trait(m.block, args...)
automatically to make Daggered look like a real matrix?
You code do this with some code generation. As a simple example
for op ā ops_i_want_to_use
@eval $op(m::Daggered, args...) = $op(m.block, args...)
end
though ideally you shouldnāt use splatting. In practice I often see people do this separately for unary, binary and trinary operators, but another (probably better) alternative would be to use MacroTools.jl which provides some really useful tools for deconstructing function syntax.
Note also that āDaggered
ā already exists, itās called Adjoint
and you can get it by just doing A'
or adjoint(A)
for some matrix A
. (Be sure to import the package Compat
first, as Iām showing syntax for 0.7 and I think adjoint
was called something else in 0.6.)
One further comment, Iām not sure if your example was just demonstrative or intended as an actual use, but in general, if you want to create an array type, it should inherit from AbstractArray
. For example
struct Daggered{T,N} <: AbstractArray{T,N}
block::Array{T,N}
end
this will then inherit all of the methods of AbstractArray
(which is a lot). You only need to implement a few simple functions to make it work. One of the great virtues of Julia is that inheriting from abstract types in Base
is a much more common practice than in any other language I have seen, and arrays are a really good example of how powerful this can be.
There is also the @forward
macro from Lazy.jl
:
help?> Lazy.@forward
@forward T.x functions...
Define methods for functions on type T, which call the relevant function on the field x.
Example
ā”ā”ā”ā”ā”ā”ā”ā”ā”
struct Wrapper
x
end
@forward Wrapper.x Base.sqrt # now sqrt(Wrapper(4.0)) == 2.0
Thanks for your reply,
code generation is a good idea, but not good enough.
For future extensions, we still have to define two set of functions for both Daggered and original version.
Adjoint has the same problem.
Iām not quite sure Iām understanding you correctly, but it sounds like you want to define a new function for arrays, and then also extend that to a new type.
It might help if you could give a broader explanation of what youāre trying to do. Itās still sounding a bit like you just want some new AbstractArray
methods, in which case what you should do is define Daggered <: AbstractArray
and then simply define some methods which take an AbstractArray
argument, i.e.
trait(A::AbstractArray, args...) = # some code
(perhaps see some documentation on abstract types).
Again, not sure if this is a real example, but Daggered
of a matrix sounds quite a lot like an adjoint to me, so it might be worth looking through some of the array and linear algebra docs to see if what youāre doing is already implemented.
Daggered may be a poor example, it was defined under the context of quantum circuit simulation in my case. Never mind ā¦
I have read the source code of Adjoint
, I think it is not elegant.
Letās use the Cached
object as an example,
In real programming, we often need something like Cached
object that sharing the same interface with original object. It has difference only in some specific methods related to caching.
I need this kind of logic āstruct A is same as B, only for functions in a countable set, it is treated special.ā
Thatās sounds quite a lot like inheritance to me. Ideally youāre objects would inherit from a common abstract type. If you are working with existing types that canāt do that, you can still generate functions as discussed above, but you may need to look through Julia introspection tools for an automated way of finding them all.
For something like quantum circuits, I donāt think itās a good idea to completely forsake all of the nice linear algebra functionality already existing in Base
, so itās good to at least be aware of it. Indeed, even if you have specialized operator types, itās probably a good idea to also have methods which use AbstractArray
s since in many cases the specialized operators will simply wrap those. At least in the finite dimensional case of quantum circuits, I canāt think of any reason why operators shouldnāt be AbstractArray
s, at least off the top of my head. It might be worth taking a look at QuantumOptics for some inspiration, itās quite a nice package.