diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 9ba3078c6dbda..7e21a563615a5 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -5,6 +5,36 @@ typealias AbstractMatrix{T} AbstractArray{T,2} ## Basic functions ## +const _oldstyle_array_vcat_ = true + +if _oldstyle_array_vcat_ + function oldstyle_vcat_warning() + warn_once("[a,b,...] concatenation is deprecated; use [a;b;...] instead") + end + function vect(A::AbstractArray...) + oldstyle_vcat_warning() + vcat(A...) + end + function vect(X...) + for a in X + if typeof(a) <: AbstractArray + oldstyle_vcat_warning() + break + end + end + vcat(X...) + end +else + vect{T}(X::T...) = T[ X[i] for i=1:length(X) ] + function vect(X...) + T = promote_type(map(typeof, X)...) + T[ X[i] for i=1:length(X) ] + end +end + +typed_vect_or_ref(T::NonTupleType, x) = (a = Array(T,1); a[1] = x; a) +typed_vect_or_ref(a, b) = getindex(a, b) + size{T,n}(t::AbstractArray{T,n}, d) = (d>n ? 1 : size(t)[d]) eltype(x) = Any eltype{T,n}(::AbstractArray{T,n}) = T @@ -627,6 +657,11 @@ end ## cat: general case function cat(catdim::Integer, X...) + T = promote_type(map(x->isa(x,AbstractArray) ? eltype(x) : typeof(x), X)...) + cat_t(catdim, T, X...) +end + +function cat_t(catdim::Integer, typeC::Type, X...) nargs = length(X) dimsX = map((a->isa(a,AbstractArray) ? size(a) : (1,)), X) ndimsX = map((a->isa(a,AbstractArray) ? ndims(a) : 1), X) @@ -671,7 +706,6 @@ function cat(catdim::Integer, X...) ndimsC = max(catdim, d_max) dimsC = ntuple(ndimsC, compute_dims)::(Int...) - typeC = promote_type(map(x->isa(x,AbstractArray) ? eltype(x) : typeof(x), X)...) C = similar(isa(X[1],AbstractArray) ? full(X[1]) : [X[1]], typeC, dimsC) range = 1 @@ -687,12 +721,15 @@ end vcat(X...) = cat(1, X...) hcat(X...) = cat(2, X...) +typed_vcat(T::Type, X...) = cat_t(1, T, X...) +typed_hcat(T::Type, X...) = cat_t(2, T, X...) + cat{T}(catdim::Integer, A::AbstractArray{T}...) = cat_t(catdim, T, A...) cat(catdim::Integer, A::AbstractArray...) = cat_t(catdim, promote_type(map(eltype, A)...), A...) -function cat_t(catdim::Integer, typeC, A::AbstractArray...) +function cat_t(catdim::Integer, typeC::Type, A::AbstractArray...) # ndims of all input arrays should be in [d-1, d] nargs = length(A) @@ -753,6 +790,9 @@ end vcat(A::AbstractArray...) = cat(1, A...) hcat(A::AbstractArray...) = cat(2, A...) +typed_vcat(T::Type, A::AbstractArray...) = cat_t(1, T, A...) +typed_hcat(T::Type, A::AbstractArray...) = cat_t(2, T, A...) + # 2d horizontal and vertical concatenation function hvcat{T}(rows::(Int...), as::AbstractMatrix{T}...) @@ -830,22 +870,20 @@ function hvcat_fill(a, xs) a end -function hvcat(rows::(Int...), xs::Number...) +function typed_hvcat(T::Type, rows::(Int...), xs...) nr = length(rows) nc = rows[1] - #error check for i = 2:nr if nc != rows[i] error("hvcat: row ", i, " has mismatched number of columns") end end - T = typeof(xs[1]) - for i=2:length(xs) - T = promote_type(T,typeof(xs[i])) - end hvcat_fill(Array(T, nr, nc), xs) end +hvcat(rows::(Int...), xs::Number...) = + typed_hvcat(promote_type(map(typeof, xs)...), rows, xs...) + ## Reductions and scans ## function isequal(A::AbstractArray, B::AbstractArray) diff --git a/base/array.jl b/base/array.jl index c8e60b3aad180..52168ac4ea2ff 100644 --- a/base/array.jl +++ b/base/array.jl @@ -170,7 +170,9 @@ function getindex{T<:Number}(::Type{T}, r::Ranges) copy!(Array(T,length(r)), r) end +if _oldstyle_array_vcat_ function getindex{T<:Number}(::Type{T}, r1::Ranges, rs::Ranges...) + warn_once("T[a:b,...] concatenation is deprecated; use T[a:b;...] instead") a = Array(T,length(r1)+sum(length,rs)) o = 1 copy!(a, r1, o) @@ -181,6 +183,7 @@ function getindex{T<:Number}(::Type{T}, r1::Ranges, rs::Ranges...) end return a end +end function fill!{T<:Union(Int8,Uint8)}(a::Array{T}, x::Integer) ccall(:memset, Ptr{Void}, (Ptr{Void}, Int32, Csize_t), a, x, length(a)) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index ff74e1cbb3c24..9951d5fde26d1 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -787,12 +787,14 @@ (loop (list 'typed_dict ex)) (loop (list 'ref ex))) (case (car al) + ((vect) + (if (length> al 2) + (loop (list* 'ref ex (cdr al))) + (loop (list* 'typed_vect_or_ref ex (cdr al))))) ((dict) (loop (list* 'typed_dict ex (cdr al)))) ((hcat) (loop (list* 'typed_hcat ex (cdr al)))) ((vcat) - (if (any (lambda (x) - (and (pair? x) (eq? (car x) 'row))) - (cdr al)) + (if (length> al 2) (loop (list* 'typed_vcat ex (cdr al))) (loop (list* 'ref ex (cdr al))))) ((comprehension) @@ -1223,21 +1225,20 @@ (error (string "missing comma or " closer " in argument list")))))))))) -; parse [] concatenation expressions and {} cell expressions -(define (parse-vcat s first closer) +(define (parse-vect s first closer) (let loop ((lst '()) (nxt first)) (let ((t (require-token s))) (if (eqv? t closer) (begin (take-token s) - (cons 'vcat (reverse (cons nxt lst)))) + (cons 'vect (reverse (cons nxt lst)))) (case t ((#\,) (take-token s) (if (eqv? (require-token s) closer) ;; allow ending with , (begin (take-token s) - (cons 'vcat (reverse (cons nxt lst)))) + (cons 'vect (reverse (cons nxt lst)))) (loop (cons nxt lst) (parse-eq* s)))) ((#\;) (error "unexpected semicolon in array expression")) @@ -1247,7 +1248,7 @@ (error "missing separator in array expression"))))))) (define (parse-dict s first closer) - (let ((v (parse-vcat s first closer))) + (let ((v (parse-vect s first closer))) (if (any dict-literal? (cdr v)) (if (every dict-literal? (cdr v)) `(dict ,@(cdr v)) @@ -1325,7 +1326,7 @@ (parse-dict s first closer))) (case (peek-token s) ((#\,) - (parse-vcat s first closer)) + (parse-vect s first closer)) ((for) (take-token s) (parse-comprehension s first closer)) @@ -1597,6 +1598,7 @@ (if (null? vex) '(cell1d) (case (car vex) + ((vect) `(cell1d ,@(cdr vex))) ((comprehension) `(typed_comprehension (top Any) ,@(cdr vex))) ((dict_comprehension) diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index ec3429dd97aec..338e91d8fddd3 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1477,7 +1477,13 @@ (pattern-lambda (: a b) `(call (top colon) ,a ,b)) - ;; hcat, vcat + ;; vect, hcat, vcat + (pattern-lambda (vect . a) + `(call (top vect) ,@a)) + + (pattern-lambda (typed_vect_or_ref t . a) + `(call (top typed_vect_or_ref) ,t ,@a)) + (pattern-lambda (hcat . a) `(call (top hcat) ,@a)) @@ -1497,38 +1503,22 @@ `(call (top vcat) ,@a))) (pattern-lambda (typed_hcat t . a) - (let ((result (gensy)) - (ncols (length a))) - `(block - (if (call (top !) (call (top isa) ,t Type)) - (call error "invalid array index")) - (= ,result (call (top Array) ,t 1 ,ncols)) - ,@(map (lambda (x i) `(call (top setindex!) ,result ,x ,i)) - a (cdr (iota (+ ncols 1)))) - ,result))) - - (pattern-lambda (typed_vcat t . rows) - (if (any (lambda (x) (not (and (pair? x) (eq? 'row (car x))))) rows) - (error "invalid array literal") - (let ((result (gensy)) - (nrows (length rows)) - (ncols (length (cdar rows)))) - (if (any (lambda (x) (not (= (length (cdr x)) ncols))) rows) - (error "invalid array literal") - `(block - (if (call (top !) (call (top isa) ,t Type)) - (call error "invalid array index")) - (= ,result (call (top Array) ,t ,nrows ,ncols)) - ,@(apply nconc - (map - (lambda (row i) - (map - (lambda (x j) `(call (top setindex!) ,result ,x ,i ,j)) - (cdr row) - (cdr (iota (+ ncols 1))))) - rows - (cdr (iota (+ nrows 1))))) - ,result))))) + `(call (top typed_hcat) ,t ,@a)) + + (pattern-lambda (typed_vcat t . a) + (if (any (lambda (x) + (and (pair? x) (eq? (car x) 'row))) + a) + ;; convert nested hcat inside vcat to hvcat + (let ((rows (map (lambda (x) + (if (and (pair? x) (eq? (car x) 'row)) + (cdr x) + (list x))) + a))) + `(call (top typed_hvcat) ,t + (tuple ,@(map length rows)) + ,@(apply nconc rows))) + `(call (top typed_vcat) ,t ,@a))) ;; transpose operator (pattern-lambda (|'| a) `(call ctranspose ,a)) diff --git a/test/arrayops.jl b/test/arrayops.jl index b5bf6ba41a7c6..8bbf1cb377c0a 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -184,6 +184,17 @@ Y = [1. 2. 3.; 4. 5. 6.] @test size(X) == size(Y) for i = 1:length(X) @test X[i] === Y[i] end +_array_equiv(a,b) = eltype(a) == eltype(b) && a == b +@test _array_equiv(Uint8[1:3;4], [0x1,0x2,0x3,0x4]) +if !Base._oldstyle_array_vcat_ + @test_throws Uint8[1:3,] + @test_throws Uint8[1:3,4:6] + a = Array(Range1{Int},1); a[1] = 1:3 + @test _array_equiv([1:3,], a) + a = Array(Range1{Int},2); a[1] = 1:3; a[2] = 4:6 + @test _array_equiv([1:3,4:6], a) +end + # "end" X = [ i+2j for i=1:5, j=1:5 ] @test X[end,end] == 15