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确实如此.
正如一些人指出的那样,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)正是这样做的。这就是他们工作的原因。
请记住哪些方法可用于或不可用于扩展,如果文档不够清晰,将欢迎错误报告(或者可能是修复)。
| 归档时间: |
|
| 查看次数: |
898 次 |
| 最近记录: |