Skip to content

Commit

Permalink
Merge pull request #16 from racinmat/master
Browse files Browse the repository at this point in the history
Added support for broadcasted piping .|>.
  • Loading branch information
oxinabox authored Jun 3, 2020
2 parents 6ba6d1c + a59c92a commit bc7f09e
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 22 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ julia:
- 1.0
- 1.2
- 1.3
- 1.4
- nightly
notifications:
email: false
Expand Down
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "Pipe"
uuid = "b98c9c47-44ae-5843-9183-064241ee97a0"
version = "1.2.0"
version = "1.3.0"

[compat]
julia = "1"
Expand Down
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Pipe


- Julia 0.7: [![Build Status 0.6](https://travis-matrix-badges.herokuapp.com/repos/oxinabox/Pipe.jl/branches/master/1)](https://travis-ci.org/oxinabox/Pipe.jl)
- Julia 1.0: [![Build Status 0.6](https://travis-matrix-badges.herokuapp.com/repos/oxinabox/Pipe.jl/branches/master/2)](https://travis-ci.org/oxinabox/Pipe.jl)
- Julia Nightly: [![Build Status Nightly](https://travis-matrix-badges.herokuapp.com/repos/oxinabox/Pipe.jl/branches/master/7)](https://travis-ci.org/oxinabox/Pipe.jl)
- Julia 1.0: [![Build Status 1.0](https://travis-matrix-badges.herokuapp.com/repos/oxinabox/Pipe.jl/branches/master/1)](https://travis-ci.org/oxinabox/Pipe.jl)
- Julia 1.2: [![Build Status 1.2](https://travis-matrix-badges.herokuapp.com/repos/oxinabox/Pipe.jl/branches/master/2)](https://travis-ci.org/oxinabox/Pipe.jl)
- Julia 1.3: [![Build Status 1.3](https://travis-matrix-badges.herokuapp.com/repos/oxinabox/Pipe.jl/branches/master/3)](https://travis-ci.org/oxinabox/Pipe.jl)
- Julia 1.4: [![Build Status 1.4](https://travis-matrix-badges.herokuapp.com/repos/oxinabox/Pipe.jl/branches/master/4)](https://travis-ci.org/oxinabox/Pipe.jl)
- Julia Nightly: [![Build Status Nightly](https://travis-matrix-badges.herokuapp.com/repos/oxinabox/Pipe.jl/branches/master/5)](https://travis-ci.org/oxinabox/Pipe.jl)

## Usage

Expand Down
69 changes: 52 additions & 17 deletions src/Pipe.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,62 @@ export @pipe

const PLACEHOLDER = :_

function rewrite(ff::Expr,target)
function replace(arg::Any)
arg #Normally do nothing
end
function replace(arg::Symbol)
if arg==PLACEHOLDER
target
else
arg
end
end
function replace(arg::Expr)
rep = copy(arg)
rep.args = map(replace,rep.args)
rep
function replace(arg::Any, target)
arg #Normally do nothing
end

function replace(arg::Symbol, target)
if arg==PLACEHOLDER
target
else
arg
end
end

rep_args = map(replace,ff.args)
function replace(arg::Expr, target)
rep = copy(arg)
rep.args = map(x->replace(x, target), rep.args)
rep
end

function rewrite(ff::Expr, target)
rep_args = map(x->replace(x, target), ff.args)
if ff.args != rep_args
#_ subsitution
ff.args=rep_args
ff.args = rep_args
return ff
end

#No subsitution was done (no _ found)
#Apply to a function that is being returned by ff,
#(ff could be a function call or something more complex)
rewrite_apply(ff,target)
end

function rewrite_broadcasted(ff::Expr, target)
temp_var = gensym()
rep_args = map(x->replace(x, temp_var), ff.args)
if ff.args != rep_args
#_ subsitution
ff.args = rep_args
return :($temp_var->$ff)
end

#No subsitution was done (no _ found)
#Apply to a function that is being returned by ff,
#(ff could be a function call or something more complex)
rewrite_apply_broadcasted(ff,target)
end

function rewrite_apply(ff, target)
:($ff($target)) #function application
end

function rewrite_apply_broadcasted(ff, target)
temp_var = gensym()
:($temp_var->$ff($temp_var))
end

function rewrite(ff::Symbol, target)
if ff==PLACEHOLDER
target
Expand All @@ -47,6 +69,14 @@ function rewrite(ff::Symbol, target)
end
end

function rewrite_broadcasted(ff::Symbol, target)
if ff==PLACEHOLDER
target
else
rewrite_apply_broadcasted(ff,target)
end
end

function funnel(ee::Any) #Could be a Symbol could be a literal
ee #first (left most) input
end
Expand All @@ -55,6 +85,11 @@ function funnel(ee::Expr)
if (ee.args[1]==:|>)
target = funnel(ee.args[2]) #Recurse
rewrite(ee.args[3],target)
elseif (ee.args[1]==:.|>)
target = funnel(ee.args[2]) #Recurse
rewritten = rewrite_broadcasted(ee.args[3],target)
ee.args[3] = rewritten
ee
else
#Not in a piping situtation
ee #make no change
Expand Down
22 changes: 22 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ using Test

_macroexpand(q) = macroexpand(Main, q)

rml! = Base.remove_linenums!
# performs linenum removal and temp variable replacing to avoid different names of temp variables in different julia versions
stringify_expr(e::Expr) = replace(string(rml!(e)), r"##\d{3}"=>"##000")
pipe_equals(e1::Expr, e2::Expr) = stringify_expr(_macroexpand(e1)) == stringify_expr(e2)

#No change to nonpipes functionality
@test _macroexpand( :(@pipe a) ) == :a #doesn't change single inputs
@test _macroexpand( :(@pipe b(a)) ) == :(b(a)) #doesn't change inputs that a function applications
Expand Down Expand Up @@ -47,3 +52,20 @@ end
@test _macroexpand( :(@pipe a|>b|>c(_) ) ) == :(c(b(a)))
@test _macroexpand( :(@pipe a|>b(x,_)|>c|>d(_,y) ) ) == :(d(c(b(x,a)),y))
@test _macroexpand( :(@pipe a|>b(xb,_)|>c|>d(_,xd)|>e(xe) |>f(xf,_,yf)|>_[i] ) ) == :(f(xf,(e(xe))(d(c(b(xb,a)),xd)),yf)[i]) #Very Complex

# broadcasting
vars = 1:10 .|> y->gensym() # Julia < 1.3 changes how Symbols are stringified so we compute the representation here
@test pipe_equals(:(@pipe 1:10 .|> _*2 ), :(1:10 .|> $(vars[1])->$(vars[1]) * 2))
@test pipe_equals(:(@pipe 1:10 .|> fn ), :(1:10 .|> $(vars[2])->fn($(vars[2]))))
@test pipe_equals(:(@pipe a .|> fn .|> _*2 ), :(a .|> ($(vars[3])->fn($(vars[3]))) .|> ($(vars[4])->$(vars[4])*2)))
@test pipe_equals(:(@pipe a .|> fn |> _*2 ), :((a .|> $(vars[5])->fn($(vars[5]))) * 2))
@test pipe_equals(:(@pipe [1,2,2] |> atan.([10,20,30], _) ), :(atan.([10,20,30], [1,2,2])))
@test pipe_equals(:(@pipe [1,2,2] .|> atan.([10,20,30], _) ), :([1,2,2] .|> $(vars[6])->atan.([10,20,30], $(vars[6]))))
@test pipe_equals(:(@pipe fn |> _.(1:2) ), :(fn.(1:2)))
@test pipe_equals(:(@pipe fn .|> _.(1:2) ), :(fn .|> $(vars[7])->$(vars[7]).(1:2)))

@test pipe_equals(:(@pipe [true,false] .|> ! ), :([true, false] .|> $(vars[8])->!$(vars[8])))
@test pipe_equals(:(@pipe [1, 2] |> .+(_, x) ), :([1, 2] .+ x))
@test pipe_equals(:(@pipe [1, 2] |> _ .+ x ), :([1, 2] .+ x))
@test pipe_equals(:(@pipe [1, 2] .|> .+(_, x) ), :([1, 2] .|> $(vars[9])->$(vars[9]).+x))
@test pipe_equals(:(@pipe [1, 2] .|> _ .+ x ), :([1, 2] .|> $(vars[10])->$(vars[10]).+x))

2 comments on commit bc7f09e

@oxinabox
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/15815

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.3.0 -m "<description of version>" bc7f09e838a1a2f347b8c02a2675f5cd275104d8
git push origin v1.3.0

Please sign in to comment.