Вход:  Пароль:  
Free Source | Каталог | Изменения | НовыеКомментарии | Пользователи | Регистрация |
Это старая версия AltLinux/Sisyphus/Alterator/internals/3 за 2005-07-20 12:26:14..

Третья часть рассказа. Наверное самая сложная, но если что-то будет неясно – ничего страшного, в следующих частях всё постепенно прояснится.

2.6 Несколько замечаний про функции

В прошлый раз было подробно рассказано как описываются функции. Несколько полезных замечаний:


1. У длинного определения
(define f (lambda (x y) ... ))
есть более короткая форма
(define (f x y) ... )
если процедура без аргументов, то определение в упрощённой форме будет выглядеть как:
(define (f) ... )


2. Процедура является таким же полноправным типом данных как и числа и строки, поэтому их можно как передавать в качестве аргумента, так и возвращать в качестве ответа.
Вот, например, как можно было бы определить функцию «модуль числа»:
(define (abs x) ((if (< x 0) – +) x))


3. Дополнение к предыдущему.
Если вас не смущает сведение выражения:

к:
(* (+ 1 2) 5)


то не должно смущать и сведение:

к:
(g (lambda (x) (+ x x)))


То есть когда вы передаёте функцию в качестве аргумента, то можно сначала сконструировать, дать ей имя и передать указывая имя, а можно и не давать имени, а сразу сконструировать и передать.

2.7 О символах


Из чего сделана переменная? Переменная — это некоторое «имя» и «связь» между этим именем и каким-то объектом, и прежде всего именно «связь» (связи может не быть, а имена есть всегда). То есть можно рассматривать по отдельности: отдельно имя, и отдельно некоторая таблица, которая ставит соответствие между именами и объектами, на которые они ссылаются.


(define a 4)


Это значит есть, имя a и оно ссылается на объект – число 4.


Когда интерпретатор видит выражение (define b a), он обнаруживает наличие имени a, а потом производит поиск в своей таблице имён, отмечает, что a ссылается на объект – число 4 и производит подстановку, после которой выражение приобретает вид (define b 4).


А что если мы хотим получить просто «имя»? Тогда мы говорим интерпретатору: пожалуйста, не надо размышлять над следующим выражением, дай мне его «как есть» – эта процедура носит имя quote.
(define b (quote a)) – назначит «имени» b, уже не не 4, а просто «имя» a.


«имена» являются одним из типов данных схемы и называются символами.
У длинного варианта записи:
(quote объект)
Существует сокращенный вариант записи:
'объект
То есть можно написать так:
(define b 'a)


Чтобы ещё лучше прочувствовать символы, запустим интерпретатор. Мы будем вводить выражения, а он будет писать, во что они проинтерпретировались:


Обратите внимание на то что переменной b нет (точнее связи нет), но «имя» b без связи с чем-либо замечательно интерпретируется.


Не сильно огорчайтесь, если чего-то сейчас не ясно, всё прояснится, когда мы чуть глубже поймём как работает интерпретатор.

2.8 Универсальный клей


Практически нет программ, которые работали бы с базовыми типами предоставляемыми языком (строки, числа, символы), каждый язык предоставляет возможность разработчику создавать свои, новые типы, составленные из других типов (из базовых или других составных).


Scheme предлагает только один способ сделать составной тип – объединение двух объектов в пару.
Делается это так:

Доступ к первому и второму элементу пар обеспечивают функции car и cdr:


Пары вполне достаточно чтобы создать такую известную структуру как односвязный список.
Для этого первый элемент пары будет ссылаться на содержимое элемента списка, а второй – на следующий элемент списка. Последний элемент списка должен ссылаться на «никого нет», мы для этого введём специальное имя ().


Вот например так создаётся список из двух элементов, содержащих 3 и 4:


В «развернутом виде» это выглядит так:
(define elem1 (cons 3 (cons 4 '())))


Если захотим сделать список из трёх елементов 1, 2 и 3, то надо написать:
(cons 1 (cons 2 (cons 3 '())))


Как видно конструкция очень громоздкая, поэтому есть более короткий вариант:
(list 1 2 3)


Поскольку список склеен из пар, то и работать с ним можно при помощи при помощи тех же car и cdr.
(define a (list 1 2 3))



Опять-таки для веера из car и cdr существует сокращенные варианты записи:


вместо (car (car .. – (caar ..
вместо (car (cdr .. – (cadr ..
вместо (car (cdr (cdr ... – (caddr ..
вместо (car (car (cdr ... – (caadr ..
вместо (car (cdr (cdr (cdr .. – (cadddr ..


Надеюсь что уловили закономерность? Впрочем пользоваться этим скорее всего не придётся. В нашем примере:

2.9 Снова про alterator


На конструкции языка можно смотреть как на последовательный вызов функций, а можно как на фразу на каком-то другом языке более высокого уровня
(vbox (button “aaa”) (button “bbb”))
Можно прочитать как «вызвать функцию которая вернёт вертикальную группу с двумя параметрами, результатами вызова функций одна из которых создаст кнопку с именем aaa, а другая – с именем bbb. А можно как «вертикальная группа из кнопкок aaa и bbb«.
На alterator можно смотреть как на сборище функций, а можно как на словарь. Когда вы решаете какую-нибудь задачу на alterator, вы просто формулируете проблему на некотором языке, а он её решает. Именно формулируете, а не программируете последовательный вызов функций.


Давайте сделаем последовательность из двух диалогов, один спросит наше имя, а второй напечатает приглашение.


Для того чтобы связать диалоги, надо присвоить им имена. В alterator каждый диалог имеет уникальный URL, и имеется таблица соответствий между этими URL и файлами которые содержат описания диалогов. Основной диалог, с которым происходит запуск приложения, всегда должен иметь имя /.


Пусть описание диалога с вопросом будет жить в файле q.scm, а описание диалога с приглашением w.scm, назовём первый, как требуется правилами, /, а второй — /welcome.


Описание будет выглядеть так:

Что на языке mapper записывается как:


Сохраним это в файле simple_map.scm


Теперь создадим описание диалога с приветствием: вертикальная группа в которую вставили:
– метку “My first alterator dialog”
– горизонтальная группа с меткой “Your name:» и полем редактирования по имени username, по умолчанию пустым.
– кнопка “OK”, при нажатии на которую происходит перeключение на URL /welcome и передаётся параметр по имени name со значением взятом из поля редактирования username.


Сначала разберём конструкции, с которыми ещё не сталкивались:

  1. Поле редактирования, по умолчанию пустое, описывается как: (edit "")
  2. Сказать, поле с именем username, это значит: (id 'username (edit ""))
  3. Сказать что взять содержимое из поля по имени username, это: (username text)
  4. Сказать, что «при нажатии перейти ...», это значит: (on-click (goto «/welcome» 'name (username text)))

Переключение диалога означает, что вы просто заменяете содержимое окна, то есть остаётесь на самом деле в том же самом диалоге, просто с другим содержимым.


Обратите внимание на использование символов, когда мы обрабатываем фразы, содержащие «имя». В конструкции с id мы имеем просто имя, когда уже забираем текст, у нас в наличие уже не просто имя, а имя связанное с конкретным виджетом, поэтому обращаться к нему можно уже без использования quote.
Соединим всё это теперь вместе:


И сохраним в файл q.scm


Аргументы, которые передавались диалогу доступны через функцию global.
Описание диалога приветствия:


Вертикальная группа из:


Вот содержимое файла w.scm:


Теперь произведём запуск одной компоненты, alterator которая собственно занимается диалогом с пользователем:
lookout -m simple_map.scm.


Всё – ваше первое приложение под alterator готово. Согласитесь, что за три лекции мы уже кое-чему научились.


Продолжение будет ...


 
Файлов нет. [Показать файлы/форму]
Комментариев нет. [Показать комментарии/форму]