Reference AppleScript引用对象-帮助我理解它们

Reference AppleScript引用对象-帮助我理解它们,reference,applescript,pass-by-reference,appleevents,Reference,Applescript,Pass By Reference,Appleevents,为什么会存在这些呢?这似乎很荒谬。与大多数动态语言一样,AppleScript类型似乎要么是不可变的基本类型,如integers和reals,它们将按值传递,并且与引用一起使用没有任何意义,要么是对象类型,如applications、scripts,或记录s,它们已通过引用传递。对的引用怎么不是完全冗余的?下面是一个来自苹果的AppleScript语言指南的示例(如果您丢失了链接): 你的意思是说如果我这样做 tell app "Finder" to set diskObj to startup

为什么会存在这些呢?这似乎很荒谬。与大多数动态语言一样,AppleScript类型似乎要么是不可变的基本类型,如
integer
s和
real
s,它们将按值传递,并且与
引用
一起使用没有任何意义,要么是对象类型,如
application
s、
script
s,或
记录
s,它们已通过引用传递。
的引用怎么不是完全冗余的?下面是一个来自苹果的AppleScript语言指南的示例(如果您丢失了链接):

你的意思是说如果我这样做

tell app "Finder" to set diskObj to startup disk
--result: startup disk of application "Finder"
applescript运行时将向Finder进程发送一个apple事件,告诉它,“嘿,有人刚刚让你将/dev/disks01的八位字节流返回给我!哈哈!我想他应该要求
引用它!让我们开始吧!这需要一段时间!”

我正在用Python编程,我这样做:

m = fileHandle.read( 1000000000 ) #and then wait a little while
n = m 
我只是在内存中复制了一格数据吗?当然不是。但是AppleScript中存在对
的引用,这意味着将对象分配给新变量是一种按值操作。如果是这样的话,
copy
命令的作用是什么

这是怎么回事

更新:好吧,把我当成一个困惑的Python程序员。我还是想说清楚一点

tell app "Finder" to set diskRef to a ref to startup disk
--result: startup disk of application "Finder"

是一个糟糕的例子(摘自applescript语言指南)。但是@Chuck的
引用
属性本身的例子是一个更好的例子,该属性本身包含一个可以重新分配的基元类型。依我看,
引用
对象实际上是一个变量/属性,它包含指向另一个变量或属性的指针。

我的理解是,可以将引用视为指针

set x = 5
set y to reference to x
set contents of y to 10
log x -- 10
通常,您不会手动创建引用。AppleScript库和字典可能会返回它们,但是您可以使用返回项的属性(例如启动盘的名称)

老实说,我不理他们。在使用AppleScript的二十年中,我可能不得不查找一次参考文献。如果您试图在AppleScript中执行某些操作,并且认为需要创建一个引用变量,那么您可能没有以最直接的方式执行


查看有关AppleScript引用的更详细讨论。

AppleScript中的两个变量(如Python中的变量)可以共享相同的值。每个变量都有对其值的引用,但“reference”一词有其他含义。字符串
“https://stackoverflow.com/“
是对网站的引用;整数
42
是道格拉斯·亚当斯作品的参考;AppleScript中类
reference
的对象是另一种引用

reference
的对象推迟对某个对象的元素或属性的访问。它几乎像Python中的lambda,因为AppleScript

set v to {11, 22, 33}
set r to a reference to item 2 of v
就像蟒蛇一样

v = [11, 22, 33]
r = lambda: v[1]
通过延迟对列表第二项的访问。然后AppleScript中r的
内容或Python中的
r()
将获得该项。AppleScript还可以将项目设置为
将r的内容设置为99
;Python无法使用此lambda设置项。Python的lambdas可以完成AppleScript引用无法完成的许多事情

对操作员的引用
描述了对
运算符的引用,但遗漏了一些重要的细节。运算符有一个操作数;编译器还接受
引用操作数
引用操作数
,然后将它们重写为对操作数的引用

如果操作数是形式为
A of B
B的A
的表达式,则运算符将表达式包装在类
引用的对象中。此表达式可以是元素,如q的
项2
,也可以是属性,如q的
长度

如果操作数是变量,则运算符附加一个隐式的
my
of me
。例如,运行处理程序中对q的引用与对my q的引用相同。在
q
my q
不同的范围内,这会让人感到困惑

对于其他操作数,则运算符仅返回操作数。例如,
对3的引用返回3,它不是
引用
类的对象

运算符捕获变量的当前值。例如,
对q的i项的引用
捕获i和q的值。相比之下,
对q的引用不捕获q的值,因为它与对我的q的引用相同,因此它将q视为一个属性,而不是一个变量

to demo()
    set q to {11, 22, 33}
    set rq to a reference to q
    set i to 2
    set ri to a reference to item i of q
    set i to 3
    set item 2 of q to 55
    set q to {77, 88, 99}
    {contents of rq, contents of ri}
end demo

set q to "a string"
demo()
这个脚本的结果是{“一个字符串”,55}。参考rq忽略了本地q,并从运行处理程序中使用了
my q
。参考ri捕获了i和q的局部值,忽略了后来对i和q的赋值,但没有忽略对q第2项的赋值

使用带有大列表的引用 《AppleScript语言指南》还提供了一些示例,使用
a reference to
操作符来提高访问大列表的速度。指南使用

但未能解释该引用隐式地
引用了我的bigList
,因此访问是通过脚本对象
me
。它之所以有效,是因为代码在运行处理程序中,
bigList
mybiglist
是同一个列表

事实证明,如果引用通过任何脚本对象,访问大列表的速度都很快。其他访问速度较慢。下一个脚本通过使用快速访问创建一个包含7000个项目的列表来显示这一点,然后使用慢速和快速访问读取列表

to bench(what)
    set start to current date
    repeat with i from 1 to 7000
        if item i of what is not 42 then
            error "wrong value"
        end if
    end repeat
    (current date) - start
end bench

to bench2()
    script box
        property nums : {}
    end script
    repeat 7000 times
        set end of box's nums to 42
    end repeat
    {bench(box's nums), bench(a reference to box's nums)}
end bench2

bench2()
我在我的电脑上运行了这个脚本
set bigListRef to a reference to bigList
to bench(what)
    set start to current date
    repeat with i from 1 to 7000
        if item i of what is not 42 then
            error "wrong value"
        end if
    end repeat
    (current date) - start
end bench

to bench2()
    script box
        property nums : {}
    end script
    repeat 7000 times
        set end of box's nums to 42
    end repeat
    {bench(box's nums), bench(a reference to box's nums)}
end bench2

bench2()