#import <Foundation/Foundation.h> int main() parts := ['hello', 'world'] greeting := '' for String part in parts if part == parts[0] Locale myLocale = Locale.currentLocale greeting << part.capitalizedString else greeting << ' ' greeting << part Log('%@', greeting + '!') return 0
На днях из любопытства решил посмотреть, на какой стадии находится проект Eero — диалект Objective-C с альтернативным легким синтаксисом. Оказалось, что проделан уже большой фронт работ и Eero представляет из себя очень интересную разработку.
Пример кода
Для затравки традиционное сравнение небольшого участка кода на Eero и на Objective-C.
#import <Foundation/Foundation.h> @interface FileHelper : NSObject @property (readonly) NSString* name; @property (readonly) NSString* format; -(NSFileHandle*) openFile: (NSString*) path; -(NSFileHandle*) openFile: (NSString*) path withPermissions: (NSString*) permissions; @end @implementation FileHelper -(NSString*) name { return @"Macintosh"; } -(NSString*) format { return @"HFS+"; } -(NSFileHandle*) openFile: (NSString*) path { return [NSFileHandle fileHandleForReadingAtPath: path]; } -(NSFileHandle*) openFile: (NSString*) path withPermissions: (NSString*) permissions { NSFileHandle* handle = nil; if ([permissions isEqualTo: @"readonly"] || [permissions isEqualTo: @"r"]) { handle = [NSFileHandle fileHandleForReadingAtPath: path]; } else if ([permissions isEqualTo: @"readwrite"] || [permissions isEqualTo: @"rw"]) { handle = [NSFileHandle fileHandleForUpdatingAtPath: path]; } return handle; } @end
#import <Foundation/Foundation.h> interface FileHelper String name {readonly} String format {readonly} openFile: String, [withPermissions: String], return FileHandle end implementation FileHelper name, return String = 'Macintosh' format, return String = 'HFS+' openFile: String path, withPermissions: String = 'readonly', return FileHandle = nil if permissions == 'readonly' or permissions == 'r' return FileHandle.fileHandleForReadingAtPath: path else if permissions == 'readwrite' or permissions == 'rw' return FileHandle.fileHandleForUpdatingAtPath: path end
Введение
Eero это полностью интерфейсно и бинарно совместимый диалект Objective-C. Реализован с помощью форка LLVM/clang компилятора, т.е. генерирует бинарный код напрямую, благодаря чему с ним работают стандартные инструменты разработки LLVM/Clang, включая отладчик, статический анализатор и прочие. Также заявлена экспериментальная конвертация Eero кода в стандартный Objective-C код 1.
В Eero можно напрямую использовать все Cocoa-фреймворки и любой Objective-C/C++ код, достаточно лишь подключить нужные заголовочные файлы. Также легок и обратный процесс: если для Eero-класса интерфейс определить на Objective-C, то его можно использовать напрямую, бинарные файлы полностью совместимы.
По существу, Eero является мощным синтаксическим сахаром для Objective-C, повышая читаемость, безопасность и сокращая объём кода. По словам автора (Andy Arvanitis), изначально он всего лишь хотел избавиться от скобочек в Objective-C, а название языка выбрал, когда увидел модель стола-постамента, который успешно выполнял свои функции без лишних мешающихся ножек. Итак, язык назван в честь финского архитектора стола Eero Saarinen. Я не силён в финском, но судя по всему, название должно звучать примерно как «эро» с ударением на первый слог.
Синтаксис
Документация написана качественно и легко читается, для каждой особенности языка указывается мотивация, почему решили сделать именно так, в основном это: читаемость, безопасноть, DRY, WYSIWYG. Интересных деталей в языке много, я не буду рассматривать все, а ограничусь небольшим субъективным списком.
Во-первых, в Eero для выделения блоков вместо фигурных скобок используются отступы, как в Python или Ruby. Точка с запятой в конце инструкций и определений не обязательна.
int count = 0 while ( count < 100 ) something = false count++ i++; j++
В Eero отправка сообщений записывается через нотацию с точкой, для сообщений без аргументов это аналогично нотации для свойств (property). Аргументы передаются после двоеточия, несколько аргументов разделяются запятыми.
id myarray = NSMutableArray.new myarray.addObject: myobject myarray.insertObject: myobject, atIndex: 0
Поскольку в Objective-C нельзя представить объект никак иначе, кроме как через указатель, в Eero все переменные классовых типов обрабатываются как указатели, без использования звездочки (*).
NSString mystring = myobject.description NSString otherString = (NSString) someObject
При декларации локальных переменных можно не указывать их тип, он будет автоматически выведен из присваиваемого выражения. Для этого используется специальный оператор ":=".
i := 100 mystring := myobject.description
В Eero реализована такая замечательная вещь, как пространства имён (namespaces). Префикс «NS» подключен по-умолчанию, т.е. все типы из фреймворка Foundation можно использовать без префикса.
mystring := String.stringWithUTF8String: "Hello, World"
Компилятор сначала проверяет имена сущностей в том виде, как они указаны в коде, и, если имя не найдено, добавляет зарегистрированные префиксы. Декларация дополнительных префиксов осуществляется с помощью директивы using prefix
.
using prefix AB ... theAddressBook := AddressBook.sharedAddressBook
Однако в текущей реализации есть существенный недостаток: возникновение коллизий в результате опущения префиксов никак не отслеживается, просто используется первый подходящий вариант:
void AAPrint(String str) NSLog('AA: %@', str); void BBPrint(String str) NSLog('BB: %@', str); using prefix AA using prefix BB ... Print('test') // AA: test
В Eero не обязательно указывать имена аргументов метода, в случае опущения, они автоматически определяются из селектора. Например, в следующем методе аргументы получат имена bytes, length и encoding:
initWithBytes: const void*, length: UInteger, encoding: StringEncoding
Тип возвращаемого значения указывается после аргументов, по умолчанию используется void.
initWithBytes: const void*, length: UInteger, encoding: StringEncoding, return id
В Objective-C в случае, когда у метода есть опциональные параметры, принято определять несколько методов с разным количеством аргументов. В Eero можно декларировать методы с необязательными параметрами.
interface MyClass openFile String, [withPermissions: String], return FileHandle end
В имплементации дефолтное значение опционального аргумента обозначается с помощью знака "=".
implementation MyClass openFile: String, withPermissions: String = 'r', return FileHandle handle := nil if permissions == 'r' handle = FileHandle.fileHandleForReadingAtPath: file else if permissions == 'w' or permissions == 'rw' handle = FileHandle.fileHandleForUpdatingAtPath: file return handle end
Можно указать дефолтное возвращаемое значение, что например позволяет определять очень компактные геттеры:
implementation MyClass model, return String = 'G35' serialNumber, return String = 'X344434AABC' end
Свойства декларируются очень просто. Атрибуты при необходимости задаются в фигурных скобках.
interface MyClass String name {nonatomic, copy} String desc {readonly} end
При определении блоков используются отступы, и не используется знак каретки "^". По сравнению с синтаксисом Objective-C, блоки выглядят очень просто:
myblock := (int x, int y) if x < 0 printf( "value was negative! (%d)\n", x ) x = 0 return x + y
Также поддерживается компактная форма записи для простых блоков, состоящих только из возвращаемого выражения:
xyblock := (int x, int y | return x + y) descriptions := mylist.mapWith: (id element | return element.description)
В Eero реализована перегрузка операторов. Во-первых, для всех объектов оператор "==" является алиасом для метода isEqual. Что актуально в первую очередь для читабельного и безопасного сравнения строк:
mystring := MutableString.new mystring.appendString: 'Hello, World' if mystring == 'Hello, World' // попадаем сюда, т.к. выражение выше истинно
При использовании бинарного оператора "+" сообщение stringByAppendingString будет послано всем объектам, которые могут на него ответить (преимущественно NSString и его субклассы):
helloString := 'Hello' worldString := 'World' helloWorldString := helloString + ', ' + worldString
Аналогично оператор "<<" посылает сообщение appendString:
mystring := '' mystring << 'Hello, World'
Для своих классов можно перегружать следующие операторы:
Оператор | Селектор | Примечание |
+ | plus: | Включая оператор += |
— | minus: | Включая оператор -= |
* | multipliedBy: | Включая оператор *= |
/ | dividedBy: | Включая оператор /= |
% | modulo: | Включая оператор %= |
< | isLessThan: | |
<= | isLessThanOrEqualTo: | |
> | isGreaterThan: | |
>= | isGreaterThanOrEqualTo: | |
<< | shiftLeft: | |
>> | shiftRight: |
Ну, и наконец, в языке на уровне компилятора запрещен goto
. 🙂
Установка и использование
Данный раздел написан по опыту использования Eero в сборке 2013-12-08, XCode 5.0.2 и Mac OS X 10.8.5.
Ставится Eero очень просто. Достаточно скачать и установить плагин для XCode, который уже содержит сборку форка компилятора LLVM. При установке также добавятся шаблоны XCode для создания новых .eero и .eeh файлов. После установки достаточно перезапустить XCode и всё, — можно приступать к работе.
Работает подсветка синтаксиса, автодополнение. Однако, не работает выпадающий список с навигацией по классу, вместо него статичная надпись «No Selection».
Точнее говоря, XCode не видит классы и методы, определенные в файле, но можно воспользоваться инструкциями #pragma mark ...
, — они в выпадающем списке видны.
Проверил работу отладчика (он же debugger), всё в порядке. Однако, к сожалению XCode падал при попытке просмотра quick help к выделенному коду. Ещё не всегда корректно работают авто-отступы, но это совсем мелочь. Больше проблем не обнаружено.
Заключение
Лично на меня Eero произвел самое приятное впечатление. Да, язык достаточно молод (домен eerolanguage.org зарегистрирован в январе 2011, а на гитхабе проект появился в декабре того же года), и потому присутствуют недостатки, характерные для данной стадии развития (в основном с интеграцией с IDE). Однако, неразрешимих и критичных проблем не видно, а потому и у меня появилось стойкое желание попробовать его в будущих проектах.
Ссылки
- Официальный сайт
- GitHub
- Блог и твиттер автора Andy Arvanitis
1) На данный момент функция конвертирования Eero -> Objective-C сыровата, у меня удачно отработала только на элементарных примерах.
ссылка на оригинал статьи http://habrahabr.ru/post/129993/
Добавить комментарий