Re: [julia-users] Flexible construction of types

2014-11-26 Thread Mauro
How about

immutable MyType{T:Real}
x::T
v::Vector{T}
s::String

function MyType(x, v, s)
x = subtractpi(x)
v = map(subtractpi, v)
new(x, v, s)
end
end
MyType{T1:Real, T2:Real}(x::T1, v::Vector{T2}, s::String) = 
(T=promote_type(T1,T2); MyType{T}(x, v, s))

T1 and T2 are both needed to fulfil 5.  Otherwise calling `MyType(11.4, [1, 2, 
55])
will set T to Float64 and thus error on the array

On Wed, 2014-11-26 at 22:20, Marc Gallant marc.j.gall...@gmail.com wrote:
 Suppose I have a type called MyType that has one floating point field x. 
 When constructed, if the value provided for x is greater than, let's say, 
 5, it has pi subtracted from it. For example,

 a = MyType(4)  # x = 4.0
 b = MyType(-11) # x = 11.0
 c = MyType(10)  # x = 6.8584
 d = MyType(-1.443)  # x = -1.443

 What is the best way to declare MyType and its constructor(s) to ensure 
 that:

 1. You can provide MyType with any real number to construct it
 2. typeof(a.x) and typeof(c.x) are both Float64
 3. The pi constraint is properly applied (is an inner constructor 
 appropriate here?)
 4. The same behaviour applies to the entries of a second field y that is 
 a vector (e.g., MyType(10, [3, 10, 11, -2]) has x = 6.8584, y = [3.0, 
 6.8584, 7.8584, -2.0]).
 5. (if possible) You can construct MyType from a mixture of real number 
 types (e.g., MyType(11.4, [1, 2, 55]))
 6. MyType has a third field z that is a string

 Here is an implementation I wrote that doesn't meet 1, 5, or 6:

 function subtractpi(x::Real)
 x, y = promote(x, x - pi)
 return x  5 ? y : x
 end

 immutable MyType{T:FloatingPoint}
 x::T
 v::Vector{T}

 function MyType(x, v)
 x = subtractpi(x)
 v = map(subtractpi, v)
 new(x, v)
 end
 end
 MyType{T:FloatingPoint}(x::T, v::Vector{T}) = MyType{T}(x, v)

 Thanks. I am working on my understanding of types in Julia.



Re: [julia-users] Flexible construction of types

2014-11-26 Thread Marc Gallant
Thanks for your quick response! I have a couple questions/concerns about 
your implementation:

- MyType(1, [2, 3], xyz) fails requirement #2
- MyType(1, [2, 10], xyz) throws InexactError()
- Does the declaration s::String cause the ambiguities described in the FAQ 
here 
http://docs.julialang.org/en/latest/manual/faq/#how-do-abstract-or-ambiguous-fields-in-types-interact-with-the-compiler?
 
More specifically, does MyType suffer from the same ambiguity 
as MyStillAmbiguousType in the FAQ?

Thanks again!
Marc


Re: [julia-users] Flexible construction of types

2014-11-26 Thread Mauro
 Thanks for your quick response! I have a couple questions/concerns about 
 your implementation:

 - MyType(1, [2, 3], xyz) fails requirement #2

MyType{T1:Real, T2:Real}(x::T1, v::Vector{T2}, s::String) = 
(T=promote_type(T1,T2,Float64); MyType{T}(x, v, s))

If you want to keep Float16, etc this does not work.  It will be at
least Float64 (or BigFloat).

If you need Float16 etc kept then it's going to be quite a bit more
verbose as arithmetic with pi promotes to Float64.

If you're fine with just Float64 and don't care about BigFloat then just
do:

immutable MyType
x::Float64
v::Vector{Float64}
s::String
...
end 


 - MyType(1, [2, 10], xyz) throws InexactError()

Should be fixed as well

 - Does the declaration s::String cause the ambiguities described in the FAQ 
 here 
 http://docs.julialang.org/en/latest/manual/faq/#how-do-abstract-or-ambiguous-fields-in-types-interact-with-the-compiler?
  
 More specifically, does MyType suffer from the same ambiguity 
 as MyStillAmbiguousType in the FAQ?

I think this should only affect functions which actually use .s but not
.x or .v. 

You can check this like so:

julia f(a::MyType) = a.x+a.v[1]
f (generic function with 1 methods)

julia f(aa)
3.0

julia @code_typed f(aa)
1-element Array{Any,1}:
 :($(Expr(:lambda, {:a}, {{},{{:a,MyType{Float64},0}},{}}, :(begin  # none, 
line 1:
return 
(top(box))(Float64,(top(add_float))((top(getfield))(a::MyType{Float64},:x)::Float64,(top(arrayref))((top(getfield))(a::MyType{Float64},:v)::Array{Float64,1},1)::Float64))::Float64
end::Float64

This shows that Julia knows that the return type is Float64 (the last
bit of the returned thingy).

Compare this to:

julia immutable MyType2
   x
   v::Vector
   s::String
   end

julia b=MyType2(1, [2, 10], xyz)
MyType2(1,[2,10],xyz)

julia g(a::MyType2) = a.x+a.v[1]
g (generic function with 1 method)

julia g(b)
3

julia @code_typed g(b)
1-element Array{Any,1}:
 :($(Expr(:lambda, {:a}, {{},{{:a,MyType2,0}},{}}, :(begin  # none, line 1:
return (top(getfield))(a::MyType2,:x) + 
(top(arrayref))((top(getfield))(a::MyType2,:v)::Array{T,1},1)
end

No type annotation at the end of the output here, thus Julia cannot
infer the return type.


Re: [julia-users] Flexible construction of types

2014-11-26 Thread Jameson Nash
it should be noted that there's nothing inherently wrong or bad about
using non-concrete type specifications in type declarations. it does,
however, limit certain optimizations that might provide performance
benefits, and may be especially important for native numerical types.

On Wed Nov 26 2014 at 4:54:37 PM Marc Gallant marc.j.gall...@gmail.com
wrote:

 Thanks for your quick response! I have a couple questions/concerns about
 your implementation:

 - MyType(1, [2, 3], xyz) fails requirement #2
 - MyType(1, [2, 10], xyz) throws InexactError()
 - Does the declaration s::String cause the ambiguities described in the
 FAQ here
 http://docs.julialang.org/en/latest/manual/faq/#how-do-abstract-or-ambiguous-fields-in-types-interact-with-the-compiler?
 More specifically, does MyType suffer from the same ambiguity
 as MyStillAmbiguousType in the FAQ?

 Thanks again!
 Marc