在clojure里有几个流水线宏->,->>
,他们是为了避免出现过多中间变量而设计的,
例子:
(->> coll
(filter #(> % 1))
(map inc))
这两个宏默认的参数位置分别是函数的第一个位置和最后一个位置
为了简单起见,我写了一个thread-as宏,以后还得接着改良
# 替换表达式里的临时变量
function Base.replace(expr::Expr,prev::Symbol,into)
for index = 1:length(expr.args)
if expr.args[index] == prev
expr.args[index] = into
end
end
end
macro thread_as(expr,as,proccesses...)
val = eval(expr)
for proccess in proccesses
replace(proccess,as,val)
val = eval(proccess)
end
val
end
试一试
@thread_as([1 2 3 4],filter(x->x>1,_),map(x->x+1,_)) # -> [3 4 5]
# 也请各位小伙伴试一试看,我也不一定改
另外有些特殊符号不能用,比如$,我也不知道怎么回事
总结以下从这个宏的编写学到的东西:宏就是把表达式看作数据,并对其进行操作,使其生成新的表达式的过程
1 个赞
(我觉得这个叫“链式调用(chaining)”好一点,串行对应的是并行,有别的含义了。
有一些现有的包能做到这一点,不过我觉得标准库里的那些看起来的纯函数就应该支持返回函数。
julia> import Base: filter
julia> filter(f::Function)::Function = x -> filter(f, x)
filter (generic function with 9 methods)
julia> [1 2 3 4] |> filter(x -> x>1) |> x -> x.+1
3-element Array{Int64,1}:
3
4
5
函数链式调用的讨论 issue。这里面神仙打架
opened 02:16PM - 27 Jan 14 UTC
closed 07:26PM - 09 Apr 21 UTC
Would it be possible to allow calling any function on Any so that the value is p… assed to the function as the first parameter and the parameters passed to the function call on the value is added afterwards?
ex.
```
sum(a::Int, b::Int) -> a + b
a = 1
sum(1, 2) # = 3
a.sum(2) # = 3 or
1.sum(2) # = 3
```
Is it possible to indicate in a deterministic way what a function will return in order to avoid run time exceptions?
julia> Base.getindex(f::Function, x...) = (y...) -> f(x..., y...)
julia> [1 2 3 4] |> filter[x -> x>1] |> map[x -> x.+1]
3-element Array{Int64,1}:
3
4
5
—— @MikeInnes
部分现有的包
Lazy.jl
using Lazy
# isprime defined in terms of the prime numbers:
isprime(n) =
@>> primes begin
takewhile(x -> x<=sqrt(n))
map(x -> n % x == 0)
any; !
end
Pipe.jl
@pipe a |> b(x,_) # == b(x,a) #Not: (b(x,_))(a)
@pipe a |> b(_...) # == b(a...)
@pipe a |> b(_(1,2)) # == b(a(1,2))
@pipe a |> b(_[3]) # == b(a[3])
Hose.jl
@hose a |> b(x, _) # produces b(x, a)
@hose a |> _[b] # produces a[b]
@hose a |> @testmacro _ b # equivalent of @testmacro(a, b)
2 个赞
2020.4.12 改进
考虑到一些惰性操作,思路改为将表达式翻译完毕后再返回
macro thread_as(nums_expr,as,exprs...)
fn(from,as,to) = Expr(:call,replace(to.args,as=>from)...)
iter = function iter(exprs,res)
if length(exprs) == 1
fn(res,as,first(exprs))
else
iter(Iterators.drop(exprs,1),fn(res,as,first(exprs)))
end
end
iter(exprs,nums_expr)
end