I think an argument for linspace returning an Array is that it makes 
teaching new programmers Julia a lot easier. 

 If it returns an Array, its sufficient to teach students the Array type.  But 
if it returns a Range, one has to teach an extra data type before the students 
can use it.  Teaching [1:5;] is not as bad as one can just teach that as the 
syntax for creating an array of [1,2,3,4,5].  (Teaching the syntax 
[linspace(1,5,1);]  is too over the top I think.)


+ linrange exists for experts





> On 1 Oct 2015, at 5:49 pm, Tim Holy <[email protected]> wrote:
> 
> Ranges check bounds when you index them with x[i], but not when you use `for 
> y 
> in x`. Someone could submit a PR for the appropriate change in base/ops.jl.
> 
> --Tim
> 
> On Thursday, October 01, 2015 02:55:25 PM Sheehan Olver wrote:
>> The timings seem to be a sign that special functions over ranges are not yet
>> optimized, see variants below using comprehensions that do much better. 
>> Note also that collect uses 2x the memory with only a 30% speedup (or 10%
>> slow down, if you also count the time to collect).
>> 
>> 
>> 
>> julia> function expfor(n)
>>       x= linspace(0, 1, n)
>>       [exp(y) for y in x]
>>       end
>> julia> function expcollect(n)
>>       x= collect(linspace(0, 1, n))
>>       exp(x)
>>       end
>> julia> function explin(n)
>>       x= linspace(0, 1, n)
>>       exp(x)
>>       end
>> 
>> julia> @time for k=1:10 expfor(1_000_000);end
>>  0.180067 seconds (20 allocations: 76.295 MB, 4.09% gc time)
>> 
>> julia> @time for k=1:10 expcollect(1_000_000);end
>>  0.209594 seconds (50 allocations: 152.590 MB, 6.43% gc time)
>> 
>> julia> @time for k=1:10 explin(1_000_000);end
>>  0.254747 seconds (20 allocations: 76.295 MB, 2.85% gc time)
>> 
>> julia> x=collect(linspace(0, 1, 1_000_000));
>> julia> @time for k=1:10 exp(x);end
>>  0.136381 seconds (20 allocations: 76.295 MB, 4.74% gc time)
>> 
>>> On 1 Oct 2015, at 2:45 pm, Christoph Ortner <[email protected]>
>>> wrote:
>>> 
>>> 
>>> 
>>> On Wednesday, 30 September 2015 21:42:33 UTC+1, Steven G. Johnson wrote:
>>> 
>>> 
>>> On Wednesday, September 30, 2015 at 4:01:17 PM UTC-4, Christoph Ortner
>>> wrote: I simply dislike is that linspace does not behave as expected, and
>>> I expect that this is the main reason for other as well. To give an
>>> extreme analogy, we don't go around and start defining A * B = A + B
>>> either, and linspace and similar names are just so ingrained in the
>>> Matlab (and apparently also Python) community, that it trips us up when
>>> they suddenly behave differently.
>>> 
>>> This is a bad analogy.  linspace still returns an AbstractVector with the
>>> same elements.   So, it's basically doing the same thing as before, and
>>> is just implemented differently.
>>> 
>>> My point was about "changing the expected behaviour", and I said this was
>>> an extreme analogy.
>>> 
>>> The question is, why does this implementation detail of linspace matter to
>>> you?  It still behaves the same way in nearly every context.
>>> 
>>> as you say, "nearly".
>>> 
>>> The cases where it behaves differently are probably mostly bugs (overly
>>> restrictive types of function parameters) that were waiting to be
>>> caught.> 
>>> julia> x = linspace(0, 1, 1_000_000);
>>> julia> y = collect(x);
>>> julia> @time exp(x);
>>> 
>>>  0.021086 seconds (6 allocations: 7.630 MB)
>>> 
>>> julia> @time exp(y);
>>> 
>>>  0.012749 seconds (6 allocations: 7.630 MB)
>>> 
>>> julia> @time AppleAccelerate.exp!(y,y);
>>> 
>>>  0.001282 seconds (4 allocations: 160 bytes)
>>> 
>>> julia> @time AppleAccelerate.exp!(x,x);
>>> ERROR: MethodError: `exp!` has no method matching
>>> exp!(::LinSpace{Float64}, ::LinSpace{Float64})
>>> 
>>> (a) the speed improvement is probably hidden in the call to collect, but
>>> if I don't know about it and call several functions on x, then I will
>>> feel it. (b) The error tells what is going wrong, which is good, so now I
>>> can go and fix it. But it is an extra 5-10 minutes taking me out of my
>>> flow-state, which in practise will cost me more like 1h or so.
>>> 
>>> You could now argue that when I try to optimise like that then I should
>>> know what I am doing. But I would equally argue that when you care
>>> whether linspace is a vector or a "range", then I should know whether to
>>> call linspace or linrange.> 
>>> Finally, I don't buy the argument that linspace should be abstracted
>>> because of memory. It always creates one-dimensional grids, and those
>>> aren't the issue. There is a much stronger argument to create an
>>> abstraction for meshgrid and I even disliked that that one was dropped.> 
>>> We don't need an abstraction for meshgrid, since in pretty much all
>>> applications of meshgrid you can use broadcasting operations instead (far
>>> more efficiently).
>>> 
>>> I used to want meshgrid too, but it was only because I wasn't used to
>>> broadcasting operations. Since then, I have never found a case in which
>>> meshgrid would have been easier than the broadcasting operations.
>>> 
>>> same point really. Why not provide mesh-grid and make it behave as
>>> expected,  and add a comment in the documentation (maybe even in the
>>> doc-string of mesh grid) that for performance one should use
>>> broadcasting.
>>> 
>>> The whole discussion reminds a bit about issue #10154,
>>> https://github.com/JuliaLang/julia/issues/10154, whether floating-point
>>> indexing should be implemented. By now I am used to it, and I will get
>>> used to linspace behaving as it does. But with every little change like
>>> that, the entry barrier for Matlab / R / Python users becomes higher and
>>> the take-up of the language by non-experts will decrease. The reason I
>>> started with Julia was that it behaved as I expected. I am now sticking
>>> with it because I like the type system, the Python interface (and the
>>> speed). But if I tried it right now, coming from Matlab, I would have
>>> struggled more than I did in the 0.2 version.
>>> 
>>> Christoph
> 

Reply via email to