From c784d897ae9ab137128cf35311ebb2432d520e86 Mon Sep 17 00:00:00 2001 From: Mike Nolta Date: Tue, 7 Jan 2014 21:55:53 -0500 Subject: [PATCH] deprecate concatenating [a,b,...] and T[a,b,...] closes #2488, closes #3737 --- base/abstractarray.jl | 63 +++++++++++++++++++++++++++++++++++++------ base/array.jl | 4 +++ src/julia-parser.scm | 26 ++++++++---------- src/julia-syntax.scm | 56 +++++++++++++------------------------- test/arrayops.jl | 12 +++++++++ 5 files changed, 101 insertions(+), 60 deletions(-) diff --git a/base/abstractarray.jl b/base/abstractarray.jl index 4972221da154f..0279605a74467 100644 --- a/base/abstractarray.jl +++ b/base/abstractarray.jl @@ -6,6 +6,45 @@ typealias AbstractVecOrMat{T} Union(AbstractVector{T}, AbstractMatrix{T}) ## Basic functions ## +vect() = Array(None, 0) +vect{T}(X::T...) = T[ X[i] for i=1:length(X) ] + +const _oldstyle_array_vcat_ = true + +if _oldstyle_array_vcat_ + function oldstyle_vcat_warning(n::Int) + if n == 1 + before = "a" + after = "a;" + elseif n == 2 + before = "a,b" + after = "a;b" + else + before = "a,b,..." + after = "a;b;..." + end + warn_once("[$before] concatenation is deprecated; use [$after] instead") + end + function vect(A::AbstractArray...) + oldstyle_vcat_warning(length(A)) + vcat(A...) + end + function vect(X...) + for a in X + if typeof(a) <: AbstractArray + oldstyle_vcat_warning(length(X)) + break + end + end + vcat(X...) + end +else + function vect(X...) + T = promote_type(map(typeof, X)...) + T[ X[i] for i=1:length(X) ] + end +end + size{T,n}(t::AbstractArray{T,n}, d) = (d>n ? 1 : size(t)[d]) eltype(x) = Any eltype{T,n}(::AbstractArray{T,n}) = T @@ -791,6 +830,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) @@ -834,7 +878,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 @@ -850,12 +893,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) @@ -916,6 +962,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(nbc::Integer, as...) @@ -1003,22 +1052,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("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 87720d6f80f82..3dd396d455832 100644 --- a/base/array.jl +++ b/base/array.jl @@ -157,12 +157,15 @@ end getindex(T::(Type...)) = Array(T,0) +if _oldstyle_array_vcat_ # T[a:b] and T[a:s:b] also contruct typed ranges function getindex{T<:Number}(::Type{T}, r::Ranges) + warn_once("T[a:b] concatenation is deprecated; use T[a:b;] instead") copy!(Array(T,length(r)), r) end 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, o, r1) @@ -173,6 +176,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 10c14e03aa121..873ecb544bcb4 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -845,14 +845,10 @@ (loop (list 'typed_dict ex)) (loop (list 'ref ex))) (case (car al) + ((vect) (loop (list* '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)) - (loop (list* 'typed_vcat ex (cdr al))) - (loop (list* 'ref ex (cdr al))))) + ((vcat) (loop (list* 'typed_vcat ex (cdr al)))) ((comprehension) (loop (list* 'typed_comprehension ex (cdr al)))) ((dict_comprehension) @@ -1289,21 +1285,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")) @@ -1313,7 +1308,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)) @@ -1349,7 +1344,7 @@ (if (pair? outer) (fix 'vcat (update-outer vec outer)) (if (or (null? vec) (null? (cdr vec))) - (fix 'vcat vec) ; [x] => (vcat x) + (fix 'vect vec) ; [x] => (vect x) (fix 'hcat vec)))) ; [x y] => (hcat x y) (case t ((#\; #\newline) @@ -1390,8 +1385,8 @@ (else (parse-dict s first closer))) (case (peek-token s) - ((#\,) - (parse-vcat s first closer)) + ((#\, closer) + (parse-vect s first closer)) ((for) (take-token s) (parse-comprehension s first closer)) @@ -1663,6 +1658,7 @@ (if (null? vex) '(cell1d) (case (car vex) + ((vect) `(cell1d ,@(cdr vex))) ((comprehension) `(typed_comprehension (top Any) ,@(cdr vex))) ((dict_comprehension) @@ -1698,7 +1694,7 @@ ((eqv? t #\[ ) (take-token s) (let ((vex (parse-cat s #\]))) - (if (null? vex) '(vcat) vex))) + (if (null? vex) '(vect) vex))) ;; string literal ((eqv? t #\") diff --git a/src/julia-syntax.scm b/src/julia-syntax.scm index 73c97a9f76294..75cd990231701 100644 --- a/src/julia-syntax.scm +++ b/src/julia-syntax.scm @@ -1796,6 +1796,9 @@ (error "invalid \":\" outside indexing")) `(call colon ,.(map expand-forms (cdr e)))) + 'vect + (lambda (e) (expand-forms `(call (top vect) ,@(cdr e)))) + 'hcat (lambda (e) `(call hcat ,.(map expand-forms (cdr e)))) @@ -1818,47 +1821,26 @@ `(call vcat ,@a))))) 'typed_hcat - (lambda (e) - (let ((t (cadr e)) - (a (cddr e))) - (let ((result (gensy)) - (ncols (length a))) - `(block - #;(if (call (top !) (call (top isa) ,t Type)) - (call (top error) "invalid array index")) - (= ,result (call (top Array) ,(expand-forms t) 1 ,ncols)) - ,.(map (lambda (x i) `(call (top setindex!) ,result - ,(expand-forms x) ,i)) - a (cdr (iota (+ ncols 1)))) - ,result)))) + (lambda (e) `(call (top typed_hcat) ,(expand-forms (cadr e)) ,.(map expand-forms (cddr e)))) 'typed_vcat (lambda (e) (let ((t (cadr e)) - (rows (cddr e))) - (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 (top error) "invalid array index")) - (= ,result (call (top Array) ,(expand-forms t) ,nrows ,ncols)) - ,.(apply nconc - (map - (lambda (row i) - (map - (lambda (x j) - `(call (top setindex!) ,result - ,(expand-forms x) ,i ,j)) - (cdr row) - (cdr (iota (+ ncols 1))))) - rows - (cdr (iota (+ nrows 1))))) - ,result)))))) + (a (cddr e))) + (expand-forms + (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))))) '|'| (lambda (e) `(call ctranspose ,(expand-forms (cadr e)))) '|.'| (lambda (e) `(call transpose ,(expand-forms (cadr e)))) diff --git a/test/arrayops.jl b/test/arrayops.jl index e4b2e043fb3ed..b16df37ae1aae 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -236,6 +236,18 @@ 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,] + @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