Comments 63
Увидев ":=" я сразу вспомнил Pascal и Delphi… Эххх были времена… :)
-1
Во-первых, в Eero для выделения блоков вместо фигурных скобок используются отступы, как в Python или Ruby.
Это какие-то неправильные руби
+2
Диспозиция:
Вывод:
2013-12-16 13:17:24.637 Test[1224:907] getter
2013-12-16 13:17:24.815 Test[1224:907] test 0 1
Вопрос:
Как это повторить?
P.S.: Я знаю, что так делать не стоит, но раз вы предлагаете Eero как замену Objective-C — он так тоже должен уметь.
@interface TestObject : NSObject
{
int test;
}
@property (nonatomic, assign, getter = getTest) int test;
@end
@implementation TestObject
@synthesize test;
- (id) init
{
if (self = [super init])
{
NSLog(@"test %d %d", self->test, self.test);
}
return self;
}
- (int) getTest
{
NSLog(@"getter");
return 1;
}
@end
Вывод:
2013-12-16 13:17:24.637 Test[1224:907] getter
2013-12-16 13:17:24.815 Test[1224:907] test 0 1
Вопрос:
Как это повторить?
P.S.: Я знаю, что так делать не стоит, но раз вы предлагаете Eero как замену Objective-C — он так тоже должен уметь.
0
Примерно так:
Но по философии языка он должен выполнять те же функции, что Objective-C, но не являться его копией, взяв лучшее, и выкинув худшее. Поэтому далеко не все трюки можно перенести (особенно нежелательные в использовании). Например, в Eero запрещено затенять переменные (shadowed variables):
interface TestObject
int test {nonatomic}
end
implementation TestObject
int _test
init, return instancetype = self
if (self = super.init)
Log('test %d %d', _test, self.test);
test, return int = 1
Log('getter');
end
Но по философии языка он должен выполнять те же функции, что Objective-C, но не являться его копией, взяв лучшее, и выкинув худшее. Поэтому далеко не все трюки можно перенести (особенно нежелательные в использовании). Например, в Eero запрещено затенять переменные (shadowed variables):
counter := 0
if isReady
counter := 0 // compiler error
0
Собственно в этом коже getter не нужен даже, надо только функцию в
> Например, в Eero запрещено затенять переменные (shadowed variables)
А можноо про это поподробне?
То есть я не смогу сделать так
?
Правда надо признать, более красивый код я придумать не смог :)
Навеяно вот этим кодом: pastebin.com/csQmX1BS
- (int) test
переименовать.> Например, в Eero запрещено затенять переменные (shadowed variables)
А можноо про это поподробне?
То есть я не смогу сделать так
BOOL status = NO;
if (!status && <длинное условие>)
status = YES;
if (!status && <второе длинное условие>)
status = YES;
if (!status && <третье длинное условие>)
status = YES;
?
Правда надо признать, более красивый код я придумать не смог :)
Навеяно вот этим кодом: pastebin.com/csQmX1BS
0
Нет, это что-то типа (пример фигня, конечно):
Хотя иногда, например в лямбде, бывает удобно назвать переменную так же, как и снаружи, ибо другого нормального имени не придумаешь (пишу про CoffeeScript, меня там это пару раз доставало)
BOOL status = NO;
if(cond){
BOOL status = YES;
...
}
Хотя иногда, например в лямбде, бывает удобно назвать переменную так же, как и снаружи, ибо другого нормального имени не придумаешь (пишу про CoffeeScript, меня там это пару раз доставало)
+1
Да, иногда это бывает полезно. С другой стороны, защищает от потенциальных ошибок. Чисто субъективно, я бы предпочел вариант с warning, а не с compile error.
0
У меня как раз наоборот — ошибки лезут когда приходится создавать новую переменную, а обращаюсь случайно к старой.
Правда это специфично для Haskell. Там нельзя написать
В ML можно, в Haskell придумал замену
Правда это специфично для Haskell. Там нельзя написать
let n = n+1 in ...
надо давать новое имя let n1 = n+1 in ...
В ML можно, в Haskell придумал замену
case n+1 in n -> ...
но уж больно многословно получается.0
Нет, в вашем коде используется одна и та же переменная, так естественно можно писать. Запрещено в локальной области видимости определять новую переменную с тем же именем, что и в родительской. В Objective-С/C так делать можно (можно настроить, чтобы выдавался warning).
BOOL status = NO;
if (...){
BOOL status = YES;
}
0
Забавно, как побаловаться.
Но пока шило на мыло помоему.
В любом случае многие очень сильные проекты начинались именно вот с такого вот рода экспериментов.
Но пока шило на мыло помоему.
В любом случае многие очень сильные проекты начинались именно вот с такого вот рода экспериментов.
+1
Какая-то хипстерота. Читать невозможно. Функции как списки переменных выглядят.
+4
Вообще непонятно зачем? У всех языков свой синтаксис, странным он кажется только тем людям, которые его просто видят в первый раз, если человеку необходим этот язык он начнет его учить и через уже месяц не будет никаких проблем, а, возможно, он даже ему понравится намного больше чем остальные, тут есть множество своих плюсов, как и в любом другом языке. Давайте для Java создадим тоже свой Ero с блекджеком и щлюхами, я подозреваю, что для людей, программирующих на ассемблере или Pascale Java тоже кажется с очень странным синтаксисом.
0
На вопрос «зачем?» автор отвечает: «для читаемости, т.к. код читается гораздо чаще, чем пишется».
Вообще, я согласен, что привыкаешь ко всему, Objective-C лично я воспринимаю абсолютно нормально, особенно после 5 лет разработки. :)
Но объективно говоря, код на Eero получается куда лаконичнее, плюс дополнительные функции, такие как опциональные аргументы, перегрузка операторов, полная поддержка instancetype, итераторы типа
Вообще, я согласен, что привыкаешь ко всему, Objective-C лично я воспринимаю абсолютно нормально, особенно после 5 лет разработки. :)
Но объективно говоря, код на Eero получается куда лаконичнее, плюс дополнительные функции, такие как опциональные аргументы, перегрузка операторов, полная поддержка instancetype, итераторы типа
for int i in 0 .. 10
и прочее. Т.е. дело не только в синтаксисе.+6
Ну если бы не другой синтаксис — возможно, я бы его даже попробовал. А так… Нет, я останусь на Obj-C :)
+2
Мне Objective-C нравится: философией, рантаймом. Но от синтаксиса я не в восторге, хотя и привык. По-моему, если подходить непредвзято, и забыть про привычки, то можно объективно сказать, что синтаксис Objective-C далек от совершенства: для тех же самых функций можно было придумать куда более удобную запись.
+2
Groovy, Scala, Clojure…
+2
И у этого языка свой синтаксис, при обеспечении совместимости по библиотекам. Что плохого то?
0
Нам не нравится непонятный синтаксис обжСи, поэтому мы сделали свой непонятный синтаксис! Теперь непонятных синтаксисов два.
При всем моём неприятии синтаксиса обж си,
в оригинале куда понятнее. И что за мода вообще, делать эти руби/питон стайл диалекты языкам…
При всем моём неприятии синтаксиса обж си,
name, return String = 'Macintosh'
format, return String = 'HFS+'
в оригинале куда понятнее. И что за мода вообще, делать эти руби/питон стайл диалекты языкам…
0
Лучше бы они старый добрый и всем понятный C++-синтаксис для Obj-C сделали, если хотели избавиться от вложенных квадратных скобок при обращении к методам.
А Python-стиль для C — это как-тонеправильно совсем запутывает, имхо.
А Python-стиль для C — это как-то
-3
В C++ нет именованных параметров, поэтому его синтаксис никак не применить.
+1
Хотя мое мнение никого не интересует, но скажу
Они напоминают сказочный сюжет про сундук. В сундуке — медведь. В медведе — утка. В утке яйцо. В яйце — игла. На конце иглы — смерть.
Мне очень нравятся квадратные скобки
Они напоминают сказочный сюжет про сундук. В сундуке — медведь. В медведе — утка. В утке яйцо. В яйце — игла. На конце иглы — смерть.
int death = [NSBox boxWithBear:[NSBear bearWithDuck:[NSDuck duckWithEggs:[NSEgg eggWithNiddle:[NSNiddle alloc] init]]]];
0
Да, так намного лучше:
int death = NSBox.boxWithBear(NSBear.bearWithDuck(NSDuck.duckWithEggs(NSEgg.eggWithNiddle(new NSNiddle))));
+2
[NSNiddle niddleWithADeath:[[NSDeath alloc] init] atTheEnd:theEnd]
+1
Ваш пример лучше. В моем умышленная ошибка, никто не поправил.
-1
Собственно, я не поправил, а расширил создание объекта иглы — остальное было лень набирать.
А у вас да, ошибка, в death будет не смерть, а сундук :)
А у вас да, ошибка, в death будет не смерть, а сундук :)
+1
Ошибка в части
Никто не поправил очевидно потому, что в скобочках таки легко запутаться. :)
[NSEgg eggWithNiddle:[NSNiddle alloc] init]
Никто не поправил очевидно потому, что в скобочках таки легко запутаться. :)
-2
Зачем замарачиваться скобками, если их компилятор проверит ;)
+1
Чтобы не было ситуации «чукча не читатель, чукча писатель». Код читается намного чаще, чем пишется.
Кроме того, компилятор не всесилен. Предположим, мы решили понизить связанность классов и сделать их более универсальными, так, чтобы в одной сущности могло находиться по 2 других:
Слабо сходу понять, чем отличаются следующие синтаксически верные варианты:
Если просто убрать лишние скобки, оставаясь в рамках Objective-C, и воспользоваться нотацией через точку, то уже намного понятнее:
На практике «скобочный ад» тоже иногда бывает, например при использовании fluent-интерфейсов, при использовании ReactiveCocoa. Т.е. не «ад», конечно, но «ещё чуть-чуть, и будет ад».
В общем, Readability matters!
Кроме того, компилятор не всесилен. Предположим, мы решили понизить связанность классов и сделать их более универсальными, так, чтобы в одной сущности могло находиться по 2 других:
@protocol NSContaining <NSObject>
-(instancetype)initWith:(id)content;
-(instancetype)initWith:(id)content and:(id)anotherContent;
@end
@interface NSBear : NSObject <NSContaining> @end
@interface NSDuck : NSObject <NSContaining> @end
@interface NSEgg : NSObject <NSContaining> @end
Слабо сходу понять, чем отличаются следующие синтаксически верные варианты:
[[NSBear alloc] initWith:[[NSDuck alloc] initWith:[[NSEgg alloc] initWith:[[NSNeedle alloc] init]]] and:[[NSEgg alloc] init]];
[[NSBear alloc] initWith:[[NSDuck alloc] initWith:[[NSEgg alloc] initWith:[[NSNeedle alloc] init]] and:[[NSEgg alloc] init]]];
[[NSBear alloc] initWith:[[NSDuck alloc] initWith:[[NSEgg alloc] initWith:[[NSNeedle alloc] init] and:[[NSEgg alloc] init]]]];
Если просто убрать лишние скобки, оставаясь в рамках Objective-C, и воспользоваться нотацией через точку, то уже намного понятнее:
[NSBear.alloc initWith:[NSDuck.alloc initWith:[NSEgg.alloc initWith:NSNeedle.alloc.init]] and:NSEgg.alloc.init];
[NSBear.alloc initWith:[NSDuck.alloc initWith:[NSEgg.alloc initWith:NSNeedle.alloc.init] and:NSEgg.alloc.init]];
[NSBear.alloc initWith:[NSDuck.alloc initWith:[NSEgg.alloc initWith:NSNeedle.alloc.init and:NSEgg.alloc.init]]];
На практике «скобочный ад» тоже иногда бывает, например при использовании fluent-интерфейсов, при использовании ReactiveCocoa. Т.е. не «ад», конечно, но «ещё чуть-чуть, и будет ад».
В общем, Readability matters!
0
За такой код руки отрывать надо.
Во-первых, можно сразу бить в табло за кривые имена параметров. Ибо правильно
Во-вторых, бить по пальцам за отсутствие форматирования.
Сравните:
В-третьих, стоило бы тут вынести агрументы ав отдельные переменные
В-четвёрных, от этого кода пахнет архитектурной… попой.
P.S.: форматеры хабра и pastebin'а пытаются выравнять код по 80 символов, что в реалях Obj-C — идиотское занятие. Скопируйте в XCode, и смотрите там.
Во-первых, можно сразу бить в табло за кривые имена параметров. Ибо правильно
initWithDuck:(NSDuck*)duck
Во-вторых, бить по пальцам за отсутствие форматирования.
Сравните:
NSBear *bear = [[NSBear alloc] initWithDuck:[[NSDuck alloc] initWithEgg:[[NSEgg alloc] initWithNeedle:[[NSNeedle alloc] init]]]
egg:[[NSEgg alloc] init]];
NSBear *bear = [[NSBear alloc] initWithDuck:[[NSDuck alloc] initWithEgg:[[NSEgg alloc] initWithNeedle:[[NSNeedle alloc] init]]
secondEgg:[[NSEgg alloc] init]]];
NSBear *bear = [[NSBear alloc] initWithDuck:[[NSDuck alloc] initWithEgg:[[NSEgg alloc] initWithNeedle:[[NSNeedle alloc] init]
egg:[[NSEgg alloc] init]]]];
В-третьих, стоило бы тут вынести агрументы ав отдельные переменные
В-четвёрных, от этого кода пахнет архитектурной… попой.
P.S.: форматеры хабра и pastebin'а пытаются выравнять код по 80 символов, что в реалях Obj-C — идиотское занятие. Скопируйте в XCode, и смотрите там.
0
Кстати, код всё равно кривой. Если нет ARC — будет течь память. Ибо, по конвенции, функции, init* и copy возвращают значение с retainCount = 1. Объексты с retainCount = 0 возвращают функции вида [NSNeedle needle].
-1
Объекты с «retainCount = 0» никакие методы не возвращают. См. autorelease и NSAutoReleasePool.
0
Да понятно, что не возвращает. Назовём это «когда-нибудь 0».
0
Нет. Если уж Вы решили вспомнить manual reference counting (хотя это абсолютно не к месту), то конвенцию надо приводить полностью и правильно (“alloc”, “new”, “copy”, “mutableCopy”, никакого «init»!), и не писать очевидную чушь. Вас могут читать новички в Objective-C.
0
Не придерайтесь, это к вопросу читабельности кода не относится.
А новичкам — брысь читать эту статью: Advanced Memory Management Programming Guide
P.S.: Оригинально вы выражаете несогласие в споре. Думаю, в таком случа, нет смысла его продолжать.
А новичкам — брысь читать эту статью: Advanced Memory Management Programming Guide
P.S.: Оригинально вы выражаете несогласие в споре. Думаю, в таком случа, нет смысла его продолжать.
0
Ясно, что обсуждаем абстрактный пример в вакууме. И в равных условиях (что есть форматирование, что нет — вариант с меньшим количеством скобок читабельнее).
А ваш вариант не по теме, я же условие поставил: классы — универсальные контейнеры, реализующие протокол NSContaining (имена селекторов специально сократил, чтоб не так широко было). Или вы универсальные протоколы не используете, и классы у вас всегда жестко связаны?
А ваш вариант не по теме, я же условие поставил: классы — универсальные контейнеры, реализующие протокол NSContaining (имена селекторов специально сократил, чтоб не так широко было). Или вы универсальные протоколы не используете, и классы у вас всегда жестко связаны?
0
Гм, зря сократили. Вводит в заблуждение.
В любом случае, последние 3 пункта не отменяются.
> Или вы универсальные протоколы не используете, и классы у вас всегда жестко связаны?
Практически не использую, кстати. Для хранения данных намного лучше подходят классы с конкретными именами и конкретными типами полей.
По поводу универсальных контейнеров у меня для есть отличный комментарий: govnokod.ru/12170#comment161695
В любом случае, последние 3 пункта не отменяются.
> Или вы универсальные протоколы не используете, и классы у вас всегда жестко связаны?
Практически не использую, кстати. Для хранения данных намного лучше подходят классы с конкретными именами и конкретными типами полей.
По поводу универсальных контейнеров у меня для есть отличный комментарий: govnokod.ru/12170#comment161695
0
Практически не использую, кстати.
Жесткая связанность классов — наше всё?
Если строим иерархию, например, сотрудников, то вместо универсального протокола {начальник; подчиненные} сотрудники будут выглядеть так:
ДиректорВасильев {ЗаместительКрючков; ЗаместительСвязнов}
ЗаместительКрючков {ДиректорВасильев; НачальникОтделаКадровПучков; НачальникОтделаФинансовТранжиров}
...
Каждой сущности — свой класс. Очевидно нелепо, но именно так выглядит ваша поправка с Медведем, Уткой и Яйцами. Чтобы Утку заменить на Курицу, придется менять класс Медведя.
0
вроде бы со скобками все ок, а вот тип переменной death не очень уж совпадает с типом объекта коробки
0
умышленная ошибка
Не niddle, а needle ;-)
0
Отсутствие скобочек, куча сахара, итераторы, дефолтные значения параметров это круто очень. Но синтаксис просто жесть, все вывернуто через зад, не понятно зачем. Лучше бы они пошли по пути RubyMotion и MonoTouch, где куча сахара и плюшек из оригинальных языков, и при этом все легко читается, и порог входа сильно ниже.
0
Objective-C:
Ruby Motion:
Eero:
По-моему, явных преимуществ у Ruby нет.
Зато в Eero есть плюсы: это тот же Objective-C со статической типизацией, категориями, расширениями классов и пр. Ruby же изначально не писался под runtime Objective-C, и могут возникать сложности в самых простых местах (пример отсюда):
Это конечно не отменяет того, что в Ruby Motion много своих плюсов.
В Mono Touch же вообще нужно биндинг для использования Objective-C кода писать, насколько я знаю.
[obj makeBoxWithOrigin: origin andSize: size];
Ruby Motion:
obj.makeBoxWithOrigin(origin, andSize: size)
Eero:
obj.makeBoxWithOrigin: origin, andSize: size
По-моему, явных преимуществ у Ruby нет.
Зато в Eero есть плюсы: это тот же Objective-C со статической типизацией, категориями, расширениями классов и пр. Ruby же изначально не писался под runtime Objective-C, и могут возникать сложности в самых простых местах (пример отсюда):
Objective-C
@interface CustomView : UIView
@property (copy) NSString *text;
@end
@implementation CustomView
- (id) initWithFrame:(CGRect)frame {
[super initWithFrame:frame];
self.text = @"";
return self;
}
- (id) initWithText:(NSString*)text {
UIFont *font = [UIFont systemFontOfSize:12];
CGRect size = [text sizeWithFont:font];
// skip local initializer
[super initWithFrame:{{0, 0}, size}];
self.text = text;
return self;
}
@end
Ruby Motion
class CustomView < UIView
alias :'super_initWithFrame:' :'initWithFrame:'
def initWithFrame(frame)
super.tap do
@text = ''
end
end
def initWithText(text)
font = UIFont.systemFontOfSize(12)
size = text.sizeWithFont(font)
super_initWithFrame([[0, 0], size]).tap do
@text = text
end
end
end
Eero
interface CustomView : UIView
String text {copy}
end
implementation CustomView
initWithFrame:CGRect, return instancetype = self
if (self = super.initWithFrame: frame)
self.text = ''
initWithText:String, return instancetype = self
font := UIFont.systemFontOfSize: 12
size := text.sizeWithFont: font
CGRect rect = {{0, 0}, size}
if (self = super.initWithFrame:rect)
self.text = ''
end
Это конечно не отменяет того, что в Ruby Motion много своих плюсов.
В Mono Touch же вообще нужно биндинг для использования Objective-C кода писать, насколько я знаю.
+1
А я обожаю скобки!
+1
Про ObjC: не синтаксис в языке главное.
+2
Чем обосновываете удаление goto?
0
Andy Arvanitis просто hater — goto это не управляющая команда, а способ мышления.
Даже убрав эту команду, Andy Arvanitis продолжает ваять if return else return.
Уверен, он и break оставил.
Поэтому считаю, что удаление goto не обосновано ни разу, кроме как капризностью.
Даже убрав эту команду, Andy Arvanitis продолжает ваять if return else return.
Уверен, он и break оставил.
Поэтому считаю, что удаление goto не обосновано ни разу, кроме как капризностью.
+2
А Вы давно goto видели где-то за пределами чистого Си? В каком-нибудь ядре Linux оно нужно и оправдано, зачем оно в более высокоуровневом языке?
0
Выход из вложенных циклов же!
0
Ну лично я сам использую в C++.
...
m_pLockedData = new unsigned char[memoryRequired];
ComputeVertexDescription(m_pLockedData + m_FirstUnwrittenOffset);
desc.m_nFirstVertex = 0;
desc.m_nOffset = m_FirstUnwrittenOffset;
return true;
fail:
ComputeVertexDescription(NULL, 0, desc);
desc.m_nFirstVertex = 0;
desc.m_nOffset = 0;
return false;
...
return handle;
fail_plink:
glDeleteProgram(program);
fail_pcreate:
glDeleteShader(pixelShader);
fail_ps:
glDeleteShader(vertexShader);
fail_init:
return SHADER_PROGRAM_HANDLE_INVALID;
0
фуу.
так же убого как coffee script
скобки это круто знает каждый лиспер.
во что круто =)
common-lisp.net/projects/cl-objc/cl-objc.pdf
так же убого как coffee script
скобки это круто знает каждый лиспер.
во что круто =)
common-lisp.net/projects/cl-objc/cl-objc.pdf
+2
Не нравится. О чем я реально мечтаю так это Scala c синтаксисом Smalltalk.
+1
Начали за здравие, а закончили за упокой. Убрали квадратные скобки — круто, но зачем отступы в стиле питон?
Плохо читать оторванные друг от друга токены. Лучше бы сделали привычный стиль:
openFile String, [withPermissions: String], return FileHandle
Плохо читать оторванные друг от друга токены. Лучше бы сделали привычный стиль:
FileHandle openFile(String, [withPermissions: String])
handle = FileHandle.fileHandleForReadingAtPath(file)
+2
Такой синтаксис для Objective-C неоднозначен.
Представьте следующий интерфейс:
Что произойдёт в результате вызова
Я понимаю, что пример надуманный. Но если синтаксис создаётся специально под Objective-C рантайм, он определенно должен быть однозначен.
Представьте следующий интерфейс:
typedef id(^FileHandleFactoryBlock)(NSString *);
@interface FileHandle : NSObject
+(instancetype)fileHandleForReadingAtPath:(NSString *)path;
+(FileHandleFactoryBlock)fileHandleForReadingAtPath;
@end
Что произойдёт в результате вызова
FileHandle.fileHandleForReadingAtPath(file)
? Будут отослано сообщение fileHandleForReadingAtPath: с одним аргументом или fileHandleForReadingAtPath без аргументов с последующим вызовом полученного блока?Я понимаю, что пример надуманный. Но если синтаксис создаётся специально под Objective-C рантайм, он определенно должен быть однозначен.
+1
Не смотря на спорный синтаксис, первый убегу программировать на этом языке, если сделают parametrized types
0
Я не стал раздувать статью, но в Eero поддерживается instancetype не только для возвращаемых значений, но и для аргументов.
Это позволяет делать что-то типа типизированных функторов. Упрощенный пример для типизированных коллекций:
(Класс MutableArray должен быть прокси, перенаправляющий сообщения из интерфейсов NSString/NSNumber всем элементам коллекции)
Не полноценные parametrized types конечно, но всё же.
Подробнее про instancetype: nshipster.com/instancetype/
Про типизированные коллекции в Objective-C: www.jonmsterling.com/posts/2012-02-05-typed-collections-with-self-types-in-objective-c.html
Это позволяет делать что-то типа типизированных функторов. Упрощенный пример для типизированных коллекций:
stringArray := (String<MutableArray>)MutableArray.new
stringArray.addObject: '123'
stringArray.addObject: @13 // Warning: incompatible pointer type
numArray := (Number<MutableArray>)MutableArray.new
numArray.addObject: @13
numArray.addObject: 'ABC' // Warning: incompatible pointer type
(Класс MutableArray должен быть прокси, перенаправляющий сообщения из интерфейсов NSString/NSNumber всем элементам коллекции)
Не полноценные parametrized types конечно, но всё же.
Подробнее про instancetype: nshipster.com/instancetype/
Про типизированные коллекции в Objective-C: www.jonmsterling.com/posts/2012-02-05-typed-collections-with-self-types-in-objective-c.html
+1
Sign up to leave a comment.
Eero — Objective-C без скобочек