AppleScript 参考对象 - 帮助我理解它们

发布于 2024-11-03 19:14:27 字数 1504 浏览 4 评论 0原文

为什么这些甚至存在?这似乎很荒谬。与大多数动态语言一样,AppleScript 类型似乎是不可变的原始类型,例如整数和实数,它们将按值传递,并且不会产生任何影响。与引用或类似对象类型(例如应用程序脚本记录)一起使用的意义s,它们已经通过引用传递。 的引用为何不完全多余?以下是摘自 Apple 的 AppleScript 语言指南 ( https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html):

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

所以你的意思是告诉我,如果我这样做,

tell app "Finder" to set diskObj to startup disk
--result: startup disk of application "Finder"

applescript运行时将向 Finder 进程发送一个苹果事件,告诉它,“嘿 - 有人刚刚要求你将 /dev/disks01 的八位字节流返回给我!哈哈!我想他应该要求 参考 让我们开始吧!”

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

m = fileHandle.read( 1000000000 ) #and then wait a little while
n = m 

我是否刚刚在内存中复制了一大堆数据?当然不是。但 AppleScript 中引用的存在意味着将对象分配给新变量是一种按值操作。如果是这样的话,复制命令是怎么回事?

这是怎么回事?

更新:好吧,就当我是一个困惑的 Python 程序员吧。为了让这一点更清楚,我仍然认为

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

这是一个糟糕的例子(取自 applescript 语言指南)。但 @Chuck 的对属性本身的引用的示例持有一个可以重新分配的原始类型,这是一个更好的例子。 IOW,引用对象实际上是一个变量/属性,它保存指向另一个变量或属性的指针。

Why do these even exist? It seems absurd. Like with most dynamic languages, AppleScript types seem to be either immutable primitive types like integers and reals which are going to be handed around by value and don't make any sense to use with a reference to, or object-like types like applications, scripts, or records, which are being passed around by reference already. How is a reference to not completely redundant? Here's an example taken from Apple's AppleScript Language Guide (https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/introduction/ASLR_intro.html):

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

So do you mean to tell me that if I did this instead,

tell app "Finder" to set diskObj to startup disk
--result: startup disk of application "Finder"

that the applescript runtime is going to send an apple event sent across to the Finder process telling it, "hey - some guy just asked you to return an octet stream of /dev/disks01 back to me! Haha! I guess he should have asked for a reference to it! Let's get started! This is going to take a while!"

I'm programming in Python and I do this:

m = fileHandle.read( 1000000000 ) #and then wait a little while
n = m 

Did I just copy a gig of data around in memory? Of course not. But the existence of a reference to in AppleScript implies that assigning objects to new variables is a by-value operation. And if that's the case, what's the deal with the copy command?

What's going on here?

UPDATE: Well, just consider me a confused Python programmer. Just to make this a bit more clear, I still think

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

is a poor example (taken from the applescript language guide). But @Chuck's example of a reference to the property itself holding a primitive type that can then be reassigned is a better one. IOW, a reference object is really a variable/property that holds a pointer to another variable or property.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷…雨湿花 2024-11-10 19:14:28

AppleScript 中的两个变量(与 Python 中一样)可以共享相同的值。每个变量都有对其值的引用,但“引用”一词还有其他含义。字符串 "https://stackoverflow.com/" 是对网站的引用;整数 42 引用了 Douglas Adams 的作品; AppleScript 中 reference 类的对象是一种不同类型的引用。

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

set v to {11, 22, 33}
set r to a reference to item 2 of v

行为与 Python 类似

v = [11, 22, 33]
r = lambda: v[1]

,推迟对列表第二项的访问。然后 AppleScript 中的 r 内容或 Python 中的 r() 内容将获取该项目。 AppleScript 还可以通过将 r 的内容设置为 99 来设置该项目; Python 无法使用此 lambda 设置项目。 Python 的 lambda 表达式可以做许多 AppleScript 引用无法做的事情。

运算符的引用

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

如果操作数是 A of BB's A 形式的表达式,则运算符将表达式包装在 reference 类的对象中。该表达式可以是一个元素,例如 q 的第 2 项,也可以是一个属性,例如 q 的长度

如果操作数是变量,则运算符附加隐式myof me。例如,运行处理程序中对 q 的引用对 my q 的引用相同。在 qmy 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()

该脚本的结果是 {"a string", 55}。引用 rq 忽略本地 q 并使用运行处理程序中的 my q 。引用 ri 捕获了 i 和 q 的局部值,忽略了后来对 i 和 q 的赋值,但没有忽略对 q 的第 2 项的赋值。

对大列表使用引用

AppleScript 语言指南还提供了使用引用运算符来提高访问大列表速度的示例。 指南使用

set bigListRef to a reference to bigList

但未能解释该引用隐式对我的bigList的引用,因此访问是通过脚本对象me进行的。它之所以有效,是因为代码位于运行处理程序中,其中 bigListmy bigList 是相同的列表。

事实证明,如果引用经过任何脚本对象,则对大列表的访问会很快。其他访问速度很慢。下一个脚本通过使用快速访问创建包含 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()

我在运行 PowerPC Mac OS X 10.4.11 的旧机器上运行了这个脚本。结果是{19, 0},所以慢速访问用了19秒,快速访问用了0秒。

set end of box's nums to 42 行无需使用引用运算符即可进行快速访问。它速度很快,因为访问是通过脚本对象 box 进行的。

Two variables in AppleScript, like in Python, can share the same value. Each variable has a reference to its value, but the word "reference" has other meanings. The string "https://stackoverflow.com/" is a reference to a web site; the integer 42 is a reference to the works of Douglas Adams; and an object of class reference in AppleScript is a different kind of reference.

An object of class reference postpones access to an element or property of some object. It's almost like a lambda in Python, because the AppleScript

set v to {11, 22, 33}
set r to a reference to item 2 of v

acts like the Python

v = [11, 22, 33]
r = lambda: v[1]

by postponing access to the 2nd item of a list. Then contents of r in AppleScript or r() in Python would get the item. AppleScript can also set the item with set contents of r to 99; Python can't set the item with this lambda. Python's lambdas can do many things that AppleScript's references can't do.

a reference to operator

The AppleScript Language Guide describes the a reference to operator but misses some important details. The operator has one operand; the compiler also accepts reference OPERAND or ref OPERAND, then rewrites them as a reference to OPERAND.

If the operand is an expression of the form A of B or B's A, then the operator wraps the expression in an object of class reference. This expression can be an element, like item 2 of q, or a property, like length of q.

If the operand is a variable, then the operator attaches an implicit my or of me. For example, a reference to q in the run handler is the same as a reference to my q. This becomes confusing in scopes where q and my q are different.

For other operands, then the operator only returns the operand. For example, a reference to 3 returns 3, which is not an object of class of reference.

The operator captures the current value of variables. For example, a reference to item i of q captures the values of i and q. For contrast, a reference to q doesn't capture the value of q, because it is the same as a reference to my q, so it sees q as a property, not a variable.

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()

The result of this script is {"a string", 55}. Reference rq ignored the local q and used my q from the run handler. Reference ri captured the local values of i and q, ignored later assignments to i and q, but didn't ignore the assignment to item 2 of q.

Using references with big lists

The AppleScript Language Guide also has examples using the a reference to operator to increase the speed of accesses to a big list. The Guide uses

set bigListRef to a reference to bigList

but fails to explain that the reference is implicitly a reference to my bigList, so the access is through the script object me. It only works because the code is in the run handler, where bigList and my bigList are the same list.

It turns out that accesses to a big list are fast if the reference goes through any script object. Other accesses are slow. The next script shows this by creating a list of 7000 items using fast accesses, and then reading the list using both slow and fast accesses.

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()

I ran this script on my old machine running PowerPC Mac OS X 10.4.11. The result was {19, 0}, so the slow accesses took 19 seconds, and the fast accesses took 0 seconds.

The line set end of box's nums to 42 does a fast access without using the a reference to operator. It is fast because the access goes through box, a script object.

心清如水 2024-11-10 19:14:28

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

set x = 5
set y to reference to x
set contents of y to 10
log x -- 10

通常,您不会手动创建引用。 AppleScript 库和字典可能会返回它们,但随后您将使用返回项的属性(例如启动磁盘的名称)。

老实说,我会忽略他们。在使用 AppleScript 的二十年中,我可能不得不查找一次文档以获取参考资料。如果您尝试在 AppleScript 中执行某些操作并认为需要创建引用变量,那么您可能不会以最直接的方式执行此操作。

请查看这篇 MacTech 文章了解更多详细信息AppleScript 参考文献的讨论。

My understanding is that you can think of references as pointers.

set x = 5
set y to reference to x
set contents of y to 10
log x -- 10

In general, you don't manually create references. AppleScript libraries and dictionaries may return them, but then you work with the properties of the returned item (name of startup disk for example).

Honestly, I'd ignore them. In twenty years of working with AppleScript, I've probably had to look up the documentation to references once. If you're trying to do something in AppleScript and believe you need to create a reference variable, you're probably not doing it in the most straightforward manner.

Check out this MacTech article for a more detailed discussion of AppleScript references.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文