Julia 是否有一个函数可以让我控制变量arg的数量?

Julia 是否有一个函数可以让我控制变量arg的数量?,julia,Julia,我有以下代码: circ(x) = x./sqrt(sum(x .* x)) x -> cat(circ(x), circ(x); dims = 1) 但是我希望能够创建一个函数,在这里我输入一个数字,然后它连接这个数字的circ(x) 例如: function Ncircs(n) #some way to make cat() have as its parameter circ n number of times end 我可以打电话给Ncircs(2),然后 x->cat(

我有以下代码:

circ(x) = x./sqrt(sum(x .* x))

x -> cat(circ(x), circ(x); dims = 1)
但是我希望能够创建一个函数,在这里我输入一个数字,然后它连接这个数字的circ(x)

例如:

function Ncircs(n)
  #some way to make cat() have as its parameter circ n number of times
end
我可以打电话给Ncircs(2),然后
x->cat(循环(x),循环(x);dims=1)
Ncircs(3)
并获取
x->cat(循环(x)、循环(x)、循环(x);dims=1)
Ncircs(4)
并获取
x->cat(circ(x)、circ(x)、circ(x)、circ(x);dims=1)

等等

有没有办法做到这一点?我必须使用宏吗?

您可以编写:

Ncircs(n) = x -> cat(Iterators.repeated(circ(x), n)...; dims = 1)
如果您知道您将始终执行
dims=1
,则使用
vcat
reduce

Ncircs(n) = x -> reduce(vcat, Iterators.repeated(circ(x), n))
对于大型
n
,效率更高

作为旁注:使用另一个选项(
vcat
)将产生类型稳定的结果,而第一个选项不是类型稳定的

编辑

为什么不允许对空集合进行缩减? 一般来说,原因是你无法判断减少的结果。如果要允许空集合,则应添加
init
关键字参数。以下是一个例子:

julia> reduce(vcat, [])
ERROR: ArgumentError: reducing over an empty collection is not allowed

julia> reduce(vcat, [], init = [1])
1-element Array{Int64,1}:
 1

julia> reduce(vcat, [[2,3], [4,5]], init = [1])
5-element Array{Int64,1}:
 1
 2
 3
 4
 5
结果是类型稳定的是什么意思 这意味着Julia能够在编译时(在执行代码之前)判断函数返回值的类型。类型稳定的代码通常运行得更快(不过这是一个广泛的主题-我建议您阅读Julia手册以详细了解它)。您可以使用
@code\u warntype
测试来检查函数的类型是否稳定。@extensated

在这里,让我对您的具体案例进行解释(我截断了一些输出以缩短答案)

上面的任何表示编译器不知道答案的类型。原因是在这种情况下,此类型取决于
dims
参数。如果它是
1
它将是一个向量,如果它是
2
它将是一个矩阵

我如何知道它对于大型
n
您可以运行
@哪个
宏:

julia> @which reduce(vcat, [[1,2,3], [4,5,6]])
reduce(::typeof(vcat), A::AbstractArray{#s72,1} where #s72<:(Union{AbstractArray{T,2}, AbstractArray{T,1}} where T)) in Base at abstractarray.jl:1321
一个编辑器将打开,您会看到它调用了一个内部函数
\u-typed\u-vcat
,该函数针对
vcat
进行了优化,使用了大量数组。之所以引入此优化,是因为使用类似于
vcat([[1,2,3],[4,5,6]])
的splatting在结果上是等效的,但您必须进行splatting(即
),这本身就有一些成本,可以使用
reduce
版本避免

为了确保我所说的是真实的,您可以执行以下基准测试:

julia> using BenchmarkTools

julia> y = [[i] for i in 1:10000];

julia> @benchmark vcat($y...)
BenchmarkTools.Trial:
  memory estimate:  156.45 KiB
  allocs estimate:  3
  --------------
  minimum time:     67.200 μs (0.00% GC)
  median time:      77.800 μs (0.00% GC)
  mean time:        102.804 μs (8.50% GC)
  maximum time:     35.179 ms (99.47% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark reduce(vcat, $y)
BenchmarkTools.Trial:
  memory estimate:  78.20 KiB
  allocs estimate:  2
  --------------
  minimum time:     67.700 μs (0.00% GC)
  median time:      69.700 μs (0.00% GC)
  mean time:        82.442 μs (6.39% GC)
  maximum time:     32.719 ms (99.58% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark cat($y..., dims=1)
ERROR: StackOverflowError:

您可以看到
reduce
版本的速度略快于
vcat
的splatting版本,而
cat
对于非常大的
n
(对于较小的
n
,它可以工作,但速度要慢一些)。

谢谢!这是一个了不起的反应!我想知道你是否介意回答几个问题,这样我就可以了解:你怎么知道对大n使用你的建议会更有效?另外,对于类型稳定的结果意味着什么?另外,我想选择性地将n设置为零,但不允许在空集合上减少。我将如何解决这个问题?此外,我回顾了上下文,并意识到如果这有帮助的话,我永远不会真正需要一个非常大的n。我将在答案中添加额外的注释。
@edit reduce(vcat, [[1,2,3], [4,5,6]])
julia> using BenchmarkTools

julia> y = [[i] for i in 1:10000];

julia> @benchmark vcat($y...)
BenchmarkTools.Trial:
  memory estimate:  156.45 KiB
  allocs estimate:  3
  --------------
  minimum time:     67.200 μs (0.00% GC)
  median time:      77.800 μs (0.00% GC)
  mean time:        102.804 μs (8.50% GC)
  maximum time:     35.179 ms (99.47% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark reduce(vcat, $y)
BenchmarkTools.Trial:
  memory estimate:  78.20 KiB
  allocs estimate:  2
  --------------
  minimum time:     67.700 μs (0.00% GC)
  median time:      69.700 μs (0.00% GC)
  mean time:        82.442 μs (6.39% GC)
  maximum time:     32.719 ms (99.58% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark cat($y..., dims=1)
ERROR: StackOverflowError: