在 Julia 中绑定函数参数
Bind function arguments in Julia
Julia 是否在 C++ 中提供了类似于 std::bind
的东西?我希望按照以下方式做一些事情:
function add(x, y)
return x + y
end
add45 = bind(add, 4, 5)
add2 = bind(add, _1, 2)
add3 = bind(add, 3, _2)
如果可行,是否会产生任何性能开销?
如回答,您可以在 Julia 中使用高阶函数获得此行为。
关于性能。应该没有开销。实际上,编译器应该在这种情况下内联所有内容,甚至执行常量传播(这样代码实际上可以更快)。在另一个答案 中使用 const
只是因为我们在全球范围内工作。如果所有这些都将在函数中使用,则不需要 const
(因为采用此参数的函数将被正确编译),因此在下面的示例中我不使用 const
.
让我用 Base.Fix1
和你的 add
函数举个例子:
julia> using BenchmarkTools
julia> function add(x, y)
return x + y
end
add (generic function with 1 method)
julia> add2 = Base.Fix1(add, 10)
(::Base.Fix1{typeof(add), Int64}) (generic function with 1 method)
julia> y = 1:10^6;
julia> @btime add.(10, $y);
1.187 ms (2 allocations: 7.63 MiB)
julia> @btime $add2.($y);
1.189 ms (2 allocations: 7.63 MiB)
请注意,我没有将 add2
定义为 const
,因为我们在全球范围内,我需要在它前面加上 $
以将其值插入基准测试套件。
如果我不这样做你会得到:
julia> @btime add2.($y);
1.187 ms (6 allocations: 7.63 MiB)
本质上是相同的时间和内存使用,但分配是 6 次而不是 2 次分配,因为在这种情况下 add2
是一个类型不稳定的全局变量。
我在 DataFrames.jl 工作,使用我们在这里讨论的模式非常有用。让我举一个例子:
julia> using DataFrames
julia> df = DataFrame(x = 1:5)
5×1 DataFrame
Row │ x
│ Int64
─────┼───────
1 │ 1
2 │ 2
3 │ 3
4 │ 4
5 │ 5
julia> filter(:x => <(2.5), df)
2×1 DataFrame
Row │ x
│ Int64
─────┼───────
1 │ 1
2 │ 2
该操作的作用是选取列 :x
中的值小于 2.5
的行。这里要理解的关键是 <(2.5)
的作用。它是:
julia> <(2.5)
(::Base.Fix2{typeof(<), Float64}) (generic function with 1 method)
所以你可以看到它类似于如果我们定义 x -> x < 2.5
函数(本质上固定 <
函数的第二个参数,如 Julia <
只是一个二元函数)。像上面的 <(2.5)
这样的快捷方式在 Julia 中默认为几个常见的比较运算符定义。
Julia 是否在 C++ 中提供了类似于 std::bind
的东西?我希望按照以下方式做一些事情:
function add(x, y)
return x + y
end
add45 = bind(add, 4, 5)
add2 = bind(add, _1, 2)
add3 = bind(add, 3, _2)
如果可行,是否会产生任何性能开销?
如回答
关于性能。应该没有开销。实际上,编译器应该在这种情况下内联所有内容,甚至执行常量传播(这样代码实际上可以更快)。在另一个答案 const
只是因为我们在全球范围内工作。如果所有这些都将在函数中使用,则不需要 const
(因为采用此参数的函数将被正确编译),因此在下面的示例中我不使用 const
.
让我用 Base.Fix1
和你的 add
函数举个例子:
julia> using BenchmarkTools
julia> function add(x, y)
return x + y
end
add (generic function with 1 method)
julia> add2 = Base.Fix1(add, 10)
(::Base.Fix1{typeof(add), Int64}) (generic function with 1 method)
julia> y = 1:10^6;
julia> @btime add.(10, $y);
1.187 ms (2 allocations: 7.63 MiB)
julia> @btime $add2.($y);
1.189 ms (2 allocations: 7.63 MiB)
请注意,我没有将 add2
定义为 const
,因为我们在全球范围内,我需要在它前面加上 $
以将其值插入基准测试套件。
如果我不这样做你会得到:
julia> @btime add2.($y);
1.187 ms (6 allocations: 7.63 MiB)
本质上是相同的时间和内存使用,但分配是 6 次而不是 2 次分配,因为在这种情况下 add2
是一个类型不稳定的全局变量。
我在 DataFrames.jl 工作,使用我们在这里讨论的模式非常有用。让我举一个例子:
julia> using DataFrames
julia> df = DataFrame(x = 1:5)
5×1 DataFrame
Row │ x
│ Int64
─────┼───────
1 │ 1
2 │ 2
3 │ 3
4 │ 4
5 │ 5
julia> filter(:x => <(2.5), df)
2×1 DataFrame
Row │ x
│ Int64
─────┼───────
1 │ 1
2 │ 2
该操作的作用是选取列 :x
中的值小于 2.5
的行。这里要理解的关键是 <(2.5)
的作用。它是:
julia> <(2.5)
(::Base.Fix2{typeof(<), Float64}) (generic function with 1 method)
所以你可以看到它类似于如果我们定义 x -> x < 2.5
函数(本质上固定 <
函数的第二个参数,如 Julia <
只是一个二元函数)。像上面的 <(2.5)
这样的快捷方式在 Julia 中默认为几个常见的比较运算符定义。