Эталонные объекты AppleScript — помогите мне понять их

Почему они вообще существуют? Это кажется абсурдным. Как и в большинстве динамических языков, типы AppleScript кажутся либо неизменяемыми примитивными типами, такими как integers и reals, которые будут передаваться по значению и не имеют никакого смысла для использования с a reference to, либо объектными типами, такими как applications, scripts, или records, которые уже передаются по ссылке. Как a reference to не является полностью избыточным? Вот пример, взятый из Руководства Apple по языку AppleScript (http://developer.apple.com/library/mac/#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 отправит событие apple, отправленное процессу Finder, сообщая ему: «Эй, какой-то парень только что попросил вас вернуть мне поток октетов /dev/disks01! Ха-ха! Я думаю, он должен был спросить за a reference to это! Давайте начнем! Это займет некоторое время!"

Я программирую на Python, и я делаю это:

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

Я только что скопировал гиг данных в память? Конечно, нет. Но существование a reference to в AppleScript подразумевает, что присваивание объектов новым переменным является операцией по значению. И если это так, что делать с командой copy?

Что тут происходит?

ОБНОВЛЕНИЕ: Ну, просто считайте меня запутавшимся программистом на Python. Просто чтобы сделать это немного более ясным, я все еще думаю,

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

плохой пример (взято из руководства по языку applescript). Но пример @Chuck a reference to самого свойства, содержащего примитивный тип, который затем можно переназначить, является лучшим. IOW, объект reference на самом деле является переменной/свойством, которое содержит указатель на другую переменную или свойство.


person Ted Middleton    schedule 28.04.2011    source источник


Ответы (2)


Насколько я понимаю, вы можете думать о ссылках как об указателях.

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

Как правило, вы не создаете ссылки вручную. Библиотеки и словари AppleScript могут возвращать их, но тогда вы работаете со свойствами возвращаемого элемента (например, name of startup disk).

Честно говоря, я бы их игнорил. За двадцать лет работы с AppleScript мне, наверное, один раз приходилось искать ссылки в документации. Если вы пытаетесь сделать что-то в AppleScript и считаете, что вам нужно создать ссылочную переменную, вы, вероятно, делаете это не самым простым способом.

Прочтите эту статью о MacTech, чтобы обсуждение ссылок AppleScript.

person Chuck    schedule 28.04.2011
comment
Забавно, что я так привык к объектной модели в стиле python с неизменяемыми примитивными типами и чистыми, почти невидимыми ссылочными переменными, что не мог этого увидеть. Что расстраивает, так это то, что большинство примеров в руководстве по языку Applescript (например, пример с загрузочным диском) на самом деле не очень полезны для демонстрации этого. Что действительно необходимо, так это примеры, подобные тому, что вы дали, - присвоение эталонной цели. Вот где странность переназначения объектов на месте в AppleScript становится ясной. Спасибо @Чак! - person Ted Middleton; 29.04.2011

Две переменные в AppleScript, как и в Python, могут иметь одно и то же значение. Каждая переменная имеет ссылку на свое значение, но слово «ссылка» имеет и другие значения. Строка "https://stackoverflow.com/" является ссылкой на веб-сайт; целое число 42 является ссылкой на работы Дугласа Адамса; а объект класса reference в AppleScript — это ссылка другого типа.

Объект класса reference откладывает доступ к элементу или свойству некоторого объекта. Это почти как лямбда в Python, потому что 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]

путем отсрочки доступа ко 2-му элементу списка. Тогда contents of r в AppleScript или r() в Python получит элемент. AppleScript также может установить элемент с помощью set contents of r to 99; Python не может установить элемент с помощью этой лямбды. Лямбда-выражения Python могут делать многие вещи, которые не могут делать ссылки AppleScript.

a reference to оператор

Руководство по языку AppleScript описывает оператор a reference to, но упускает некоторые важные детали. Оператор имеет один операнд; компилятор также принимает reference OPERAND или ref OPERAND, а затем переписывает их как a reference to OPERAND.

Если операнд является выражением формы A of B или B's A, то оператор заключает выражение в объект класса reference. Это выражение может быть элементом, например item 2 of q, или свойством, например length of q.

Если операнд является переменной, то оператор присоединяет неявный my или of me. Например, a reference to q в обработчике запуска совпадает с a reference to my q. Это становится запутанным в областях, где q и my q различны.

Для других операндов оператор возвращает только операнд. Например, a reference to 3 возвращает 3, что не является объектом класса reference.

Оператор захватывает текущее значение переменных. Например, a reference to item i of q фиксирует значения i и q. Напротив, a reference to q не захватывает значение q, потому что оно такое же, как a reference to my 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, но не игнорировала присвоение элементу 2 q.

Использование ссылок с большими списками

В Руководстве по языку AppleScript также есть примеры использования оператора a reference to для увеличения скорости доступа к большому списку. Руководство использует

set bigListRef to a reference to bigList

но не объясняет, что ссылка неявно a reference to my bigList, поэтому доступ осуществляется через объект скрипта me. Это работает только потому, что код находится в обработчике выполнения, где bigList и my 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 выполняет быстрый доступ без использования оператора a reference to. Это быстро, потому что доступ идет через box, объект скрипта.

person George Koehler    schedule 23.10.2017