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}) 
>>>>>
>>>>>

Reply via email to