Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: redesign of tuples and tuple types #10380

Merged
merged 7 commits into from
Apr 17, 2015
Merged

WIP: redesign of tuples and tuple types #10380

merged 7 commits into from
Apr 17, 2015

Conversation

JeffBezanson
Copy link
Sponsor Member

I have only just barely begun to implement this, but I'm filing this early to keep everybody apprised of the new design. This is my current pick for highest-priority breaking change to system internals for 0.4.

Summary of the approach:

  • The representation currently used for heap-allocated tuples (a length following by some pointers) will instead be used for a new type called SimpleVector. This way many internal things can keep using the same representation (at least for a while).
  • Tuples will be immutable DataTypes, and DataType will change very little
  • Tuples and tuple types are now totally different, distinguished by jl_is_tuple and jl_is_tuple_type. jl_typeof and jl_is_type are now much simpler.
  • Internal names starting with jl_tuple are generally changed to jl_sv (for SimpleVector)
  • The horribly-named jl_null is changed to jl_emptytuple and jl_emptysv
  • Tuples will be accessed with jl_fieldref
  • The Vararg type is replaced with a boolean flag in DataType

Syntax changes:

  • Construct tuple types with {}
  • deprecate (Type,Type) to {Type,Type}, eventually have it return a tuple of types instead
  • deprecate (Type...) to {Type...}, eventually have it splat instead

Planned follow-on changes:

  • make NTuple a concrete type, for efficiently handling large homogeneous tuples
  • reduce use of SimpleVector as much as possible

Addressed issues:
#8470 - use {} for tuple types
#4869 - splatting in tuple construction
#7941 - Towards array nirvana
#3440 - optimization tracker

Related issues:
#7568 - WIP: implementation of fixed-size arrays
#2299 - SIMD types

@timholy
Copy link
Sponsor Member

timholy commented Mar 2, 2015

I can't find anything to complain about in that list. Quite the contrary, in fact.

@ivarne
Copy link
Sponsor Member

ivarne commented Mar 2, 2015

I bet we can find a better usage for {} than tuple types. I feel like we're out of ASCI characters for new syntax all the time, and tuple types is so obscure that most users have managed well without them. Tuple{} looks pretty nice too, and has a similar feeling to the other parametric types.

I will also express my negative feelings for pushing the 0.4 release further into the future. We're past due already, and stalled releases gives a negative impression about our progress.

(If this gets into 0.4, we'll also need to keep {} as a depreciation for Any[], if we are to follow our depreciation policy)

Ps: otherwise this seem like a really great change!

@Jutho
Copy link
Contributor

Jutho commented Mar 3, 2015

+1 for every single suggestion... Does this also mean that a NTuple{N,ConcreteType} field inside a type definition will be 'inlined', so that we can easily build ImmutableVector and redo CartesianIndex ?

@nalimilan
Copy link
Member

@ivarne What candidates do you have in mind for an alternative use of {}? I think that's an interesting data point for the discussion.

@timholy
Copy link
Sponsor Member

timholy commented Mar 3, 2015

Hmm, @ivar's point about one cycle's worth of deprecation for {} does seem important.

@ivarne
Copy link
Sponsor Member

ivarne commented Mar 3, 2015

@nalimilan See #10386.

(@timholy I'm @ivarne, not @ivar. (Sorry to my name brother in Vancouver))

@timholy
Copy link
Sponsor Member

timholy commented Mar 3, 2015

Sorry to both.

@JeffBezanson
Copy link
Sponsor Member Author

I'm willing to use Tuple{}. In a few cases this could be awkward though, like ccall(f, T, Tuple{A, B}, x, y). ccall could maybe continue to use a tuple of types instead of an actual tuple type.

@Jutho yes tuples of bits types will be inlined.

As for release timing, my current thinking is to get this change in, but punt most of the rest of what's currently in the 0.4 milestone. Any very disruptive changes that we know we need, we should do as soon as possible. Many of the other 0.4 issues are not that disruptive, e.g. if they can be deprecated easily.

@StefanKarpinski
Copy link
Sponsor Member

What about Tuple{(A,B)}? That way Tuple always has a single parameter which is the tuple of types.

@JeffBezanson
Copy link
Sponsor Member Author

That's an interesting idea. Off-line I actually worked through ~3 possible designs for this, and I considered some things like that. One unusual feature of such a design is that the length of a tuple is not actually stored anywhere; you just have a cycle of objects for each possible length. Of course you could store the length anyway, but you can't get to it just by looking at the parameter(s) of a tuple type, which is a bit surprising. It also entails allocating more objects per tuple type, and there are a lot of tuple types.

@StefanKarpinski
Copy link
Sponsor Member

I was just thinking that allowing varargs parametric types was kind of a complication to the type system. Would you be able to declare your own varargs parametric types? Or would it be something that is special to Tuple?

@ivarne
Copy link
Sponsor Member

ivarne commented Mar 3, 2015

Aren't types kind of varargs already (in that you can have incompletely specified types like Array{Int})?

@JeffBezanson
Copy link
Sponsor Member Author

I wasn't planning to add general varargs type parameters; this would be specific to tuples.

Varargs parameters could mean two things: allowing a type to be instantiated with any number of parameters, or allowing ... to be present (which I guess would be a kind of pattern for matching trailing arguments). The second feature is a bit odd without covariance.

We don't have this already, because the number of parameters is always limited. No type actually accepts any number of parameters (except tuples).

@tkelman
Copy link
Contributor

tkelman commented Mar 8, 2015

Could jl_sv be made at least a few characters more descriptive? jl_svec maybe?

@JeffBezanson
Copy link
Sponsor Member Author

Ok.

@joschu
Copy link

joschu commented Mar 13, 2015

I don't like the {} syntax, because it's at odds with mathematical notation, where curly braces denote sets, and most other programming languages, where curly braces denote unordered collections. (E.g., in python, where {} constructs a set or dict, and Lua and Matlab, where {} constructs an unordered map.)

@IainNZ
Copy link
Member

IainNZ commented Mar 13, 2015

@joschu we already use curly brackets to denote tuples of types in a lot of places though, e.g.

type MyType{A,B}
  foo::A
  bar::B
end

MyType(5.0, 2)  # MyType{Float64,Int}

So it doesn't seem too ambiguous

@StefanKarpinski
Copy link
Sponsor Member

It kind of makes sense:

  • (a,b) is just the argument part of f(a,b) without the function
  • {A,B} is just the parameter part of T{A,B} without the type.

@joschu
Copy link

joschu commented Mar 13, 2015

Ah! I misread the original proposal as saying that all tuples would be constructed using that notation.
Using {} for tuple types completely makes sense. Cheers.

@JeffBezanson
Copy link
Sponsor Member Author

Making good progress here.

One minor thing I ran into: it's a bit odd that usually T{} == T, but Tuple{} != Tuple == Tuple{Any,...}.

And a major thing: we have no way to destructure tuple types. We used to be able to use all tuple functions on tuple types, which was pretty convenient, but we've never had variadic DataTypes before so there's no infrastructure for that. This mostly affects convert for tuple types. I could use a staged function but I'd rather avoid that.

The traditional approach would be a recursive representation, e.g. the type of (1,2,3.0) is Product{Int,Product{Int,Product{Float64,{}}}}. That's pretty disruptive. We could accomplish something similar just with a function that takes Tuple{A,B,C} to Tuple{B,C}. I'm not sure how to do that any more elegantly than a staged function or a builtin.

@StefanKarpinski
Copy link
Sponsor Member

Making the type parameter the tuple of types solves both of these issues, no? Tuple{} == Tuple != Tuple{(Any...)}. You can also do destructuring on the parameter itself, so the only inconvenient step is pulling it out of the type. Might it be possible to hack the representation so that the actual tuple object need not be stored?

@JeffBezanson
Copy link
Sponsor Member Author

A good way to do that would be to have a parameters(T) function (instead of T.parameters) that gives you a tuple of the parameters.

I hesitate there because of the large number of silly tuple types we'd need to generate: typeof(parameters(typeof((1,2)))) == Tuple{Type{Int},Type{Int}}. We'd need that instead of Tuple{DataType,DataType} for the full effect. It seems like instead of moving around between the type and value level, you should just be able to manipulate the type directly. The type we started with, Type{Int,Int}, already has all the needed information.

@JeffBezanson
Copy link
Sponsor Member Author

I thought my last commit did not work. Funny thing is, it actually did work, but just took so long to start up that I gave up waiting... how amusing... :)

@ViralBShah
Copy link
Member

👍

@JeffBezanson
Copy link
Sponsor Member Author

If anybody wants to kick the tires, this is now usable with sys0.ji. Don't try to build sys.ji; just interrupt it.

@mdcfrancis
Copy link

Makes sense, thanks for the clarification.

@yuyichao yuyichao mentioned this pull request Jun 6, 2015
mbauman pushed a commit to mbauman/julia that referenced this pull request Jun 6, 2015
mbauman pushed a commit to mbauman/julia that referenced this pull request Jun 6, 2015
I believe the bug was due to the need to hash typename->primary
specially, based on how other type functions treat it.
mbauman pushed a commit to mbauman/julia that referenced this pull request Jun 6, 2015
…0875)

- add a linearly-searched part of the type cache for more difficult types
- assign UIDs earlier so they can't change after cache insertion
mbauman pushed a commit to mbauman/julia that referenced this pull request Jun 6, 2015
DSLituiev pushed a commit to DSLituiev/JLD.jl that referenced this pull request Oct 19, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet