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. >