Yes, the distinction between `T[i]` on 0.3.x and `T.parameters[i]` on 0.4-
and up is because of a change to tuples that took place in the 0.4-dev
cycle; before the change, `typeof((3.5, 2)) == (Float64, Int)`, i.e. the
type of a tuple was a tuple of the types of the elements, but after the
change tuples got their own type and now `tuple((3.5,2)) == Tuple{Float64,
Int}`. (This was so disruptive to on-the-edge packages it was nick-named
"The Tuplocalypse"...)
// T
On Monday, October 5, 2015 at 1:26:51 PM UTC+2, [email protected] wrote:
>
> I am on Version 0.5.0-dev+433 (2015-09-29 15:39 UTC) and probably should
> have mentioned that!
>
> On Monday, October 5, 2015 at 12:19:34 PM UTC+1, Glen O wrote:
>>
>> Perhaps the distinction is due to 0.3 vs 0.4 - I'm still using 0.3 until
>> the final release, because I don't want to go through the hassle of manual
>> installation when the PPA will be updated as soon as 0.4 is officially
>> released. The code worked perfectly for me. Anyway, Tomas has provided the
>> way to access it, it seems, so it should work - just a bit more complicated
>> along the way.
>>
>> On Monday, 5 October 2015 20:51:20 UTC+10, [email protected] wrote:
>>>
>>> Sorry, I ran your code and got an error so assumed it wouldn't work, but
>>> I think I see your point. If we modify it a bit:
>>>
>>> function mycode2{T}(x...;t::T=x)
>>> for j=1:length(x)
>>> println(x[j])
>>> end
>>> println(T)
>>> return(T)
>>> end
>>>
>>> This: mycode2(2, 4., 4 + 5im, 4. + 2im) returns:
>>>
>>> Tuple{Int64,Float64,Complex{Int64},Complex{Float64}}
>>>
>>> and prints the correct values. So how do I access the types in Tuple{}
>>> since T[i] will give errors?
>>>
>>> On Monday, October 5, 2015 at 11:31:06 AM UTC+1, Glen O wrote:
>>>>
>>>> I'll admit, I didn't entirely follow what you're trying to do, but
>>>> based on what I was able to see, is there any reason why my last
>>>> suggestion
>>>> wouldn't work? I'll copy it here:
>>>>
>>>> function mycode{T}(x...;t::T=x)
>>>> for j=1:length(x)
>>>> println(typeof(x[j])<:T[j])
>>>> end
>>>> end
>>>>
>>>> By making t take the value of x, you are allowing t to have the same
>>>> "type" as x - namely, a tuple containing the input arguments. Then, by
>>>> having t::T, it makes T hold their types. And because it's a keyword
>>>> argument, it can be placed after x..., and doesn't need to be input at
>>>> all,
>>>> because it's defaulted to x. It certainly satisfies the requirements you
>>>> put forward in your original question.
>>>>
>>>> On Monday, 5 October 2015 18:30:48 UTC+10, [email protected] wrote:
>>>>>
>>>>> Hi Glen,
>>>>>
>>>>> Perhaps in my previous email when I wrote:
>>>>>
>>>>> f(1, 2, 3) rather than f((1, 2 , 3))
>>>>>
>>>>> I should have written something like f(1, 2.3, 5 + 3.im, 3 + 1im,
>>>>> Nullable{Float64}(5.)) to make it explicit that I would like to
>>>>> parametrise
>>>>> different types. I think David Gold's suggestion is the closest to what I
>>>>> want but doesn't quite solve the problem. If I wanted to lift a set of
>>>>> Julia's functionality to new types having an arbitrary set of input
>>>>> types,
>>>>> I could:
>>>>>
>>>>> 1. Spend alot of time writing code to parse different subsets of
>>>>> modules. This would take an immense amount of work and the libraries
>>>>> would
>>>>> inevitably change.
>>>>> 2. If we could model a variadic template function having the semantics
>>>>> as I specified previously:
>>>>>
>>>>> function {T...}my_fun(x...)
>>>>> for i in 1:length(x)
>>>>> println(typeof(x[i]) <: T[i])
>>>>> end
>>>>> end
>>>>>
>>>>> The above function for simplicity. Here T... are the types of x... and
>>>>> they could be all different or the same
>>>>>
>>>>> We could lift functionality of all the relevant function in one go
>>>>> with a sketch implementation like:
>>>>>
>>>>> # Import the functions ...
>>>>> import Base: get, +, -, /, *, ^, ...
>>>>>
>>>>> # Function symbols to be lifted
>>>>> funs = [:+, :-, ...]
>>>>>
>>>>> # Generic get function
>>>>> # Assume appropriate get functions are written for each type
>>>>> function get{T}(x::T)
>>>>> x
>>>>> end
>>>>>
>>>>> # My new type is T1{T}()
>>>>>
>>>>> S = Union{Symbol, Expr}
>>>>>
>>>>> # My lifter function
>>>>> function lift(fun_name::S, new_type::S)
>>>>> quote
>>>>> function $fun_name{T...}(x...)
>>>>> y = Array(Any, length(x))
>>>>> for i in 1:length(x)
>>>>> y[i] = get(i)
>>>>> end
>>>>> ret = $fun_name(y...)
>>>>> U = typeof(ret)
>>>>> return $new_type{U}(ret)
>>>>> end
>>>>> end
>>>>> end
>>>>>
>>>>> # Then lift the functions
>>>>> for i in funs
>>>>> eval(lift(i, :T1))
>>>>> end
>>>>>
>>>>> Could then do T1(3.4) + 9 and so on for all the functions regardless
>>>>> of number of arguments return type etc
>>>>>
>>>>> DP
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On Monday, October 5, 2015 at 7:20:55 AM UTC+1, Glen O wrote:
>>>>>>
>>>>>> Just to be clear, are you looking for something that will
>>>>>> parameterise across a variety of types, or are you wanting to restrict
>>>>>> to a
>>>>>> single type?
>>>>>>
>>>>>> If the latter, it can be easily done with
>>>>>>
>>>>>> function mycode{T}(x::T...)
>>>>>> <code here>
>>>>>> end
>>>>>>
>>>>>> which will make all values in the varargs list the same. To restrict
>>>>>> to a specific subset, there's also
>>>>>>
>>>>>> function mycode(x::Union(Int,Array)...)
>>>>>> <code here>
>>>>>> end
>>>>>>
>>>>>> which will require that the arguments in x be either Ints or Arrays
>>>>>> (and can have both).
>>>>>>
>>>>>> If you're actually after the former, is there a reason why you can't
>>>>>> just ask for typeof(x[i]), directly? Alternatively, would this work?
>>>>>>
>>>>>> function mycode{T}(x...;t::T=x)
>>>>>> for j=1:length(x)
>>>>>> println(typeof(x[j])<:T[j])
>>>>>> end
>>>>>> end
>>>>>>
>>>>>