This seems to be an unnecessarily obfuscated implementation of typeof. Julia already knows how to deal with `typeof(x[j])` very efficiently, while it doesn't understand any of `typeof(x).parameters[j]`, or `T.parameters[j]`, or `t::T=x` particularly well.
On Mon, Oct 5, 2015 at 7:17 AM <[email protected]> wrote: > Thanks Thomas so we can modify Glen's code as: > > function mycode3{T}(x...;t::T=x) > for j=1:length(x) > println(typeof(x[j])<:T.parameters[j]) > end > end > > and mycode3(2, 4., 4 + 5im, 4. + 2im) will print: > > true > true > true > > > On Monday, October 5, 2015 at 11:56:54 AM UTC+1, Tomas Lycken wrote: >> >> In this case, typeof(x[j]) is probably preferable, but if you have >> access only to the type and not the values, you can also use >> T.parameters[j] to the same end. >> >> // T >> >> On Monday, October 5, 2015 at 12:53:36 PM UTC+2, data.pu…@gmail.com >> wrote: >> >> I see we can do typeof(x[j]) >>> >>> On Monday, October 5, 2015 at 11:51:20 AM UTC+1, [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 >>>>>>> >>>>>> >> >
