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

Dimspec should include Range #1829

Closed
stevengj opened this issue Dec 27, 2012 · 12 comments
Closed

Dimspec should include Range #1829

stevengj opened this issue Dec 27, 2012 · 12 comments
Labels
needs decision A decision on this change is needed

Comments

@stevengj
Copy link
Member

Julia uses a type Dimspec to define sets of dimensions for things like sum(A, dims), currently defined as typealias Dimspec Union(Int,Dims) where Dims is typealias Dims (Int...).

I have been playing with this (for #1805), and it seems like it would be very convenient to have Dimspec include Range{Int} as well.

For example, this would allow you to do things like sum(x, 1:ndims(x)-1) to sum over all but the last dimension of x. Currently, in order to do this you need something like sum(x, ntuple(ndims(x)-1, i -> i)), which is rather ugly. I keep running into cases like this.

It would also be nice for sum(x, :) to be equivalent to sum(x) (and similarly for other functions accepting Dimspec types). I don't really grok how : by itself works in Julia right now, though.

@johnmyleswhite
Copy link
Member

+1 for this. I would love to see this be added.

I believe that : is replaced by the parser with something like 1:end. But that's just speculation based on trying to define an operation that worked on Colon directly and never seemed to receive it.

@JeffBezanson
Copy link
Member

Outside of indexing, : by itself is a singleton of type Colon. We could change it to be like that everywhere, there are just a lot of moving parts.
It'd be even better to get rid of ad-hoc union types like Dimspec and allow anything that implements contains (or whatever). Different flavors of a function shouldn't be distinguished based on whether an argument is of some random set of types.

@ViralBShah
Copy link
Member

If we are going to include Range, we might as well go all the way and include AbstractArray. Dimspec is certainly a bit arbitrary and a more general solution is certainly preferable.

@stevengj
Copy link
Member Author

Why not just support anything that has length and ref in such contexts? This includes arrays, tuples, ranges, and potentially just about any container type.

The only thing that is missing right now, surprisingly, is scalars. length works on a scalar and returns 1, but ref does not, e.g. 1.3[1] gives no method ref(Float64,Int64). But this is easily fixed.

@StefanKarpinski
Copy link
Member

I still rather object to making scalars iterable. This is a bad idea, imo, especially because it means something very different to iterate certain scalars, such as strings.

@stevengj
Copy link
Member Author

@StefanKarpinski

It seems to me that your interface for strings already treats them as containers of characters, not as scalars. length("Hello") returns 5, not 1 after all. Can you give any concrete problems that would arise from making scalars iterable?

Making scalars iterable (with length 1) has the advantages:

  • It makes "vectorized" code that accepts either a scalar or an array argument much easier to write. Such functions are ubiquitous and idiomatic in any Matlab-style language. Not having ref for scalars often means having to code two cases for such functions (or using some awkward syntax like wrapping such arguments x in [x] or [x...] to construct unnecessary arrays). (Note that the compiler should be able to eliminate unnecessary loops when compiling code that iterates over scalar arguments.)
  • Many of your operations already allow you to treat scalars as if they were arrays or tuples of length 1: length, numel, ndims (see below), concatenation, the ... syntax, etcetera. Why should ref be the exception?
  • Matlab compatibility: you choose to have Julia syntax be close to Matlab's in cases where it makes sense (i.e. where Matlab is not too crazy or too incompatible with Julia's design). Why not ref of a scalar?
  • Linear algebra: scalars are, of course, a perfectly good vector space of dimension 1, or a tensor of rank 0 (and ndims on a scalar indeed returns 0; of course, a tensor of rank 0 has no indices, but you already allow a[i] to give the i-th value in an array regardless of the dimensionality, including 0-dimensional arrays which have one element).

@johnmyleswhite
Copy link
Member

I have to say that I'm on board with the idea of a no-op ref(s::Scalar) = s. I actually tried to do 1[1] the other day and thought it would simplify a bunch of code I've been writing.

@JeffBezanson
Copy link
Member

It's true unfortunately; if scalars weren't iterable it would create nasty special cases in array indexing. In fact we would almost need to add an interface index_start, index_next, index_done for iterating over indexes in that case. Or manual if statements, which hardly seems better.

@StefanKarpinski
Copy link
Member

Ok, maybe this is fine. Let's give it a try. I guess it does jive with the idea of scalers as zero-dimensional tensors.

@ViralBShah
Copy link
Member

Yes, having scalars iterable makes it a lot easier for indexing, which was also the context of earlier discussions.

@stevengj
Copy link
Member Author

So, the proposal at this point is to add a ref operation for numeric scalars, and to extend Dimspec to be a union of Int, (Int...), AbstractArray{Int}, and Range{Int}?

Or is there some more general way to declare an arbitrary iterable container of Int? (Or not declare it at all and wait for an error to show up when ref etcetera is used on a type that doesn't support it?)

@ViralBShah
Copy link
Member

Range is a subtype of AbstractArray. This sounds about right, but I would want to hear what @JeffBezanson has to say.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs decision A decision on this change is needed
Projects
None yet
Development

No branches or pull requests

5 participants