I find the way that you need to use `linspace` and `range` objects a bit jarring for when you want to write vectorized code, or when I want to pass an array to a function that requires an Array. I get how nice the iterators are when writing loops and that you can use `collect(iter)` to get a array (and that it is possible to write polymorphic code that takes LinSpace types and uses them like Arrays … but this hurts my small brain). But I find I that I often want to write code that uses an actual array and having to use `collect` all the time seems like a serious wart for an otherwise stunning language for science. (https://github.com/JuliaLang/julia/issues/9637 gives the evolution I think of making these iterators)
For example recently the following code was posted/refined on this mailing list:
function Jakes_Flat( fd, Ts, Ns, t0 = 0, E0 = 1, phi_N = 0 )
# Inputs:
#
# Outputs:
N0 = 8; # As suggested by Jakes
N = 4*N0+2; # An accurate approximation
wd = 2*pi*fd; # Maximum Doppler frequency
t = t0 + [0:Ns-1;]*Ts;
tf = t[end] + Ts;
coswt = [ sqrt(2)*cos(wd*t'); 2*cos(wd*cos(2*pi/N*[1:N0;])*t') ]
temp = zeros(1,N0+1)
temp[1,2:end] = pi/(N0+1)*[1:N0;]'
temp[1,1] = phi_N
h = E0/sqrt(2*N0+1)*exp(im*temp ) * coswt
return h, tf;
end
From <https://groups.google.com/forum/#!topic/julia-users/_lIVpV0e_WI>
Notice all the horrible [<blah>;] notations to make these arrays … and it seems like the devs want to get rid of this notation as well (which they should it is way too subtle in my opinion). So imagine the above code with `collect` statements. Is this the way people work? I find the `collect` statements in mathematical expressions to really break me out of the abstraction (that I am just writing math).
I get that this could be written as an explicit loop, and this would likely make it faster as well (man I love looping in Julia). That being said in this case I don't find the vectorized version a performance issue, rather I prefer how this reads as it feels closer to the math to me.
So my question: what is the Juilan way of making explicit arrays using either `range (:)` or `linspace`? Is it to pollute everything with `collect`? Would it be worth having versions of linspace that return an actual array? (something like alinspace or whatnot)
Thanks for any tips, comments etc
No that is a good point. Often you can use an iterator where an explicit array would also work. The issue I guess is that this puts the burden on the developer to always write generic code that when you would want to accept an Array you also need to accept a iterator like LinSpace.Maybe this is easier to do than I currently understand?
I find the way that you need to use `linspace` and `range` objects a bit jarring for when you want to write vectorized code, or when I want to pass an array to a function that requires an Array. I get how nice the iterators are when writing loops and that you can use `collect(iter)` to get a array (and that it is possible to write polymorphic code that takes LinSpace types and uses them like Arrays … but this hurts my small brain). But I find I that I often want to write code that uses an actual array and having to use `collect` all the time seems like a serious wart for an otherwise stunning language for science.
Just to add to Spencer's answer: Is there a particular reason to have your function arguments have type annotations at all in the function definition? You could just writefunction f(x)y= x[3:5] # or whateverz = length(x)endand now someone could call f with any kind of object that supports indexing and "length" and it will work. This is "duck-typing", if you're familiar with that term, and is the dominant paradigm in Julia precisely since it makes generic programming easier.
For efficiency you'll still want to use a concrete Vector field if you're defining your own types, but luckily there seems to be a convert method defined so you can do:type MyArr{T}x::Vector{T}end
function jakes_flat(fd, Ts, Ns, t0 = 0.0, E0 = 1.0, phi_N = 0.0) N0 = 8 N = 4N0 + 2 wd = 2π * fd t = t0 + (0:Ns-1) * Ts tf = t[end] + Ts coswt = [√2cos(wd*t)' ; 2cos(wd*cos(2π*(1:N0)/N)*t')]' temp = [phi_N; π*(1:N0)/(N0+1)] h = E0/√(2N0+1) * coswt * exp(im*temp) return (h, tf)endOn Oct 21, 2015, at 3:19 PM, Gabriel Gellner <gabriel...@gmail.com> wrote:Continuing to think about all the ideas presented in this thread. It seems that the general advice is that almost all functions should at first pass be of "Abstract" or untyped (duck typed) versions. If this is the case why is Abstract not the default meaning for Array? Is this just a historical issue? This feels like the language design is sort of fighting this advice and instead it should have been that we have Array meaning AbstractArray and Array meaning something like ConcreteArray to put the incentive/most natural way to add types. Similar for Vector, Matrix etc.
I guess I find this idea that full genericity is the correct way to do things to be a bit at odds with how the language coaxes you to do things (and the general discussion of performance in Julia). Is this a more recent feeling? Did Julia start out being more about concrete types and template like generic types? This would explain the linspace vs logspace and all other basic array creating functions (ones, zeros, rand etc) and the default names for many types vs the "Abstract" prefixed ones.
That doesn't feel like a reason that they can't be iterators, rather that they might be slow ;) a la python. My point is not about speed but the consistency of the language.
That doesn't feel like a reason that they can't be iterators, rather that they might be slow ;) a la python. My point is not about speed but the consistency of the language. Are there many cases in Julia where there is a special type like this because it is convenient/elegant to implement? This feels like a recipe for madness, my guess is that this would be crazy rare.People wondered why people might mind that we get a LinSpace object vs an Array. For me it is this strange feeling that I am getting a special case that doesn't feel well motivated other than there is a nice way to implement it (and that people, again, assumed that it would largely be used for looping). If not all things can be made consistently iterators when they are vector-like then why not have a special function that returns this special type (like your aforementioned linrange)? The fact that I lose my iterator when I use certain functions but not others is a way that this polymorphism that everyone is describing doesn't feel as nice to me, since it will not compose in cases where it likely should, outside of implementation details.
Maybe all this is just transitional that soon LinSpace objects will always work like Arrays in all code I might use as an end user. Currently as a new user I have not had this experience. I have noticed that LinSpaces where returned, and had to learn what they were and at times run `collect` to make them into what I wanted. I have not felt this abstraction bleed yet in other areas of Julia.
A related discussion is about a special Ones type representing an array
of 1, which would allow efficient generic implementations of
(non-)weighted statistical functions:
https://github.com/JuliaStats/StatsBase.jl/issues/135
But regarding zeros(), there might not be any compelling use case to
return a special type. Anyway, if arrays are changed to initialize to
zero [1], that function go could away entirely

You're making a good point about an Array being sometimes faster than a LinSpace. But a LinSpace gets you a factor N improvement in terms of memory efficiency for a size N range, an Array only gets you a constant factor improvement in speed (the factor 15 being admittedly relatively large in this example).Memory efficiency typically matters more for usability in an exploratory interactive session: if my Julia session needs 5 GB RAM, a factor 3 increase of memory will crash my computer. If my code runs for 10 seconds in an interactive session, 30 seconds is mildly annoying, but not a deal breaker. (Obviously, you can construct different examples with memory/time where this is different. But my point is that inconvenience changes discontinuously in memory usage.)
julia> function pi_half_montecarlo(n)
mysum = 0
for x in linrange(0,1,n)
y = rand()
if x*x + y*y < 1
mysum += 1
end
end
return 4.0*mysum/n
end
pi_half_montecarlo (generic function with 1 method)
julia> pi_half_montecarlo(10); @time pi_half_montecarlo(1000_000_000)/pi
elapsed time: 17.980499945 seconds (112 bytes allocated)
1.0000009913475585
very nice example - thank you - but I notice that you use linrange :).Thanks, Christoph
This is still an option but I'm yet to be convinced that we want to have that many things exported: linrange, LinRange, and linspace which just does collect on linrange? Seems like one too many.
Abstract Concrete
Signed (Integer) Int*
Unsigned (Integer) UInt*
Float Flt*
Decimal Dec*
Array Arr
Vector Vec
Matrix Mat
String Str (maybe Str{Binary}, Str{ASCII}, Str{UTF8}, Str{UTF16}, Str{UTF32})
Better yet, since we already have both AbstractVector, AbstractMatrix, AbstractArray, AbstractString, AbstractFloat and a couple of others (try typing Abstract<tab> in the REPL…) it might be time to rename Integer to AbstractInteger. I have a hard time thinking the confusion between Int and Integer would be reduced just because we also had Arr and Array et al - rather, we’d have several pairs of types where it isn’t entirely obvious that one is abstract and one is concrete.
Renaming Integer to AbstractInteger would probably cause massive breakage, though, so it’d have to be done with care. The difference between Int, Int32/Int64 and Integer is well documented (see e.g. here and here), but it seems to me that people stumble on this often enough that a naming change might be well motivated anyway.
// T
Better yet, since we already have both
AbstractVector,AbstractMatrix,AbstractArray,AbstractString,AbstractFloatand a couple of others (try typingAbstract<tab>in the REPL…) it might be time to renameIntegertoAbstractInteger. I have a hard time thinking the confusion betweenIntandIntegerwould be reduced just because we also hadArrandArrayet al - rather, we’d have several.