Excellent points Tomas. I think this would be particularly helpful for those coming from Java. Perhaps some of your comments could be worked into the manual or FAQ somewhere.
-Jacob On Tue, Apr 29, 2014 at 2:43 PM, Tomas Lycken <[email protected]>wrote: > 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. >> >
