朱莉娅有延迟设置吗? (相当于 := 来自 Mathematica)

Is there delayed set in Julia? (equivalent of := from Mathematica)

我想在程序的不同部分多次调用类似 rand((0, 1), N) 的东西(之前分配了 N 一些整数)(我将来可能会更改所有出现的地方,因为例如,rand((-1, 1), N)randn(N))。我怎样才能创建一个变量,只要它被引用,就会计算这个函数?

我不想只写类似 rand_thing = rand((0, 1), N); 的东西,因为那样随机值每次都是相同的,这是不希望的。

当然我可以定义rand_func = rand((0, 1), N);,想写rand((0, 1), N)的时候调用rand_func()。我还可以做涉及 eval 的事情,比如 rand_ex = :(rand((0, 1), N));,然后在我想写 rand((0, 1), N) 时调用 eval(rand_ex)。但是,有没有一种方法可以获得此功能并且只写 rand_thing 来生成我的随机数?

这是一个具体的例子,它是一个更大问题的一部分,即是否有某些东西可以直接实现 Mathematica 的 SetDelayed (:=) 的功能。如果我在 Mathematica 中使用 rand_thing := RandomReal[]; 而不是 thing = RandomReal[];,那么每次我写 rand_thing 我都会得到一个新的随机数。 (在 Mathematica 中,我不会使用下划线作为变量名,但无论如何。)

如果我所描述的是不可能的,那么对为什么像 SetDelayed 这样的东西在 Mathematica 中是可能的而不是在 Julia 中的一些见解将不胜感激。这是语言的根本区别吗?或者这是不同约定的问题?或者也许 Julia 可以很容易地拥有一个延迟的集合运算符,但到目前为止它还不是语言语法的一部分? (如果是这样,实现会是什么样子?)还是其他?

(首先让我说一下,我对 Wolfram 语言的唯一了解就是它基于术语重写。)

a variable that, whenever it is referenced, evaluates this function

被称为...一个 函数 ,正如您正确观察到的那样。

rand_thing() = rand((0, 1), N)

不,除了返回该符号的值之外,没有其他方法可以对符号进行求值 rand_thing。如果你改变评估的工作方式,你只能拥有它。

现在,在 Mathematica 中,求值的方式确实有所不同。你基本上有一个重写系统。默认情况下,评估的工作方式类似——"if you see a name x, look up the value of it an replace x by that value, and continue evaluation"。

{} (x = 2; x) 
  ~> {x = 2} x   # update environment
  ~> {x = 2} 2   # replace x

(这是伪符号,我使用 {} 表示携带环境,~> 代表 "evaluates to"。)

但是如果 x 是由 SetDelayed 定义的,它更像是 "look up the definition of x, replace it by the definition, and continue evaluating":

{N = 42} (x := rand(N); x)
  ~> {N = 42, x = :(rand(N))} x                # update environment
  ~> {N = 42, x = :(rand(N))} rand(N)          # replace x
  ~> {N = 42, x = :(rand(N))} rand(42)         # replace N
  ~> {N = 42, x = :(rand(N))} [0.2342343, ...] # evaluate call

在 Julia 中更改求值的唯一方法是使用 macro。但这并不比函数调用短;你必须写类似

的东西
@undelay x .+ 1

扩展到

(rand(N)) .+ 1

但我看不出有任何有利的理由。另外,您还必须弄清楚哪些值是延迟的,哪些是正常值,这使事情变得复杂。

你可以编写像

这样的语法
@delayed let x = rand(N)
    x .+ 1
end

尽管如此,但您必须自己注意保持正确的范围行为,对此我不知道一个简单的解决方案。 (即使

@delayable begin
    x := rand(N)
    x .+ 1
end

可以作为宏,但更麻烦。 )


请注意,有一个叫做 thunk 的概念,它朝着您想要的方向发展——但它是一种数据结构,是对函数的语义抽象,并且不会使语法更简单。