# This file is a part of Julia. License is MIT: http://julialang.org/license # tests related to functional programming functions and styles # map -- array.jl @test isequal(map((x)->"$x"[end:end], 9:11), ["9", "0", "1"]) # TODO: @test map!() much more thoroughly let a = [1.0, 2.0] map!(sin, a) @test isequal(a, sin([1.0, 2.0])) end # map -- ranges.jl @test isequal(map(i->sqrt(i), 1:5), [sqrt(i) for i in 1:5]) @test isequal(map(i->sqrt(i), 2:6), [sqrt(i) for i in 2:6]) # map on ranges should evaluate first value only once (#4453) let io=IOBuffer(3) map(x->print(io,x), 1:2) @test takebuf_string(io)=="12" end # map over Bottom[] should return Bottom[] # issue #6719 @test isequal(typeof(map(x -> x, Array{Union{}}(0))), Array{Union{},1}) # maps of tuples (formerly in test/core.jl) -- tuple.jl @test map((x,y)->x+y,(1,2,3),(4,5,6)) == (5,7,9) @test map((x,y)->x+y, (100001,100002,100003), (100004,100005,100006)) == (200005,200007,200009) # maps of strings (character arrays) -- string.jl @test map((c)->Char(c+1), "abcDEF") == "bcdEFG" # issue #10633 @test isa(map(Integer, Any[1, 2]), Vector{Int}) @test isa(map(Integer, Any[]), Vector{Integer}) # filter -- array.jl @test isequal(filter(x->(x>1), [0 1 2 3 2 1 0]), [2, 3, 2]) # TODO: @test_throws isequal(filter(x->x+1, [0 1 2 3 2 1 0]), [2, 3, 2]) @test isequal(filter(x->(x>10), [0 1 2 3 2 1 0]), []) @test isequal(filter((ss)->length(ss)==3, ["abcd", "efg", "hij", "klmn", "opq"]), ["efg", "hij", "opq"]) # numbers @test size(collect(1)) == size(1) # zip and filter iterators # issue #4718 @test collect(filter(x->x[1], zip([true, false, true, false],"abcd"))) == [(true,'a'),(true,'c')] let z = zip(1:2) @test collect(z) == [(1,), (2,)] # Issue #13979 @test eltype(z) == Tuple{Int} end let z = zip(1:2, 3:4) @test collect(z) == [(1,3), (2,4)] @test eltype(z) == Tuple{Int,Int} end let z = zip(1:2, 3:4, 5:6) @test collect(z) == [(1,3,5), (2,4,6)] @test eltype(z) == Tuple{Int,Int,Int} end @test eltype(Filter(isodd, 1:5)) == Int # typed `collect` @test collect(Float64, Filter(isodd, [1,2,3,4]))[1] === 1.0 @test isa(collect(Any, [1,2]), Vector{Any}) # enumerate (issue #6284) let b = IOBuffer("1\n2\n3\n"), a = [] for (i,x) in enumerate(eachline(b)) push!(a, (i,x)) end @test a == [(1,"1\n"),(2,"2\n"),(3,"3\n")] end # zip eachline (issue #7369) let zeb = IOBuffer("1\n2\n3\n4\n5\n"), letters = ['a', 'b', 'c', 'd', 'e'], res = [] for (number, letter) in zip(eachline(zeb), letters) push!(res, (parse(Int,strip(number)), letter)) end @test res == [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')] end @test length(zip(cycle(1:3), 1:7)) == 7 @test length(zip(cycle(1:3), 1:7, cycle(1:3))) == 7 @test length(zip(1:3,Base.product(1:7,cycle(1:3)))) == 3 @test length(zip(1:3,Base.product(1:7,cycle(1:3)),8)) == 1 # rest # ---- let s = "hello" _, st = next(s, start(s)) @test collect(rest(s, st)) == ['e','l','l','o'] end @test_throws MethodError collect(rest(countfrom(1), 5)) # countfrom # --------- let i = 0 for j = countfrom(0, 2) @test j == i*2 i += 1 i <= 10 || break end end # take # ---- let t = take(0:2:8, 10), i = 0 @test length(collect(t)) == 5 for j = t @test j == i*2 i += 1 end @test i == 5 end let i = 0 for j = take(0:2:100, 10) @test j == i*2 i += 1 end @test i == 10 end @test length(take(1:3,typemax(Int))) == 3 @test length(take(countfrom(1),3)) == 3 @test length(take(1:6,3)) == 3 # drop # ---- let i = 0 for j = drop(0:2:10, 2) @test j == (i+2)*2 i += 1 end @test i == 4 end @test length(drop(1:3,typemax(Int))) == 0 @test Base.iteratorsize(drop(countfrom(1),3)) == Base.IsInfinite() @test_throws MethodError length(drop(countfrom(1), 3)) # cycle # ----- let i = 0 for j = cycle(0:3) @test j == i % 4 i += 1 i <= 10 || break end end # repeated # -------- let i = 0 for j = repeated(1, 10) @test j == 1 i += 1 end @test i == 10 end let i = 0 for j = repeated(1) @test j == 1 i += 1 i <= 10 || break end end @test eltype(repeated(0)) == Int @test eltype(repeated(0, 5)) == Int @test Base.iteratorsize(repeated(0)) == Base.IsInfinite() @test Base.iteratorsize(repeated(0, 5)) == Base.HasLength() @test Base.iteratoreltype(repeated(0)) == Base.HasEltype() @test Base.iteratoreltype(repeated(0, 5)) == Base.HasEltype() @test Base.iteratorsize(zip(repeated(0), repeated(0))) == Base.IsInfinite() # product # ------- # empty? for itr in [Base.product(1:0), Base.product(1:2, 1:0), Base.product(1:0, 1:2), Base.product(1:0, 1:1, 1:2), Base.product(1:1, 1:0, 1:2), Base.product(1:1, 1:2 ,1:0)] @test isempty(itr) @test isempty(collect(itr)) end # collect a product - first iterators runs faster @test collect(Base.product(1:2)) == [(i,) for i=1:2] @test collect(Base.product(1:2, 3:4)) == [(i, j) for i=1:2, j=3:4] @test collect(Base.product(1:2, 3:4, 5:6)) == [(i, j, k) for i=1:2, j=3:4, k=5:6] # iteration order let expected = [(1,3,5), (2,3,5), (1,4,5), (2,4,5), (1,3,6), (2,3,6), (1,4,6), (2,4,6)] actual = Base.product(1:2, 3:4, 5:6) for (exp, act) in zip(expected, actual) @test exp == act end end # collect multidimensional array let a, b = 1:3, [4 6; 5 7] p = Base.product(a, b) @test size(p) == (3, 2, 2) @test length(p) == 12 @test ndims(p) == 3 @test eltype(p) == NTuple{2, Int} cp = collect(p) for i = 1:3 @test cp[i, :, :] == [(i, 4) (i, 6); (i, 5) (i, 7)] end end # with 1D inputs let a, b, c = 1:2, 1.0:10.0, Int32(1):Int32(0) # length @test length(Base.product(a)) == 2 @test length(Base.product(a, b)) == 20 @test length(Base.product(a, b, c)) == 0 # size @test size(Base.product(a)) == (2, ) @test size(Base.product(a, b)) == (2, 10) @test size(Base.product(a, b, c)) == (2, 10, 0) # eltype @test eltype(Base.product(a)) == Tuple{Int} @test eltype(Base.product(a, b)) == Tuple{Int, Float64} @test eltype(Base.product(a, b, c)) == Tuple{Int, Float64, Int32} # ndims @test ndims(Base.product(a)) == 1 @test ndims(Base.product(a, b)) == 2 @test ndims(Base.product(a, b, c)) == 3 end # with multidimensional inputs let a, b, c = randn(4, 4), randn(3, 3, 3), randn(2, 2, 2, 2) args = Any[(a,), (a, a), (a, b), (a, a, a), (a, b, c)] sizes = Any[(4, 4), (4, 4, 4, 4), (4, 4, 3, 3, 3), (4, 4, 4, 4, 4, 4), (4, 4, 3, 3, 3, 2, 2, 2, 2)] for (method, fun) in zip([size, ndims, length], [x->x, length, prod]) for i in 1:length(args) @test method(Base.product(args[i]...)) == method(collect(Base.product(args[i]...))) == fun(sizes[i]) end end end # more tests on product with iterators of various type let iters = (1:2, rand(2, 2, 2), take(1:4, 2), Base.product(1:2, 1:3), Base.product(rand(2, 2), rand(1, 1, 1)) ) for method in [size, length, ndims, eltype] for i = 1:length(iters) args = iters[i] @test method(Base.product(args...)) == method(collect(Base.product(args...))) for j = 1:length(iters) args = iters[i], iters[j] @test method(Base.product(args...)) == method(collect(Base.product(args...))) for k = 1:length(iters) args = iters[i], iters[j], iters[k] @test method(Base.product(args...)) == method(collect(Base.product(args...))) end end end end end # product of finite length and infinite length iterators let a = 1:2 b = countfrom(1) ab = Base.product(a, b) ba = Base.product(b, a) abexp = [(1, 1), (2, 1), (1, 2), (2, 2), (1, 3), (2, 3)] baexp = [(1, 1), (2, 1), (3, 1), (4, 1), (5, 1), (6, 1)] for (expected, actual) in zip([abexp, baexp], [ab, ba]) for (i, el) in enumerate(actual) @test el == expected[i] i == length(expected) && break end @test_throws ArgumentError length(actual) @test_throws ArgumentError size(actual) @test_throws ArgumentError ndims(actual) end # size infinite or unknown raises an error for itr in Any[countfrom(1), Filter(i->0, 1:10)] @test_throws ArgumentError length(Base.product(itr)) @test_throws ArgumentError size(Base.product(itr)) @test_throws ArgumentError ndims(Base.product(itr)) end end # iteratorsize trait business let f1 = Filter(i->i>0, 1:10) @test Base.iteratorsize(Base.product(f1)) == Base.SizeUnknown() @test Base.iteratorsize(Base.product(1:2, f1)) == Base.SizeUnknown() @test Base.iteratorsize(Base.product(f1, 1:2)) == Base.SizeUnknown() @test Base.iteratorsize(Base.product(f1, f1)) == Base.SizeUnknown() @test Base.iteratorsize(Base.product(f1, countfrom(1))) == Base.IsInfinite() @test Base.iteratorsize(Base.product(countfrom(1), f1)) == Base.IsInfinite() end @test Base.iteratorsize(Base.product(1:2, countfrom(1))) == Base.IsInfinite() @test Base.iteratorsize(Base.product(countfrom(2), countfrom(1))) == Base.IsInfinite() @test Base.iteratorsize(Base.product(countfrom(1), 1:2)) == Base.IsInfinite() @test Base.iteratorsize(Base.product(1:2)) == Base.HasShape() @test Base.iteratorsize(Base.product(1:2, 1:2)) == Base.HasShape() @test Base.iteratorsize(Base.product(take(1:2, 1), take(1:2, 1))) == Base.HasShape() @test Base.iteratorsize(Base.product(take(1:2, 2))) == Base.HasLength() @test Base.iteratorsize(Base.product([1 2; 3 4])) == Base.HasShape() # iteratoreltype trait business let f1 = Filter(i->i>0, 1:10) @test Base.iteratoreltype(Base.product(f1)) == Base.HasEltype() # FIXME? eltype(f1) is Any @test Base.iteratoreltype(Base.product(1:2, f1)) == Base.HasEltype() # FIXME? eltype(f1) is Any @test Base.iteratoreltype(Base.product(f1, 1:2)) == Base.HasEltype() # FIXME? eltype(f1) is Any @test Base.iteratoreltype(Base.product(f1, f1)) == Base.HasEltype() # FIXME? eltype(f1) is Any @test Base.iteratoreltype(Base.product(f1, countfrom(1))) == Base.HasEltype() # FIXME? eltype(f1) is Any @test Base.iteratoreltype(Base.product(countfrom(1), f1)) == Base.HasEltype() # FIXME? eltype(f1) is Any end @test Base.iteratoreltype(Base.product(1:2, countfrom(1))) == Base.HasEltype() @test Base.iteratoreltype(Base.product(countfrom(1), 1:2)) == Base.HasEltype() @test Base.iteratoreltype(Base.product(1:2)) == Base.HasEltype() @test Base.iteratoreltype(Base.product(1:2, 1:2)) == Base.HasEltype() @test Base.iteratoreltype(Base.product(take(1:2, 1), take(1:2, 1))) == Base.HasEltype() @test Base.iteratoreltype(Base.product(take(1:2, 2))) == Base.HasEltype() @test Base.iteratoreltype(Base.product([1 2; 3 4])) == Base.HasEltype() @test collect(Base.product(1:2,3:4)) == [(1,3) (1,4); (2,3) (2,4)] @test isempty(collect(Base.product(1:0,1:2))) @test length(Base.product(1:2,1:10,4:6)) == 60 @test Base.iteratorsize(Base.product(1:2, countfrom(1))) == Base.IsInfinite() # flatten # ------- import Base.flatten @test collect(flatten(Any[1:2, 4:5])) == Any[1,2,4,5] @test collect(flatten(Any[flatten(Any[1:2, 6:5]), flatten(Any[10:7, 10:9])])) == Any[1,2] @test collect(flatten(Any[flatten(Any[1:2, 4:5]), flatten(Any[6:7, 8:9])])) == Any[1,2,4,5,6,7,8,9] @test collect(flatten(Any[flatten(Any[1:2, 6:5]), flatten(Any[6:7, 8:9])])) == Any[1,2,6,7,8,9] @test collect(flatten(Any[2:1])) == Any[] @test eltype(flatten(UnitRange{Int8}[1:2, 3:4])) == Int8 @test_throws ArgumentError collect(flatten(Any[])) @test Base.iteratoreltype(Base.Flatten((i for i=1:2) for j=1:1)) == Base.EltypeUnknown() # foreach let a = [] foreach(()->push!(a,0)) @test a == [0] a = [] foreach(x->push!(a,x), [1,5,10]) @test a == [1,5,10] a = [] foreach((args...)->push!(a,args), [2,4,6], [10,20,30]) @test a == [(2,10),(4,20),(6,30)] end # generators (#4470, #14848) @test sum(i/2 for i=1:2) == 1.5 @test collect(2i for i=2:5) == [4,6,8,10] @test collect((i+10j for i=1:2,j=3:4)) == [31 41; 32 42] @test collect((i+10j for i=1:2,j=3:4,k=1:1)) == reshape([31 41; 32 42], (2,2,1)) let A = collect(Base.Generator(x->2x, Real[1.5,2.5])) @test A == [3,5] @test isa(A,Vector{Float64}) end let f(g) = (@test size(g.iter)==(2,3)) f(i+j for i=1:2, j=3:5) end @test collect(Base.Generator(+, [1,2], [10,20])) == [11,22] # generator ndims #16394 let gens_dims = [((i for i = 1:5), 1), ((i for i = 1:5, j = 1:5), 2), ((i for i = 1:5, j = 1:5, k = 1:5), 3), ((i for i = Array{Int}()), 0), ((i for i = Array{Int}(1)), 1), ((i for i = Array{Int}(1, 2)), 2), ((i for i = Array{Int}(1, 2, 3)), 3)] for (gen, dim) in gens_dims @test ndims(gen) == ndims(collect(gen)) == dim end end # generator with destructuring let d = Dict(:a=>1, :b=>2), a = Dict(3=>4, 5=>6) @test Dict( v=>(k,) for (k,v) in d) == Dict(2=>(:b,), 1=>(:a,)) @test Dict( (x,b)=>(c,y) for (x,c) in d, (b,y) in a ) == Dict((:a,5)=>(1,6),(:b,5)=>(2,6),(:a,3)=>(1,4),(:b,3)=>(2,4)) end let i = 1 local g = (i+j for i=2:2, j=3:3) @test first(g) == 5 @test i == 1 end # generators and guards let gen = (x for x in 1:10) @test gen.iter == 1:10 @test gen.f(first(1:10)) == next(gen, start(gen))[1] for (a,b) in zip(1:10,gen) @test a == b end end let gen = (x * y for x in 1:10, y in 1:10) @test collect(gen) == collect(1:10) .* collect(1:10)' @test first(gen) == 1 @test collect(gen)[1:10] == collect(1:10) end let gen = Base.Generator(+, 1:10, 1:10, 1:10) @test first(gen) == 3 @test collect(gen) == collect(3:3:30) end let gen = (x for x in 1:10 if x % 2 == 0), gen2 = Filter(x->x % 2 == 0, x for x in 1:10) @test collect(gen) == collect(gen2) @test collect(gen) == collect(2:2:10) end let gen = ((x,y) for x in 1:10, y in 1:10 if x % 2 == 0 && y % 2 == 0), gen2 = Filter(x->x[1] % 2 == 0 && x[2] % 2 == 0, (x,y) for x in 1:10, y in 1:10) @test collect(gen) == collect(gen2) end # generators with nested loops (#4867) @test [(i,j) for i=1:3 for j=1:i] == [(1,1), (2,1), (2,2), (3,1), (3,2), (3,3)] @test [(i,j) for i=1:3 for j=1:i if j>1] == [(2,2), (3,2), (3,3)] # partition(c, n) let v = collect(Base.partition([1,2,3,4,5], 1)) @test all(i->v[i][1] == i, v) end let v = collect(Base.partition([1,2,3,4,5], 2)) @test v[1] == [1,2] @test v[2] == [3,4] @test v[3] == [5] end let v = collect(Base.partition(enumerate([1,2,3,4,5]), 3)) @test v[1] == [(1,1),(2,2),(3,3)] @test v[2] == [(4,4),(5,5)] end for n in [5,6] @test collect(Base.partition([1,2,3,4,5], n))[1] == [1,2,3,4,5] @test collect(Base.partition(enumerate([1,2,3,4,5]), n))[1] == [(1,1),(2,2),(3,3),(4,4),(5,5)] end @test join(map(x->string(x...), Base.partition("Hello World!", 5)), "|") == "Hello| Worl|d!" let s = "Monkey 🙈🙊🙊" tf = (n)->join(map(x->string(x...), Base.partition(s,n)), "|") @test tf(10) == s @test tf(9) == "Monkey 🙈🙊|🙊" @test tf(8) == "Monkey 🙈|🙊🙊" @test tf(7) == "Monkey |🙈🙊🙊" @test tf(6) == "Monkey| 🙈🙊🙊" @test tf(5) == "Monke|y 🙈🙊🙊" @test tf(4) == "Monk|ey 🙈|🙊🙊" @test tf(3) == "Mon|key| 🙈🙊|🙊" @test tf(2) == "Mo|nk|ey| 🙈|🙊🙊" @test tf(1) == "M|o|n|k|e|y| |🙈|🙊|🙊" end