On Sun, 25 May 2014 14:11:41 -0700 (PDT), Adam Smith wrote: > Actually, no. I'm not going to pretend this is a good thing. You're right > that it is "consistent and logical" when you're using an academic > type-correctness viewpoint. However, it is not consistent from a developer > perspective, and here's why.
Well, it's not a good thing in kinda the same way that π = 3.1415926535897... It would be much more convenient if π = 3, but that just does not work. The way around dealing with this problem is not not declare types in function signatures which works just fine most of the time. If one needs to declare parametric types then one needs to be aware of some of the intricacies of the type system. For instance that parametric types are invariant: http://docs.julialang.org/en/latest/manual/types/#parametric-composite-types On Sun, 25 May 2014 14:11:41 -0700 (PDT), Adam Smith wrote: > Actually, no. I'm not going to pretend this is a good thing. You're right > that it is "consistent and logical" when you're using an academic > type-correctness viewpoint. However, it is not consistent from a developer > perspective, and here's why. > > On most functions, I don't need to specify parametric types (which is good: > there is less clutter). Let's say I have a function: > function output(context::Context, string::String) > context.something() > println(string) > end > > output(context, "Hi there") > > And a few days later I decide it would be better to accept a list of > strings instead, so I do the most natural thing, and I just put Vector{} > around the type that was already working: > > function output(context::Context, strings::Vector{String}) > context.something() > for string in strings println(string) end > end > > output(context, ["Hi there"]) > > This is absolutely what every new Julia developer will expect to work > (regardless of how "correct" it is), and it will fail. It's especially > confusing because for some types, it works (like changing Int to > Vector{Int}). It is simply bizarre to new developers using the language > that the type matching worked on a single element of that type, but not on > a parametric collection of that type. > > Yes, I know why it is the way it is, and yes, I know why a textbook says it > should be this way, but thinking from a UX perspective (where the "user" is > a developer new-ish to Julia), it's quite off-putting. > > On Sunday, May 25, 2014 1:50:19 PM UTC-4, Adam Smith wrote: > > > > You're right, that's not bad at all. Thanks. > > > > On Sunday, May 25, 2014 12:41:04 PM UTC-4, Iain Dunning wrote: > >> > >> julia> f{T<:String}(strs::Vector{T}) = dump(strs) > >> f (generic function with 1 method) > >> > >> julia> f(["foo"]) > >> Array(ASCIIString,(1,)) ASCIIString["foo"] > >> > >> > >> Seems fine to me, and more importantly (to me), is consistent and > >> logical. Vector{String} is a concrete type, its a specific thing. > >> Vector{T},T<:String, is the family of vectors that contain String-y things. > >> Unless you are writing library code, not much point to getting trick with > >> type signatures anyway - there is no speed benefit to doing so, its just a > >> defensive programming thing. > >> > >> > >> On Sunday, May 25, 2014 12:23:34 PM UTC-4, Adam Smith wrote: > >>> > >>> I'd just like to add that this behavior is a real downer when dealing > >>> with strings, too. During testing/debugging inline strings are > >>> ASCIIStrings, but I don't want to hardcode my functions to use > >>> ASCIIStrings > >>> (or have to make Unions absolutely every place I want a vector of > >>> strings): > >>> > >>> julia> f(strs::Vector{String}) = dump(strs) > >>> f (generic function with 1 method) > >>> > >>> julia> f(["foo"]) > >>> ERROR: no method f(Array{ASCIIString,1}) > >>> > >>> julia> g(strs::Vector{UTF8String}) = dump(strs) > >>> g (generic function with 1 method) > >>> > >>> julia> g(["foo"]) > >>> ERROR: no method g(Array{ASCIIString,1}) > >>> > >>> julia> h(strs::Vector{ASCIIString}) = dump(strs) > >>> h (generic function with 1 method) > >>> > >>> julia> h(["foo"]) > >>> Array(ASCIIString,(1,)) ASCIIString["foo"] > >>> > >>> > >>> > >>> On Sunday, May 25, 2014 11:46:43 AM UTC-4, Pierre-Yves Gérardy wrote: > >>>> > >>>> > >>>> > >>>> On Sunday, May 25, 2014 5:44:26 PM UTC+2, Pierre-Yves Gérardy wrote: > >>>>> > >>>>> On Sunday, May 25, 2014 5:10:49 PM UTC+2, James Crist wrote: > >>>>>> > >>>>>> Yeah, that's what I've been using. My issue with it is that the > >>>>>> declarations get long for functions with more than 2 arrays. Was > >>>>>> hoping > >>>>>> there was a more concise way. > >>>>>> > >>>>> > >>>>> You can use typealias Fp FloatingPoint , then > >>>>> > >>>> > >>>> ... or Fp = FloatingPoint , types are first class objects. > >>>> > >>>> > >>>>> > >>>>> > >>>> function foo{T1<:Fp, T2<:Fp}(a::Array{T1}, b::Array{T2}) > >>>>> > >>>>>
