我能编写一个像"c ++模板函数"一样"尽可能"工作的Julia方法吗?

Ben*_*ohn 7 polymorphism julia

rand 适用于范围:

rand(1:10)
Run Code Online (Sandbox Code Playgroud)

我想要rand使用Array,以及任何可索引的东西,并具有length:

import Base.Random
rand(thing) = thing[rand(1:length(thing))]

array = {1, 2, 3}
myRand(array)

range = 1:8
myRand(range)

tupple = (1, 2, 3, "a", "b", "c")
myRand(tupple)
Run Code Online (Sandbox Code Playgroud)

...但是,如果我尝试这个,我的实现堆栈溢出,大概是因为它是完全通用的并且匹配所有传递的东西,所以它最终调用自己?

有没有办法来解决这个问题?我想更好地理解Julia的多态函数,而不是修复这个特殊的(可能是愚蠢的)函数特化.

是否还有一个工具来发现可用的各种实现,以及将使用特定参数调用的调试?


好的,有些挖掘.这是有趣的…

我将启动一个新的REPL,并且:

julia> import Base.Random

julia> rand(thing) = thing[rand(1:length(thing))]
rand (generic function with 1 method)

julia> rand({1,2,3})
ERROR: stack overflow
 in rand at none:1 (repeats 80000 times)
Run Code Online (Sandbox Code Playgroud)

...哦亲爱的,那是我正在谈论的递归调用和堆栈溢出.

但是,看这个.我杀了Julia并再次启动REPL.这次我import Base.Random.rand:

julia> import Base.Random.rand

julia> rand(thing) = thing[rand(1:length(thing))]
rand (generic function with 33 methods)

julia> rand({1,2,3})
3
Run Code Online (Sandbox Code Playgroud)

它有效 - 它将我的新实现添加到所有其他实现,并选择了正确的实现.

所以,我的第一个问题的答案似乎是 - "它只是有效".哪个太棒了 这是如何运作的?!

但是关于模块的问题听起来有点不那么有趣,为什么import Base.Random不引入rand方法或给出错误,但import Base.Random.rand确实如此.

prc*_*tro 4

方法扩展

正如一些人指出的那样,Julia 允许您扩展函数:您可以拥有针对不同类型以不同方式工作的函数(请参阅文档的这一部分)。

例如:

f(x) = 2
f(x::Int) = x
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我们有一个函数的版本(或方法),当(且仅当)参数的类型为 时,才会调用该函数Int。第一个被称为其他。

我们说我们扩展了这个f功能,现在它有2个方法。

你的问题

那么,您想要的是扩展该rand功能。

您希望您的rand函数在使用其他方法未捕获的参数调用时执行thing[rand(1:length(thing))]。如果操作正确,您将调用rand应用于Range对象的方法,因为您是1:length(thing)作为参数传递的。

虽然有缺陷(如果thing没有长度怎么办,例如复数?),但我想说你的第一次尝试是非常合理的。

问题rand无法在程序的第一个版本上进行扩展。根据这篇文档,编写import Base.Random并不能rand用于方法扩展。

在尝试扩展 时rand,您实际上覆盖了rand函数。之后,当你调用该函数时rand,就只有你的方法了!

请记住,您所依赖的事实是范围方法(例如rand(1:10))是在其他地方定义的,并且它给出了您期望的结果。发生的情况是这个方法被你的方法覆盖了,所以你的方法被再次调用(递归地)。

解决方案:导入rand可用于扩展的内容。您可以在文档的表格中看到这一点。

请注意,您的第二个程序(带有 的程序import Base.Random.rand)和 Colin 的程序(带有 的程序importall Base.Random)正是这样做的。这就是他们工作的原因。

请记住哪些方法可用于或不可用于扩展,如果文档不够清晰,将欢迎错误报告(或者可能是修复)。