Пару месяцев назад купил Meta Quest 3. Теперь это моя (и моего сына) любимая игровая консоль. Большой собственный магазин приложений + доступ к стиму, xbox. В автономном режиме можно использовать в дороге - на нем работает MS-Офис, браузеры, можно смотреть фильмы. Особенно удобно, что нет тряски - в машине, поезде, самолете. Использую шлем для работы - беспроводное подключение к лаптопу огромные экраны с кодом и документами висят прямо поверх изображения моей комнаты. Один недостаток - сын постоянно отбирает шлем.
Если $500 за Quest3 дорого, можно взять Quest2 за $250 картинка похуже, внешние камеры хуже, но для игр и даже недолгой работы - вполне приемлемо. Вот это - самый настоящий массовый продукт, который в данный момент создает рынок.
Шлем - это совершенно новый форм-фактор персонального компьютера - и новая концепция его использования. В ближайщем будущем шлемы станут компактнее, превратятся в очки, и мы будем носить их не снимая вместо сотовых телефонов.
Как человек пять лет проработавший в Гугле подтверждаю все безобразия, описанные в статье. Добавлю только, что в течение последнего года на почти все менеджерские должности назначили индусов - вчерашних тестеров и интернов, которые ни в чем не разбираются и даже не пытаются делать вид, что хотят разобраться. А во время layoffs выгнали всех более-менее инициативных инженеров. Это захват компании. Поэтому, в отличие от автора, я не верю в возможность "излечения".
В Аргентуме есть цикл loop expression, который требует, чтобы expression возвращал значение типа ?T.Цикл крутится, пока возвращается nothing. Как только возвращается не-nothing-значение, оно распаковывается из optional и становится результатом loop.
В моей компании используется другой стиль кодирования, в котором приветствуется ранний return. Вы легко можете изменить мой код, чтобы поддержать единственный return.
Кстати обратите внимание на 1h No hidden data/control flow. Боюсь, это - прямой запрет на стейт-машины.
Вы это так написали как будто это что-то плохое. Да именно жесткий формат числа с плавающей точкой. Это было исходное задание. Причем код построчно повторяет грамматику, то есть самодокументирующийся. А токены не нужны. Они были нужны во времена перфокарт, когда надо было между пассами компиляторов передавать промежуточные данные, и хранить один байт вместо ключевого слова из пяти байт было принципиально. Сегодня и ключевые слова в языках стали контекстно зависимы, и токенизация больше не может различать границы (как например >> в именах шаблонов С++) и поток токенов, увешанный метаданными значительно превышает по объему и исходный текст и усложняет/замедляет парсеры. Сегодня даже в грамматиках напрямую используют символы (например, в ANTLR).
В методе рекурсивного спуска есть поток токеров, словари правил и матчер, который рекурсивно вызывает себя с различными словарями правил. Если матчер захардкодить, и для разных словарей правил построить отдельные функции матчинга, например: "skip_whitespace", "get_sign", "parse_int",- то такая реализация рекурсивного спуска может и не содержать явную рекурсию, но метод все равно будет называться методом рекурсивного спуска.
Это классический LL(0) парсер рекурсивным спуском (конечно однобуквенные переменные надо переименовать). Но код все равно понятен как отче наш любому, кто знаком с "Драконом" Ахо-Ульмана. Или учился на книгах Вирта.
Не думаю, что стандарт на прошивки автомобилей ISO26262 требует, чтобы код прошел одобрение Шалыто.
class Animal {
say() { log("I'm an animal, my parents were animals") }
}
class Cat {
+Animal {
say() { log("Meow") }
}
}
default = Animal;
a = +Cat; // если поменять на ?Cat, скажет I'm an animal...
x = a?_~Animal:default;
x.say(); // скажет Meow
То есть кастить придется руками. Надо подумать, может быть действительно имеет смысл автоматически выводить общего предка.
Можно конечно спроектировать эзотерический язык, в котором всякий операнд любой операции будет лямбдой, но это не практично и ведет к долгой компиляции. Поэтому в Аргентуме лямбда - это то, что программист будет вызывать, не в том же самом месте, где оно объявлено. И у лямбды есть единственный синтаксис (параметры){тело}.
А то, что стоит справа (и слева) в операторах (? : && ||) это операнды. И у них тоже единственный синтаксис - это просто "выражение".
{} - это не отдельный синтаксис лямбды, это групповой оператор. Его можно использовать где угодно.
x ? (data) { data.something() }
Такой синтаксис в Аргентуме уже занят. Он означает, что x - это optional лямбда, и мы тут распаковываем ее из optional, предоставляя (data){data.something()} в качестве результата, если в optional ничего нет.
на мой взгляд, это ?=data очень страшно выглядит
В век, когда нормой считается такой синтаксис struct RP<'a,'b>(&'a u32,&'b u32)говорить о страшности синтаксиса ?=dataдля введения временного имени это вкусовщина.
3) В языке есть функционал для обработки optional значений по типу
y = x ? _ + 1
но такой функционал нужен не только для optional значений, а и для других случаев, например, Promise. Пусть у нас есть Promise, который может вернуть какое-то число, и хотелось бы получить Promise, возвращающий увеличенное на 1 число. Нельзя ли использовать аналогичный синтаксис?
Или у нас есть список чисел, а хотелось бы получить список увеличенных на 1 чисел.
Не стоит ли сделать единый синтаксис для всех таких случаев, когда надо сделать какую-то операцию над обернутым в контейнер значением?
Или вот еще один пример: у нас есть Promise, возвращающий User. Мы бы хотели из него получить промиз, возвращающий Address, а из адреса - Promise, возвращающий улицу. Было бы хорошо, если бы была возможность сделать это кратко и логично, вроде:
street_promise = user_promise->address->street
Монада - удобная математическая абстракция. К сожалению как все обстракции при инженерном применении в реальной жизни она протекает. Промис, как асинхронный процесс должен иметь возможность прерывания и опроса прогресса. Список, как итеративный процесс должен иметь возможность определения порядка и направления обхода и прерывания, поскольку реальный код всегда работает в IO-монаде. Если у вас есть идеи, как вписать все многообразие вариантов маппинга содержимого контейнера с помощью одно примивной низкоуровневой операции "?", поделитесь.
2) Справа от оператора ? с помощью символа _ , видимо, создается выражение для преобразования содержимого переменной. То есть, это выражение работает только в операторе ? . Но почему бы не сделать эту конструкцию более универсальной и применимой везде, чтобы символ _ создавал анонимную функцию, [как это сделано в Swift](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures/#Shorthand-Argument-Names) с символами $0, $1 и тд ?
Позиционные нумерованные параметры - это последнее, что я бы хотел иметь в языке.
В Аргентуме есть анонимные функции с именованными параметрами: (parameters){body}, возможно имеет смысл добавить облегченный стрелочный синтаксис или \-синтаксис.
Пробема здесь, как мне кажется, в том, что x=.. и a/5 очень далеко разнесены друг от друга. Это снижает читабельность. Вместо короткого оператора присваивания мы имеем длинную многострочную конструкцию. А если там будет не 3, а 20 строк и еще несколько вложенных блоков?
x=.. и a/5 разнесены друг от друга не дальше чем оператор return от заголовка функции. Будем запрещать локальные функции?
готов посмотреть на ваш пример с рантайм "интроспекцией" (ну хак хаком же) где это по вашему уместно
Интроспекция и dynamic cross-casts уместны и полезны в обобщенных view-model фреймворках, автоматизации и скриптовании, логгировании отладке и тестах, сериализации, ORM, RMI и много еще где.
Быстрый dynamic downcast может заменить опасный static_cast во всех сценариях, значительно подняв безопасность приложения и добавить простой паттерн-матчинг по рантайм-типам. В сущности std::variant обеспечивает именно его, и при всех его недостатках, его именно за это и любят.
в тех же растах у вас просто будет несколько контейнеров (а)рс где один и тот же объект боксится несколько раз по разным крэйтам
Почему unique_ptr непригоден для организации иерархий объектов, я уже описал тут: https://habr.com/ru/articles/751630/ см. "Композиция в С++/Rust/Swift". Вкратце:
Его таргет может удалиться в тот момент, когда в стековых кадрах есть ссылки на него. В многослойных приложения, когда объекты модели и бизнес-логика, работающая над этими объектами пишется и сопровождается разными командами разработчиков или если жизненный чикл приложения измеряется годами это происходит очень часто.
Он не своместим с weak_ptr, и не может в ассоциативные кросс-связи.
Поэтому остаются только shared/weak_ptr, которые имеют двойную ширину со всеми оверхедами, включая удары по кешу.
Пару месяцев назад купил Meta Quest 3. Теперь это моя (и моего сына) любимая игровая консоль. Большой собственный магазин приложений + доступ к стиму, xbox. В автономном режиме можно использовать в дороге - на нем работает MS-Офис, браузеры, можно смотреть фильмы. Особенно удобно, что нет тряски - в машине, поезде, самолете. Использую шлем для работы - беспроводное подключение к лаптопу огромные экраны с кодом и документами висят прямо поверх изображения моей комнаты. Один недостаток - сын постоянно отбирает шлем.
Если $500 за Quest3 дорого, можно взять Quest2 за $250 картинка похуже, внешние камеры хуже, но для игр и даже недолгой работы - вполне приемлемо. Вот это - самый настоящий массовый продукт, который в данный момент создает рынок.
Шлем - это совершенно новый форм-фактор персонального компьютера - и новая концепция его использования. В ближайщем будущем шлемы станут компактнее, превратятся в очки, и мы будем носить их не снимая вместо сотовых телефонов.
Гугл купила компанию, сделавшую Андроид. Это не собственная разработка Гугла.
Как человек пять лет проработавший в Гугле подтверждаю все безобразия, описанные в статье. Добавлю только, что в течение последнего года на почти все менеджерские должности назначили индусов - вчерашних тестеров и интернов, которые ни в чем не разбираются и даже не пытаются делать вид, что хотят разобраться. А во время layoffs выгнали всех более-менее инициативных инженеров. Это захват компании. Поэтому, в отличие от автора, я не верю в возможность "излечения".
Можно проще:
В Аргентуме есть цикл
loop expression
, который требует, чтобыexpression
возвращал значение типа?T.
Цикл крутится, пока возвращаетсяnothing
. Как только возвращается не-nothing-значение, оно распаковывается изoptional
и становится результатомloop
.В моей компании используется другой стиль кодирования, в котором приветствуется ранний return. Вы легко можете изменить мой код, чтобы поддержать единственный return.
Кстати обратите внимание на 1h No hidden data/control flow. Боюсь, это - прямой запрет на стейт-машины.
Вы это так написали как будто это что-то плохое. Да именно жесткий формат числа с плавающей точкой. Это было исходное задание. Причем код построчно повторяет грамматику, то есть самодокументирующийся. А токены не нужны. Они были нужны во времена перфокарт, когда надо было между пассами компиляторов передавать промежуточные данные, и хранить один байт вместо ключевого слова из пяти байт было принципиально. Сегодня и ключевые слова в языках стали контекстно зависимы, и токенизация больше не может различать границы (как например >> в именах шаблонов С++) и поток токенов, увешанный метаданными значительно превышает по объему и исходный текст и усложняет/замедляет парсеры. Сегодня даже в грамматиках напрямую используют символы (например, в ANTLR).
В методе рекурсивного спуска есть поток токеров, словари правил и матчер, который рекурсивно вызывает себя с различными словарями правил. Если матчер захардкодить, и для разных словарей правил построить отдельные функции матчинга, например: "skip_whitespace", "get_sign", "parse_int",- то такая реализация рекурсивного спуска может и не содержать явную рекурсию, но метод все равно будет называться методом рекурсивного спуска.
Это классический LL(0) парсер рекурсивным спуском (конечно однобуквенные переменные надо переименовать). Но код все равно понятен как отче наш любому, кто знаком с "Драконом" Ахо-Ульмана. Или учился на книгах Вирта.
Не думаю, что стандарт на прошивки автомобилей ISO26262 требует, чтобы код прошел одобрение Шалыто.
Можно упростить: https://onlinegdb.com/4U-2Q6w0K
Пока так:
То есть кастить придется руками. Надо подумать, может быть действительно имеет смысл автоматически выводить общего предка.
Можно конечно спроектировать эзотерический язык, в котором всякий операнд любой операции будет лямбдой, но это не практично и ведет к долгой компиляции. Поэтому в Аргентуме лямбда - это то, что программист будет вызывать, не в том же самом месте, где оно объявлено. И у лямбды есть единственный синтаксис
(параметры){тело}
.А то, что стоит справа (и слева) в операторах (? : && ||) это операнды. И у них тоже единственный синтаксис - это просто "выражение".
{} - это не отдельный синтаксис лямбды, это групповой оператор. Его можно использовать где угодно.
Такой синтаксис в Аргентуме уже занят. Он означает, что
x
- это optional лямбда, и мы тут распаковываем ее из optional, предоставляя(data){data.something()}
в качестве результата, если в optional ничего нет.В век, когда нормой считается такой синтаксис
struct RP<'a,'b>(&'a u32,&'b u32)
говорить о страшности синтаксиса?=data
для введения временного имени это вкусовщина.Оператор ":" всегда имеет тип (?T) : (T) -> (T). Например, если T=void, то тип будет bool : void ->void, как у else-ветки в Cи-подобных языках.
Он просто распаковывет LHS, и возвращает. Если вернуть нечего, исполняет RHS и возвращает его.
Монада - удобная математическая абстракция. К сожалению как все обстракции при инженерном применении в реальной жизни она протекает. Промис, как асинхронный процесс должен иметь возможность прерывания и опроса прогресса. Список, как итеративный процесс должен иметь возможность определения порядка и направления обхода и прерывания, поскольку реальный код всегда работает в IO-монаде. Если у вас есть идеи, как вписать все многообразие вариантов маппинга содержимого контейнера с помощью одно примивной низкоуровневой операции "?", поделитесь.
Позиционные нумерованные параметры - это последнее, что я бы хотел иметь в языке.
В Аргентуме есть анонимные функции с именованными параметрами: (parameters){body}, возможно имеет смысл добавить облегченный стрелочный синтаксис или \-синтаксис.
x=..
иa/5
разнесены друг от друга не дальше чем оператор return от заголовка функции. Будем запрещать локальные функции?Если A?B:C применить по-старому, он и работать будет по-старому.
Ели хочется, чтобы приложение прямо падало (на сервере или у клиента), напиши
x = myOptVar : terminate();
По стандарту: 5.2.9 Static cast 11 [...] The null pointer value (4.10) is converted to the null pointer value of the destination type.
Интроспекция и dynamic cross-casts уместны и полезны в обобщенных view-model фреймворках, автоматизации и скриптовании, логгировании отладке и тестах, сериализации, ORM, RMI и много еще где.
Быстрый dynamic downcast может заменить опасный static_cast во всех сценариях, значительно подняв безопасность приложения и добавить простой паттерн-матчинг по рантайм-типам. В сущности
std::variant
обеспечивает именно его, и при всех его недостатках, его именно за это и любят.Box в Расте не допускает множественного владения.
Почему unique_ptr непригоден для организации иерархий объектов, я уже описал тут: https://habr.com/ru/articles/751630/ см. "Композиция в С++/Rust/Swift". Вкратце:
Его таргет может удалиться в тот момент, когда в стековых кадрах есть ссылки на него. В многослойных приложения, когда объекты модели и бизнес-логика, работающая над этими объектами пишется и сопровождается разными командами разработчиков или если жизненный чикл приложения измеряется годами это происходит очень часто.
Он не своместим с weak_ptr, и не может в ассоциативные кросс-связи.
Поэтому остаются только shared/weak_ptr, которые имеют двойную ширину со всеми оверхедами, включая удары по кешу.