понедельник, 23 ноября 2009 г.

My favorite Google Wave Gadgets & Robots

Gadgets:
Robots:

Изменяем редактор по умолчанию в Ubuntu Linux

1-й способ (только для ubuntu):
sudo update-alternatives --config editor
затем выбрать одну из предоставленных альтернатив

2-й способ:
добавить в ~/.bashrc строчку "EDITOR=вашлюбимыйреактор && export EDITOR" - это годится не только для ubuntu

пятница, 14 августа 2009 г.

22 вещи, которые вы не знали о своих покупателях

http://habrahabr.ru/blogs/eCommerce/67056/
Вы не знаете кое-чего о ваших потребителях. Дело не в вас, а в них. Но вам необходимо узнать это. Вот некоторые тяжелые уроки, которые я выучил за много лет — они относятся к юзабилити, любимым мозолям и другим забавным штукам. Выучите эти уроки и получите больше довольных потребителей, посетителей, читателей и поклонников:

1. Читать с экрана тяжело всем.

Главный принцип юзабилити: людям тяжело читать в онлайне. Намного сложнее, чем читать печатный текст. Помните это. Напишите это у себя на лбу. Мелкий шрифт, странный макет страницы и ненормальные цветовые схемы могут выглядеть здорово, но они отрицательно повлияют на ваш бизнес в долгосрочной перспективе.

2. Они любят короткие абзацы.

Старейшее правило маркетинга, пришедшее с тех пор, когда мы печатали на бумаге и пользовались почтой и прочими штуками: пишите абзацы не длиннее 4-5 строк. Прочитайте книгу My Life in Advertising and Scientific Advertising (Advertising Age Classics Library) чтобы узнать, как мало изменилось в правилах игры с тех времен.

3. Они любят короткие строки

Читать с экрана тяжело. Обычный человек в лучшем случае может прочесть 10-20 слов на строке. Не больше. Если вы используете микроскопические шрифты, чтобы втиснуть мрножество слов на строку, исправьтесь.

4. Они любят большие междустрочные интервалы и и поля

Большие междустрочные интервалы улучшают читаемость текста. Поля укорачивают строки, и на строке остается меньше слов (см.выше).

Люди действительно читают быстрее, если междустрочное расстояние очень мало, но они хуже понимают и меньше запоминают. Отличное исследование университета Уичито доказывает это.

5. Они любят темный текст на светлом фоне

Мы приучены читать темный текст на светлом фоне. Мы привыкли к этому. так что это:

Съешь ещё этих мягких французских булок, да выпей яду

читается лучше, чем



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

Вы ненавидите свою аудиторию? Нет? Тогда используйте темный текст на светлом фоне.

6. Они не против вертикальной прокрутки

С удобными колесиками прокрутки, люди перестали расстраиваться из-за прокрутки — это больше не проблема юзабилити, если, конечно, вы не размещаете текст на 5000 слов. Не обязательно впихивать домашнюю страницу, или любую другую страницу вашего сайта, в одно окно. Длинные страницы — ето ОК!

7. Списки облегчают им жизнь

Вы можете написать текст в одну строку, и цвета будут выглядеть как красный, зеленый, синий.

Или, вы можете оформить список списком, чтобы цвета выглядели так:
Красный;
Зеленый;
Синий.
Вашей аудитории понравится второй вариант.

8. Взгляд пользователя описывает F-образный путь при просмотре страницы

Прочитайте отличную статью Якоба Нильсена про движение глаз пользователя.

Поместите самое важное на этом пути, и получите хорошие результаты.

9. Они не запоминают адрес вашего сайта.

Серьёзно. Никто никогда не запоминает адреса сайтов. Конечно, если вы mts.ru или mail.ru, вас помнят. Но если вы drom.ru или autocadabra.ru, удачи вам.

Дайте людям множество возможностей подписаться, внести сайт в закладки или запомнить другим образом. И зарезервируйте адреса, похожие на ваш, чтобы защитить имя.

10. Они не хотят входить на сайт.

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

11. Они даже не хотят думать, что им нужно логиниться
.
Я знаю, что вы думаете: «Отлично, я просто размещу форму входа слева и добавлю маленькую кнопочку справа, на которой написано, что вы можете зайти гостем».

Нет. Это:

http://daemdobro.ru/skitched-20090814-115831.jpg

говорит мне, покупателю: «Ты не принадлежишь нашему эксклюзивному клубу. Нажми на кнопку „Продолжить“ и купи, но ты же неудачник».

На полном серьезе, потребители не верят интернету. Вероятность того, что у них украдут кредитку в ресторане, в 10 раз больше, но это неважно. Они видят веб как огромное взаимосвязанное пристанище воров. Если вы хоть намекнете на то, что собираетесь сохранить их информацию, вы теряете их доверие. Не делайте этого.

12. Они не хотят даже маленького намека на то, что в какой-то момент в будущем им придется логиниться.

Просто дайте им оформить заказ. Во имя разумного, доброго и вечного. Можно просто забыть об этом?

13. Они не хотят «взаимодействия».

Бессмертны слова Якоба Нильсена: «Большинство людей просто хочет войти, получить и уйти».

Добавлять динамические «вебдванольные штучки» (содрогаясь) лишь потому, что они есть у «того парня», глупо. Все, что заставляет меня кликать дважды вместо одного раза, впечатлит меня в первый раз и охладит в будудем. Среди примеров:
Корзины для покупки с перетаскиванием. Кликать проще.
Заставки перед главной страницей. Нажатие на «пропустить заставку» — лишняя работа.
Эффекты медленного всплывания, проявления или приближения. Каждый раз, делая их, вы заставляете покупателя ждать. Зачем?
Посетители и покупатели не хотят взаимодействия. Они хотят сервиса. Только дизайнеры и фанаты вроде меня отождествляют хороший продукт или сервис с удачным применением библиотек Javascript. Остальные 99% населения хотят войти, получить и уйти.

Не верьте моим словам. Посмотрите на вебсайт суперпродвинутой в дизайне компании: Apple.com. Много там спецэффектов?

14. Они и правда хотят вашу новостную рассылку.

Трудно поверить после всей этой истерии про спам, но заметная часть вашей аудитории все еще хочет получать новостную рассылку. Так сделайте ее легкодоступной.

Я был главным борцом с этой идеей. На нашем корпоративном сайте у нас была мелкая иконочка подписки на e-mail в виде письма, зарытая на треть в глубину страницы.

Мы сделали простейшее изменение, добавив форму подписки на каждую страницу рядом с иконкой, и увидели через неделю прирост числа подписчиков:
http://daemdobro.ru/skitched-20090814-120009.jpg

15. Им неважно, насколько вы умны.

Если вы можете сказать «АФК Система обсуждает покупку фирмы Infineon», просто скажите это. Не говорите «К микроэлектронике проявился макроинтерес». Первое просто сообщает факты. Второе звучит забавно, но не помогает в этом.

16 Они не соблазняются тайнами.

Ваша онлайн-аудитория соблазняется ясностью, классным товаром, хорошей историей и подобным. Они вообще не соблазняются тайнами.

Поэтому, заголовок вроде «Отписка в получении» не так помогает, как «Ющенко ответил на послание Медведева», а «Ласки-шоу» — бессмысленен по сравнению с «Визит Обамы в Москву прошел в удивительно доброжелательной обстановке».

17 Они часто теряются

Посетителю сайта легко потеряться. Неработающая ссылка тут, отсутствующая кнопка там, и бам, они смущены и рассержены.

Заведите дружелюбную страницу ошибки 404, хороший инструмент поиска на сайте и действительно понятную навигацию. Затем, следите за запросами пользователя и 404 ошибками — они скажут, куда хотят и не попадают ваши посетители.

18 Они не используют сотовые телефоны. Пока ещё.

Если вы занимаетесь бизнесом в Северной Америке, велика вероятность того, что ваши покупатели не ходят на ваш сайт с сотового телефона. Даже в блоге, где размещена эта статья, в котором доля продвинутых технарей выше, очень мало просмотров с мобильника:
http://www.conversationmarketing.com/21things/cm-user-browsers.gif

Планируйте мобильную версию. Учитесь создавать мобильные CSS. Но не перестраивайте весь проект и не удваивайте его стоимость только ради совместимости с мобильниками.

19 Они не ищут ваше название.

Ваша аудитория не знает вас. Они ищут не по названию. Они ищут ответ на свой вопрос и найдут вас, если вы дадите на него ответ. Поэтому, хотя находиться на первой позиции в поисковиках по вашему имени и здорово, оно никак не повлияет на доходы.

20 Они все еще юзают Internet Explorer.

Не все пока понимают, что Firefox — Великое Откровение. Большая часть аудитории, очевидно, еще использует IE:
http://www.conversationmarketing.com/21things/browser-versions-ma.gif
И многие из них все еще использует (чуть слышно) его шестую версию:
http://www.conversationmarketing.com/21things/browser-versions-ma2.gif

Проектируйте, разрабатывайте и планируйте в соответстсвии с этим фактом.

21. Они покупают классные мониторы (и компьютеры).

С другой стороны, большая часть вашей аудитории следит за графическими характеристиками своих компьютеров. Можете спокойно проектировать страницу шириной в 900 пикселей:
http://www.conversationmarketing.com/21things/screen-resolutions-809.gif

Проверьте статистику своего сайта перед тем, как делать изменения!

Прим.переводчика: хотя в целом то же самое можно сказать и про нашу аудиторию, есть нюансы:
http://daemdobro.ru/1-20090814-114134.jpg
Opera Mini имеет ощутимую долю, согласно статистике Liveinternet по сайтам рунета. С этим же связан и заметный процент мобильных разрешений экрана:
http://daemdobro.ru/2-20090814-114320.jpg
Можно также порадоваться за то, что у нас сильнее распространились альтернативные браузеры, но IE6 нельзя будет сбрасывать со счетов еще минимум месяцев 9.


22. Им нужно хотеть

Люди покупают то, что хотят, а не то, что им нужно. Нам всем нужна автостраховка. Мы все хотим айфон или другие блестящие штучки.

Не знаю про вас, но у меня нет такого же чувства радостного предвкушения, какое я получаю при мысли об HTC Hero, когда я ищу страховую компанию для автомобиля.

Мы все можем плакать по этому поводу, а можем использовать его. Потребителю нужно хотеть. Действительно крутой маркетолог объясняет, почему ты хочешь то, что тебе нужно.

(Я позаимствовал принцип желания и потребности у какого-то великолепного маркетолога, которого не могу вспомнить. Сам я недостаточно умен, чтобы придти к этому)

Вот в чем дело...

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

Верстка на HTML5

http://habrahabr.ru/blogs/webdev/67049/

четверг, 30 июля 2009 г.

Компьютерные навыки на всю жизнь

Life-Long Computer Skills (February 26, 2007)
автор: 2007.02.26 Якоб Нильсен
перевод: 2007.07.29 Александр Качанов

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

Недавно я заглянул в учебник по компьютерной грамотности для третьего класса. В одной из глав (с заголовком «Большой Калькулятор») приводится подробный список команд, с помощью которых можно отформатировать таблицы с числами в Microsoft Excel. Все бы хорошо, да вот только новая версия Excel оснащена полностью переделанным пользовательским интерфейсом, в котором все традиционные команды и меню заменены на полосу кнопок с моментальным выводом результатов.

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

Проблема, естественно, состоит в том, что образование слишком тесно привязано к специфическим программным продуктам. Даже если Microsoft и не переделывал бы Excel в этом году, он бы сделали бы это рано или поздно. И выход вовсе не в том, что все учебники надо обновить новой информацией о Microsoft Office 2007. В пользовательских интерфейс этих программ непременно будут внесены новые изменения еще до того, как нынешние третьеклассники станут искать работу через 10-15 лет – и даже до того, как они уйдут на пенсию в 2065 году.

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

Обучение пожизненным компьютерным навыкам в школе важно еще и потому, что им даются знания, которые они не смогут приобрести самостоятельно. По мере того, как программы становятся все проще и проще, всякий через несколько лет разберется, как нарисовать график. Как пользоваться новыми функциями программ, люди сами разберутся, когда им они понадобится – при этом и мотивация будет выше. А вот в концептуальных вещах они сами не смогут разобраться, без формального образования.

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

Нынешний рынок поисковых серверов через 20 лет возможно исчезнет, и уж точно изменятся за это время дизайны страниц поисковых серерверов, доминирующих сейчас на рынке. Так что незачем учить детей, как выжать из Google максимум.

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

При исследовании веб-сайтов с помощью детей мы обнаружили, что дети чаще щелкают по рекламе, чем взрослые. Очень важно научить детей распознавать различные типы рекламы, например, различать спонсорские ссылки и реальные результаты выдачи в поиске. Но надо идти и дальше. Надо обучать детей оценивать достоверность информации, найденной в Интернете. Тинейджеры особенно нетерпеливы при работе в Интернете, и потому чаще попадаются на обман и уловки.
Лавина информации

В будущем мы будем получать еще больше электронных писем, еще больше сообщений SMS и голосовой почты по телефону, еще больше видео-звонков и сообщений, слушать еще больше подкастов, а веб-сайты станут еще более информационно насыщенными. Все это будет крутиться и вертеться в вашем офисе, дома, в дороге, в любом помещении, где вы будете находиться и на различных приборах, которыми вы будете пользоваться.

Для борьбы с этой лавиной информации люди пока используют простые приемы, но в будущем нам понадобятся еще более изощренные трюки.
Как писать для тех, кто читает с экрана компьютера

Все более важным становится умение четко выражать свои мысли в Интернете, в офисной сети и в других интерактивных средствах общения. Глубокое исследование показало, что пользователи читают с экрана совершенно иначе, чем с печатного листа. Следовательно, надо обучать тому, как писать именно для Интернета, а не просто, как составлять документы.
Навыки компьютерной презентации

Хорошие ораторы знают, как использовать PowerPoint, чтобы произвести впечатление на слушателей, а не вогнать их в спячку сухими столбцами цифр. Большинство деловых людей согласны с тем, что навыки составления хороших презентаций очень способствуют карьерному росту. Лишь немногие из них понимают, что нынешние презентации все больше становятся компьютерными презентациями, а следовательно одних только блестящих ораторских навыков уже не достаточно.

Многие ученики уже сейчас используют PowerPoint для представления своих учебных проектов. Надо пойти дальше простого обучения тому, как показывать слайды через проектор. Детей следует обучать тому, как сделать с помощью компьютера презентацию наиболее эффективной.
Эргономика рабочего места

Наша жизнь становится все более компьютеризированной. Туннельный синдром и «травма большого пальца» испортила жизнь немалому количеству людей. Детей следует учить тому, как следить за своим здоровьем, как организовывать рабочее место в соответствии с правилами эргономики. Все знают Правило №1: делать частые перерывы. Но этого мало. Как правильно разместить монитор на столе, какой выбрать стул, какова должна быть высота рабочего стола, где и какое разместить освещение. Многие рабочие места, которые мы наблюдали, вредны для здоровья, из-за этого у людей возникают головные боли, боли в спине и травмы суставов.
Отладка

Разумеется мы не требуем превращать учеников в программистов, но основные навыки отладки просто необходимы для выживания в нынешнем веке компьютеров. В таблице Excel в формулу может случайно вкрасться ошибка, и если человек не знает, как отыскать эту ошибку, он будет принимать решения, основываясь на неверных данных.
Тесты с пользователями и прочие основные навыки юзабилити

Точно также, как я не ожидаю, что каждый ученик должен стать программистом, я не требую, чтобы каждый из них стал специалистом по юзабилити или дизайнером интерфейсов. Но, чем больше мы работаем в интерактивной среде, тем важнее для всех нас станет понимание фундаментальных принципов юзабилити. Для образованного человека понимание таких основных понятий юзабилити как «единообразие» и «узнавание против вспоминания», станет таким же обязательным, как умение разрезать лягушку на уроке биологии.

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

И даже если ученики никогда в своей взрослой жизни не проведут ни одного теста с участием пользователей, я считаю, что в школе они должны это сделать хотя бы раз. Проведение такого теста поможет детям оценить важность многих понятий юзабилити. Например, учитель может попросить учеников создать простой веб-сайт на какую-либо тему, а потом протестировать его на своем соседе по парте. Когда вы видите своими глазами, что ваш сосед по парте не может понять, как работать с вашим веб-сайтом, вы понимаете гораздо больше, чем при виде жирной двойки под вашим сочинением.

В книге The New Division of Labor: How Computers Are Creating the Next Job Market Фрэнк Левай и Ричард Мюрнейн (Frank Levy и Richard J. Murnane) приводят три навыка, которые, по их мнению, в будущем будут важны и которые никогда нельзя будет автоматизировать или перевести в оффшор в Индию или Китай. Это умение решать задачи, понимание связей между разрозненными понятиями, умение общаться.

Те компьютерные навыки, что я привел выше, также подготовят учеников к той работе, которая ждет их в их будущем с глобальной экономикой.

Якоб Нильсен

Проверочный список для веб-стандартов

A web standards checklist
автор: 2004.08.13 Russ Weakley
перевод: 2004.10.31 Александр Качанов
Веб-стандарты - это большее, чем просто "бестабличная верстка"

Для разных людей термин "веб-стандарты" означает разные вещи. Для некоторых это просто "страницы без таблиц", для других - "правильный код". Однако веб-стандарты это нечто намного большее. Сайт, простроенный по веб-стандартам, это сайт, который придерживается стандартов (HTML, XHTML, XML, CSS, XSLT, DOM, MathML, SVG и т.д.) и лучших отработанных решений (валидный код, доступный код, семантически правильный код, дружественные URL-ы)

Другими словами сайт, построенный по стандартам в идеале должен быть легким, чистым, основанным на CSS, доступным, удобным и дружественным к поисковым серверам.
О проверочном списке

Этот проверочный список не претендует на звание "супер-пупер" полного проверочного списка. Возможно его еще можно дополнить и расширить. Что более важно, так это то, что это список не следует рассматривать как обязательный для каждого сайта, который вам придется разрабатывать. Это всего лишь список советов, который можно использовать:

* как обширный список всех имеющихся веб-стандартов
* как удобный инструмент для разработчиков, которым они могут пользоваться при разработке сайтов
* как пособие для тех разработчиков, которые решили двигаться в направление веб-стандартов

Список

1. Качество кода
1. Указан ли у страниц правильный Doctype?
2. Указан ли у страниц charset?
3. Валиден ли (X)HTML код страниц сайта?
4. Валидны ли CSS-таблицы сайта?
5. Использует ли сайт какие-либо CSS-хаки?
6. Используются ли на сайте какие-либо лишние и ненужные классы (class) и идентификаторы (id)?
7. Хорошо ли структурирован код страниц?
8. Есть ли на сайте сломанные ссылки?
9. Как у сайта со скоростью загрузки страниц и с их размерами?
10. Выдает ли браузер какие-либо ошибки JavaScript при работе со страницей?
2. Степень разделения контента и представления
1. Используется ли на сайте CSS для всех аспектов оформления страницы (шрифты, цвета, отступы, границы и т.д.)?
2. Перенесена ли вся декоративная графика в CSS, или она все еще встречается в (X)HTML-коде?
3. Доступность для пользователей
1. Используется ли атрибут "alt" во всех значимых изображениях?
2. Используется ли на сайте для шрифта относительные единицы измерения вместо фиксированных?
3. Ломается ли каким-либо образом компоновка страницы при увеличении размера шрифта?
4. Есть ли на странице видимая ссылка "пропустить"?
5. Используются ли на сайте доступные формы?
6. Используются ли на сайте доступные таблицы?
7. Достаточно ли контрастны и ярки цвета на страницах сайта?
8. Используется ли только цвет для выделения критической информации?
9. Используется ли задержка в выпадающих меню (для пользователей с медленной моторикой)?
10. Все ли ссылки содержат описания (для слепых пользователей)?
4. Доступность для устройств
1. Достаточно ли хорошо сайт работает и в современных и в старых браузерах?
2. Можно ли работать с материалами сайта при отключенном CSS или в броузере, где нет поддержки CSS?
3. Можно ли работать с материалами сайта при отключенных изображениях или при отсутствии поддержки их вывода на экран?
4. Работает ли сайт в текстовых броузерах, таких как Lynx?
5. Хорошо ли выглядит сайт при распечатке?
6. Работает ли сайт на наладонных устройствах?
7. Снабжен ли сайт детальным набором метаданных?
8. Работает ли сайт в окнах различных размеров?
5. Основы юзабилити
1. Имеется ли на странице четкая визуальная иерархия элементов?
2. Легко ли отличить один уровень заголовков от другого?
3. Достаточно ли легко понять навигацию по сайту?
4. Используется ли однообразная навигация на всех страницах сайта?
5. Используется ли на сайте приемлемый и однообразный язык текстов?
6. Есть ли у сайта карта и страница с контактной информацией? Легко ли их найти?
7. Если ваш сайт очень большой, есть ли на нем инструмент поиска?
8. Присутствует ли на каждой странице сайта ссылка на его главную страницу?
9. Подчеркнуты ли ссылки?
10. Четко ли выделены цветом ссылки, которые пользователь уже посетил?
6. Управление сайтом
1. Есть ли у сайта понятная и полезная страница ошибки 404, которая работает с любого уровня сайта?
2. Используются ли на сайте дружественные URL-ы?
3. Можно ли к вашему сайте доступиться, набрав адрес без "www"?
4. Есть ли у сайта пиктограмма для закладок?

1. Качество кода
1.1 Указан ли у страниц правильный Doctype?

Doctype (сокращенно от 'document type declaration' - "декларация типа документа") сообщает валидатору, какая версия (X)HTML используется в вашей странице. Декларация должна присутствовать в начале каждой веб-страницы. Doctype - ключевой компонент страницы, претендующей на соответствие стандартам: ваша разметка и CSS не пройдут валидацию, если в вашем документе отсутствует Doctype.
статья на webmascon.com Почему так важен DOCTYPE

См. также:

* http://www.w3.org/QA/2002/04/valid-dtd-list.html
* http://css.maxdesign.com.au/listamatic/about-boxmodel.htm
* http://gutfeldt.ch/matthias/articles/doctypeswitch.html

1.2 Указан ли у страниц кодировка (charset)?

Если пользовательский агент (например браузер) не может самостоятельно определить кодировку вашей веб-страницы, пользователи увидят на экране нечитаемый текст. Эта информация в особенности важна для тех, кто создает и поддерживает многоязычные веб-сайты. Но вообще объявление кодировки очень важно для тех, кто создает страницы в XHTML/HTML и CSS.
http://www.w3.org/International/tutorials/tutorial-char-enc/

См. также:

* http://www.w3.org/International/O-charset.html

1.3. Валиден ли (X)HTML код страниц сайта?

Валидный код браузер выведет быстрее, чем невалидный. Валидный код браузер выведет лучше, чем невалидный. Все больше и больше браузеры подчиняются стандартам, и потому все более важным является валидный и стандартный HTML-код.
http://www.maxdesign.com.au/presentation/sit2003/06.htm

См. также:

* http://validator.w3.org/

1.4. Валидны ли CSS-таблицы сайта?

Не забывайте убедиться, что ваш HTML-код и CSS-страницы не содержат ошибок, так как ошибки приведут к искаженному отображению документа на экране.
http://www.meyerweb.com/eric/articles/webrev/199904.html

См. также:

* http://jigsaw.w3.org/css-validator/

1.5. Использует ли сайт какие-либо CSS-хаки?

В сущности каждый сам решает, какие хаки ему использовать. Это зависит от того, насколько хорошо вы знакомы со всеми вариантами, и от того, какой дизайн вы хотите создать.
http://www.mail-archive.com/wsg@webstandardsgroup.org/msg05823.html

См. также:

* http://css-discuss.incutio.com/?page=CssHack
* http://css-discuss.incutio.com/?page=ToHackOrNotToHack
* http://centricle.com/ref/css/filters/

1.6. Используются ли на сайте какие-либо лишние и ненужные классы (class) и идентификаторы (id)?

Я заметил, что разработчики, осваивая новые приемы и технологии, часто создают замечательные CSS-таблицы, и при этом - плохой XHTML-код. В особенности часто в XHTML-коде встречаются ненужные и лишние "div" и "id". Из-за этого HTML-код теряет стройность, а CSS-файлы становятся запутанными.
http://www.clagnut.com/blog/228/
1.7. Хорошо ли структурирован код страниц?

Семантически правильная разметка подразумевает использование html-элементов по их прямому назначению. Хорошо структурированный HTML-документ хорошо воспринимается всем спектром пользовательских программ (браузерами без поддержки стилевых таблиц, текстовыми броузерами, наладонниками, поисковыми роботами и т.д.)
http://www.maxdesign.com.au/presentation/benefits/index04.htm

См. также:

* http://www.w3.org/2003/12/semantic-extractor.html

1.8. Есть ли на сайте "сломанные" ссылки?

"Сломанные" ссылки разочаровывают пользователей и потенциально отвращают от вашего сайта ваших клиентов. "Сломанные" ссылки могут также сказаться на том, как поисковые роботы будут индексировать ваш сайт.

См. также:

* http://validator.w3.org/checklink

1.9. Как у сайта со скоростью загрузки страниц и с их размерами?

Не заставляйте меня ждать... Вот какую мысль подразумевают пользователи при проведении всех исследований. Даже пользователи с широким каналом устают от медленной загрузки.
http://www.websiteoptimization.com/speed/
1.10. Выдает ли браузер какие-либо ошибки JavaScript при работе со страницей?

Internet Explorer для Windows позволяет включить отладчик, который будет выскакивать на экран всякий раз, когда на странице будет обнаружена ошибка в JavaScript. Эта опция находится в меню "Internet Options" на закладке "Advanced". Уберите галочку с пункта "Disable script debugging".

* * *
2. Степень разделения контента и представления
2.1. Используется ли на сайте CSS для всех аспектов оформления страницы (шрифты, цвета, отступы, границы и т.д.)?

Используйте стилевые таблицы для управления компоновкой страницы и ее внешним видом
http://www.w3.org/TR/WCAG10/wai-pageauth.html#tech-style-sheets
2.2. Перенесены ли вся декоративная графика в CSS, или она все еще встречается в (X)HTML-коде?

Ваша цель, как веб-разработчика, состоит в том, чтобы убрать из html-кода вашей страницы все оформительские элементы. Благодаря чему код станет чище и семантически правильнее.
http://www.maxdesign.com.au/presentation/benefits/index07.htm

* * *
3. Доступность для пользователей
3.1 Используется ли атрибут "alt" во всех значимых изображениях?

Каждый нетекстовый элемент сопровождайте текстовым описанием
http://www.w3.org/TR/WCAG10/wai-pageauth.html#tech-text-equivalent
3.2. Используется ли на сайте для шрифта относительные единицы измерения вместо фиксированных?

В коде и в стилевых таблицах используйте относительные, а не абсолютные единицы для указания размеров элементов
http://www.w3.org/TR/WCAG10/wai-pageauth.html#tech-relative-units

См. также:

* http://www.w3.org/TR/WCAG10/wai-pageauth.html#tech-relative-units
* http://www.clagnut.com/blog/348/
* Власть народу - относительные размеры шрифтов
* Размер шрифта пусть выбирают сами пользователи

3.3. Ломается ли каким-либо образом компоновка страницы при увеличении размера шрифта?

Проведите простой тест. Откройте свой веб-сайт в любом браузере, где есть функция изменения размера шрифта. Теперь увеличьте размер шрифта. Еще раз увеличьте. И еще раз... Посмотрите на свой веб-сайт. По-прежнему ли компоновка страницы осталась неизменной? При разработке сайта не рассчитывайте, что у посетителя в браузере размер шрифта совпадает с вашим.
3.4. Есть ли на странице видимая ссылка "пропустить"?

"... Следует предусмотреть способ, который позволяет пользователю перейти к контенту сайта, пропустив навигацию..."
http://www.section508.gov/index.cfm?FuseAction=Content&ID=12

"... сгруппируйте родственные ссылки, опишите группу и представьте способ пользователям пропустить эту группу при просмотре..."
http://www.w3.org/TR/WCAG10-TECHS/#tech-group-links

".. масса навигационных на странице ссылок доставляет неприятности не только слепым пользователям. Вспомните и о тех, у кого затруднена моторика и кому придется нажимать много раз клавишу Tab, чтобы пройти по всем этим ссылкам к тексту страницы..."
http://joeclark.org/book/sashay/serialization/Chapter08.html#h4-2020

См. также:

* http://www.niehs.nih.gov/websmith/508/o.htm

3.5. Используются ли на сайте доступные формы?

Формы на веб-страницах не самая простая вещь для людей с физическими недостатками. Одно дело - навигация по странице с текстовым материалом, и совсем другое - переход по полям формы и ввод информации в нее.
http://www.htmldog.com/guides/htmladvanced/forms/

См. также:

* http://www.webstandards.org/learn/tutorials/accessible-forms/01-accessible-forms.html
* http://www.accessify.com/tools-and-wizards/accessible-form-builder.asp
* http://accessify.com/tutorials/better-accessible-forms.asp

3.6. Используются ли на сайте доступные таблицы?

Что касается таблиц. Не забудьте указать заголовки для столбцов и рядов... Для таблиц, где имеются два и более логических уровней рядов и столбцов, воспользуйтесь вспомогательными элементами языка html, чтобы связать логически ячейки данных с ячейками заголовков.
http://www.w3.org/TR/WCAG10/wai-pageauth.html#tech-table-headers

См. также:

* http://www.bcc.ctc.edu/webpublishing/ada/resources/tables.asp
* http://www.accessify.com/tools-and-wizards/accessible-table-builder_step1.asp
* http://www.webaim.org/techniques/tables/

3.7. Достаточно ли контрастны и ярки цвета на страницах сайта?

Убедитесь, что разница между цветом фона и цветом текста достаточно контрастна, чтобы не вызывать затруднений при чтении у людей с пониженным восприятием цвета.
http://www.w3.org/TR/WCAG10/wai-pageauth.html#tech-colour-contrast

См. также:

* http://www.juicystudio.com/services/colourcontrast.asp

3.8. Используется ли только цвет для выделения критической информации?

Убедитесь, что вся важная информация, выделенная цветом, также выделена при отсутствии цвета, например с помощью контекста или элементами логической разметки.
http://www.w3.org/TR/WCAG10/wai-pageauth.html#tech-colour-convey

Существует в основном три типа нарушения цветовосприятия: дейтеранопия (нарушение в восприятии красного и зеленого цветов), протанопия (другая форма нарушения восприятия красного и зеленого цветов) и тританопия (нарушение восприятия синего и желтого цветов - очень редкий случай)

См. также:

* http://colorfilter.wickline.org/
* http://www.toledo-bend.com/colourblind/Ishihara.html
* http://www.vischeck.com/vischeck/vischeckURL.php

3.9. Используется ли задержка в выпадающих меню (для пользователей с медленной моторикой)?

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

Ссылки должны быть достаточно понятными, чтобы они имели смысл при чтении вне контекста - либо при простом чтении или при чтении в виде списка.
http://www.w3.org/TR/WCAG10/wai-pageauth.html#tech-meaningful-links

* * *
4. Доступность для устройств
4.1. Достаточно ли хорошо сайт работает и в современных и в старых браузерах?

Прежде чем начинать верстать страницы с использованием CSS, определитесь, какие браузеры вы собираетесь поддерживать и до какой степени.
http://www.maxdesign.com.au/presentation/process/index_step01.cfm
4.2. Можно ли работать с материалами сайта при отключенном CSS или в броузере, где нет поддержки CSS?

На ваш сайт могут зайти люди, у которых браузер не поддерживает CSS или поддержка CSS отключена. Если ваши страницы правильно структурированы, у таких посетителей не возникнет никаких проблем при работе с ними.
4.3. Можно ли работать с материалами сайта при отключенных изображениях или при отсутствии поддержки их вывода на экран?

Некоторый пользователи просматривают веб-сайты не загружая графические элементы страниц. Так поступают в особенности те, у которых подключение к Интернету слишком медленное. Ваши страницы не должны вызывать затруднений в работе у таких посетителей.
4.4. Работает ли сайт в текстовых броузерах, таких как Lynx?

Текстовый браузер это как бы комбинация отключенных графики и CSS. Текстовые браузеры полагаются целиком на структуру документа при создании изображения на экране.

См. также:

* http://www.delorie.com/web/lynxview

4.5. Хорошо ли выглядит сайт при распечатке?

К любому (X)HTML-документу можно прикрепить стиль для вывода на печать и для этого не потребуется трогать разметку самого документа.
статья на webmascon.com В печать!

См. также:

* http://www.d.umn.edu/itss/support/Training/Online/ webdesign/css.html#print

4.6. Хорошо ли работает ли сайт на наладонных устройствах?

Этот момент вызывает наибольшие затруднения, так как в настоящее время нет единообразия в том, как наладонные устройства поддерживают веб-страницы. Однако некоторые решения в компоновке страниц поддерживаются на наладонниках лучше, чем другие. Поддержка наладонных устройств зависит от целевой аудитории вашего сайта.

См. также:

* Дизайн для портативных устройств: ваш веб-сайт на маленьком экране

4.7. Снабжен ли сайт детальным набором метаданных?

Метаданные - это информация, которая понятна для машин.
http://www.w3.org/Metadata/

Метаданные - это структурированная информация, которая создается людьми специально для того, чтобы описать ею какой-либо ресурс. Другими словами, метаданные - это "данные о данных".
4.8. Работает ли сайт в окнах различных размеров?

Среди веб-разработчиков бытует устойчивое убеждение, что с каждым годом средние размеры экрана у посетителей растут. Некоторые разработчики убеждены, что средний размер экрана у посетителей их сайтов составляет по ширине 1024 пикселей. Ну а что насчет пользователей с меньшими размерами экранов или с владельцами наладонников? Являются ли они частью вашей целевой аудитории, и будут ли они испытывать затруднения при работе с вашим сайтом?

* * *
5. Основы юзабилити
5.1. Имеется ли на странице четкая визуальная иерархия элементов?

Организуйте и выделяйте важность того или иного материала с помощью размеров, отступов и логических связей.
http://www.great-web-design-tips.com/web-site-design/165.html
5.2. Легко ли отличить один уровень заголовков от другого?

Используйте заголовки для того, чтобы раскрыть структуру документов, при этом используйте их в соответствие со спецификацией.
http://www.w3.org/TR/WCAG10/wai-pageauth.html#tech-logical-headings
5.3. Достаточно ли легко понять навигацию по сайту?

Навигация вашего сайта должна подсказывать посетителю, на какой странице сайта он сейчас находится и куда он может следовать дальше.
http://www.1stsitefree.com/design_nav.htm
5.4. Используется ли однообразная навигация на всех страницах сайта?

Если на каждой странице вашего сайта навигация придерживается одного и того же стиля, посетителям легче будет работать с сайтом и они быстрее будут находить нужную им информацию.
http://www.juicystudio.com/tutorial/accessibility/navigation.asp
5.5. Используется ли на сайте приемлемый и однообразный язык текстов?

Ясный и простой язык материалов позволяет эффективно вести диалог с посетителем. Не забывайте, что ваш сайт могут читать пользователи, для которых ваш язык не является родным.
http://www.juicystudio.com/tutorial/accessibility/clear.asp
5.6. Есть ли у сайта карта и страница с контактной информацией? Легко ли их найти?

Большинству карт сайтов не удается раскрыть многоуровневую структуру архитектуры сайта. В тестах на юзабилити пользователи часто игнорируют карту сайта или просто не могут ее найти. Сложность карты также является проблемой: карта должна быть именно картой, а не головоломкой по навигации.
http://www.useit.com/alertbox/20020106.html

См. также:

* Карта сайта и индекс: что это такое и для чего это нужно?

5.7. Если ваш сайт очень большой, есть ли на нем инструмент поиска?

Для маленького сайта функция поиска не особенно нужна. Всегда найдутся люди, которые никогда не пользуются поиском по сайту. Тем не менее функция поиска является дополнительным хорошим инструментом навигации по сайту для посетителей.
5.8. Присутствует ли на каждой странице сайта ссылка на его главную страницу?

Многие пользователи зарывшись в глубины сайта хотят быстро попасть на его главную страницу. Главная страница является как бы отправной точкой для таких пользователей, на которой они заново собираются с силами, чтобы нырнуть в новые глубины сайта.
5.9. Подчеркнуты ли ссылки?

Для полноты восприятия пользователями ссылок текст ссылок должен быть оформлен другим цветом и подчеркнут. Посетители не должны метаться по странице в поисках ссылки.
http://www.useit.com/alertbox/20040510.html
5.10. Четко ли выделены цветом ссылки, которые пользователь уже посетил?

Самое главное, если четкое выделены ссылки, которые пользователь уже посетил, он не нажмет на них случайно, и не будет попадать на ту же самую страницу, где уже побывал.
http://www.useit.com/alertbox/20040503.html

* * *
6. Управление сайтом
6.1. Есть ли у сайта понятная и полезная страница ошибки 404, которая работает с любого уровня сайта?

Вы запросили страницу - либо набрав URL в адресной строке, либо щелкнув по ссылке - и обнаружили, что провалились в Ничто. Дружественные к пользователю веб-сайты подадут руку помощи потерявшемуся пользователю, а другие сайты будут рассчитывать на то, что браузер пользователь сам их как-нибудь вытащит из бездны киберпространства.
статья на webmascon.com Совершенная 404-ая страница
6.2. Используются ли на сайте дружественные URL-ы?

Большинство поисковых серверов (за исключением лишь некоторых - например, Google) не будут индексировать страницы, в чьих URL-ах присутствует символ "?" или какой либо иной символ (скажем "&" или "="). Что хорошего в веб-сайте, если его никто не может найти?
http://www.sitepoint.com/article/search-engine-friendly-urls

С точки зрения пользовательского интерфейса самым ужасным является URL-ы. Тем не менее, если они коротки, логичны и самоисправляющиеся, с ними становится удобно работать.
http://www.merges.net/theory/20010305.html

См. также:

* URL как элемент пользовательского интерфейса
* http://www.sitepoint.com/article/search-engine-friendly-urls
* http://www.websitegoodies.com/article/32
* http://www.merges.net/theory/20010305.html

6.3. Можно ли к вашему сайту доступиться, набрав адрес без "www"?

В целом не очень критичное требование, а иногда его даже невозможно удовлетворить. Но тем не менее всегда неплохо, если у ваших посетителей есть такая возможность. Если посетитель наберет название вашего сайта без "www" и не сможет до него доступиться, это будет плохо и для вас и для него.
6.4. Есть ли у сайта пиктограмма для закладок?

Пиктограмма для закладок (favicon) это графический файл с картинкой в нескольких разрешениях. Они как правило используются на всех профессионально выполненных сайтах. Пиктограмма для закладок дает веб-мастеру еще один способ рекламы сайта.
http://www.favicon.com/

Разумеется, пиктограмма для закладок не является критичной. Однако ее отсутствие порождает волну ошибок 404 в ваших лог-файлах. Такие браузеры как IE всегда запрашивают у сервера эту пиктограмму, когда пользователь помещает ссылку на ваш сайт в закладки. Если на вашем сайте этой пиктограммы нет, в логи попадет ошибка "404 File not found". Так что наличие такой пиктограммы поможет вам значительно сократить размер файла ошибок. То же самое относится и к файлу "robots.txt".
Об этом списке

Данный список появился впервые в общих чертах в списке рассылки Web Standards Mail list в мае 2004 года. Он был представлен группе Sydney Web Standards Group 5 августа 2004 года. Также этот список доступен в pdf-формате.

Последняя проверка перед запуском сайта

Чеклист запуска сайта

Этот чеклист будет полезен всем, кто запускает сайты или следит за этим увлекательным процессом. Ничего не пропустите!

Перед запуском

Контент и стиль

● Типографика
◦ Корректные символы. Проставить корректные символы тире, кавычек и апострофов, в зависимости от языка сайта
◦ Переносы слов. Проставить в важных местах неразрывные пробелы между инициалами, тире, перед последними словами
◦ Для английского: Лигатуры. Проставить лигатуры в заголовках, если требуется
● Вычитать тексты и проверить правописание
● Связность текстов
◦ Проверить регистр в важных текстах и заголовках
◦ Обеспечить единый стиль текстов
◦ Единство повторяющихся фраз (т.е. «Узнать больше», «Читать далее», «N комментариев» и др.)
◦ Пунктуация в списках (напр. если пункт списка заканчивается точкой, следующий пункт должен начинаться с заглавной буквы и наоборот для точки-запятой)
● Проверить нет ли на сайте вшитых ссылок на dev-сервер (т.е. после запуска ссылки должны вести на сайт «в миру»)
● Проверить не осталось ли на сайте тестового контента
● Проверить печатные версии важных страниц
● При редизайне или изменении информационной архитектуры, проверить стоят ли редиректы со старых адресов разделов на новые
● Проверить скрытые текст (e.g. alt/title атрибуты HTML тегов, тексты в Javascript функциях)

Стандарты и валидация

● Доступность для людей с ограниченными возможностями (не препятствуют ли нарушения восприятия цвета, звука и т.д. навигации по сайту)
● HTML валидация
● Javascript валидация
● CSS валидация

Доступность в поисковиках, SEO и статистика

● Заголовки страниц очень важны; убедиться, что они осмысленны и содержат важные ключевые слова
● Заполнить мета-тег «description» для важных страниц
● Привести ссылки на главную страницу к единому виду (т.е. выбрать что-то одно из вариаций site.ru www.site.ru www.site.ru/index.html)
● Гарантировать предыдущий пункт редиректом на выбранную версию (напр. редирект с www.site.ru/* на site.ru/*)
● Убедиться в семантически-грамотном использовании HTML тегов (h1, h2,… и т.д.)
● Проверить наличие важных ключевых слов в контенте
● Привести формат ссылок к читабельному виду (напр. site.ru/blog/how-to-make-coffee, site.ru/user/vasya и т.д.)
● Прикрутить Google Analytics, FeedBurner, и/или другие системы измерения статистики
● Создать XML Sitemap
● Добавить сайт в Google Webmaster Tools

Тестирование функциональности

● Проверить весь заказанный/особый/сложный функционал
● Проверить работу поиска (включая релевантность)
● Проверить работу сайта в разных браузерах (Internet Explorer, Firefox, Opera, Safari, Chrome etc.), версиях (6, 7, 2.2, 3.1 etc.) и платформах (Windows, OSX, Linux)
● Проверить вид сайта на разных разрешениях экрана (1280×1024, 1024×768, 1920×1200, 800×600...)
● Протестировать все формы (контактов, комментариев, фидбека, ...), поставить на них капчу или другую защиту
● Проверить все e-mail шаблоны
● Проверить работоспособность сайта с выключенным Javascript, Flash, и другими компонентами
● Проверить работоспособность внешних ссылок

Безопасность/Риски

● Настроить бекапы по расписанию, и проверить восстановление из них.
● Проверить нет ли у посетителей доступа к служебным/секретным/закрытым страницам
● Закрыть поисковикам доступ к служебным/секретным/закрытым разделам сайта, используя robots.txt
● Отключить вывод ошибок на экран
● Проверить количество доступного дискового пространства и вычислить на сколько его хватит
● Настроить email/SMS уведомления о неработоспособности сайта/сервера;

Производительность

● Провести нагрузочное тестирование
● Провести оптимизацию изображений/графики
● Проверить и реализовать кэширование где это необходимо
● Проверить общий размер/скорость загрузки страниц сайта
● Минимизировать/сжать статику (Javascript/HTML/CSS)
● Оптимизировать CSS: короткие пути к изображениям; использовать «каскадную» природу стилей, и т.д.
● Проверить наличие индексов в таблицах БД
● Проверить другие настройки производительности на всех уровнях (Сервера, БД, CMS и т.д.)
● Включить логи ошибок/производительности на сервере

Финальные штрихи

● Создать свои страницы 404/403
● Создать страницу «Сайт на обслуживании»
● Создать favicon

После запуска

Маркетинг

● Добавить сайт в социальные медиа: Twitter, ВКонтакте, LinkedIn, Facebook, и т.д.
● Добавить сайт в поисковики
● Настроить PPC/Google Adwords кампании, если требуется
● Проверить форматирование сайта в результатах выдачи поисковиков

Другое

● Мониторить фидбек (прямой с сайта, на Социальных Медиа, в выдаче Google и т.д.)
● Отлавливать в статистике возможные проблемы с некоторыми разделами/страницами сайта
● Обновлять контент

Версию для печати можно найти здесь — drupaldance.com/blog/website-launch-checklist

Забыли упомянуть: прикрепить сайт к Яндекс.Вебмастер и Google Webmaster Tools
Если сайт компании:
Зарегистрировать в Яндекс.Адресах и Гугл.Адресах, добавить на Wikimapia.org

среда, 22 июля 2009 г.

CSS-debug

* { outline: 2px dotted red; }
* * { outline: 2px dotted green; }
* * * { outline: 2px dotted orange; }
* * * * { outline: 2px dotted blue; }
* * * * * { outline: 1px solid red; }
* * * * * * { outline: 1px solid green; }
* * * * * * * { outline: 1px solid orange; }
* * * * * * * * { outline: 1px solid blue; }

понедельник, 29 июня 2009 г.

How to add ruby\bin to your path

How to add ruby\bin to your path:
either do this on the command line thus:
set PATH=c:\ruby-1.9.1-p0-i386-mingw32\bin;%PATH%

or change the PATH variable within my computer -> properties ->
advanced -> environment variables (add it to the front of path within
"system variables").

== How to determine success ==
If successful you should get an output like (for 1.8):

C:\>ruby -v
ruby 1.8.6 (2009-03-31 patchlevel 368) [i386-mingw32]

пятница, 26 июня 2009 г.

A critique of Abelson and Sussman or Why calculation is better than scheming

статья Филиппа Вадлера, перевод
Абельсон и Сассман написали прекрасную книгу, которая, может быть, положит начало революции в обучении программированию. Вместо акцентирования на некотором языке программирования, они делают упор на применение стандартных инженерных методов. Но, все же, их книга тесно связана с языком Scheme - диалектом Lisp'a. Я думаю, тот же подход, примененный на примере таких языков, как KRC или Miranda, может быть более удачным введением в программирование как инженерной дисциплины. Мое убеждение основано на опыте обучения Scheme и после знакомства с KRC оно только усиливается.

В этой статье, частично пользуясь текстом Абельсона и Сасмана, выявляются различия в обучении на примере Scheme и на примере KRC и Miranda. Scheme - это диалект Lisp'a с лексической областью видимости, языки похожего стиля - это T и Common Lisp. KRC - это функциональный язык в алгебраическом стиле, Miranda - его преемник. SASL и Orwell - языки, подобные KRC. (Только те читатели, которые знают, что KRC расшифровывается как "Kent Recursive Calculator" смогут оценить заголовок этой статьи).

Есть четыре языковых свойства, отсутствующих в Scheme и существующих в KRC/Miranda:


1. Сопоставление с образцом
2. Синтаксис, близкий к традиционной математической нотации
3. Статическая типизация и пользовательские типы
4. Ленивые вычисления



KRC и SASL не имеют статической типизации, так что пункт 3 относится только к Miranda, LML, и Orwell.

Эта статья - прежде всего рассуждения об относительной важности этих языковых свойств, а не просто сравнение достоинств двух типов языков. Но для удобства в этой статье "Lisp" и "Miranda" будут использоваться для различения двух семейств. (В ранних версиях этой статьи термин "функциональный" использовался для характеристики языков семейства Miranda, но только пункт 4 отражает тот факт, что эти языки функциональные).

Это статья по большей части основана на моем более чем двухлетнем опыте знакомства с двумя различными курсами: курсом для первокурсников, основанном на книге Абельсона и Сассмана и преподаваемом Joe Stoy, использующего Scheme (хотя на самом деле, использовался язык T, модифицированный так, чтобы выглядеть как Scheme); и курсе функционального программирования для магистров, преподаваемом Ричардом Бердом, использующего KRC.

Статья организована следующим образом. В первом разделе обсуждаются типы данных. В разделе 2 рассматриваются противорения между программами и данными. В разделе 3 обсуждаются программы, которые манипулируют программами. В разделе 4 - ленивые вычисления. И в разделе 5 подводится заключение.

1. Типы данных

1.1 Списки

Много лет назад Питер Ландин сформулировал прекрасный способ описания типов данных. Описание списков, использущее этот метод выглядит так:

СПИСОК это
или пусто(nil)
или ячейка(cons), которая содержит
голову, обозначаемую A
и хвост, который есть СПИСОК


Из описания типа, мы ясно видим структуру программы, которая оперирует такими списками. Например, вот программа на Miranda, подсчитывающая сумму списка из чисел:

sum [] = 0
sum (x:xs) = x + sum xs


Это определение состоит из двух высказываний, по одному на каждый пункт (nil и cons) в определении СПИСКА (В Miranda nil записывается как [], а cons с головой x и хвостом xs как x:xs.)

Вот подобная функция, записанная на Lisp:

(define (sum xs)
(if (null? xs)
0
(+ (car xs) (sum (cdr xs)))))


Такое определение более сложно для чтения, даже хотя оно имеет ту же структуру, что и предыдущее. Основная проблема - отсутствие сопоставления с образцом. Это определение также сложнее читать из-за синтаксиса (вернее, из-за отстутствия синтаксиса) Лиспа.

Более того, Lisp программа скрывает симметрию между двумя случаями. Вариант с nil проверяется явно, тогда как вариант с cons подразумевается в обратном случае. Симметрия может быть возвращена, таким вот описанием:

(define (sum xs)
(cond ((null? xs) 0)
((pair? xs) (+ (car xs) (sum (cdr xs))))))


Эта программа, возможно, еще более непонятна, чем предшествующая. Она также слегка неэффективна, так как производит два сравнения вместо одного.

Не забывайте, что существуют хорошо известные способы эффективной компиляции выражений сопоставления с образцом.

В Miranda строгая типизация контролирует, что функция sum может быть применена только к списку чисел.

Т.к. Miranda использует вывод типов, программист может указать тип функции явно или оставить его для вывода компилятору. Другими словами, вывод типов означает, что типизация(typing of data) не приводит к дополнительным нажатиям пальцев (typing with fingers).

Строгая типизация необходима по двум взаимодополняющим причинам. Во-первых, типизация - это удобный способ рассуждений о функциях и определениях функций.

Во-вторых, компилятор (language system) гарантирует, что определенные типы ошибок не возникнут во время работы программы.

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

1.2 Доказательсто свойств программ

Допустим что мы хотим доказать что функция append - ассоциативна. Вот описание append (обозначенное ++) в стиле Miranda:


[] ++ ys = ys (1)
(x:xs) ++ ys = x:(xs ++ ys) (2)


Мы хотим доказать, что для всех списков xs, ys, и zs:

(xs ++ ys) ++ zs = xs ++ (ys ++ zs)


Доказательство проведем по индукции по xs

Базовый случай: Заменим xs на []

([] ++ ys) ++ zs
= ys ++ zs - раскрываем, пользуясь (1)
= [] ++ (ys ++ zs) - обратная операция (1)


Индукция: Заменяем xs на x:xs

((x:xs) ++ ys) ++ zs
= (x:(xs ++ ys)) ++ zs - раскрываем, пользуясь (2)
= x:((xs ++ ys) ++ zs) - раскрываем, пользуясь (2)
= x:(xs ++ (ys ++ zs)) - предположение индукции
= (x:xs) ++ (ys ++ zs) - обратная операция (2)


Доказательство завершено.

Теперь рассмотрим определение append на Lisp:

(define (append xs ys)
(if (null? xs)
ys
(cons (car xs) (append (cdr xs) ys))))


Выражение, которое должно быть доказано:

(append (append xs ys) zs) = (append xs (append ys zs))


Читателю предлагается описать доказательство в терминах Lisp'а. Обратите внимание на две определенные сложности.

Во-первых, в Miranda доказательство, прямые и обратные шаги могут быть объяснены как простые замены равного на равное. Аналогичное раскрытие в Lisp требует подстановки определения, а затем упрощения. Например, первый шаг базового случая, отвечающий раскрытию, использующему (1), запишется так:

(append nil (append ys zs))
= (if (null? nil)
(append ys zs)
(cons (car nil)
(append (cdr nil) (append ys zs))))
= (append ys zs)


Обратная операция еще более проблематична.

Здесь, главная идея состоит в том, что сопоставление с образцом серьезно упрощает механизм доказательства.

Во-вторых, каждый шаг Miranda доказательства - это просто перестраивание скобок. Хотя те же структурные элементы аналогично предствлены в Lisp, префиксная нотация требует больших умственных усилий для совершения каждого шага. Этот эффект наиболее явно проявляется при доказательстве ассициативности, но, в общем, любая алгебраическая манипуляция проще в инфиксной нотации; собственно, из-за этого такая нотация и применяется.

По этим причинам, написание полного доказательства более сложно в Lisp нотации, чем в Miranda. Это серьезная помеха при обучении студентов даже простым методам доказательства. Я и несколько моих коллег, столкнувшись с этой проблемой, решили, что проще обучить студентов Miranda-подобной нотации, нежели чем пытаться доказывать что-либо прямо на Lisp. Первоначальное обучения Miranda-подобной нотации может быть сделано быстро и неформально, т.к. эта нотация достаточно естественна.

Некоторые люди могут возразить, что многие проблемы, описанные в этой статье, это "просто синтаксис".

Действительно, большинство дебатов о синтаксисе приносят мало пользы. Но учите что, хороший выбор нотации может значительно помочь обучению и размышлениям, а плохой выбор стать помехой этому. В частности, сопоставление с образцом, кажется, помогает рассуждениям об анализе случеев, делая проще создание программ и доказательство их свойств, пользуясь индукцией. Также, математической нотацией по сравнению с Lisp нотацией легче манипулировать алгебраически.

1.3 Мобили

Вот часть упражнения 2-27 из Абелсона и Сассмана:

Бинарный мобиль состоит из двух ветвей, левой и правой. Каждая ветвь представляет
собой стержень о пределенной длины, с которого свисает либо гирька, либо еще один
бинарный мобиль. Мы можем представить бинарный мобиль в виде составных данных,
соединив две ветви (например, с помощью list):

(define (make-mobile left right)
(list left right))

Ветвь состоит из длины length (которая должна быть числом) и стуктуры structure,
которая может быть либо числом (представляющим простую гирьку), либо еще одним
мобилем:

(define (make-branch length structure)
(list length structure))

a. Напишите соответствующие селекторы left-branch и right-branch,
которые возвращают ветви мобиля, и branch-length и
branch-structure, которые возвращают компоненты ветви.

b. Используюя эти селекторы, определите процедуру total-weight,
которая возвращает общий вес мобиля.



Опытному программисту не составит труда найти ответ:


(define (left-branch struct) (car struct))
(define (right-branch struct) (cadr struct))
(define (branch-length branch) (car branch))
(define (branch-structure branch) (cadr branch))

(define (total-weight struct)
(if (atom? struct)
struct
(+ (total-weight-branch (left-branch struct))
(total-weight-branch (right-branch struct)))))

(define (total-weight-branch branch)
(total-weight (branch-structure branch)))


К сожалению, ответ не так-то легко найти начинающему программисту. Это потому, что, хотя вопрос тщательно сформулирован, он полностью игнорирует очень важный аспект структуры данных - а именно, основной случай вырожденного мобиля (или структуры), состоящего из одной гирьки. На самом деле, вопрос путает студентов, так как между мобилями и структурами сделано четкое разграничение, а задача ставится о нахождении функции, вычисляющей, скорее, общий вес мобиля, а не структуры.

В языке с возможностью определения пользовательских типов, первый шаг к решению этой проблемы - написать подходящие определения типов. Это сразу же обращает внимание на базовый случай. Вот подходящие определения на Miranda:

stucture ::= Weight num | Mobile branch branch
branch ::= Branch num structure


Функция, подсчитывающая общий вес, может быть записана в лоб, используя определение типов как руководство.

totalWeight (Weight w) = w
totalWeight (Mobile l r)
= totalWeightBranch l + totalWeightBranch r

totalWeightBranch (Branch d s) = totalWeight s


Программа на Miranda отражает структуру типов более прямолинейно, чем программа на Lisp, эта программа также проще для чтения. Более того, селектирующие функции вообще не используются.

1.4 Представление данных и абстрактные типы данных

Задача о мобилях продолжается следующим образом:

d. Представьте что мы изменили представление мобилей так, что
конструкторы теперь приняли такой вид:

(define (make-mobile left right)
(cons left right))

(define (make-branch length structure)
(cons length structure))

Как много Вам нужно изменить в программах, чтобы перейти на новое
представление?


В Lisp мы должны перейти в селекторах right-branch и branch-structure на использование cdr вместо cadr. Для Miranda подобный вопрос не имеет значения, потому что здесь нет селекторов. Это указывает на некоторые преимущества, но также и на недостатки использования Miranda для обучения представлению данных.

Первое преимущество состоит в том, что для некоторых типов данных, называемых свободными типами данных, Miranda позволяет писать программы на более высоком уровне абстракции, где выбор представления не важен. Тип данных называется свободным, если два объекта этого типа эквивалентны тогда и только тогда, когда они сконструированы одинаковым способом. И списки, и мобили - свободные типы данных. Например, списки свободны, т.к. x:xs = y:ys тогда и только тогда, когда x = y и xs = ys. Пример несвободного типа данных - множество, потому что {x} U xs = {y} U {ys} не подразумевает что x=y и xs = ys.

В Lisp, по существу, один свободный тип данных - S-выражения. Если пользователь нуждается в другом свободном типе данных, например, списке или мобиле, тогда он или она должны выбрать представление этого типа в терминах S-выражений. Как мы видели на примере мобилей, существует более чем один вариант выбора. В Miranda пользователь может объявлять новые свободые типы данных явно. Здесь нет необходимости выбирать некоторое произвольное представление. Поэтому, для задачи о мобилях вопрос о смене представления неуместен, потому что мы решили задачу на более высоком уровне абстракции.

Второе преимущество заключается в том, что там, где выбор представления важен, Miranda предоставляет языковую особенность - абстрактные типы данных - для разделения использования типов от выбора из представления. Например, Абельсон и Суссман обсуждают несколько различных путей представления множеств. В разработке программ, классической способ для абстрагирования от произвольного выбора представления - это абстрактные типы данных. Хотя Абельсон и Суссман детально обсуждают абстракцию данных, они не говорят об абстрактных типах данных явно, потому что Lisp не содержит подходящих механизмов для скрытия. Такие языки как Miranda и LML поддерживают классический механизм абстрактных типов данных и поэтому, возможно, лучше подходят для обучения этой теме.

Недостаток состоит в том, что сопоставление с образцом, будучи таким полезным, не может быть использовано с абстрактными типами данных. Пути решения этой проблемы видны на горизонте. Одна из возможностей - алгебраические типы данных с правилами - реализована в Miranda и позволяет использовать сопоставление с образцом с некоторыми несвободными типами данных. Другая - это Views, языковая конструкция, которая позволяет использовать сопоставление с образцом с любыми произвольными представлениями. В Lisp нет подобной проблемы, но так как он выливает младенца вместе с водой, в нем нет сопоставления с образцом вообще.

1.5 Послесловие об упражнении с мобилями

Напоследок хочу обратить внимание на один момент. Упражнение с мобилями, на самом деле, не очень хорошая модель для рассказа студентам о смене представления. Проблема в том, что хотя представления мобилей и ветвей скрыто за селекторами, представления обычной гирьки нет. Это не проблема в Lisp, т.к. в нем легко добавить необходимые конструкторы и селекторы:

(define (make-weight weight) weight)
(define (weight? struct) (atom? struct))
(define (weight struct) (struct))


Тогда исправленное определение total-weight выглядит так:

(define (total-weight struct)
(if (weight? struct)
(weight struct)
(+ (total-weight-branch (left-branch struct))
(total-weight-branch (right-branch struct)))))


2. Неразбериха между программой и данными

Важнейшее свойство Lisp, то что программа и данные имеют одно и тоже представление, называемое S-выражениями, и специальная форма "quote" служит для превращения программы в данные. Это приводит к удобному стилю для написания программ, которые манипулируют программами, такие как интерпретаторы. Это также делает Lisp языком, простым для расширения.

C другой стороны, новички путаются в отношениях между программами и данными.

В этом разделе описываются подобные случаи, которые я наблюдал у многих студентов на протяжении обучения. Более того, когда дело доходит до написания программ, которые манипулируют программами. Хотя Lisp отлично для этого подходит, Miranda нисколько не хуже.

2.1 Lisp списки не самоцитируемы (self-quoting)

В Lisp числа как данные самоцитируются, тогда как списки нет. Например, для включения числа 3 как данных в программу, мы просто пишем 3, тогда как для списка (1 2 3) как данных, мы пишем (quote (1 2 3)) (что часто сокращается до '(1 2 3))

Различие между (1 2 3) и (quote (1 2 3)) едва заметно, и неизбежно путает студентов. В частности, оно приводит к хаосу при рассмотрении подстановочной модели вычислений. Например, можно использовать подстановочную модель для объяснения вычисления (* (+ 3 4) 6) таким образом:

(* (+ 3 4) 6) ---> (* 7 6) ---> 42


Все три шага преобразования ((* (+ 3 6)), (* 7 6), 42) сами по себе - корректные Lisp выражения.

Теперь попробуем использовать подстановочную модель для объяснения вычисления выражения (list (list 1 2) nil):

(list (list 1 2) nil)
---> (list (1 2) nil)
---> (list (1 2) ())
---> ((1 2) ())


Промежуточные шаги - больше не корректные Lisp выражения. Мы должны помнить, какие части выражения уже были вычислены, а какие еще нет. Можно было бы избежать этого, написав:

(list (list 1 2) nil)
---> (list '(1 2) nil)
---> (list '(1 2) '())
---> '((1 2) ())


Но я считаю, что это слишком сложно объяснить.

С другой стороны, в Miranda мы просто пишем [[1,2], []]. Здесь просто нет никаких вычислений для объяснения.

Если вычисления есть, они могут быть описаны простыми подстановками:

[7*6, 5*9] ---> [42, 5*9] ---> [42, 54]


Каждый шаг преобразования является правильным Miranda выражением.

Речь здесь не о том, что вычисление (list (list 1 2) nil) нельзя объяснить. Конечно, можно. Но это займет больше времени, чемобъяснение Miranda выражения [[1,2], []]. Возможно, в этом случае можно позволить себе дополнительные усилия. Но проблема серьезно усугубляется, когда необходимо объяснить это в середине какого-нибудь другого вывода. Я сталкивался с подобным множество раз.

2.2 Еще больше путаницы с цитированием

Вот упражнение 2-30 из книги Абельсона и Суссмана:

Ева Лу Атор вводит при работе с интерпретатором выражение

(car ''abracadabra)

К ее удивлению, интерпретатор печатает quote. Объясните, что будет
напечатано в ответ на

(cdddr '(this list contains '(a quote)))


Ответ на первый вопрос: (car ''abracadabra) эквивалентно (car
(quote (quote abracadabra))). Поэтому при вычислении мы получаем:

(car (quote (quote abracadabra)))
---> (car (quote abracadabra))
---> quote


В этом случае отслеживания тех частей, которые еще не были вычислены, не
избежать.

Ответом на второй вопрос является то, что Lisp трансформирует при вводе данное выражение в:

(cddr (quote (this list contains (quote (a quote)))))


и результатом вычисления будет ((quote (a quote))).

Все это выглядит довольно мрачно.

В книге Абельсона и Сассмана, эквивалентность 'a и (quote a) объясняется только в сноске. Но для того, чтобы полностью понимать Lisp, вы должны понимать вещи такого рода. В языке без цитирования(quote), такого типа проблемы просто не возникают.

2.3 Вычисляя слишком мало, или слишком много

Т.к. программа и данные имеют одну и ту же форму в Lisp, выражение само по себе не говорит о том, с чем мы имеем дело - с программой или данными. Как было показано выше, мы вынуждены отслеживать эту информацию во время применения подстановок. Студентам легко потерять нить рассуждений, и в результате вычислить слишком мало или слишком много.

Какое значение у этого выражения?

(car (quote (a b)))


Правильный ответ, конечно, a. Однако, я встречал студентов, которые давали ответ quote, что является результатом слишком малого вычисления. Такая ошибка случается практически постоянно, после того, как они завершат вышеописанное упражнение с abracadabra.

Я также встречал студентов, дававших ответ -"значение переменной a", что является результатом слишком многих вычислений. Это потому, что студенты вначале вычисляют достаточно, чтобы получить правильный ответ "a", а затем вычисляют еще один шаг.

Студенты совершают эту ошибку даже если никакой переменной с именем a не упоминалось в связи с этой проблемой.

И опять, подобного типа проблемы не возникают в языках без цитирования(quote)

2.4. Путаница со списками

Есть еще пара сложных моментов, встречавшихся мне во время обучения студентов типу данных - СПИСОК. Эти сложности проистекают от самих списков и проявляются при обучении как на примере Lisp, так и на примере Miranda, потому что студенты уже страдают от путаницы между данными и программой.

Первая проблема в том, что студенты неизбежно путают список, содержащий один элемент x, с самим элементом x. Проблема тесно связана с Lisp, потому что в нем список из одного элемента записывается как (list x) или (x), в зависимости от того, было ли значение вычислено или нет. В Miranda всегда пишется [x]. Особенности синтаксиса Miranda также слегка помогают: студенты склонны отбрасывать круглые скобки, так что (x) превращается в x. В строготипизированном языках как Miranda, маловероятно что они будут превращать [x] в x, т.к. если x имеет тип t, тогда [x] имеет тип список с элементами типа t; и ошибка будет обнаружена средой при проверке типов.

Вторая проблема в том, что студенты путаются между cons и list. Опять же, эта проблема проявляется сильнее в Lisp, потому что (cons x y) и (list x y) выглядят так похоже, тогда как x:y и [x,y] выглядят достаточно различно. И, опять же, проблему проще объяснить и найти в строготипизированном языке.

2.5. Синтаксис

Наконец, сложно не упомянуть о знаменитом синтаксисе S-выражений в Lisp. У синтаксиса есть серьезные преимущества. Его просто изучить, и он дает студентам хорошее понимание нижележащей абстрактной структуры.

С другой стороны, как показано выше, Lisp программы более массивны, чем аналогичные программы на Miranda. Также, как замечено выше, S-нотация мешает рассуждениям об алгебраических свойствах, таких, как ассоциативность. Возможно, наиболее важно то, что непривычность Lisp синтаксиса может быть реальным препятствием на пути начинающих студентов.

Я помню случай, когда, рассказывыя небольшой группе студентов, пытался убедить их в великой силе и легкости использования Lisp. Объяснив, что 3 + 4 записывается как (+ 3 4), я стал писать несколько больших выражений. Одно из них было ((+ 3 4) = (+ 5 2)), которое заставило интерпретатор сообщить об ошибке. Я быстро исправил код, но я потерял почву под ногами в попытке объяснить студентам насколько "натурален" синтаксис S-выражений. Если даже я, опытный Lisp программист, совершаю такие ошибки, то хотел бы я знать, сколько неприятностей причиняет он студентам?

3. Программы которые манипулируют программами

Lisp известен легкостью, с которой на нем можно создавать программы, которые манипулируют программами, такие как интерпретаторы, компиляторы, и системы преобразования программ. Однако Miranda также имеет ряд преимуществ в дополнение к тем, что есть в Lisp, для создания подобных программ. В этом разделе сравниваются стили Lisp и Miranda для написания таких программ.

3.1. Простой интерпретатор на Miranda и Lisp

В качестве простого примера интерпретатора, возьмем вычислитель выражения лямбда исчисления. Существует три типа выражений: переменные(variables), лямбда абстракции и аппликации. Также еще один тип выражения - замыкание(closure), которое будет использоваться внутри интерпретатора.

Интерпретатор состоит из двух взаимно рекурсивных функций. Вызов (eval e t) вычисляет свободное выражение t в окружении e. Вызов (apply t0 t1) вычисляет аппликацию выражения t0 (которое должно быть замыканием) к терму t1. Miranda и Lisp версии интерпретатора показаны в листингах 1 и 2. Типы данных, использующиеся в этих программах, детально разбираются ниже.

3.2. Свободные типы данных для представления программ

В Miranda типы данных для выражений лямбда исчисления запишутся следующим образом:

term := Var var
| Lambda var term
| Apply term term
| Closure env var term

env == [(var, term)]
var == [char]


Выражение Closure e v t представляет собой замыкание в окружении e лямбда терма со связанной переменной v и телом t. Две последние строчки декларируют, что окружение представляется списоком пар переменная-выражение, и что имена переменных представляются списком символов.

В таком представлении, выражение:

(λx. (x x)) (λx. (x x))


записывается как:

(Apply (Lambda "x" (Apply (Var "x") (Var "x")))
(Lambda "x" (Apply (Var "x") (Var "x"))))


Преимущество Miranda в том, что определения типов для выражения точно и информативно, а сопоставление с образцом делает программу проще для написания и для чтения. Недостаток в том, что описания программы-как-данных громоздко. Вкратце: манипулирование данными просто, но написание данных для манипуляций сложно.

Опыт обучения KRC и Orwell показал, что вышеприведенная нотация, хоть и громоздкая, но все же применима на практике для малых и средних по размеру примеров.

Часто можно сократить проблемы, введя немного дополнительных определений, делающие данные проше к введению. Например, мы можем определить:

lambda (var v) t = Lambda v t
app t0 t1 = Apply t0 t1
x = Var "x"


а затем записать:

app (lambda x (app x x)) (lambda x (app x x))


запись вполне приемлема, если даже не элегантна.

Лучшим подходом будет написание парсеров для конвертирования между двумя нотациями: нотацией, удобной для чтения и записи программ как данных, и нотацией, удобной для манипулирования ими.

Естественно, это требует больше работы, но это также приносит больше выгоды. Парсеры сами по себе интересная задача, и важны для практических систем, работающих с программами как данными. Один из интересных подходов к созданию парсеров на функциональных языках описывается в [Wadler 1985c].

3.3 Представление программ с помощью почти абстрактного синтаксиса

В Lisp есть несколько способов представления лямбда-термов. Один из наиболее распространенных вариантов:

v - переменная
(lambda (v) t) - лямбда абстракция
(t0 t1) - аппликация
(closure e v t) - замыкание


В таком представлении исходное выражение запишется:

'((lambda (x) (x x)) (lambda (x) (x x)))


что менее громоздко, чем подобное Miranda выражение.

Подобное представление обычно называют "абстрактным синтаксисом", но более уместно называть его "почти абстрактным синтаксисом". Настоящий абстрактный синтаксис выглядит так:

(var v) - переменная
(lambda v t) - лямбда абстракция
(apply t0 t1) - аппликация
(closure e v t) - замыкание


И теперь выражение запишется как:

'(apply (lambda x (apply (apply (var x) (var x))))
(lambda x (apply (apply (var x) (var x)))))


что также громоздко, как и в Miranda.

Ключевая идея почти абстрактного синтаксиса состоит в том, что если для немногих общих выражений предоставлена подходящая нотация(в этом случае - для переменных и аппликаций), тогда приемлим полный абстрактный синтаксис для всего остального. Представления, основанные на "почти абстрактном синтаксисе", достаточно распространены в Lisp. Например, представление мобилей, обсуждаемых в разделе 1, использует это принцип там, где специальная нотация предоставлена для гирек, но ветви и мобили используют полностью абстрактную нотацию.

Манипулирование программами как данными выглядит проще в Miranda, но ввод данных проще в Lisp. В значительной степени это обусловлено принципом "почти абстрактного синтаксиса", нежели тем, что программы и данные представлены одинаково в Lisp.

Может ли подобный принцип быть каким-то образом добавлен в Miranda-подобный язык, например, добавив специальную нотацию для некоторых элементов данных?

Листинг 1: Вычислитель лямбда выражения на Miranda

|| data types

term ::= Var var
| Lambda var term
| Apply term term
| Closure env var term

env == [(var, term)]
var == [char]

|| evaluate and apply

eval e (var v) = lookup e v
eval e (Lambda v t) = Closure e v t
eval e (Apply t0 t1) = apply (eval e t0) (eval e t1)

apply (Closure e v t0) t1 = eval (extend e v t1) t0

|| environment manipulation

lookup ((v0,t):e v1 = t, if (v0 = v1)
= lookup e, v1, otherwise

extend e v t = (v,t):e
empty = []

Листинг 2: Вычислитель лямбда выражения на Lisp

;; evaluate term t in environment e

(define (eval e t)
(cond ((variable? t)
(lookup e (variable-name t)))
((lambda? t)
(make-closure e (lambda-var t) (lambda-body t)))
((apply? t)
(apply (eval e (apply-operator t))
(eval e (apply-operand t))))))


;; apply term t0 to term t1
(define (apply t0 t1)
(cond ((closure? t0)
(eval (extend (closure-env t0) (closure-var t0) t1)
(closure-body t0))))

;; environment manipulation

(define (lookup v e)
(cond ((pair? e)
(if (eq? v (caar e)) (cadr e) (lookup v (cdr e))))))

(define (extend e v t) (cons (cons v t) e))
(define empty nil)

;; crate and access terms

(define (make-var v) v)
(define (variable? t) (atom? t))
(define (variable-name t) t)

(define (make-lambda v t) (list 'lambda (list v) t))
(define (lambda? t) (and (not (atom? t)) (eq? (car t) 'lambda)))
(define (lambda-var t) (caadr t))
(define (lambda-body t) (caddr t)

(define (make-apply t0 t1) (list t0 t1))
(define (apply? t)
(and (not (atom? t)) (not eq? (car t) 'lambda)))
(define (apply-operator t) (car t))
(define (apply-operand t) (cadr t))

(define (make-closure e v t) (list 'closure e v t))
(define (closure? c) (and (not (atom? c)) (eq? (car c) 'closure)))
(define (closure-env c) (cadr c))
(define (closure-var (caddr c)))
(define (closure-body c) (cadddr c))



4. Ленивые вычисления

Мощь Miranda заключается в использовании ленивых вычислений. Некоторые аргументы в пользу ленивых вычислений содержатся в [Turner 82, Hughes 85, Wadler 85c].

Абельсон и Сассман признают важность ленивых вычислений и включили в книгу ограниченную версию ленивых вычислений, назвав ее потоками (streams). В разделе "Потоки" обсуждаются важные методы программирования с ленивыми вычислениями. Однако, как обычно, Lisp более громоздок, чем Miranda. Например, для нахождения суммы квадратов нечетных чисел от 1 до 100 мы пишем:


sum [i*i | i <- [1..100]; odd i]


в Miranda, а в Lisp


(sum-stream
(collect (* i i)
((i (enumerate-interval 1 100)))
(odd i)))


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

Более коварная, и поэтому более серьезная проблема возникает при взаимодействии потоков и аппликативного порядка вычислений, используемого в Lisp. Например, достаточно полезная теорема

map f (xs ++ ys) = map f xs ++ map f ys
(функция map f xs применяет f к каждому элементу списка xs,
а xs ++ ys соединяет списки xs и ys)


к сожалению, не выполняется в Lisp! Например, вычисление

(head
(map sqrt
(append-stream (enumerate-interval 7 42)
(enumerate-interval -42 -7))))


возвращает квадратный корень из 7, тогда как вычисление

(head
(append-stream
(map sqrt (enumerate-interval 7 42))
(map sqrt (enumerate-interval -42 -7))))


сообщает об ошибке времени выполнения при попытке найти квадратный корень из -42. Проблема в том, что append-stream, как и все функции в Lisp, должен вычислить все свои аргументы.

(Конкретно этой проблемы можно избежать, если изменить потоки таким образом, чтобы заморозить вычисление головы потока так же, как заморожено вычисление хвоста. Однако, теорема все равно не будет выполняться, как вы можете увидеть, заменив (enumerate-interval -42 -7) на (bottom), где вычисление (bottom) приводит к бесконечному циклу.

Очевидно, проблемы, подобные этой, наносят ущерб представлению программирования как применения математического подхода.

Они также могут приводить к ошибкам в программе (например см упражнение 3-54 и его обсуждение в книге Абельсона и Сассмана).

Абельсон и Сассман обнаружили эти проблемы, и их обсуждение потоков включает объяснение, почему потоки наиболее хорошо подходят для языков с нормальным(ленивым) порядком вычислений. Они объясняют свой отказ от выбора нормального порядка вычислений тем, что это сделало бы присваивания сложными в использовании. Их выбор позволяет показать студентам два важных подхода к построению программ: присваивания и потоки; но в результате потоки не могут быть показаны во всей красе.

Я настаиваю на том, что преимущества ленивых вычислений перевешивают преимущества возможности обучения присваиваниям на первом курсе. Я верю, что основное преимущество ленивых вычислений в том, что можно отложить рассказ о присваиваниях до завершения первого курса (Абельсон и Сассман согласны с тем, что присваивания не должны преподаватся слишком рано, они отложили это вплоть до середины своей книги).

4.2. С ленивыми вычислениями специальные формы не нужны.

Вот упражнение 1-4 из Абельсона и Сассмана:

Алиса П. Хакер не понимает, почему if должно быть реализовано как
специальная форма: "Почему мы не можем определить if как обычную
процедуру с помощью cond?" Лизина подруга Ева Лу Атор утверждает, что,
разумеется, можно, и определяет новую версию if:

(define (new-if predocate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))

Обрадованная Лиза переписывает через new-if программу вычисления
квадратного корня:

(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))

Что получится, когда Лиза попытается использовать эту процедуру для
вычисления квадратных корней? Объясните.


Ответ, конечно, состоит в том, что sqrt-iter войдет в бесконечный цикл, потому что new-if всегда вычисляет все свои аргументы, тогда как специальная форма (if e1 e2 e3) вычисляет e2 только когда e1 есть nil, или e3 в противном случае.

Только очень способные студенты отвечают на этот вопрос правильно, и
требуется приложить довольно большие усилия для объяснения остальным,
что такое "специальные формы" и зачем они нужны.

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

newIf true x y = x
newIf false x y = y


и newIf будет вычислять только e2 или e3 в зависимости от значения e1. Нет необходимости в специальных формах. Следовательно, подстановочная модель вычисления становится более стройной и проще для объяснения.

5. Заключение

Книга Абельсона и Сассмана является прекрасным введением в программирование как инжененерную дисциплину. Мой опыт подсказывает, что такие языки, как KRC и Miranda значительно лучше подходят для этого, нежели Lisp.

В разделе 1 показано как сопоставление с образцом и определяемые пользователем типы предоставляют лучший подход к типам данных. В разделе 2 показано, что содержание программы и данных в одной форме приводит к неразберихе в Lisp, чего не происходит в KRC и Miranda. Иногда утверждается, что подобная неразбериха необходима длясоздания программ, которые манипулируют программами. В разделе 3 показано, что это не совсем верно, и что подходы как Lisp так и Miranda обладают определенными преимуществами. В разделе 4 показано, что с потоками легче работать в языке с ленивым порядком вычислений, и в них также не возникают некоторые проблемы со специальными формами. Плата за это - отложенное на последующий курс обучение присваиваниям.

Некоторые читатели могут сказать, что языки подобные KRC и Miranda "недостойны" использовться в обучении, т.к. они не используются в реальном мире. Верно, что первый курс, использующий KRC или Miranda, не достаточен для подготовки студентов к реальному миру, и тоже самое верно для первого курса, использующего Lisp. Цель первого курса - обучить основным принципам и развить правильный образ мыслей. В этой статье я объясняю, почему я верю, что такие языки, как KRC и Miranda хорошо подходят для этого. Дальнейшие курсы должны применять эти принципы к императивным языкам, таким как Pascal иди Modula, и, возможно, даже к другим языками для баз данных или распределенных вычислений. Then the student is prepared to program in Fortran or Cobol, if need be, and to agitate for the introduction of Pascal, Lisp, or Miranda where they are appropriate.

После этого студент готов к программированию на Fortran или Cobol, если потребуется, и применять Pascal, Lisp или Miranda в зависимости от задачи.

Я приступал к обучению Lisp, считая, что различия с KRC и Miranda будут вызывать, как максимум, небольшое раздражение. Основные концепции были теми же, и я не считал, что предубеждение перед синтаксисом Lisp'a будет большой преградой. Опыт убедил меня в обратном. Хотя каждая сложность сама по себе минимальна, общий эффект достаточно значителен.


Благодаря Абельсону и Сассману возник новый подход в обучении программированию. Я рассчитываю, что другие учителя последуют по этому пути, и с нетерпением жду нового поколения учебников, написанных с использованием KRC или Miranda.

Благодарности

Хэл Абельсон и Джерри Сассаман сделали множество подробных и тонких комментариев к черновику этой статьи. Комментарии от Ричарда Берда и Джо Стоя также очень помогли в написании этой статьи.

среда, 24 июня 2009 г.

SLIME для Windows

Как установить SLIME для Windows:

1. Скачать и установить Emacs.

2. Скачать и установить SBCL, например в директорию C:\SBCL.

3. Скачать и распаковать SLIME, например в директорию C:\SLIME.

4. Отредактировать init.el добавив следующий lisp код:

(setq inferior-lisp-program "c:/sbcl/sbcl.exe")
(add-to-list 'load-path "c:/home/site/slime-2.0/")
(require 'slime)
(slime-setup)

Теперь SLIME должен работать.

суббота, 28 марта 2009 г.

Постоянные читатели

Обо мне

Моя фотография
For such a time as this I was placed upon the earth To hear the voice of God, and do his will - whatever it is. Группа крови: II+. Рост: 176см. Вес: 65кг. Радикальный христианин, толстокожий, тугодум, миролюбивый, свободолюбивый, теплолюбивый, солнцелюбивый, романтик, жаворонок, читаю по слогам, но очень люблю читать любимые книги, люблю красивые пейзажи: горы, море, небо, закаты, но больше всего люблю вас, мои драгоценные друзья!