Yet another point of view - incidentally the one that convinced me that 
Julia has got this right, while most others don't - is the fact that in the 
grand scheme of things, JIT is *cheap *while working with types that might 
have subtypes is *really painful* if you don't want to compromise with 
performance. Julia does an absolutely beautiful job with a function 
definition such as

function sum(x)
    # implementation goes here
end

with no arguments defined at all. Mostly, you don't need to define your 
argument types, since the compiler will generate a strongly typed function 
for you whenever you need it. For whatever type you need it. If, for some 
reason, you actually do have an instance of `Array{Real}`, containing both 
floats, ints and rationals, the above method will (probably) Just Work(TM) 
anyway, since most operations for real numbers are implemented to make them 
work with each other. And if you can write an implementation of `sum` that 
works more or less optimally on `Array{Float64}`, chances are the compiler 
can too - *and it will, as soon as you need one, *without you doing 
anything more than asking nicely (and you don't even have to realize that 
you're asking!). The same user code will be used to compile both methods, 
and for the Array{Float64} case it will be as fast as it can be, while for 
the more general method it will not be slower than it would be otherwise.

And if you want to be able to say to the compiler that "this is going to be 
an array of numbers - I don't know what kind of numbers yet, but they'll 
all be the same type", well, then that's already included in the language. 
You only need the type parameter on the function to say 
f{T<:Number}(x::Array{T}) and you're done.

My point is that the problems that types like Array{Real} solve in other 
languages - e.g. being able to sum a collection of numbers without knowing 
what type of numbers they are - is solved instead by JIT-compiling and 
multiple dispatch, just as efficiently (if not better). The syntax - and 
sometimes the mind-set of the programmer - needs to be a little different, 
but there are no problems (that I can see) that can't be solved just as 
efficiently, albeit in another way.

OK, well, just because I wrote that, I realize there is one problem that I 
can't off the top of my head say how I'd solve: type assertions for e.g. 
arrays. Say I have a variable x, and I want to make sure that it's an array 
of real numbers that are all of the same type, but I don't care which one. 
Can I say x::Array{T<:Real} as a type assertion? (I'm at a computer without 
Julia atm, so I can't test it for myself...)

But yeah, other than that, I can't really think of a problem that isn't 
just as solve-able in Julia as in any other language. One just has to 
embrace the slightly different way of doing things, that is a result of a 
slightly unusual (in a good way!) type system.

// T

On Tuesday, April 29, 2014 7:37:52 PM UTC+2, Jason Merrill wrote:
>
> On Tuesday, April 29, 2014 9:29:56 AM UTC-7, Oliver Woodford wrote:
>>
>> On Tuesday, April 29, 2014 5:14:01 PM UTC+1, Jason Merrill wrote:
>>>
>>> Suppose the types that you want existed. Let's call them ConcreteArray, 
>>> and Cell.
>>>
>>> ConcreteArray gives the guarantee that all of it's elements are stored 
>>> directly with a fixed stride.
>>>
>>> Can you give some examples of functions that would use these in their 
>>> type signature?
>>>
>> Sure. sum(x::ConcreteArray{Number}). Because currently if I write 
>> sum(x::Array{Real}) and try to pass in an Array{Float64} I get an error.
>>
>> Note that most arrays are actually homogeneous (as Jacob and Matt both 
>> stated), so if you want to make sure of that you need to use static 
>> parameters. I'm suggesting a system that doesn't require static parameters 
>> for the usual case.
>>
>
> Take a look at the actual implementations of sum in reduce.jl:
>
> https://github.com/JuliaLang/julia/blob/master/base/reduce.jl#L179
> https://github.com/JuliaLang/julia/blob/master/base/reduce.jl#L275
>
> Julia often has method definitions that are significantly more generic 
> than sum(x::ConcreteArray{Number}), which I think is really nice. The 
> definitions above are fast for Array{Float64}, but the very same 
> definitions also work for e.g. an array of matrices, or anything else with 
> + defined (zero(T) might have to be defined too if the array is empty or 
> has only 1 element).
>
> I don't see much advantage of having an implementation like 
> sum(x::ConcreteArray{Number}) if someone later comes along and defines 
> sum(x::AbstractArray) with essentially the same body.
>

Reply via email to