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

New library features for strings and ranges #610

Closed
wants to merge 2 commits into from
Closed

New library features for strings and ranges #610

wants to merge 2 commits into from

Conversation

timholy
Copy link
Sponsor Member

@timholy timholy commented Mar 19, 2012

These commits support more generic indexing on ASCIIStrings and deep-copy on range types. I'm not certain the last one is really desired, but I'm sure you'll decide.

With this commit, now you can do this:
   s = "swap me"
   indx = [4,3,6]
   s[indx]
This commit adds a deep-copy operation for range objects. If this is
not desired, feel free to ignore.
@JeffBezanson
Copy link
Sponsor Member

I believe ranges are intended to be immutable.

@timholy
Copy link
Sponsor Member Author

timholy commented Mar 19, 2012

I wondered about that. Presumably, the second patch isn't useful then. However, the first seems to be. Do I need to do something to extract the 5fefef8 patch, or can you cherry pick?

@JeffBezanson
Copy link
Sponsor Member

Cherry picked 327c39c.

@timholy
Copy link
Sponsor Member Author

timholy commented Mar 19, 2012

It seems that the following works if you include my range patch, and doesn't if you don't:
rngc = {100:300,70:400}
rng = convert(Array{Range1{Int},1},rngc)

Is there a better way to do this? Statements like [100:300,70:400] expand into one long list.

I guess the alternative is
rng = Array(Range1{Int},2)
rng[1] = 100:300
rng[2] = 70:400
and to use a loop when the number of dimensions gets bigger than 2.

@JeffBezanson
Copy link
Sponsor Member

Ah, it's the old shallow-vs-deep copying problem. Range is actually a kind of AbstractArray, since you often want it to work like a vector. Therefore without your patch, the following unintentionally happens:

julia> copy(1:2)
[1, 2]

I'll take a look, and it might be better to just make array copying shallow by default. We could also add

copy(x::Ranges) = x

to fix this.

@timholy
Copy link
Sponsor Member Author

timholy commented Mar 20, 2012

On a related note, I'll ask whether there's any chance that range expansion, as in [3:5], could be viewed as a convenience-motivated potential "wart" on the language.

Let's suppose we want to create a function with this syntax:
function rangefunc(a::Array{Range1{Int},1})
In particular, we're interested in using multiple dispatch to ensure this gets called for an array of range objects, but not for other objects.

Let's consider how to initialize a:
julia> a = [3:5,6:8,15:20]
[3, 4, 5, 6, 7, 8, 15, 16, 17, 18, 19, 20]

Let's try {}:
julia> a = {3:5,6:8,15:20}
{3:5, 6:8, 15:20}

julia> typeof(a)
Array{Any,1}

So {} is not very useful (?) unless convert(Array{Range1{Int},1},a) works.

How about ()?
julia> a = (3:5,6:8,15:20)
(3:5,6:8,15:20)

julia> typeof(a)
(Range1{Int32},Range1{Int32},Range1{Int32})

I don't think this is directly useful? (I'd love to be wrong.)

julia> [a...]
[3, 4, 5, 6, 7, 8, 15, 16, 17, 18, 19, 20]

julia> convert(Array{Range1{Int32},1},a)
no method convert(Type{Array{Range1{Int32},1}},(Range1{Int32},Range1{Int32},Range1{Int32}))
in method_missing at base.jl:60
in convert at base.jl:3

julia> function tuple2array(a)
b = [ a[i] | i = 1:length(a) ]
end

julia> tuple2array(a)
{3:5, 6:8, 15:20}

julia> map(x->x,a)
(3:5,6:8,15:20)

The following works, but it's uncomfortably long:
julia> type myrange
min::Int
max::Int
end

julia> a1 = myrange(3,5)
myrange(3,5)

julia> a2 = myrange(6,8)
myrange(6,8)

julia> a3 = myrange(15,20)
myrange(15,20)

julia> aall = [a1,a2,a3]
[myrange(3,5), myrange(6,8), myrange(15,20)]

julia> b = map(x->x.min:x.max,aall)
[3:5, 6:8, 15:20]

How about a vector of pairs?
julia> minmax = [[3,5] [6,8] [15,20]]
2x3 Int32 Array:
3 6 15
5 8 20

Since this gets converted to a matrix, I'm not sure how to use this via map (one wants a "map over columns").

This works:
julia> av=Array(Range1{Int},length(a))
[undef, undef, undef]

julia> for i = 1:length(a)
av[i] = a[i]
end

julia> av
[3:5, 6:8, 15:20]

In my view, using convert on {} is the best of these; currently it doesn't work, but could be made to do so. But my concern is that [3:5] -> [3,4,5] is the real root of the problem. I recognize that there are surely many more people who want a convenient syntax for range expansion than people who are interested in arrays of range objects, but the fact that their natural syntaxes collide seems like an issue worth raising. Would it be worth forcing people to use an "expand" function explicitly?

@JeffBezanson
Copy link
Sponsor Member

The thing is that [x,y,z] does not mean "make an array of x, y, z", it means concatenation. And there have been many cases where people wanted to expand ranges, or concatenate ranges with other vectors, [v, a:b, x] etc.

Short answer is that Range1{Int}[1:2, 3:4] works. That syntax does mean "make array of".

The convert version will work if we add the correct (do nothing) implementation of copy for ranges, and/or do shallow copying.

Somebody did write "map over columns", I believe it's called amap.

@timholy
Copy link
Sponsor Member Author

timholy commented Mar 20, 2012

Very informative! Thanks!

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

2 participants