【问题标题】:How does Julia interpret 10:1?Julia 如何解释 10:1?
【发布时间】:2017-09-26 00:54:54
【问题描述】:

我是一个长期关注 R 的外籍人士,其中 :(冒号)运算符创建从第一个参数到第二个参数的整数序列:

1:10
# [1]  1  2  3  4  5  6  7  8  9 10
10:1
# [1] 10  9  8  7  6  5  4  3  2  1

注意到这似乎在 Julia 中同样有效,我遇到了一个错误:

1:10 .== 10:1

DimensionMismatch("数组不能被广播到一个共同的大小")

因为:

10:1

输出

10:9

我很困惑这怎么会发生。不需要使用10:-1:1 似乎很自然——为什么Julia 认为10:910:1 的正确解释?

【问题讨论】:

    标签: julia sequences


    【解决方案1】:

    Julia 不是 R。还有其他语言对冒号语法的解释与 Julia 类似。 MATLAB 将 10:1 视为空数组,Python 的切片语法(虽然在其他方面有所不同)也将使用 10:1 的索引视为空选择。 Julia 选择对空整数范围进行归一化,使得 start 和 stop 之间的差异始终为 -1,因此它变为 10:9

    所以我认为10:1 没有明确的解释。然而,在我看来,对于 Julia 的解释,有一些非常有利的论据:

    • 空范围10:9用于表示some APIs中索引9和10之间的位置。

    • 范围是 Julia 中的核心构造,for x in 1:10 绝对且明确地必须与等效的 C 循环一样快。因为语法 x:y 总是递增一(并且永远不会负一),所以 Julia(和 LLVM)可以在编译 for 循环时利用该常量来实现进一步的优化。使这不是恒定的 --- 或更糟糕的是,根据端点的值在 UnitRangeStepRange 之间动态切换会阻碍这种优化或类型不稳定。

    • 就个人而言,我发现 R 的解释与 Julia 的解释一样令人惊讶。我认为需要明确表示您想要-1 的步骤在可读性和错误预防方面都是有利的。但我承认,我对先前语言的经验与您的一样有偏见。

    【讨论】:

    • 我会把优化原因放在首位——这是sine qua non。感谢您的洞察力;我有一个偷偷摸摸的怀疑,有一个优化超过鲁棒性的论点在起作用。
    • 我不认为这是优化与稳健性的对比,真的。它的优化和鲁棒性。来自 R,我非常喜欢 Julia 的行为。在 R 中,当您编写端点来自其他计算的复杂代码时,您经常会遇到错误,因为您没有明确处理起始值高于结束值的情况。在大多数情况下,您实际上需要一个空范围。
    • @MilanBouchet-Valat 很公平;我不能说我没有被 R 中的那种错误击中。
    【解决方案2】:

    在 Julia 中,我们假设 a:b 构造了一个步长为 1 的范围,所以 10:1 是一个 UnitRange,它应该是一个空范围。由于a:a-1也是一个空范围,它相当于a:b其中b<a, 请看源码here

    julia> dump(10:1)
    UnitRange{Int64}
      start: Int64 10
      stop: Int64 9
    
    julia> dump(10:-1:1)
    StepRange{Int64,Int64}
      start: Int64 10
      step: Int64 -1
      stop: Int64 1
    

    这里10:-1:1 是一个步长为-1 的StepRange,我认为它更准确、更自然地表示“10 比1”的概念。

    【讨论】:

    • 这种奇怪的行为有什么理由吗?我想是a:b 创建的对象属于某个需要a<b 的类?为什么不为10:1 输出一个StepRange
    • @MichaelChirico doc 清楚地说明了这种行为(a:ba:1:b)。更何况,在 Matlab、Julia、Python 和 R 中,只有 R 将 10:1 解释为 1:10
    • 作为 Julia 的新手,我不知道如何找到 : 的文档——在 R 中是否有类似 ?":" 的东西?另外,我发现文档具有误导性,因为a:b 不等于a:1:ba:b 创建一个 UnitRange 对象; a:1:b 创建一个 StepRange 对象。
    • @MichaelChirico 对不起,你是对的。文档中似乎只有一个 colon 函数。我通常使用apropos() 函数来搜索相关文档。 (例如 apropos(1:2) )
    • @MichaelChirico 然后apropos("a:b") 在 julia-v0.5 中工作,apropos(1:2) 在 v0.6 中工作。
    猜你喜欢
    • 2020-08-06
    • 1970-01-01
    • 1970-01-01
    • 2023-02-12
    • 2016-11-08
    • 2021-06-06
    • 1970-01-01
    • 2017-10-21
    • 1970-01-01
    相关资源
    最近更新 更多