Skip to content
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

promote_rule with automatic return type casting? #7014

Closed
RainerHeintzmann opened this issue May 28, 2014 · 2 comments
Closed

promote_rule with automatic return type casting? #7014

RainerHeintzmann opened this issue May 28, 2014 · 2 comments

Comments

@RainerHeintzmann
Copy link

I am wondering how to make a julia type, which behaves exaclty like existing array classes but (for example) uses a different show function. Ideally I would not want to rewrite all existing methods but automatically all exiting methods should also apply to my new datatype.

In OOP based thinking this is only very few lines of code. However, in Julia it seems next to impossible to achieve this. On the web I found several implementations, which redefined all operations on arrays (e.g. +,-,.*) in a more or less automated way, but there really should be a simple solution to express this.

Here is a bit of code that demonstrates my problem:

type Img{T,N} <: DenseArray{T,N}  # If you derive from DenseArray, then at least the plus works after defining it. However promotion seems to be ignored
    data::DenseArray{T,N}
end
a=[4 5 6 75 34.2];
b=Img(a);
b.data

Base.ndims{T,N}(animg::Img{T,N}) = Base.ndims(animg.data)
Base.size{T,N}(animg::Img{T,N}) = Base.size(animg.data)
Base.getindex{T,N}(animg::Img{T,N}, anind::Real) = Base.getindex(animg.data, anind)
Base.getindex{T,N}(animg::Img{T,N}, anind::DenseArray{T,N}) = Base.getindex(animg.data, anind)
Base.getindex{T,N}(animg::Img{T,N}, anind::AbstractArray{T,N}) = Base.getindex(animg.data, anind)
Base.getindex{T,N}(animg::Img{T,N}, varargs...) = Base.getindex(animg.data, varargs...)
Base.setindex!{T,N}(animg::Img{T,N}, varargs...) = Base.setindex!(animg.data, varargs...)

Base.similar{T,N}(animg::Img{T,N},::Type{T}) = Base.similar(animg.data,varargs...)
Base.similar{T,N}(animg::Img{T,N},varargs...) = Base.similar(animg.data,varargs...)
c=b+b;
c
# This is now a  1x5 Array{Float64,20}, but I really want it to be of type Img{Float64,2}
# How can this be achieved?

Interestingly assignments do work, if c is first defined as an Img{Float64,2] datatype.
So how can one enforce that creation of new variables will have to Img datatype rather than the Array datatype? Or is this behavior a bug after all?

An alternative might be that promote_rule is somewhat extended, such that julia can know under what circumstances a result of a function call should automatically be cast to the type defined in promote_rule. E.g. one could use a tupel where the second type is the one to which the returned value should be cast to:

promote_rule{T,N}(::Type{Img{T,N}},::Type{Img{T,N}} ) = (Type{Img{T,N}},Type{Img{T,N}})
promote_rule{T,N}(::Type{Img{T,N}},::Type{DenseArray{T,N}} ) = (Type{Img{T,N}},Type{Img{T,N}})

Would this be doable?
Any ideas?

@JeffBezanson
Copy link
Member

See also #2248

@JeffBezanson
Copy link
Member

I think the promotion issue is the same as #2326. However, your similar method should return something of the same type as animg; that's what + is using to make its result.

This is captured by existing issues; closing as dup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants