What is the rationale for Tuple() not working as a constructor as a struct type would?
It’s fine to use tuple() instead for general purposes, but it messes with the pattern of using types as general constructors when working in the AST. You have to specifically handle Tuple to use tuple() instead of just constructing X(args…).
Obviously not going to be changing right now, but it would be good to understand the rationale for it.
It could easily be the other way around, and this would be more intuitive:
struct Example
a
b
c
end
julia> typeof(Example(1, 2, 3)).name.wrapper(1.0, 2.0, 3.0)
Example(1.0, 2.0, 3.0)
julia> typeof((1, 2, 3)).name.wrapper(1.0, 2.0, 3.0)
ERROR: MethodError: no method matching Tuple(::Float64, ::Float64, ::Float64)
There might be counterexample of the opposite kind of unintuitive if it were switched, so maybe it was a coin flip
string does not guarantee you to return String. In general you can get other subtype of AbstractString. As an input you can pass any objects.
String guarantees that you will get String but has a limited number of methods - it will only accept String, SubString{String}, Symbol or several variants of UInt8 or AbstractChar arrays.
Oh, interesting. I think I’ve only ever used string() to get string representations of numbers (Ints and Floats) and Regexs, both of which do return String. What are examples where it returns something else?
Looking at this a little more, I think string() actually works for all my uses, including those where I currently use String(). I wonder if it would be a good idea to just use that function as a general case rather than trying to use the converting version.
So SubstitutionString{String} remains a SubstitutionString{String}. But it is pretty obscure case. However, when you start using e.g. https://github.com/JuliaString/Strs.jl this would become a serious issue.
There is a convention that when T is a collection type, you can construct it from another similar collection using T(other). Examples:
julia> Array(1:3)
3-element Array{Int64,1}:
1
2
3
julia> Tuple(1:3)
(1, 2, 3)
julia> Dict(i=>i for i in 1:2)
Dict{Int64,Int64} with 2 entries:
2 => 2
1 => 1
I agree this is somewhat at odds with the default constructors for struct types, which accept field values as separate arguments. However, structs aren’t collections of their fields! A struct might represent something totally different, e.g. a single number.