Last active
May 4, 2020 12:21
-
-
Save aviatesk/e855b3168231b744f11ac43f25a7eb34 to your computer and use it in GitHub Desktop.
`@collect` and `@generator` macro -- might be useful in competitive programming, etc...
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using MacroTools | |
function decompose_forblk(forblk) | |
spec, body = forblk.args | |
i, itr = spec.args | |
return i, itr, body | |
end | |
""" | |
@collect ex | |
Converts the outermost `for` block in `ex` into the corresponding list comprehension expressions. | |
## Example | |
```julia | |
julia> function cumsum′(itr::AbstractVector{T}) where {T<:Number} | |
s::T = zero(T) | |
return @collect for i in itr | |
s += i | |
end | |
end | |
cumsum′ (generic function with 1 method) | |
julia> @assert cumsum(1:1000) == cumsum′(1:1000) | |
``` | |
""" | |
macro collect(ex) | |
done = false | |
return MacroTools.prewalk(ex) do x | |
(done || !Meta.isexpr(x, :for)) && return x | |
done = true | |
i, itr, body = decompose_forblk(x) | |
return :([$(body) for $(i) in $(itr)]) | |
end |> esc | |
end | |
""" | |
@generator ex | |
Converts the outermost `for` block in `ex` into the corresponding generator expressions. | |
## Example | |
```julia | |
julia> @generator for i in 1:10; i; end .|> print; | |
12345678910 | |
``` | |
""" | |
macro generator(ex) | |
done = false | |
return MacroTools.postwalk(ex) do x | |
(done || !Meta.isexpr(x, :for)) && return x | |
done = true | |
i, itr, body = decompose_forblk(x) | |
return :(($(body) for $(i) in $(itr))) | |
end |> esc | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment