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

Add Folds.foreach #29

Merged
merged 2 commits into from
Mar 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,24 @@ version = "0.2.2-DEV"
[deps]
Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
BangBang = "198e06fe-97b7-11e9-32a5-e1d131e6ad66"
Baselet = "9718e550-a3fa-408a-8086-8db961cd8217"
DefineSingletons = "244e2a9f-e319-4986-a169-4d1fe445cd52"
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
InitialValues = "22cec73e-a1b8-11e9-2c92-598750a2cf9c"
MicroCollections = "128add7d-3638-4c79-886c-908ea0c25c34"
Referenceables = "42d2dcc6-99eb-4e98-b66c-637b7d73030e"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Transducers = "28d57a85-8fef-5791-bfe6-a80928e7c999"

[compat]
Accessors = "0.1.1"
BangBang = "0.3.30"
Baselet = "0.1"
DefineSingletons = "0.1.1"
InitialValues = "0.2.10"
MicroCollections = "0.1.0"
Transducers = "0.4.35"
Referenceables = "0.1.2"
julia = "1.4"

[extras]
Expand Down
17 changes: 15 additions & 2 deletions docs/Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ version = "0.3.30"
[[Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[Baselet]]
git-tree-sha1 = "aebf55e6d7795e02ca500a689d326ac979aaf89e"
uuid = "9718e550-a3fa-408a-8086-8db961cd8217"
version = "0.1.1"

[[Compat]]
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
git-tree-sha1 = "919c7f3151e79ff196add81d7f4e45d91bbf420b"
Expand Down Expand Up @@ -82,10 +87,10 @@ uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
version = "0.26.1"

[[Folds]]
deps = ["Accessors", "BangBang", "DefineSingletons", "Distributed", "InitialValues", "MicroCollections", "Test", "Transducers"]
deps = ["Accessors", "BangBang", "Baselet", "DefineSingletons", "Distributed", "InitialValues", "MicroCollections", "Referenceables", "Test", "Transducers"]
path = ".."
uuid = "41a02a25-b8f0-4f67-bc48-60067656b558"
version = "0.2.0-DEV"
version = "0.2.2-DEV"

[[Future]]
deps = ["Random"]
Expand Down Expand Up @@ -172,6 +177,14 @@ uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
deps = ["Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[Referenceables]]
deps = ["Adapt"]
git-tree-sha1 = "e681d3bfa49cd46c3c161505caddf20f0e62aaa9"
repo-rev = "release"
repo-url = "https://github.com/tkf/Referenceables.jl.git"
uuid = "42d2dcc6-99eb-4e98-b66c-637b7d73030e"
version = "0.1.2"

[[Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "cfbac6c1ed70c002ec6361e7fd334f02820d6419"
Expand Down
5 changes: 4 additions & 1 deletion src/Folds.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import DefineSingletons

function reduce end
function mapreduce end
function foreach end
function collect end
function copy end
function map end
Expand Down Expand Up @@ -48,10 +49,12 @@ using BangBang:
union!!,
merge!!,
setdiff!!
using Baselet: Baselet
using MicroCollections: emptyshim, singletonshim
using Base: add_sum, mul_prod, mapreduce_empty
using DefineSingletons: @def_singleton
using InitialValues: InitialValue, asmonoid
using InitialValues: @def_monoid, InitialValue, asmonoid
using Referenceables: isreferenceable
using Transducers:
Consecutive,
DefaultInit,
Expand Down
33 changes: 33 additions & 0 deletions src/docs/foreach.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
Folds.foreach(f, collections...; [executor_options...])
Folds.foreach(f, collections..., executor)

Call `f` on the elements of `collections` in parallel.

This is equivalent to

```Julia
for x in zip(collections...)
f(x...)
end
```

except that `f` may be applied in parallel and in unspecified order.

[Referenceables.jl](https://github.com/tkf/Referenceables.jl) can be used to
update the elements in (a subset of) `collections`.

See [`Folds.reduce`](@ref) for more information.

# Examples

```julia
julia> using Folds, Referenceables

julia> xs = 1:2^20;

julia> ys = ones(length(xs));

julia> Folds.foreach(referenceable(ys), xs) do y, x
y[] = sin(y[] * x)
end
```
38 changes: 38 additions & 0 deletions src/reduce.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,44 @@ function Folds.mapreduce(f, op, itr, itrs...; init = InitialValue(op), kwargs...
return result
end

@def_monoid return_nothing
@inline return_nothing(_) = nothing
@inline return_nothing(_, _) = nothing

foreach_check_no_kwargs(::NamedTuple{(),Tuple{}}) = nothing
@noinline function foreach_check_no_kwargs(kwargs)
error(
"`foreach(f, itrs..., executor)` accepts no keyword arguments" *
"\ngot:" *
string(kwargs),
)
end

foreach_check_referenceables(_, _) = nothing
@noinline function foreach_check_referenceables(::DistributedEx, args)
error(
"`foreach(f, itrs..., ::DistributedEx)` is used with a referenceable. " *
"Currently, this is not supported as the mutation will not be reflected " *
"to the original collection."
)
end

function Folds.foreach(f, itr, itrs...; kwargs...)
args0, ex0 = de_snoc(itr, itrs...)
if ex0 isa Executor
xs = zip(args0...)
ex = ex0
foreach_check_no_kwargs((; kwargs...))
Baselet.Specialized.any(isreferenceable, args0) &&
foreach_check_referenceables(ex, args0)
else
xs = zip(itr, itrs...)
ex = parallel_executor(bottom_foldable(xs); kwargs...)
end
transduce(MapSplat(f), return_nothing, nothing, xs, ex)
return
end

"""
ReducerFunctionAndFoldable

Expand Down
1 change: 1 addition & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Folds = "41a02a25-b8f0-4f67-bc48-60067656b558"
InitialValues = "22cec73e-a1b8-11e9-2c92-598750a2cf9c"
LoadAllPackages = "b37bcd2d-1570-475d-a8c6-9b4fae6d0ba9"
PerformanceTestTools = "dc46b164-d16f-48ec-a853-60448fc869fe"
Referenceables = "42d2dcc6-99eb-4e98-b66c-637b7d73030e"
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Transducers = "28d57a85-8fef-5791-bfe6-a80928e7c999"
Expand Down
17 changes: 15 additions & 2 deletions test/environments/main/Manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ version = "0.3.30-DEV"
[[Base64]]
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"

[[Baselet]]
git-tree-sha1 = "aebf55e6d7795e02ca500a689d326ac979aaf89e"
uuid = "9718e550-a3fa-408a-8086-8db961cd8217"
version = "0.1.1"

[[CategoricalArrays]]
deps = ["DataAPI", "Future", "JSON", "Missings", "Printf", "Statistics", "StructTypes", "Unicode"]
git-tree-sha1 = "5861101791fa76fafe8dddefd70ffbfe4e33ecae"
Expand Down Expand Up @@ -113,10 +118,10 @@ uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
version = "0.24.11"

[[Folds]]
deps = ["Accessors", "BangBang", "DefineSingletons", "Distributed", "InitialValues", "MicroCollections", "Test", "Transducers"]
deps = ["Accessors", "BangBang", "Baselet", "DefineSingletons", "Distributed", "InitialValues", "MicroCollections", "Referenceables", "Test", "Transducers"]
path = "../../.."
uuid = "41a02a25-b8f0-4f67-bc48-60067656b558"
version = "0.2.0-DEV"
version = "0.2.2-DEV"

[[Formatting]]
deps = ["Printf"]
Expand Down Expand Up @@ -250,6 +255,14 @@ git-tree-sha1 = "7b1d07f411bc8ddb7977ec7f377b97b158514fe0"
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
version = "0.2.0"

[[Referenceables]]
deps = ["Adapt"]
git-tree-sha1 = "e681d3bfa49cd46c3c161505caddf20f0e62aaa9"
repo-rev = "release"
repo-url = "https://github.com/tkf/Referenceables.jl.git"
uuid = "42d2dcc6-99eb-4e98-b66c-637b7d73030e"
version = "0.1.2"

[[Requires]]
deps = ["UUIDs"]
git-tree-sha1 = "cfbac6c1ed70c002ec6361e7fd334f02820d6419"
Expand Down
1 change: 1 addition & 0 deletions test/environments/main/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Folds = "41a02a25-b8f0-4f67-bc48-60067656b558"
InitialValues = "22cec73e-a1b8-11e9-2c92-598750a2cf9c"
LoadAllPackages = "b37bcd2d-1570-475d-a8c6-9b4fae6d0ba9"
PerformanceTestTools = "dc46b164-d16f-48ec-a853-60448fc869fe"
Referenceables = "42d2dcc6-99eb-4e98-b66c-637b7d73030e"
StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Transducers = "28d57a85-8fef-5791-bfe6-a80928e7c999"
Expand Down
43 changes: 43 additions & 0 deletions test/test_foreach.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module TestForeach

using Folds
using Referenceables
using Test
using Transducers: PreferParallel
include("utils.jl")

raw_testdata_executors = """
PreferParallel()
SequentialEx()
ThreadedEx()
ThreadedEx(basesize = 1)
"""

testdata_executors = map(split(raw_testdata_executors, "\n", keepempty = false)) do x
x => Base.include_string((@__MODULE__), x)
end

@testset "increment" begin
@testset "default" begin
xs = zeros(3)
Folds.foreach(referenceable(xs)) do x
x[] += 1
end
@test xs == ones(3)
end
@testset "$label" for (label, ex) in testdata_executors
xs = zeros(3)
Folds.foreach(referenceable(xs), ex) do x
x[] += 1
end
@test xs == ones(3)
end
end

@testset "DistributedEx should throw" begin
xs = ones(3)
err = @test_error Folds.foreach(identity, referenceable(xs), DistributedEx())
@test "used with a referenceable" ∈ᵉʳʳᵒʳ err
end

end # module