我正在创建一种可以编译成Swift、Rust和JavaScript(或者至少可以try )的语言.Rust和Swift都使用指针/引用/解引用等,而JavaScript则不使用.所以,用一种 rust 迹斑斑的语言,你可以这样做:
fn update(x) {
*x++
}
fn main() {
let i = 0
update(&i)
log(i) #=> 1
}
在一种类似JavaScript的语言中,如果您这样做,那么它将失败:
function update(x) {
x++
}
function main() {
let i = 0
update(i)
log(i) #=> 0
}
因为值是在传入时克隆的(我们显然知道).
所以我首先考虑的是这样做:
function update(scopeWithI) {
scopeWithI.i++
}
function main() {
let i = 0
let scopeWithI = { i }
update(scopeWithI)
i = scopeWithI.i
log(i) #=> 1
}
但这需要进行大量额外的处理,而且看起来有点不必要.相反,我可能会try 编译为以下内容:
function update(scopeWithI) {
scopeWithI.i++
}
function main() {
let scope = {}
scope.i = 0
update(scope)
log(scope.i) #=> 1
}
这意味着您创建的每个嵌套范围都必须开始手动创建/管理范围链.实际上,这是行不通的,因为update
是硬编码为i
的.所以你可能需要输入你想要的变量名.
function update(scope, ...names) {
scope[names[0]]++
}
但接下来就像是:
function update(scope, ...names) {
scope[names[0]]++
}
function main() {
let scope = {}
scope.i = 0
if random() > 0.5
let childScope = { scope }
childScope.x = 0
update(childScope, ['i'])
update(childScope, ['x'])
update(childScope, ['x'])
log(childScope.x) #=> 2
else
update(childScope, ['i'])
log(scope.i) #=> 1
}
所以这看起来可能会让我们得到somewhere美元.
那么就像,一般的解决方案是让Scope作为函数的第一个参数.
function add(scope, name1, name2) {
return scope[name1] + scope[name2]
}
取消引用意味着直接从作用域读取值,而传递引用(如Rust或C中的&name
)则意味着传递作用域和名称.
这样的东西行得通吗?或者更确切地说,需要改变或增加什么?还需要比这更复杂的事情吗?
我想try 并找到一种将面向指针的代码转换为JavaScript(转换)的方法,而不是首先try 找出看起来复杂得多的方法,即不那么直接,并通过重新定义许多方法来避免在JavaScript中进行指针模拟.似乎避免在JavaScript中使用任何指针要难得多,所以我正在try 看看是否有可能在JavaScript中模拟一个指针类型的系统.
为了避免指针模拟,必须重新定义方法.
update(x) {
*x++
}
必须在任何地方更改函数的外部用法.因此:
main() {
let i = 0
update(&i)
}
将变成:
main() {
let i = 0
i++ // inline the thing
}
对于这个简单的例子,它很好,但是对于一个更复杂的函数,它开始看起来像宏,并且可能会变得复杂.
因此,我们没有改变外部用法,而是让你必须通过范围.
另一种方法可能是让每个变量都是一个具有值的对象,因此更类似于:
update(x) {
x.value++
}
main() {
let i = { value: 0 }
update(i)
}
然后我在想,如何处理引用的引用?
update2(x) {
update(&x)
}
update(x) {
*x++
}
main() {
let i = 0
update2(&i)
}
在我描述的系统中,这类似于:
update2(x) {
// then what?
let y = { value: x }
update(y)
}
update(x) {
// like this?
x.value.value++
}
main() {
let i = { value: 0 }
update2(i)
}
所以看起来这不会真的奏效.