On Tuesday, August 30, 2016 3:57:36 PM CDT Yichao Yu wrote: > And even then, this completely looses the advantage of using tuple > (inferrable size and element types) so you shouldn't do this in general > unless you are going to do a lot of work with the tiny tuple afterwards.
Right. If you want to grow a tuple, you should use "lispy recursion" so the compiler can reason about the size, which is part of the type of the tuple. (`for` loops are completely off the table for this kind of programming.) Here's an example that builds a tuple of N `true`s (i.e., functionally equivalent to `ntuple(d->true, N)`): buildtrues{N}(::Type{Val{N}}) = _buildtrues((), Val{N}) # initialization _buildtrues{N}(out::NTuple{N}, ::Type{Val{N}}) = out # termination @inline _buildtrues{N}(out, ::Type{Val{N}}) = _buildtrues((out..., true), Val{N}) # the "inner loop" Key features include the `@inline` and the fact that `N` is available to the type system. For a particular inferrable`N<15`, the compiler will just figure out the end result and return that; the "apparent" recursion runs at compile time, not runtime. Note that if your condition isn't evaluatable at compile time, and especially if it changes from one "iteration" to the next, then you're frankly much better off using Arrays rather than tuples. Don't attempt to fake compile-time evaluation using `Val` unless the condition is already embedded in the type system (e.g., coming from an `::Array{T,N}`) or it's the same `Val` being used bazillions of times. See http://docs.julialang.org/en/latest/manual/ performance-tips/#types-with-values-as-parameters and the section after that. This is not just a theoretical concern: while tuples have enormous advantages in certain settings, trying to fake this with tuples/Val and getting it wrong could easily result in a 30-100 fold performance *penalty* compared to using Arrays. Best, --Tim