我想叫这样的东西 rand((0, 1), N)
(有 N
之前分配的某个整数)在程序的不同部分多次出现(所有出现的次数,我可能在将来会改为,例如。rand((-1, 1), N)
或 randn(N)
). 我如何创建一个变量,每当它被引用时,就会评估这个函数?
我不想只写一些像 rand_thing = rand((0, 1), N);
因为这样的话,每次的随机值都是一样的,这不是我想要的。
当然,我可以定义 rand_func = rand((0, 1), N);
并称 rand_func()
每当我想写 rand((0, 1), N)
. 我也可以做的事情涉及 eval
喜欢 rand_ex = :(rand((0, 1), N));
然后叫 eval(rand_ex)
每当我想写 rand((0, 1), N)
. 然而,有没有一种方法可以让我得到这个功能,并且只编写 rand_thing
来生成我的随机数?
这是一个具体的例子,它是一个更大的问题的一部分,即是否有一些东西直接实现了 SetDelayed
(:=
)。如果我做了 rand_thing := RandomReal[];
而不是 thing = RandomReal[];
在Mathematica中,每次我写下了 rand_thing
我得到一个新的随机数。(在Mathematica中,我不会用下划线来表示变量名,但不管怎样)。
如果我所描述的是不可能的,那么就请您深入了解一下为什么类似于 SetDelayed
在Mathematica中可以实现,但在Julia中却不可以。这是语言上的根本区别吗?还是习惯不同的问题?或者Julia可以很容易地拥有一个延迟集运算符,但到目前为止它还不是语言语法的一部分?(如果是这样,实现起来会是什么样的?)或者是其他什么?
(首先我要说的是,我对Wolfram语言的唯一了解是,它是基于术语重写的。)
一个变量,每当它被引用的时候,就会评估这个函数。
被称为......一个 函数,正如你所观察到的那样。
rand_thing() = rand((0, 1), N)
而且,没有办法对一个符号进行评价。rand_thing
,除了返回该符号的值之外,还可以有其他行为。 只有改变评估的工作方式,您才能得到这种结果。
现在,在 Mathematica 中,评估的工作方式确实不同。 在Mathematica中,您基本上有一个重写系统。 默认情况下,评估的工作方式与此类似 -- "如果您看到一个名字为 x
,查找它的价值,并替换 x
的值,并继续评估"。
{} (x = 2; x)
~> {x = 2} x # update environment
~> {x = 2} 2 # replace x
(这是个伪注解,我在这里用的是 {}
携带的环境和 ~>
代表 "评估到")。)
但如果 x
被定义为 SetDelayed
,它更像是 "查一查 "的定义。x
,用定义代替它,然后继续评估"。
{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中改变评价的唯一方法是使用一个叫做 宏观. 但这并不比函数调用短,你必须写一些类似于
@undelay x .+ 1
扩大到
(rand(N)) .+ 1
但我看不出有什么理由这样做会有好处。 另外,你还得分清哪些是延迟值,哪些是正常值,这让事情变得复杂起来。
你可以用这样的语法
@delayed let x = rand(N)
x .+ 1
end
虽然,但你必须自己注意保留正确的范围行为,对此我不知道一个简单的解决方案。 (甚至
@delayable begin
x := rand(N)
x .+ 1
end
是可以作为宏的,但更麻烦。)
注意,有一个概念叫 咚这是你想要的方向 -- 但它是一个数据结构,是对函数的语义抽象,并没有让语法变得更简单。