Для получения локального времени из GMT, по умолчанию, VW использует не средства операционной системы, а собственный класс TimeZone. Как результат - необходимость установки временной зоны в образе VW.
Для установки нужной временной зоны нужно зайти в пункт меню "System->Settings->Time Zones", выбрать код, задающий нужную зону, и выполнить его. После этого вы получите образ, корректно выдающий время для той временной зоны, которую вы установили. Но, если сменится временная зона в операционной системе, то VW это "проигнорирует". То есть, если программа распространяется в нескольких временных зонах, вам прийдётся вделать свой интерфейс для установки нужной зоны.
Для автоматизации установки временной зоны и был создан пакет OSTimeZone. Первоначально он просто создавал объект класса TimeZone по информации из операционной системы. В последних же версиях пакета содержится более правильное решение этой проблемы. Там добавленна временная зона, которая обращается к ОС для получения локального времени. То есть, после установки этой временной зоны в качестве текущей, в большинстве случаев, не нужно заботится о том, совпадает ли зона в VW с зоной установленной в ОС.
Пакет OSTimeZone поставляется в дистрибутиве с VW. Там, однако, содержится устаревшая версия пакета. Загрузить последнюю версию пакета необходимо из публичного репозитория. Перед загрузкой пакета OSTimeZone не забудьте загрузить парсел DLLCC. После загрузки необходимо выполнить в Workspace команду 'OSSystemSupportTimeZone use' и проверить результат с помощью 'Time now'.
OSTimeZone работает, как минимум, в Windows и Linux.
Ярлыки: vw
Avi Bryant - создатель веб-фреймворка основанного на продолжениях Seaside - анонсировал сайт для Seaside-сообщества. Информации пока не много, но это только начало.
Сайт доступен по адресу www.seaside.st и представляет из себя wiki - SmallWiki.
Так же, сменилась лицензия. Все новые версии Seaside будут идти под MIT лицензией.
Доступна коммерческая поддержка.
Ярлыки: seaside
Ярлыки: vw
Для VisualWorks существует открытый Store-репозиторий, содержащий ряд полезных пакетов. Некоторые из них мы рассматривали раннее. Сегодня же остановимся еще на двух пакетах.
Первоначально пакет первоначально был разработан для Squeak. И позже портрован на VW.
После загрузки пакета порождается процес с высоким приоритетом. Этот процес постоянно отслеживает глубину стека каждого процесса и если превышена определённая глубина (вероятно зацикливание), то процесс останавливается и открывается в отладчике, что позволяет обнаружить причину роста стека.
По умолчанию, порог, после которого открывается отладчик, установлен в 100'000 вызовов. См. метод класса Process class>>stackOverflowLimit
Порог для срабатывания можно установить для каждого просесса отдельно. Для этого нужно послать процессу сообщение #stackOverflowLimit: с аргументом - порогом срабатывания.
Что-бы проверить работу утилиты создайте класс Test с одним методом:
rec self rec
И затем в workspace выполните команду Test new rec
Первоначально это расширение так же было разработано для Squeak.
После загрузки этого пакета у вас появится возможность запускать операции, ограничивая время их выполнения.
Для того, что-бы ограничить время работы блока, нужно послать этому блоку сообщение #valueWithin:onTimeout:. Параметр valueWithin: задаёт время работы блока-получателя сообщения. Это объект класса Squeak.Duration (этот класс определён в пакете Squeak-Chronos). Параметр onTimeout: это блок, который запускается на выполнение при достижении тайм-аута. Если тайм-аут не достигнут, то метод возвращает результат работы блока-получателя, если достигнут - результат работы блока onTimeout:.
Рассмотрим примеры:
[ 50000 factorial ] valueWithin: 1 second onTimeout: [ 666 ]. возвращает 666 [ 3 + 4 ] valueWithin: 1 second onTimeout: [ 666 ]. возвращает 7
Советую обратить внимание на эти пакеты, так как каждый из них состоит всего из пары методов, отлично демонстрируя возможности расширения Smalltalk-а
Ярлыки: vw
В данной статье мы расскажем об особенностях объекта nil.
Сразу стоит отметить, что nil из Smalltalk и null в традиционных языках, это далеко не одно и то же. Ключевое слово nil ссылается на синглтон класса UndefinedObject, наследника Object. То есть, он является полноценным объектом и может отвечать на любые сообщения, для которых есть реализации в классах Object и UndefinedObject.
Такая реализация контрастирует с семейством C-подобных языков, где null или (void*)0 или (TYPE*)0 обозначает "ничто". Под этим определением не скрывается никакого реального объекта, оно лишь обозначает, что данное значение не содержит корректной ссылки на объект заданного типа и может участвовать лишь в проверках с другими ссылками. Таким образом переменную, содержащую null, можно использовать в качестве параметра, но никогда в качестве объекта-получателя сообщения, иначе возникнет NullPointerException либо неопределенное поведение.
То есть, фактически, каждая ссылочная переменная имеет тип не просто <Type>, а <Type | null>. Поэтому теоретически любая переменная может стать причиной исключения в отсутствие проверки вида
if (var != null)
В частности, на практике часто возникает проблема при использовании следующей конструкции
var1.equals(var2)
Хотя было бы логично, чтобы null соответствующим образом отвечал на сообщение equals, иначе приходится писать вот так
var1 == var2 || (var1 != null && var1.equals(var2))
либо определить статический метод, реализующий данную проверку, либо гарантировать, что первая ссылка заведомо не содержит null.
Некоторые встроенные конструкции содержат обход указанной проблемы, например
var instanceof SomeClass
Данный оператор уже содержит встроенную проверку на null, но этот прием доступен только разработчикам языка.
Поэтому становится очевидным почему оператор instanceof (и ряд других) не может быть реализован в таком виде как метод экземпляра класса Object. Одна нелогичность явилась результатом появления других.
Но вернемся опять к Smalltalk и объекту nil. Так как UndefinedObject является прямым наследником Object, то он содержит всю базовую функциональность, его можно использовать в выражениях, и как параметр, и как получатель сообщения.
Например эти вызовы являются безопасными:
nil = nil вернет true nil = 'a string' вернет false nil class вернет UndefinedObject nil printString вернет 'nil'
В некотором смысле Smalltalk является более "безопасным" по отношению к языкам, в которых любое обращение к null вызывает исключение.
Благодаря этому также возникла идиома, по которой сама проверка заменяется на сообщение:
self someCondition isNil ifTrue: [...] nil isNil вернет true nil notNil вернет false Object new isNil вернет false Object new notNil вернет true
Также стало возможным реализовать упрощенную условную конструкцию (как всегда, в виде обычного метода), заменяющую проверку на nil:
result := self someCondition ifNil: ['nil value'] ifNotNil: [:obj | 'non-nil value: ' , obj printString]
Например, следующим образом может быть реализован Singleton:
Singleton class>>instance ^instance ifNil: [instance := self new]
ВЫВОДЫ
Данная статья демонстрирует то, как язык, построенный на минимальном количестве базовых концепций, доступных в одинаковой мере и создателям языка и разработчикам, порождает однородный дизайн с предсказуемым поведением. В данном случае, даже такое обособленное понятие, как nil, ничем особенным не выделяется (кроме его специфической роли на уровне VM как начальное значение неинициализированных данных) и повинуется общим правилам для всех остальных объектов. Меньшее количество частных случаев дает большие возможности для разработчика, большую предсказуемость, а значит безопасность.
По данной теме у нас на сайте уже имеется статья, описывающее возможное изменение семантики обычного языка для поддержки полноценного объекта null - Null Considered Harmful?
Также имеется перевод статьи Обобщенный паттерн <Null Object>, в которой рассматривается реализация Null Object, "поедающая" сообщения.