Comments 44
Во-вторых, в С++ и С# тернарный оператор ленивый и вычисляет одно выражение. Зачем его использовать, если необходимо вычислять ветки заранее?
2. Есть предположение, что Swift оптимизирует предварительное вычисление. Проверю в следующей статье.
Кто там у них компиляторы пишет?
Я почему-то подозреваю, что трабл у них начинается не при парсинге выражения, а на стыке вывода типов и разрешения перегрузок. Но то, что ребята не освоили какого-нибудь Хиндли-Милнера, не извиняет их.
Кстати, может чего упустил, но вроде эта проблема была ещё во 2-й версии, и её клятвенно обещали пофиксить.
var res = items.Select(o => new Tuple<string, int>(o.Value.ToString(), o.Value));
Метод
Select<T>()
— дженерик. Возвращаемое значение вычислено — IEnumerable<Typle<string,int>>
. Или вы про что-то другое?Тут возвращаемое значение метода Select
вычисляется благодаря параметру типа Func<T, Tuple<string, int>
. Я же говорю о следующей ситуации:
public interface IMessage
{
string Text { get; set; }
}
public static class MessageFactory
{
static T Create<T>(string message) where T: IMessage, new()
{
var result = T();
result.Message = message;
return result;
}
}
Для вызова метода Create
необходимо явно указать тип в самом вызове:
var message1 = MessageFactory.Create<SimpleMessage>("Hello world")
SimpleMessage message2 = MessageFactory.Create<SimpleMessage>("Hello world again")
Swift, в свою очередь, позволяет сделать следующее:
protocol Message {
init()
var text: String { get set }
}
class MessageFactory {
static func create<T: Message>(text: String) -> T {
var result = T()
result.text = text
return result
}
}
let message: SimpleMessage = MessageFactory.create(text: "Hello world")
Как видите, тип не фигурирует в вызове, только в объявлении переменной. То есть, в данном случае, компилятор не тип выражения выводит исходя из того, что возвращает функция, а тип возвращаемого значения выводит из того, в каком выражении участвует вызов.
Swift3 компилятору всего один год, как и парсеру. Некоторые проблемы существуют, но они не критичные, особенно учитывая что файлы уже собранные не пересобираются. Сборка во время разработки инкрементальная. Поэтому это всё «всплывает» при сборке проекта «с нуля». Если сильно раздражает — добро пожаловать в список котрибьютеров: https://github.com/apple/swift
Если сильно раздражает — добро пожаловать в список котрибьютеров: https://github.com/apple/swift
Уже отправил резюме в Apple.
Теперь продолжим игру в честность — у вас ведь есть возможность внести свой вклад? Так почему вы этого не делаете?
И да, это логично, потому что чтоб контрибьютить в такие проекты нужно обладать огромным количеством знаний и времени. Мало кто будет делать это бесплатно.
Собственно я от этой контрибуции не получаю никакой выгоды, поэтому этим и не занимаюсь.
Так вот инкрементальная сборка срабатывает только для изменений внутри метода. А если добавляешь новый метод или еще что, то собираются вдобавок и зависимые файлы повторно. Это самое грустное отличие от Obj-C. Фаст-пруф.
Кроме того, он еще и баганутый.
Тем не менее, спасибо за ответ. Инкрементальную компиляцию рассмотрю в одной из следующих статей.
Инкрементальная не срабатывает при изменении параметров компиляции, это не проблема самого механизма инкрементальной сборки, это проблема XCode.
Если собирать с командной строки, такого не будет.
Clean не триггерит пересборку зависимостей у него, это большой плюс, так как периодически приходится делать полную очистку.
Краткая суть Carthage — он собирает предварительно framework из твоей зависимости(чем-то похоже на флаг !use_frameworks в Cocoapods), а потом достаточно ее просто подключить к проекту.
Другой наверное (но небольшой) — XCode'у не приходится индексировать исходники подов (и в Quick Open они не показываются)
Но, может быть кто-то замерял, с чем быстрее идет инкрементальный билд (в случае когда поды собраны): с carthage или cocapods
1. Пример с вычислением размера — такие упрощения в коде полезно делать не только для ускорения компиляции, но и для лучшей читаемости.
2. Уже конечно давно принято винить Apple во всем от глюков Xcode и убийства Кеннеди до неудачного расположения города Помпеи, но если все так плохо с инструментарием предоставленным Apple, то почему не используете Xamarin и ему подобные?
2. Много альтернативных платформ пробовали, объем third-party фреймворков там значительно меньше, чем у нативной разработки. Как следствие, помощи в гугле тоже меньше.
Если отходить от Xamarin и говорить в общем, то еще вылезают сложности с оптимизацией. Часто бывает, что сам движок добавляет ощутимый overhead, который никак не разгонишь.
Пока яблочное зло — наименьшее. Периодически еще тыкаемся в Appcode, но разочаровываемся. Надеюсь, Jetbrains подтянут его.
Но то что яблоки лучший вариант на рынке, это не значит, что так должно быть! Я параллельно разрабатываю backend на Java/Kotlin, так там вообще практически не к чему придраться. Такого качества я жду от Apple.
Правило следующее: у компилятора вызывают запор выражения с несколькими сложными слагаемыми. То есть теми, которые не просто являются переменными, но и выполняют какие-либо действия. А вот складывать переменные можно сколько угодно.
Вспомнилась проблема с производительностью в генераторе парсеров ANTLR. Там она как раз была связана с большим количеством однородных выражений при использовании леворекурсивных правил (пример с конкатенацией для Java.g4 грамматики: ManyStringConcatenation.java). Для решения этой проблемы такие правила нужно было переделывать, что выглядело не очень красиво и удобно. У результирующего парсера также появлялись проблемы с производительностью и при полном отказе от использования леворекурсивных правил. Если кому-то интересно, то о решении этих проблем я писал в своей статье о теории и практике парсинга исходников с помощью ANTLR и Roslyn в разделе Java- и Java8-грамматики.
К счастью, в настоящий момент проблема с леворекурсивными правилами пофикшена в ANTLR, а исправление будет доступно с версии 4.6, в которой, к слову, появится еще и поддержка Swift-рантайма.
Интересно, в чем же заключается проблема текущей версии Swift парсера и как ее можно разрешить?
Тюнинг Swift компилятора. Часть 1