Julia,多次使用 map to 运行 一个函数,

Julia, use of map to run a function multiple times,

我有一些代码 运行 没问题,可以做我想做的事,虽然可能有更简单更优雅的解决方案,但这个可行:

round(Int16, floor(rand(TruncatedNormal(150,20,50,250))))

然而,当我尝试多次执行它时,使用 map,它抛出一个错误,说它不喜欢 Int16 规范,所以这个:

map(round(Int16, floor(rand(TruncatedNormal(150,20,50,250)))), 1:2)

抛出这个错误

ERROR: MethodError: objects of type Int16 are not callable

我只想 运行 它两次(在本例中)并对结果求和。为什么不开心?谢谢。 J

map 的第一个参数是一个函数。因此,使用您的代码,Julia 正在尝试进行函数调用:

round(Int16, floor(rand(TruncatedNormal(150,20,50,250))))()

但是 round(Int16, ...) 的输出不是一个函数,它是一个数字,所以你不能调用它。这就是错误提示“Int16 类型的对象不可调用”的原因。您可以使用匿名函数解决此问题:

map(() -> round(Int16, floor(rand(TruncatedNormal(150,20,50,250)))), 1:2)

但是“Julian”的方法是使用理解:

[round(Int16, floor(rand(TruncatedNormal(150,20,50,250)))) for _ in 1:2]

编辑:

如果您要 sum 结果,那么您可以使用看起来像推导式但称为生成器表达式的东西。这基本上是上面的所有内容,表达式周围有 [ ]。生成器表达式可以直接用于 summean 等函数中

sum(round(Int16, floor(rand(TruncatedNormal(150,20,50,250)))) for _ in 1:2)

生成器表达式的优点是它们不会为整个数组分配内存。所以,如果你这样做 100 次并使用上面的 sum 方法,你就不需要为 100 个数字分配 space。


这超出了最初的问题,但 OP 想要使用 sum 表达式,其中 1:2 中的 2 是一个 1 元素向量。当然,如果输入始终是1元素向量,那么我推荐first(x) 和评论一样。但这是一个很好的机会来展示在 Julia 中将事物频繁分解为函数的重要性。例如,您可以使用整个 sum 表达式并定义一个函数

generatenumbers(n::Integer) = sum(... for _ in 1:n)

其中 n 是一个标量。然后,如果你有一些关于 n 的奇数数组表达式(1 元素向量,多维数组中的许多这样的 ns,等等),你可以这样做:

generatenumbers.(ns)
# will apply to each element and return same shape as ns

如果脱糖逻辑比逐元素应用更复杂,你甚至可以定义:

generatenumbers(ns::AbstractArray) = # ... something more complex

重点是定义一个“原子”函数,清楚地表达你想要的语句或任务,然后使用 dispatch 将它应用于实际代码中出现的更复杂的数据结构。这是 Julia 中常见的设计模式(不是唯一的选择,但却是有效的选择)。

添加来自@darsnack 的答案。 如果 您想多次 运行 它以保留结果(问题中不清楚)。然后你也可以要求 rand 通过执行以下操作来生成一个向量(并通过 floor 调用进行类型转换)。

移动自:

map(round(Int16, floor(rand(TruncatedNormal(150,20,50,250)))), 1:2)

至:

floor.(Int16, rand(TruncatedNormal(150,20,50,250), 2))

文档是 here