Pull to refresh

Comments 44

Интересно, а что в итоге то с макросами, я вот вижу что-то на них похожее, но не помню, чтобы можно было их создавать, Тоже самое касается атрибутов. Это вообще возможно?
Останутся += / -= и for-in.

Причем последний можно использовать с массивами:
for i in 1...5

а массивы можно создавать с помощью stride:
for i in 1.stride(to:5, by: 1)
Дык в object Pascal также можно:

for i in [1..5] do
Бред, конечно.
Циклы с счетчиком, изменяемым внутри тела — обычное дело в общем-то. В том же Python каждый раз эмулировать такое через while достало неимоверно.
Swift современный и крутой. Приходится быть современным, если хочешь перерасти Obj-C. Нужна решимость, чтобы избавиться от этих C-подобных циклов, использующихся с 1972 года. Будем надеяться на лучшее!

Я вот например считаю что перерастать Objective-C не требуется, это не некая устаревшая технология, а отличный инструмент со своими сильными и слабыми сторонами, как и Swift.

Хотя отказ от c-style циклов и инкрементов имеет под собой основу: инкремент в Swift представляет собой чисто синтаксическую возможность и x++ и x += 1 по сути ничем не различаются.
С циклами все более странно, в принципе в классических for циклах нет ничего плохого, но реализованы они в Swift так что
for i in 0 ..< x
работает быстрее чем
for var i = 0; i < x; i++
возможно стоит оптимизировать c-style циклы, а не убирать их из языка. Кроме того, for in не поддерживает декремент.
Согласен, но этот цикл по идее должен на каждом шаге вызывать next() проверять что следующий элемент существует и выполнять тело цикла если это так. Что совсем не тоже самое по скорости чем уменьшать значение i на 1 и проверять что оно не стало меньше нуля.
Кстати, там за бортом осталась поддержка swift test, как минимум. Для не OsX платформ это точно актуально.
> В Swift 2.2 и далее можно сравнивать кортежи, содержащие до 6 элементов Equatable
Почему именно 6 интересно, зачем было делать это магическое число и можно ли сравнивать вложенные кортежи?
С выходом 7-ого iPhone число элементов будет ++. Пардон, += 1
Не знаю как в Swift, но в C# количество элементов кортежа (тип Tuple) тоже ограничено.
В C# это связано с тем, что нет генериков с переменным числом параметров, и вообще вариадики поддерживаются только гомогенные (т. е. одного типа). Поэтому в C# определены сразу несколько типов Tuple: с одним, двумя итд. параметрами.
Если мне память не изменяет, в Swift система типов устроена сходным образом (нет генериков-вариадиков).
Кстати говоря, еще ни разу не видел оправданного использования Tuple в C#. Обычно его используют только потому, что лень создавать именованный класс, но чтение и рефакторинг такого кода превращается в пытку. Поэтому обычно лучше использовать анонимные классы с именованными полями, или же не лениться и объявить класс, если его нужно пробрасывать между методами. В крайнем случае для 2 элементов сойдет KeyValuePair.
Я тоже как-то не встречал. Пару раз пытался по опыту других языков их воткнуть, но получалось уж слишком монструозно :)
Без синтаксической поддержки языка это не более чем просто класс, аналогично не нашёл применения, в контексте метода куда удобнее анонимные типы, в контексте класса — вложенные классы. К тому же отсутсвие вывода типов в конструкторах зашумляет код. Радует что в списке фич 7 версии языка находится в разделе "Strong interest"
Что-то все повыкидывали.
Хоть я и не писал на Swift, но тенденция выкидывать общепринятые устоявшиеся за десятилетия и понятные любому программисту конструкции (типа инкремента) ИМХО странная. Это все равно что из математики выкинуть значок квадратного корня, сославшись на то что можно пользоваться возведением в степень 1/2.
В отличие от математики, программный код разбирает компьютер, а находящиеся по эту сторону монитора не желают ни вводить с клавиатуры длинные последовательности, ни ждать, пока ИИ сможет понимать код, написанный на математическом языке.
Каждая фича в языке, каждая строчка в компиляторе может стоить немалых денег в поддержке. "Общепринятые" вещи из Си отсутствуют во многих языках, на которых выросло поколение авторов Swift, языков, начавших активно выходить за пределы академической среды — функциональных языков, в основном.
Swift — очень современный в этом плане язык, авторы активно движут его к зарекомендовавшим себя и модным ныне практикам ФП, но при этом в нем слишком много фич (а особенно синтаксиса) — скорее всего поэтому авторы убирают все, что в их идеальном стиле не используется, но при этом не ограничивает круг решаемых задач.
Важно понимать, что идеология Swift подразумевает написание идеоматического высокоуровнего высокодекларативного кода, который затем трансформируется очень умным компилятором в эффективный машинный код, который предположительно должен быть таким же быстрым, как написанный с использованием таких фич, как инкремент и цикл for в стиле Си.
Конечно авторы языка на то и авторы, чтобы решать каким язык должен быть… это их право. Но у меня другой подход к дизайну языков программирования. Я бесконечно уважаю и доверяю Программисту, и считаю что даже если одному программисту из миллиона понадобится для каких-то неведомых мне Хакерских целей та или иная фича — она должна быть в языке. Пусть инкремент, пусть что-то низкоуровневое или даже оператор goto… каждый программист — Творец, и не мое дело решать чем можно пользоваться а чем нельзя. Вот как-то так))
А потом другим программистам наслаждаться поддержкой кода таких творцов. Нужно выходить за рамки — используйте низкоуровневые языки и наслаждайтесь стрельбой по ногам. А в данном случае язык рассчитан на толпы не очень хороших программистов, код которых должен и выглядеть и работать максимально качественно. В этом случае, чем жестче язык/фреймворк, тем лучше.
Да я все это прекрасно понимаю…
Но жить-то станет скучнее, программирование превратится из Хакерства в унылую конвейерную работу за копейки. Мечта менеждеров, да… но программистам-то это зачем?
Каждому делу свой инструмент только и всего :) Хакерство и творчество никуда не денется. Всегда нужны и художники и маляры, а инструменты у них в чем-то похожи, но очень разные.
А потом другим программистам наслаждаться поддержкой кода таких творцов.

Вы всерьёз считаете, что конструкции типа
for i in 1000000.stride(to:1, by: -1)
читаемы и удобнее в поддержке, чем примитивный for-цикл?
Или что операторы инкремента/декремента могут стрелять по ногам?
Понятно, что авторы языка решают что оставлять, но аргументы на тему, что конеретно эти изменения хоть как-то способны улучшить качество кода, выглядят очень странно.
Ладно бы все, как один, написали: фиг с ним с for, будем хвостовую рекурсию использовать… но нет, все про этот жуткий вариант со stride, который ещё и память на абсолютно ненужную последовательность тратить будет.
Это не все, это я сразу в несколько веток ответил, потому что страйд не самая широко известная штука.
А касательно памяти — вы уверены, что нет никакой оптимизации на уровне компилятора?
stride — это способ генерации последовательности/массива, поэтому использовать его для замены счётчика итераций значит использовать его не по назначению. Я не уверен в отсутствии оптимизаций на этот случай на уровне компилятора, но, честно говоря, присутствие таких оптимизаций было бы нелогичным. Классический цикл for отсутствует во многих функциональных языках, но в любом из них генерация списка чисел для обхода считается моветоном.
Вопросов больше, чем ответов.

  • Как без С-style цикла сделать итерацию с шагом, отличным от 1?
  • Почему функция `removeFirst` это срез? Общепринятый смысл термина «срез» — это подмножество массива.
  • Зачем убирать более удобную версию записи каррирования? Новый синтаксис с 3 и более параметрами будет выглядеть монструозно.
  • Почему сравнивать можно только кортежи до 6 элементов?
Фичу с кортежами небось прикрутили сбоку изолентой :). В C# вроде бы максимальная длина кортежа равна 8, здесь 6…
Догадайтесь почему и откуда такие магические числа.
В C# есть несколько стандартных классов типа Func, Action и Tuple, у которых есть "варианты" с различным количеством аргументов. Причина в том, что когда в .NET 2.0 добавили обобщения, особой необходимости в variadic type arguments еще не было, а потом добавить это без кардинального изменения рантайма оказалось невозможно. При необходимости кортеж произвольной длины можно создать, используя в качестве последнего элемента вложенный кортеж. И тогда они будут-таки рекурсивно сравниваться, сколько их ни навтыкай.

Однако вопрос в другом. В Swift вообще нельзя сделать кортеж из более, чем 6 элементов? Или все же можно, но он не будет сравниваться? Если так, то это однозначно сознательное ограничение, но его смысл от меня ускользает. Производительность?
Как без С-style цикла сделать итерацию с шагом, отличным от 1?

Скорее всего, авторы хотят сделать акцент на техниках функционального программирования и эти юзкейсы должны покрываться фильтром по индексу, например (псевдокод): collection.filter(eventh).map(doSomething).reduce(calcResult)

Зачем убирать более удобную версию записи каррирования? Новый синтаксис с 3 и более параметрами будет выглядеть монструозно.

В Swift слишком много синтаксиса. Скорее всего, синтаксис каррирования усложнял парсер, так как требовал разрешения неоднозначностей, а может просто прибили как наименее полезный синтаксис по версии авторов.
"Новый" синтаксис — явная форма возврата функции. На практике я довольно редко вижу применение функции больше, чем в две стадии, так что в каком-то смысле компромисс для меня очевидный.
Акцент получается довольно странный. Циклы и инкременты — слишком императивно, каррирование — слишком функционально. Прагматичность — это хорошо, но для языка и платформы ортогональность не менее важны.
Я думаю, упор не на функциональное программирование как таковое, а скорее на декларативность, достижимую с помощью средств, заимствованных из функционального программирования. Ну и на value semantics. И умный компилятор, который магически улучшает говнокод.
С таким компилятором, кстати, чем меньше свободы людям, тем больше оптимизатору.
Получается очень хороший набор базовых постулатов, с синергией. И очень в духе Apple "Мы делаем лучшие чистилки для апельсинов, потому что мы лучше всех знаем, как чистить апельсины." Можно ли чистить красные апельсины? Я думаю, для этого найдется своя Cydia.
Как без С-style цикла сделать итерацию с шагом, отличным от 1?

проще
for i in 100.stride(to:500, by: 25)
Вырвиглазно :(

for(i = 100; i < 500; i += 25)

– выглядит проще и компактнее.
Зачем убирать более удобную версию записи каррирования?

См. в motivation

Почему сравнивать можно только кортежи до 6 элементов?

Чтобы соблюсти баланс между удобством и размером библиотеки. Текущее раширение до 6 увеличило размер на 1,4 %. 12 элементов увелчивают размер на 5,5 % (+175 КБ).

Почему функция `removeFirst` это срез? Общепринятый смысл термина «срез» — это подмножество массива.

Тут просто про свифтовое ArraySlice, Sliceable и пр. базовые -slice типы (смысл которых, что они не копируют элементы, а юзают существующую память, отсюда и название и эффективность в O(1)). Вот в них и добавили removeFirst. А обычные массивы все это наследуют по иерархии.
Что-то ребята поторопились с дизайном языка.

Частичное применение функции, имхо, сделали только потому, что это модно. Теперь же оказалось, что никто это не использует потому, что слишком сложно.

По поводу кортежей на stackoverflow подсказывают, что в него можно засунуть до 1948 (!!!) элементов. Зачем это нужно, особенно если они беспокоятся по поводу размера библиотеки?
Как без С-style цикла сделать итерацию с шагом, отличным от 1?

Народ писал про stride, но, положа руку на сердце, я за 10 лет ни разу такой цикл не писал.

К слову, Андрюх, тут, скорее, можно возразить про более актуальное «а как узнать индекс текущего элемента, если убрали олдскульный for», но помимо классического:
for item in items { }

…есть менее известный:
for (index, item) in items.enumerate() { }

В том же шарпе такое только, если не изменяет память в «.Select( (index, item) => { })», а вот в обычном foreach часто не хватает. Свифт, в общем, молодец.
Прямо дежавю с Python. И это скорее хорошо.
Оффтопик. К чему эти точки и запятые в начале строк, а не в конце?
Боже мой, что это? Унарный оператор сравнения?
Это не просто if, а волшебный #if

Кстати, __такие__ волшебные переменные теперь заменены на #такие
У Erica Sadun в бложике много интересного.
UFO just landed and posted this here
Сказывается любовь к странным повторяемым символам пунктуации, теперь в моде -> вместо []

func curryThisWay(a: Int) -> (Int) -> Int {
return { (b: Int) -> Int in
return a + b
}
}
Я уж надеялся, что начиная с 2й версии на нём можно пилить что-то серьёзное и новый проект можно стартовать на Swift. Но нет, подожду-ка я до 4й :)
Sign up to leave a comment.