Как стать автором
Обновить

Комментарии 297

Может мне кто нибудь объяснить, почему компилятор для яп пишется на том же яп? На сколько я знаю, первый компилятор для TS был написан не на TS, и был написан только с одной целью — скомпилировать компилятор на TS. Так вот — это делается по идеологическим причинам или по каким то другим?
Во-первых, это традиция. Во-вторых, на новом языке нужно что-то написать, какую-то реальную программу, чтобы отладить все нюансы. Можно выдумывать абстрактную программу в вакууме, а можно начать с реальной — с компилятора.
Но вообще, конечно, это необязательно для языка. Просто хорошая традиция
Если это традиция, то где же компиляторы (или хотя бы интерпретаторы) Perl на Perl, PHP на PHP, Ruby на Ruby или Python на Python?

Чтобы отладить все нюансы есть достаточно реальных задач кроме собственно компилятора, в то время как написание компилятора не обязательно затронет все нюансы которые нужно отлаживать, но вот времени займёт просто уйму (особенно если язык сильно отличается от того на котором пишут первый компилятор).

Задачи, к тому же, необязательно должны быть такими сложными во время разработки языка — к примеру, для отладки рекурсии хватит чисел Фибоначчи, для отладки многопоточности или асинхронной обработки — web-client/server.

Но разумеется, если у разработчиков свободного времени вайлом — тогда да, почему бы и нет, собственно, пишут же эмулятор Z80 на bash
Ну, есть PyPy, есть PHPPHP.

Для интерпретируемых языков больше характерна реализация на более низкоуровневом языке (C или C++, как правило). Или наличие трансляторов в C/Javascript.
Так вы перечислили не компилируемые ЯП, если что. Они не самые быстрые, потому интерпретатор, как по мне, на том же языке писать — профита мало Да, за остальных не скажу, но есть у Питона — PyPy, можете почитать, ради интереса
Компилятор Perl6 написан на нем же.
Компилятор Python на Python, это уже упомянутый PyPy, который помимо того что следует традиции, ещё и предоставляет jit-оптимизации, и ускоряет программу в несколько раз.

Формально, PyPy — это не компилятор Python на Python.


PyPy — это реализация интерпретатора Python на подмножестве языка RPython (валидный код на Python не обязательно является валидным для RPython).


Сам PyPy написан на RPython, который уже является компилируемым языком. Но при этом компилятор RPython уже по большей части написан на Python.

НЛО прилетело и опубликовало эту надпись здесь
Про «курицу или яйцо» как-то попроще было :\
<шутка>а вы не задумывались над тем что эти люди просто научились писать в совершенстве компиляторы и больше не с чем заморачиваться не хотят <\шутка>
PHP поэтому и остался ограниченным языком для интернета. Компилируемые программы на нём никто не пишет. Питон тоже крайне медленный язык(правда есть быстрые реализации, но всё же). Так что ваше примеры только подтверждают правило, что нет полноценных языков, которые себя компилировать не могут.
Компилятор — программа переводящая нечто написанное на неком языке в форму пригодную для исполнения на неком устройстве.

— Машина работает с маш. кодами операций и аргументами в виде ячеек памяти и регистров.
— Асемблер даёт имена маш. кодам и регистрам, делая их человекочитаемыми и наворачивает немного синтаксического сахара по оформлению операций. Но всё это приводимо к маш. кодам практически 1:1
— С и иные системные языки — реализуют некоторые базовые конструкции алгоритмизации в своём синтаксисе, а также организуют среду программирования, состоящую из процедур и методов их написания. Что-то из данных процедур можно написать на асемблере и, используя соглашение о вызове процедур, внести её в среду программирования.
И так далее. То есть язык более высокого уровня добавляет некоторое количество абстракций над языком более низкого, которые в основном представляют из себя просто часто повторяемые конструкции нижележащего языка приятно оформленные в некоторый синтаксис. Когда компилятор языка пишется на самом компилируемом языке возникает ощущение, что языка в этом месте быть и не должно. Возможно нужно спуститься ниже и переписать язык более низкого уровня. Компилятор может частично быть написан на своём языке, но ядро компилятора должно быть написано на языке, в который данный компилятор программу и перегоняет… По другому смысла в компиляторе не видно.

И вообще это языковое безумие заставляет всё чаще вспоминать историю о Вавилонской башне если честно…
Компилятор — программа переводящая...
Если говорить только о самом переводе в исполнимую форму, без уточнения момента перевода, то есть более обобщающий термин — транслятор.
А уже в зависимости от того, выполняется ли трансляция целиком всей программы до выполнения, или по кусочку во время исполнения — получаем деление на компиляторы и интерпретаторы.

Грань становится тоньше, когда вспоминаем про JIT-компиляторы, которые могут также по кусочкам в рантайме программу компилировать

скорее, не тоньше, а размытее.
И вообще это языковое безумие заставляет всё чаще вспоминать историю о Вавилонской башне если честно

Вот дозахватят нас роботы, тогда и bip bop bop bop bop bip bip bip bip bip bip bip bop bop bop bop bip bip bip bip bip bop bip bop bop bop bop bip bip bop bop bip bip bip bop bop bop bop bip bip bip bip bip bop bip bop bop bop bop bip bip bop bop bip bop bip bop bop bop bop bip bip bip bip bip bop bip bop bop bop bip bop bop bop bop bop bop bip bop bop bop bop bip bip bip bop bop bop bip bop bop bop bop bip bip bip bip bop bop

Если и есть к этому предпосылки, то не в нашей вселенной.
Я бы не был так уверен

Ну да. Если посадить миллион обезьян за пишущие машинки, то рано или поздно одна из них выиграет президентские выборы?
рано или поздно одна из них выиграет президентские выборы?
Пишущие машинки для этого совершенно излишни.

"Традиция" — это довольно сырой аргумент. Нужно понимать, что такие вещи делаются чтобы деньги зарабатывать напрямую, либо использовать наработки в других местах. Это ведь не Вася из 9 класса, который написал свой первый парсер и "потому что так принято" делать никто не будет.


Раскрутка компилятора позволяет разработчикам на языке, для которого создается компилятор, этот язык и развивать. Достаточно прагматичная цель, интуитивно выглядит разумным, что разработчики, которым что-то нужно от языка, будут охотнее в него вносить изменения и им не нужно будет вникать в особенности низкоуровневой разработки на втором языке (на котором написан компилятор).
Окружение уже развёрнуто, знай себе только патчи отправляй.


Правда, если язык незрелый — для него нет никаких инструментов. Для TS куча линтеров-чекеров, поддержка в редакторах, миллиарды статей и много разработчиков, поэтому в данном случае от этого нет никаких преимуществ.


Вполне возможно, что через год-полтора сам язык торжественно передадут в сообщество (читай: забьют на разработку), а наиболее интересные решения войдут в TypeScript.

Еще два плюса:
  • Разработчики языка сами пишут на нём — хорошо для понимания проблем и развития языка.
  • Пользователям проще участвовать в разработке и в крайнем случае смотреть на детали реализации.


Пример когда другой язык реализации мешает — Java. Отчасти поэтому сейчас есть проект VM на самой Java — GraalVM.
Это называется «dogfooding».
В том смысле, что разработчики должны сами есть ту «собачью еду» что производят, чтоб лучше понимать какова она на вкус.

Наверное все же "dogfooding"

Да, конечно! Спасибо, исправил.
НЛО прилетело и опубликовало эту надпись здесь
Смотрите, вот файл из недр компилятора TypeScript github.com/Microsoft/TypeScript/blob/master/src/compiler/checker.ts 1.8 Мегабайта (!) одним куском. И его нельзя отрефакторить, потому что был использован module pattern который применяется в JS но абсолютно не имеет никакого смысла в TypeScript. И этот паттерн не расширяем. В итоге мы имеем 32К строк в одном файле? И 2624 вхождения слово function (из них большинство это действительно функции, а не комменты) И 462 стрелочных функции. И он растёт, и будет расти. Ещё в 2017 году я предпринимал попытки автоматизированными средствами это отрефакторить github.com/Microsoft/TypeScript/issues/17861 Ввиду нехватки времени на разработку предложенное решение имеет недостатки и проваливает производительность (я там бинжу все функции, а это не требуется в общем случае, но правильный детектор этого писать лень).

Так вот, новые ЯП как правило нужны для введения и демонстрации новых техник программирования, ЯП никто не релизит ради синтаксиса. И есть концепция en.wikipedia.org/wiki/Eating_your_own_dog_food которая говорит что нужно использовать свой продукт. И вот вы как разработчик языка начинаете на нём писать его — же. Понимать как на самом деле работает то что вы придумали. В случае в TS изначальная архитектура пришла из старых JS подходов, и она откровенная слаба в TS мире. Вот поэтому я считаю что нужно писать ЯП на нём самом, не если это не DSL какой-нибудь.
А почему этот модуль нельзя разбить на несколько модулей поменьше + ещё один модуль который импортирует все функции из этих «чанков» и реэкспортирует их всех в виде неймспейса ts.
Потому что в данном случае у этих функций огромный общий шареный стейт, что должно бы было быть свойствами объекта. Вот его часть
Вот его кусок, но это не всё
 const compilerOptions = host.getCompilerOptions();
        const languageVersion = getEmitScriptTarget(compilerOptions);
        const moduleKind = getEmitModuleKind(compilerOptions);
        const allowSyntheticDefaultImports = getAllowSyntheticDefaultImports(compilerOptions);
        const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks");
        const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes");
        const strictBindCallApply = getStrictOptionValue(compilerOptions, "strictBindCallApply");
        const strictPropertyInitialization = getStrictOptionValue(compilerOptions, "strictPropertyInitialization");
        const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny");
        const noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis");
        const keyofStringsOnly = !!compilerOptions.keyofStringsOnly;
        const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : ObjectFlags.FreshLiteral;

        const emitResolver = createResolver();
        const nodeBuilder = createNodeBuilder();

        const globals = createSymbolTable();
        const undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined" as __String);


И эти константы замыкаются и юзаются из кучи функций, отдаются колбеки и тп. Чтобы разделить стейт, грамотно его пробросить и всё такое нужно огромное количество усилий. И я вижу только два пути, автоматом конвертнуть типа как я предлагал и потом начать разводить по наследованию, и второе, сказать что у нас теперь есть новый компилятор tsc 2.0 и в нём написать всё это заново с новой архитектурой. Пока же эта штука продолжает расти.
Что если все эти зависимости перенести в один объект. Вроде:

const context = {
    compilerOptions: host.getCompilerOptions(),
    languageVersion: getEmitScriptTarget(compilerOptions),
    moduleKind: getEmitModuleKind(compilerOptions),
    // ...


Во всем коде использовать этот объект как Service Locator, а потом начать передавать всем, кто его хочет как зависимость?
Так я и делал в своём рефакторинге, я в том случае все свойства на this навесил и все методы пробиндил. И это даже тесты прошло полностью. Проблема в том что код стал ещё хуже и просел перформанс. А руками это сделать можно, ничего кроме объёма работы не мешает. Но сейчас никто не готов столько работы пожертвовать.
Основная причина, имхо, в том, что невозможно оценить пригодность и эффективность языка, не написав на нем хотя бы одну сложную программу. Сделать минимальный bootstrapping на другом языке, чтобы сразу писать основной код компилятора языка на нем же самом — это одновременно красивый ход для инженеров и эффективный для бизнеса.

Кроме того, усовершенствование компилятора (добавление новых оптимизаций и проверок) помогает улучшать его собственную работу.
Это делается в том числе и для доказательства того, что язык тьюринг-полный.
Не сказал бы. Тьюринг полноты не достаточно для удобного программирования, и в то же время есть много не тьюринг полных DSL которые удобны. Как пример тьюринг полнота системы типов typescript github.com/Microsoft/TypeScript/issues/14833 вот ещё посмотрите ru.wikipedia.org/wiki/Тьюринговская_трясина

Вроде был язык, в котором только 3 функции, первая печатает "Hello world", вторая выводит текст программы, а третья генерирует компилятор этого языка. Так что возможность написать компилятор языка на самом языке не является доказательством полноты по Тьюрингу.

только без генерации компилятора.
Вот пишете вы на каком-то языке, растёте и в какой-то момент хотите в нем что-то улучшить/пофиксить и опа — оказывается что ваш 20 летний опыт разработки на этом языке тут не поможет, надо пойти ботанить какой-то другой язык на котором написан компилятор.
Ну справедливости ради стоит сказать что ооочень часто средний разработчик решает задачи кратно проще чем разработка компилятора, и идея просто зайти, почитать и поправить компилятор для внесения своих фич обычно идеей и остаётся, не зависимо от того, на каком языке это написано.
Очевидно, что это не для средних, но кто-то должен развивать язык и понятно что это должны делать те, кто им пользуются, а раз пользуются, то скилы других языков теряются в связи с ненадобностью.
Это называется Bootstrapping.
Как можно создавать язык программирования, не написав к нему документацию? Это уже не первый случай. Сначала накодят что-то, а потом задним числом сочиняют спецификацию.
А почему нет? Вполне может быть что авторы ещё не представляют себе что там должно быть, как оно должно работать или вообще ещё не определились чего хотят, вот и эксперементируют, заодно собирая мнения и идеи.

Разница только в том что кто-то это делает публично, а кто-то «тайно» — в первом случае об отсутствии спецификации в начале разработки известно всем, а во втором об этом может никто и не узнать (поскольку её выложат вместе с языком) — хотя принципиальной разницы нет.

В конце концов, это ж не мостостроение, где опасно начинать строить пока нет проекта и расчётов, особенно с учётом того что нигде в продакшн это не используется.
Встречный вопрос: какой смысл писать документацию к проекту в экспериментальной стадии, когда основные фичи еще обкатываются?
Сначала накодят что-то, а потом задним числом сочиняют спецификацию

Называется Agile. И внезапно это удобно и эффективно, хотя и не везде.

Не в том ли идея чтобы он сразу мог бы параллелится?

Для упрощения этой задачи тут только иммутабельность, что само по себе не гарантирует хорошего паралеллизма.
Ну если нет циклов и идет работа со множествами то это напоминает SQL, который как раз располагает к паралеллизму…
Всё-таки давайте не будем смешивать в кучу язык общего назначения и SQL.

Кстати, fun fact: Я был так много наслышан о том, как Хаскелл хорошо параллелится, ещё когда начал учить первый язык, что когда я схватился за Хаскелл, был поражён, что параллелить надо через монаду, что накладывает не одно ограничение на мой код, т.к. я ещё не понял их и трансформеры. Итог: не один десяток малых параллельных проектов на С++ и ни одного на Хаскелле.

Вот тебе и «easy parallelism by design».
НЛО прилетело и опубликовало эту надпись здесь
А оператор `par` уже устарел?
Это и есть монада

Ничего не устарело, просто я открыл для себя с изучением Хаскеля, что недостаточно просто «сказать» программе, что я хочу её раскидать на десять кластеров, а надо-таки раскидывать этот лёгкий-для-параллелизма из коробки по парам и секам.

Написать-то можно, если задаться, но к многопоточности приходишь, как набираешься чуть опыта и видишь, где от неё профит словить.
Нет, это не монада.
Благодарю, загуглил сигнатуру, был сбит с толку другим результатом гугла.

Точно также в сиквеле, надо сразу думать множествами, а не мыслить "так, берем один элемент, проверяем..."

НЛО прилетело и опубликовало эту надпись здесь
если мы можем передать Map по ссылке, и фунция ее намутирует.

Не зная как устроена Map, это сложно понять. Не исключено, что в Map метод добавления элемента генерит новый Map просто (как в Scala).
Делаем простой и понятный язык для человека, поэтому добавляем побольше разномастных скобочек, стрелочек, знаков, двоеточий, точку с запятой в конце! *картинка с изображенеим genius*
Да-да. На первый взгляд новый язык по читаемости может поспорить с Perl, J и триграфами C++.

Мне кажется, я даже мгновенно перестал ненавидеть JavaScript после того как увидел это. Серьёзно, ещё пол-часа назад я хотел любыми силами избежать JavaScript в моей жизни, а сейчас JavaScript уже не кажется чем-то сильно плохим.
Наверно, для этого и создан новый язык, чтобы программеры понимали, что все не так плохо))) Это, конечно, шутка.)
Как вам удобнее читать формулировки теорем — в кванторах или в словах?
Слабая и неуместная аналогия. Мне удобен код с синтаксисом, который вызывает минимальную когнитивную нагрузку — моя голова и так будет загружена при чтении/написании кода. Здесь синтаксис, похоже, впитал всё самое жуткое из мира c/c++, так ещё и сверху присыпал от себя.
Если я правильно понял ваш первый комментарий, вы затронули сразу две темы — и визуальный шум, как точки с запятой, и специальные конструкции, как стрелочки. Насчёт шума я вас полностью поддерживаю. Но я хотел узнать именно про второе. Меня удивляет, что есть люди, предпочитающие писать «function», а не "=>". Пытаюсь понять причину.
Не, стрелочка в определении лямбд у меня нареканий не вызывает — это уже устоявшийся вариант.
Я про другое. Если взглянуть на этот код, то можно увидеть следующие «интересности»:
1) в классе (который назвали entity) есть const поля, а есть field. Казалось бы и то, и другое — поля класса, но к первым в коде обращаются через явное указание типа и двоеточия (Board::playerX), а ко второму через точку и this (this.cells). Нужно ли было делать такую разницу для данных в одной области видения?
2) стрелочка используется и для вызова методов класса, и для пайпинга. Нет, конечно, можно подвести эти вещи под один знаменатель, если представить что каждый метод неявно принимает параметр this (вроде того, как это сделано в Питоне). Но нужно ли?
3) потом мы видим, что через двоеточия мы по сути можем обращаемся к статическим const полям (game = game->makeAutoMove(Board::playerX, 0);). При этом само поле не помечено как static, хотя спецификатор этот есть (factory static createInitialBoard()). Кстати к этому статичному фабричному методу мы обращаемся уже через указание класса и собаку (field board: Board = Board@createInitialBoard();). Зачем надо было делать такое различие — не ясно.

Да, может всему этому есть объяснение и сложно судить по куску кода о языке. Но серьёзно, как отметили выше, ощущение такое, что ребята просто на ходу сочиняют разрозненные куски, а потом под это подведут кривую спецификацию. В то время как лучше было бы начать с другого конца.
Мне удобнее. Потому что function сразу бросается в глаза (особенно с подсветкой современных редакторов), заставляя заострить на этом куске кода внимание. "=>" же беглым взглядом вообще мало отличимо от оператора присваивания.
Ну и вот, например, тут достаточно о разнице между function и "=>". Помимо того факта, что для этих стрелочек обычно надо ещё какой-нибудь Babel городить.
Там ровно два различия: свой this и свой arguments. Но если функции нужен свой this — то это никакая не функция, а метод; а для методов в свежем стандарте есть свой синтаксис. С arguments же всё ещё проще: надо перестать их использовать.
(особенно с подсветкой современных редакторов),

Скорее в древних блокнотах. Современный редактор умеет в семантическую подсветку. А подсветка уровня кейвордов — это про древний блокнот.

Соответственно — function является лишним синтаксическим шумом, т.е. редактор умеет красить функции в уникальный цвет. И современно без разницы какие они.
sublime — это древний блокнот?
А почему нет?
Я ведь дал критерии. Может отличать функции от не-функций в каком-нибудь С++ — не блокнот и не древний. Не может? Блокнот. Да и судя по википедии оно и позиционируется как блокнот.
>> впитал всё самое жуткое из мира c/c++
Что конкретно?
На словах или в коде (в добавку к формулам). Очень часто тривиальные для понимания вещи прячут за вырвиглазными формулами с кучей нечитаемых переменных (речь про статьи по cs если что).
Вероятно, люди деляться на тех, кому проще в кванторы, и тех, кому проще в слова. И это очень странно. Потому что смысл абсолютно одинаковый, но короткие специализированные знаки должны считываться и обрабатываться мозгом быстрее. Возможно, что вы недостаточно выработали навык их чтения. Но я встречал других людей, кто предпочитает естественный язык специализированному.
Это управленческий паттерн «незаменимая команда». Когда команда, разрабатывающая один из ключевых продуктов компании, переводит его на специально ими выдуманную технологию — новый язык программирования, принципиально новую СУБД с ни с чем не совместимым языком запросов, пишет с нуля новую ОС, на которой будет крутиться сервер продукта, ну и т.д.
В итоге команда, которой удалось реализовать этот паттерн, надолго становится незаменимой — их становится очень сложно уволить, не завалив разрабатываемый продукт, потому что спецов по новой технологии в ближайшее десятилетие будет исчезающе мало.
Именно поэтому программистам очень выгодно реализовывать этот паттерн. А вот для менеджера, допустившего такое, например переписывание половины браузера на принципиально новый язык — признак профнепригодности, особенно когда компания испытывает финансовые трудности.
Это да, но самые упоротые — это «независимые консультанты». Во времена оны приходилось сталкиваться с персонажем, предлагавшим оптимизацию программ для (внимание!) «полного соответствия Ruby-way». Что самое удивительное — его даже кто-то нанимал…
У всех остальных языков есть Фатальный© Недостаток™.
Теперь мало того, что вместо вставления кода текстом — он вставлен картинками. Так мы теперь ещё и второй раз обливаем читателя дерьмом, используя для этого вместо моноширинного шрифта совершенно нечитабельный serif и блюрим картинку:



Давайте вы её еще под углом сделаете и мигающей, вдруг ещё остались люди, которым удобно читать это уг?

EDIT: Оказалось, что блурилось из-за масштабирования в браузере, но это всё-равно камень в огород автору статьи
По идее если подсветить код как JavaScript — должно быть неплохо
function internString(ref env: Map<String, Int>, str: String): Int {
    if(env.has(str)) {              //use the ref parameter
        return env.get(str);
    }

    env = env.add(str, env.size()); //update the ref parameter
    return env.size();
}
единственное место, где я нашел подсвеченный код — это pdf файл. Какой там шрифт есть, такой и есть.

Можно разве что побольше сделать картинку, чтобы читалось получше
в общем, я сделал шрифт побольше, но хабр зачем-то искажает размер картинки, поэтому замыленность всё равно есть
А если просто переписать код его вроде немного? Ду ну бред какой-то.
И вручную раскрасить? Или оставить равномерно чёрным, чтобы плевались теперь на это?
Как выше уже продемонстрировали можно включить подсветку js, а так да, текст всегда лучше чем картинка с текстом, ну если только ты не капитан джек воробей.
Это явно не язык, который ставит задачу завоевать рынок или даже быть примененным в продакшене. Это исследовательский проект, чтобы найти новое направление развития языков программирования. Тут, похоже, под ясностью и для человека, и для машины понимается создание практичного для обычного человека языка, который может формальную верификацию. Мое беглое чтение примеров формального доказательства алгоритмов на специализированных языках повергло меня в ужас как-то давно, так что смысл в этом видится вполне.
Вот вот. Среднему индусу в MS такое не осилисть.
Не осилить такое почти никому, почему формальную верификацию на практике практически нигде не видно. А то, что видно, лишь небольшие кусочки и алгоритмы. В основном максимум это статические анализаторы кода и здоровенные сборники правил как писать на каком-нить С. Даже там, где от корректности кода зависят жизни людей.
НЛО прилетело и опубликовало эту надпись здесь
И чего в нем такого нового? Исследовательского?
Языки все больше становятся похожи на какие то клиновидные записи или древнеегипетские иероглифы ('x'#PlayerMark, =>, <~, Board::playerO, @, |>, |< и т.д. и т.п. в самых неожиданных местах) и не понятно зачем вместо превычного слова «class» и «struct» или «record», которые уже не одно десятилетие в других языках применяются, выдумывать что то новое. Вместо function вставили method, тогда вместо if нужно было еще что нибудь придумать, а еще лучше вообще язык поменять на русский, была бы еще одна 1С, только в функциональном стиле.
Ну в каком-то языке программирования (JS?) это может и так, но концептуально-то разница меду функцией и методом не такая. Лучше уж сделали бы как в С++ (virtual/override) или как в джаве — где всё виртуальное (зачем нужны невиртулаьные методы? — хороший вопрос для собеседования!)
Ответ: для того, чтобы всех запутать и после cast вызывался другой метод.
Адепты С++ ответят, что тем самым экономят место в виртуальной таблице вызовов.
НЛО прилетело и опубликовало эту надпись здесь
Языки все больше становятся похожи на какие то клиновидные записи или древнеегипетские иероглифы

Ну почти все языки полны всяких «иероглифов», в заблуждение они вводят разве что новичков, со временем они запоминаются и проблем с их пониманием нет, конечно если не городить всяких заумных конструкций. Есть другая крайность — когда язык очень похож на естественный, как например SQL или COBOL, читать вербозный код не очень-то легко, а писать на таком языке вообще мрак и уныние.

вместо if нужно было еще что нибудь придумать

Ага, как в Red, if с одной ветвью, either — с двумя.
if с одной ветвью, either — с двумя.

Хм, на первый взгляд крутая идея
> тогда вместо if нужно было еще что нибудь придумать
whatever(false condition)
а еще лучше вообще язык поменять на русский

Тсс, тихо! А то ещё призовёте дьявола в 1С 8.4 в виде:

#РасходнаяНакладная↑Conclude(СуммаСовсемБез НДС).Подобно()
«Подобно» или все же «Подробно»?

А мне интересно что такое Conclude и почему не на русском? Внешняя команда или…?

Именно Подобно, этакий LIKE от отечественного производителя.
Нужен язык на кане. Код как искусство.

Ну или прямо иероглифами. Ёмкость потрясающая получится.
программы на Bosque являются детерминированными… Если программа выдала какой-то результат, то такой же результат будет и потом, никаких сюрпризов


Вот эта формулировка меня очень и очень смущает. То есть… скажем, если программа использует БПСЧ… или обращается к жесткому диску / сетевому адресу… результатом будет синий экран?

Или вот это:
алгоритмы сортировки только стабильные


под стабильными, наверное, понимаются устойчивые алгоритмы? А если я напишу на Bosque алгоритм Шелла (неустойчивый) — будет исключение рантайм? Ошибка компиляции?

Поясните, пожалуйста. Взрывает мозг…

Дословно в документации так:

Thus, Bosque does not have any undefined behavior such as allowing uninitialized variable reads and eliminates all under defined behavior as well including sorting stability and all associative collections (sets and maps) have a fixed and stable enumeration order.

As a result of these design choices there is always a single unique and canonical result for any Bosque program. This means that developers will never see intermittent production failures or flaky unit-tests!

Больше информации нет никакой.

Возможно, я что-то не так понял. Готов исправить статью
Почитайте про «неопределённое поведение». Например в Си, порядок некоторых операций не определён в стандарте и разные компиляторы выдают разный результат в таких случаях.
Авторам языка придется определить все возможные сочетания операций и выражений при всех возможных условиях. Флаг им в руки, так сказать…
Но это же в любом случае приходится делать авторам компиляторов.
Хотя бы простые и общие правила не помешали бы, почему-то есть языки, где это сделано.
НЛО прилетело и опубликовало эту надпись здесь
Вот если появится вторая реализация, появятся и UB.
UB может появляться и без второй реализации.
Непонятно, какие преимущество у этого ЯП по сравнению с другими? Тем же С++.
Вот мне нужен ЯП, смесь из ассемблера(доступ к флагам и регистрам процессора), С и С++(классы, виртуальные функции) и при этом достаточно простой. Думаю развивать идею ассемблера MASM'а(UASM), кодогенерирующие макросы .if, .while, .for, и т.п.
А по этому ЯП(назовём его Боська), в упор не вижу каких либо достоинств. Да, у меня память не очень хорошая, и очень не хочется её перегружать лишней инфой, изучая кучу очень сложных ЯП. Надо проще делать, чтобы простой как Lua и достаточно функциональный как С++.
КО подсказывает, что в С/С++-программы можно делать ассемблерные вставки, использовать intrinsics или линковать к ним модули на ассемблере.
Уже есть такой язык — Паскаль. И прост(не зря школьникам преподают) и функционален.
НЛО прилетело и опубликовало эту надпись здесь
И что, что от MS Research? Понятно, что не от MS Office. И в заголовке, кстати, нет ровно никакой желтизны.

Поясните свою мысль.
Ну от MS Research или от MS Developer Division — огромная разница.
Желтизна сегодня — она именно такая. Написать абсолютную правду, но так, чтобы сформировать ложное впечатление. «Новый язык от Microsoft» — это явно про какой-то продукт, который распространяет компания Microsoft. Не эксперимент в Research, а конкретный продукт с поддержкой в Visual Studio.
Я не в курсе про MS Developer Division и т.д. Поэтому и попросил пояснить мысль.

Так может быть вам как автору новости стоило бы всё выяснить, прежде чем торопиться писать?)

Выяснить всю структуру Microsoft?
Если бы я знал о таких нюансах, я бы конечно выяснил.
Хотя бы выяснить, что такое Microsoft Research, и какими проектами они занимаются? Тяп-ляп и в продакшен, да?

Самоутверждаетесь в комментариях, да?

В readme репозитория, на который вы даёте ссылку в начале «статьи», как раз и говорится, что язык Bosque это проект Microsoft Research и приводится ссылка на него. «Выяснить структуру Microsoft» не обязательно — вся информация не дальше первых ссылок поисковой выдачи. Это не так уж и сложно, если решили выложить некий обзор. Абзац с подведением итогов говорит о том, что вы действительно не разобрались что этот проект ни что иное как PoC.

Выглядит как первоапрельская шутка.

«Весь апрель — никому не верь!»
НЛО прилетело и опубликовало эту надпись здесь
Главная миссия дизайна языка — чтобы он был прост и понятен как для человека, так и для компьютера.

Взаимоисключающие параграфы? Языки программирования созданы так, чтобы быть понятными человеку. Для компьютера лучше всего понятен ассемблер.


рекурсия считается злом, которое может усложнить программу, поэтому рекурсивные фунции надо помечать словом rec

Почему? Многие алгоритмы наоборот в рекурсивном виде выглядят просто и естественно. А нерекурсивный вариант выглядит куда более громоздко.


А как нужно помечать потенциально рекурсивные функции, т.е. такие, которые могут вызывать сами себя, но опосредованно?


программы на Bosque являются детерминированными. Другими словами в языке нет неопределенного поведения. Например, нельзя использовать переменные, пока они не были определены; алгоритмы сортировки только стабильные и т.д.

Какие-нибудь современные языки являются недетерминированными? Вспоминается только C++. Записывать это в плюсы — все равно что писать, что в языке можно использовать не латинские идентификаторы.


Если программа выдала какой-то результат, то такой же результат будет и потом, никаких сюрпризов

Что это за чушь вообще. А что если используется функция генерации случайных чисел?


Также хочется задать авторам вопрос: чем их не устроил собственный же язык F#?

Также хочется задать авторам вопрос: чем их не устроил собственный же язык F#?
NIH в масштабе локальной команды?
Для компьютера лучше всего понятен ассемблер.

Программа на машинном языке тогда уже. Программа на мнемокодах (языки ассемблера) — тоже понятнее для человека.
чем их не устроил собственный же язык F#?

Тоже возник такой вопрос. А вообще лучше бы они Nemerle поддержали.

" чем их не устроил собственный же язык F#" Это теперь у всех такое поветрие — яростно пропихивать свою поделку, потом сами же забрасывать. Как ябочники вместо C++ зачем-то пропихивал objective-c, потом сами же его и забросили.
F# слишком сложен, он вдвое сложнее C#, а С# сам по себе непрост, у МС нет собственного простого языка (VB.NET не в счёт) а-ля Python/Go/PHP. Нужен простой, чтобы его можно было в школах преподавать.
НЛО прилетело и опубликовало эту надпись здесь
Видимо, .net имеет такую же сложность, как и функциональный стиль, соответственно, их сочетание сложность удваивает.
Так же, как я определяю, что одна книга вдвое толще другой: по количеству нового материала. Книга F# for fun and profit имеет аж 1930 страниц! F# может почти всё, что может С# плюс вдвое больше. Учитывая, что помимо самого языка нужно еще изучить функциональную парадигму программирования, привыкнуть к новому синтаксису, получается не проще, чем еще раз прочесть книгу по С# + GoF. Понятное дело, что инженеры, научные работники, а так же школьники, студенты, хипстеры и стартаперы не являются целевой аудиторий F#.
НЛО прилетело и опубликовало эту надпись здесь
F# гибридный язык, так что рискнувшему его изучить придется «запачкать ноги».
НЛО прилетело и опубликовало эту надпись здесь
а кто-то вообще с релейных диаграмм
Я не понял, сперва говорится об иммутабельных значениях, а потом о возможности объявления мутабельных переменных. Так что всё-таки иммутабельно, значения или переменные?

Вместо классов и интерфейсов в языке есть понятия entity и concept.

Но это те же интерфейсы и классы, просто названы по-другому.
В такой формулировке это звучит как утверждение, что присвоить переменной новое значение можно, а вот никакой внутренней мутабельности уже нет — если нужно заменить значение поля в объекте, изволь менять весь объект, как-то так…
НЛО прилетело и опубликовало эту надпись здесь

M$ изобрели Erlang только TypeScript

НЛО прилетело и опубликовало эту надпись здесь
Че-то я не осознал цели этого творения. Если крупная компания выводит на общее обозрение нечто, пусть и не в форме релиза, но под своим именем, она чего-то ждет. Языки имеют специализацию. А тут я че-то ничего внятного не нашел.
Хотя… возможно, это очередная попытка от MS создать Java.
А зачем MS создавать еще один Java?

Разве MS не создала свое виденье Java создав C#?
Именно. И проект, в общем-то оказался провальным. Можно сколько угодно обсуждать спешность шарпа, но его удел оказался корпоративные решения. А прибитость его к .net вообще не ясна, потому, что никакой крос-платформенности он не дает. В общем, как по мне, так акая-то хрень вышла. Как и VB до этого. Который MS сует куда не попадя, даже в свои браузеры совала. Сравнивать его с Java язык не поворачивается.
корпоративные решения… никакой крос-платформенности

Вы что-нибудь слышали про Unity?
А прибитость его к .net вообще не ясна, потому, что никакой крос-платформенности он не дает.


Я просто оставлю это здесь
image
Я тоже, просто оставлю это тут.
Несмотря на существование Mono, C# тесно привязывает разработчиков к платформе Microsoft (включая ОС, офисные решения). Таким образом, пользователь программного обеспечения, написанного на .NET, часто не имеет выбора в использовании различных компонент системы. Это приводит к так называемому vendor-locking, при котором производитель стороннего ПО может диктовать покупателю практически любые условия на поддержку внедрённого проекта. В то время, как пользователь приложения Java, как правило, может сам выбрать поставщика дополнительного ПО (такого, как БД, ОС, сервера приложений и т. д.).


Это указано на вики. И копипастю сюда не как пруф, а как текс с которым Я согласен. И имею то же мнение.

К кросплатформенности я отношу не просто исполнение кода на чем-то ином, а развитую экосистему продукта, адаптированную под платформу. MS же тянет все свое с собой. И… пфффф… Ну и повторюсь еще раз — это лишь мое мнение.
С такой точки зрения java такой же vendor-lock, т.к. стандартное явление видеть программистов, которые живут энтерпразйным java стеком и всю жизнь за его пределы не вылазят, что их даже на работу не взять себе для чего-то другого.

А в общем, вы процитировали глупость, с которой согласны лишь потому, что не имеете представления о ситуации так же как ее не имеет автор этого опуса. Кроме этого вашего mono вообще-то есть .net core.
это лишь мое мнение.

Оно какими-нибудь фактами подкреплено? На прошлых двух работах писал на дотнете совсем не под windows — мобильная разработка на Xamarin(Android, iOS) и тяжелый бэк на .NET Core(Linux) — есть вполне конкретные контрпримеры к утверждению, что оно прибито к MS-экосистеме / кроссплатформенность недостаточного качества для энтерпрайза.


К кросплатформенности я отношу не просто исполнение кода на чем-то ином, а развитую экосистему продукта, адаптированную под платформу. MS же тянет все свое с собой

nuget? Если взять топ-100 пакетов оттуда по популярности(не стал проверять дальше), все они работают на *nix без проблем.

Мне́ние — понятие о чём-либо, убеждение, суждение, заключение, вывод, точка зрения или заявление на тему, в которой невозможно достичь полной объективности, основанное на интерпретации фактов и эмоционального отношения к ним.

Подкреплено личным опытом, в период с момента его первого релиза до 2014г.
Подкреплено личным опытом, в период с момента его первого релиза до 2014г.


Слушайте, ну вы вроде как тим лид, да еще и с таким большим опытом работы с .net. Кому как не вам понимать что за 5 лет в современной индустрии меняется вообще все и ваш опыт .net пятилетней давности имеет мало общего с тем что мы имеем в 2019 году.

Или… или как тимлид с некоторым опытом, который наблюдал многострадания MS подвинуть Java, а еще и Delphi (че к нему то привязались, вообще не ясно) одним махом. При этом, завезя все, что было в VB и прибив гвоздями к своему любимому OLE. Наблюдая конвульсии шарпа с первой презентации (с криками — долой самодержавие Java!) до отказа от всех внедрений на нем в крупных компаниях и переход на Oracle.
Я таки (за 10 лет) сложил свое мнение и об языке и о его перспективах и сделал свой выбор, в свое время. И ни разу о нем не пожалел.


Вот как завезут .net на хотя бы 30% устройств как предустановленную машину, так и поговорим. А то в свое время визгу было, что мир теперь изменится, про java забудут и везде будет .net. А я как отъехал от MS так за все время, даже случайно не встретил .net на чем-то отличном от винды.

До наступления эпохи смартфонов .net как раз и был предустановлен более чем на 30% устройств.

А на смартфонах предустановленный .net и не нужен: mono прекрасно распространяется вместе с приложением.
До наступление эпохи смартфонов была эпоха динозавров, когда ничто кроме MS не было. Даже на IE 6.0 VB работал как скриптовый язык. И MS пыталась «подскочить» в уезжающий без нее поезд компактных устройств. Напомню, что MS запилила WinCE и WindowsMobile где .net устанавливалась. Ну и где оно? Это невмеру прогрессивное архитектурное и инженерное решение?

Ровно также, как только появилась Java, тут же скукожилось и съехало в небытие. Причем скукоживаться начало уже тогда, когда простые мидлеты появились на простых телефонах. Заметьте не .net, а Java машина туда ставилась. Почему бы?

С выходом первого андройда WindowsMobile был приговорен. Вялые попытки что-то там пропихнуть через покупку Nokia увенчались тоже полным крахом. Сейчас MS приторговывает… Nokia 3110 (или какого они там мамонта возродили) в оригинальном исполнении. Смешно? По мне так очень.

А на смартфонах предустановленный .net и не нужен: mono прекрасно распространяется вместе с приложением.


Возможно. Только приложения такие никому не нужны. В лес со своими дровами…
НЛО прилетело и опубликовало эту надпись здесь
Занимательная ссылка (y)
и тяжелый бэк на .NET Core(Linux)

Не вброса ради а любопытства для: в качестве ОС для разработчика на этом проекте вы использовали Windows или таки Linux?

Windows — до VS кроссплатформенным IDE не дотянуться ещё.


IIRC, ни в Rider, ни в VSCode, ни даже в Monodevelop a.k.a Xamarin Studio a.k.a VS for Mac нет edit-and-continue до сих пор.

В Rider уже есть, скоро будет в стабильном релизе: www.jetbrains.com/rider/eap
В общем, как по мне, так акая-то хрень вышла.

Какая-то аргументированная критика C# в сравнении с Java у вас есть?
Именно. И проект, в общем-то оказался провальным.

С вашей стороны весьма глупо называть провальным язык, который уже давно занял неплохую долю в своей нише и очень крупное сообщество.
Какая-то аргументированная критика C# в сравнении с Java у вас есть?
Лично я скажу, что в Шарпах в сравнении с Джавами просто прекрасные Дженерики

А в чем отличие, можете в двух словах рассказать?

var text  = GetComponent<Text>();
var image = GetComponent<Image>();

В Java невозможно так сделать — информация о дженериках теряется на этапе компиляции и этот код скомпилируется во что-то такое:
Text  text  = GetComponent();
Image image = GetComponent();

Естественно, работать не будет. В Шарпах информация о типах сохраняется и её можно использовать не только как подсказки, но и в коде.

Вот это как раз без особых проблем работает, просто вместо угловых скобок надо использовать class:


Text text = GetComponent(Text.class);
Image image = GetComponent(Image.class);
Да я понимаю, что можно без этого. В Go вон вообще без дженериков обходятся как-то. Просто это менее удобно.
Тут всего-то на 4 символа больше писать надо, это совсем не то же самое что и «без дженериков». Если сравнивать с тем как в Java «реализованы» свойства — то эти 4 символа и вовсе незаметны.
Мне оно не шибко нравится не по количеству символов, а по сути.
Да и это не единственный пример, где то, что дженерики пропадают на этапе компиляции — мешает
В том, что они не пропадают во время исполнения. Отсюда два следствия:

1. статические поля и методы также могут использовать типы-параметры;
2. можно без хитрых извращений и без тонн автогенерированного кода взять и использовать контейнер, параметризованный примитивным типом.
2. Вы о том, что в Java список может принимать только Boxed Integer, но не примитивный int?
Ага, именно об этом. Соответственно, или мириться с постоянными упаковками, которые никакой Escape analysis не уберёт по построению — или использовать отдельный интерфейс и отдельную реализацию для списка чисел.
Вы мне еще мнение запретите высказывать :))) Смешно.
Похоже на тестовый полигон, на котором будут обкатывать будущие фичи для других языков.
String[ZipCode]

Чего только люди ни придумают лишь бы не делать алгебраические типы…


Вообще конечно выглядит пока сомнительно. Особенно комбинация заявленной иммутабельности с ref — то ли авторы сами толком не определились, чего они хотят от языка, то ли не очень понимают, что immutability это совсем не то, что делает const в javascript. Вообще изрядно отдаёт какой-то фиксацией на javascript-е. Как будто авторы даже с наработками "родного" майкрософтовского F# не вполне знакомы, хотя пайп |> явно оттуда потянули.

Хм, а мне понравился отказ от циклов в пользу перебирающих методов. Ведь при работе с коллекциями обычно требуется их отфильтровать либо агрегировать. Школьные задачки типа «посчитать количество чётных чисел в массиве, стоящих на нечётных местах» в расчёт не берём — задача синтетическая и рассчитана как раз на понимание циклов.
А у меня довольно часто встречаются задачи, в которых простейший цикл выглядит проще чем комбинация фильтров. Как правило, это задачи вида map + filter + map, где из первого map нужно «прокинуть» в последний исходный объект, который при этом совершенно не нужен в фильтре. Особенно плохо всё становится, когда в ходе изменения требований необходимость этого объекта в конце цепочки то появляется, то исчезает.
К слову, один из таких случаев — когда последний map должен знать номера объектов в исходном (неотфильтрованном) списке.

Ну вообще говоря можно сначала отобразить объект в пару (объект, индекс) и потом делать всё остальное. В идеале компилятор может всю цепочку вызовов превратить в обычный цикл, но на практике, кмк, такого ещё нет.

Так об этом и речь: object -> {map} -> (object, index) -> {filter} -> (object, index) -> {map} -> object_processed_with_index.
Тогда начать можно со списка индексов, хотя это выглядит не вполне красиво. Я так делал с GUAVA c использованием Lists.transform(new AbstractList(){...}, ...).
Ну я тоже так делаю, но мне это напоминает «строительство клозуры (=замыкания) вручную». Не особо элегантно.

Меня несколько смущает, что ничего не сказано про ленивость вычислений. Если уж отказываться от циклов, то это must have.

НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Не вижу в этом языке никаких процессов и каналов. Pipe operator только называется так, а дальше коллекций дело не уходит.

За процессами и каналами — в go, в Erlang, или в Java и её библиотеку Akka, или в .NET и в библиотеку Akka.NET. Но там очереди, почему-то, есть. Как и стек. Не согласна почему-то реальность с вашими фантазиями…
НЛО прилетело и опубликовало эту надпись здесь
Львиная-то львиная — вот только совсем не та, для которой обычно очереди используют.
НЛО прилетело и опубликовало эту надпись здесь
Потому что пиковая нагрузка обычно выше чем средняя.

Уважаемый, вы путаетесь в показаниях.


Во-первых, зачем так проектировать систему, что она не справляется с нагрузкой и приходится ждать в очереди?

Вот за этим:


Единственно, что я могу признать как вариант нормального использования очереди — это выравнивание пиков нагрузки. Но тогда очереди должны быть хотя бы ограничены по ёмкости.

С одним дополнением — вы не всегда можете так просто ограничивать очередь по емкости. У вас может быть требование от бизнеса "обработать все входящие запросы".


Во-вторых, а если мы не дождемся освобождения ресурсов, либо их таки не хватит на разгрузку очереди, то что делать?

Вы опять отвечаете на свой вопрос самостоятельно:


То есть мы должны осознавать какую нагрузку мы должны принять и выравнять.

Такие ситуации нужно отслеживать и предотвращать. Ждать когда мощностей даже с очередями не хватит — глупо. Нужно с самого начала собирать статистику нагрузки, экстраполировать тренд и масштабироваться с учетом будущей нагрузки. Если ресурсов внезапно не хватит, то это ЧП и отказ в обслуживании части клиентов.


На первый вопрос ответ понятен: просто не умеем нормально проектировать.

Если вы где-то встретили решение, которое использовало очереди не по назначению, то это проблема не "очереди", а решения.


Про второй вариант ответ так же прост: мы просто сбросим содержимое очереди.

Что вы будете делать, если у вас требование от бизнеса "обработать абсолютно все входящие сообщения"? "Просто сбросить" далеко не всегда так просто, как хотелось бы. Это вы видите запросы в очереди, а другие видят в них деньги и время.


Озвучьте, пожалуйста, аксиому, которую вы пытаетесь превратить в теорему?
Не помню, чтобы кто-то всерьез заявлял "нужно везде использовать очереди".

Зачем? Функциональный, типизированный, иммутабельный, но с возможностью обойти.
Есть же F#, Clojure и Haskell (первый и третий при поддержке Microsoft)

Согласен с вопросом. Язык похож на F#. Там так же можно сделать многое из статьи и mutable переменные есть.
Почему в новых мода описывать аргументы функций как имя: тип? Чем их не устраивает обычный стиль, тип имя?
Как минимум одно из обоснований — чтобы спокойно прикрутить вывод типов и не заставлять писать везде `auto` или его аналог.
Ни от какого auto паскаль-стиль не уходит, а наоборот требует ввод кейворда для обозначения декларации переменной. Таким образом вы всегда будите писать синтаксический мусор вместо типа. Всякие там var, let и прочее.

С типом будет ещё больше мусора, а именно let/var name: type, а не type name;
Go опровергает ваши утверждения.
Что именно он опровергает? Поподробнее. Вводом := или подобной фигни? Ну дак это не опровержение — это подтверждение, т.к. это и есть кейворд для отделения декларации от использования. К тому же, он к делу отношения не имеет, т.к. почти во всех языках используется var/let. И говорим мы о таком языке.
Вот именно что опровергает. := позволяет опустить var и начать объявление с идентификатора переменной. Синтаксис полностью однозначен — либо сначала идет ключевое слово, либо идентификатор. Если мы ставим первым тип, то начинаются вечные проблемы с поиском этого типа и определением вообще, что это за хрень, чтобы потом уже определять, то ли это возвращаемое значение функции, то ли это переменная или еще какая хрень.
Я уже объяснял — это не работает. Причин тому масса. Основная из них заключается в том, что как звучал тезис? «имя: тип что-то там позволяет». := — опровергает этот тезис, т.к. в данном случае абсолютно неважно где и как написан тип — одного «имя: тип»/«имя» недостаточно для определения переменной.

К тому же, := — является таким же кейвордом, о котором я говорил. И абсолютно неважно в каком он будет виде. Т.е. мой тезис это никак не опровергает.

К тому же, это вообще находится за рамками контекста т.к. контекстом является а) синтаксис принятый в обсуждаемом языке, б) синтаксис принятый в си.

Так же, := — избыточен для ситуаций, где тип не выводится, а задаётся. Вам придётся либо использовать избыточность, либо вводить два типа операторов, что опять же — избыточность и синтаксический мусор.

К тому же, это локальные го-заморочки не присущи ни паскалю, ни всему тому, что используется его стиль.

А так же, самое важное — это вообще никак не зависит от стиля. Это работает в любом случае. Т.е. смысла приводить это в контексте разделения стилей нет — т.к. это не относится к одному из — это относится к обоим.
Основная из них заключается в том, что как звучал тезис? «имя: тип что-то там позволяет». := — опровергает этот тезис,

Если по сути, а не формально, то тезис звучал как «имя сначала, тип потом Vs тип сначала, имя потом». Далее спор шел о ключевом слове auto для авто-вывода против якобы необходимого var для обычного объявления. Двоеточие это только пример реализации первого подхода. Пример го показывает, как можно иметь имя сначала, не имея «синтаксического мусора» перед именем.

У вас простое взаимное недопонимание.

Пример го показывает, как можно иметь имя сначала, не имея «синтаксического мусора» перед именем.

Нельзя. := — это синтаксический мусор, который, к тому же, писать сложнее нежели =, либо auto.

К тому же, как я уже говорил — мы либо вводим :=/=, либо мы имеем не только := в качестве синтаксического мусора, но и аннотацию при которой := избыточно.

Двоеточие это только пример реализации первого подхода.

Это так же неверно, т.к. двоеточие не имеет никакого отношения к подходу.

Я больше скажу — в си вообще аннотация типа ненужна. Она используется только для в одном случае — определение. Да и то нужен просто какой-то флаг для выражения намерения. Подойдёт вообще что угодно. const/auto/register. Всё это уже придумано и давно. Го просто взял эту логику из си.

Нельзя. := — это синтаксический мусор, который, к тому же, писать сложнее нежели =, либо auto.

Во-первых, не мусор, а однозначность синтаксиса как для парсера, так и для человека. Во-вторых, писать это несравнимо проще auto. В-третьих, таки ничего лишнего перед именем переменной нет.

Подойдёт вообще что угодно. const/auto/register

Это ли не тот синтаксический мусор. Вместо типа мы пишем вещи, которые вообще не имеют никакого отношения к делу. Модификаторы доступа и устаревшие ключевые слова, которые нынче ничего не значат.

Го просто взял эту логику из си.

В этом нет логики, это синтаксические извращения. В Го однозначный синтаксис, которые имеет четкие правила — либо :=, либо var. Все. Пример тут не с кого брать было.
Во-первых, не мусор, а однозначность синтаксиса как для парсера, так и для человека.

Мусор. Вы как бот повторяете один и тот же набор шаблонных фраз.

Во-вторых, писать это несравнимо проще auto.

Основания этим заявлениям.

В-третьих, таки ничего лишнего перед именем переменной нет.

Есть после имени. До оно, либо после — это ничего не значит.

Это ли не тот синтаксический мусор.

Нет, вы действительно бот. Какое отношение эти рассуждения имеют к теме? Никакого. Абсолютно неважно что они значит — они значат тоже самое, что и :=, только ещё больше.

Вместо типа мы пишем вещи, которые вообще не имеют никакого отношения к делу.

Чушь какая. Они имеют отношения к делу и никто их вместо не пишет. Вам лишь сообщили, что подобная логика объявления без типа существовала и существует в си.

Модификаторы доступа и устаревшие ключевые слова, которые нынче ничего не значат.

Вы опять где-то что-то услышали и начали повторять? Ну расскажите мне про то какой бесполезный статик, либо const, либо volatile. Или это, как обычно, пустой трёп?

В этом нет логики, это синтаксические извращения.

Опять же, когда нечего сказать — пиши херню.

В Го однозначный синтаксис, которые имеет четкие правила — либо :=, либо var. Все. Пример тут не с кого брать было.

Мне надоело с ботом разговаривать.

Хотите поиграть — хорошо, я жду эквивалента кода:

int a;

На го.

я жду эквивалента кода: int a;

Это не код, это говно (неинициализированная переменная).


А что касается того, что опровергает Go, то Go опровеграет два ваших утверждения: 1) необходимость мусора в виде двоеточия, отделяющего имя переменной от типа, 2) необходимость мусора в виде ключевого слова типа let, var или auto.


Двоеточие в := не является отдельным элементом/ключевым словом. Два символа := являются одним, единым оператором, поэтому никакого мусора при его использовании уже нет. (Не будете же вы настаивать, чтобы присвоение значения переменной выполнялось вообще без единого оператора?)

Это не код, это говно (неинициализированная переменная).

Т.е. ответа нет и адепт го порвался?

А что касается того, что опровергает Go, то Go опровеграет два ваших утверждения:

Фантазии брызжущих слюной адептов го.

1) необходимость мусора в виде двоеточия, отделяющего имя переменной от типа

Я уже отвечал на эту ахинею. Эта ахинея никак не связана с темой и с моим утверждением, т.к. она применима не только к паскаль-стилю.

Т.е. я могу использовать := в любом из стилей. Это просто сахар, костыль. Определяются переменные го не так.

2) необходимость мусора в виде ключевого слова типа let, var или auto.

Что за нелепая попытка врать. Читаем мой коммент:

Ни от какого auto паскаль-стиль не уходит, а наоборот требует ввод кейворда для обозначения декларации переменной. Таким образом вы всегда будите писать синтаксический мусор вместо типа. Всякие там var, let и прочее.

Т.е. брызжущий слюной адепт го врёт, утверждая, что говорил «необходимость мусора в виде ключевого слова типа let, var или auto.», но я приводил это лишь как пример.

Двоеточие в := не является отдельным элементом/ключевым словом.

Является.

Два символа := являются одним, единым оператором, поэтому никакого мусора при его использовании уже нет.

Два символа в if «являются одним, единым оператором». Опять методичка потекла.

Два символа := являются одним, единым оператором, поэтому никакого мусора при его использовании уже нет.

Он и есть мусор, т.к. есть уже оператор =. А это другой оператор, который является костылём для решения избыточности паскаль-стиля.

(Не будете же вы настаивать, чтобы присвоение значения переменной выполнялось вообще без единого оператора?)

Опять чушь. Именно те, кто рассказывал про «проблему auto» утверждали, что переменную можно объявлять без избыточности.

Я же сообщил, что это неверно и нужен механизм отделения. В ситуации же си-синтаксиса механизм ненужен — он уже есть.

В ситуации же с паскаль-синтаксисом он нужен. Это var/let и прочая фигня. Именно с var сделан ваш го. А далее закостылено := — которая является таким же механизмом, лишней сущностью она повторяет уже существующие функционал.

Вообщем, вы, насколько я погляжу, особо вменяемостью не блещете. Спорить о чём-то с ботами бесполезно, поэтому я вернуть к сити, а именно.

Я отвечал изначально в контексте преимущества паскаль-стиля, т.е. я это опровергал. Теперь вам нужно сообщить — каким образом := относится к паскаль-стилю? Я заранее отвечу — никаким. Новы там можете попытаться что-то придумать.

Т.е. ответа нет

Вы требуете перевести незаконченный кусок кода с одного ЯП на другой. Это не всегда возможно: нужен контекст, более-менее осмысленный кусок кода. Если воспринимать приведённый код как цельный, то получается переменная, которой не присваивается значение. Это бессмысленный код, переводить нечего.


Является.

Враньё. Ни в описании языка, ни в восприятии текста программистом двоеточие не воспринимается как отдельный элемент. Ну и уж тем более оно не является ключевым словом.


Он и есть мусор, т.к. есть уже оператор =.

Это не мусор. Это важный элемент, позволяющий отличать объявление новой переменной от переприсваивания. Без него читаемость программы ухудшилась бы.


каким образом := относится к паскаль-стилю

Речь шла о том, что новые ЯП используют "паскалевский стиль". Го — один из этих новых ЯП, и именно такой, что является контрпримером к вашим тезисам.


А что касается преимущества, то речь шла совсем о другом: о том что "let/var" нужен в обоих вариантах, но в паскалевском стиле он используется единообразно во всех ситуациях, а в C является в некотором роде костылём, подпирающим конструкцию, из которой убрали необходимый элемент — тип обявляемой переменной.

Как я уже говорил, я не будут отвечать на догматы фантиков уровня «это не мусор — это важный элемент», «мы не воспринимает это как отдельный элемент» и прочий бред.

о том что «let/var» нужен в обоих вариантах

Пруфы.

но в паскалевском стиле он используется единообразно во всех ситуациях


var v1 int = 100
v1 := 100

Единообразно, да. Объясняйтесь.

а в C является в некотором роде костылём, подпирающим конструкцию, из которой убрали необходимый элемент — тип обявляемой переменной

Обоснования этому набору слов. Что именно является костылём, что там и где и что подпирает.

И ответа на самое главное нет — каким образом := относится к паскаль-стилю? Это просто костыль, который можно впилить в какой угодно стиль. Причём тут паскаль-стиль? Как это выступает за паскаль-стиль, но против си-стиля?
Я даже не поверить, что я отвечаю на настолько нелепые рассуждения.

Есть синтаксис var name type =, базовый. Данный пациент утверждает, что никакой избыточности нет. Но авторы го с ним несогласны.

Именно поэтому вводится var (), это есть ещё со времён паскаля. Потому что все очевидно, что объявление с аннотацией через var — это избыточно. Т.е. пациент спорит с объективной реальностью.

Аналогично с := — это синтаксический сахар, который был добавлен специально для решения проблемы var name auto =.

Т.е. мы имеем как минимум два варианта объявления переменных, но что же там нам сообщал пациент:

В Go объявление функции, объявления типа указателя на функцию, передача функции как объекта первого порядка — все это идентичные синтаксически вещи

Он заявлял, что проблема С++ в том, что синтаксис разный. В целом эти базовая методичка го «делаем что-то одним способом», но.

Как мы видим, что тут эта методичка ломается. Потому что способов как минимум 2(3). А почему? Потому что общий случай избыточен и добавлен специальный сахар для решения проблемы.

Аналогично с := — это синтаксический сахар, который был добавлен специально для решения проблемы var name auto =.

А это (существование какой-либо проблемы с var name =) опровергает Rust, где конструкции, аналогичной := нет. Если бы упоминаемая вами проблема реально существовала, её пришлось бы решать не только в Го, но также и в Расте.

А это (существование какой-либо проблемы с var name =) опровергает Rust,

Опять поток шизофрении. Чего он там опровергает? Там есть let, который такая же подпорка для синтаксиса. И есть избыточность let name: type, когда как в си это type name.

Если бы упоминаемая вами проблема реально существовала, её пришлось бы решать не только в Го, но также и в Расте.

Как же быстро лозунги меняются. То := меня опровергает, то уже меня опровергает раст.

Каким образом из отсутствия решения следует отсутствие проблемы? Вы вообще в логику можете?
Нельзя. := — это синтаксический мусор

Можно. Я повторю еще раз тезис, на который вы категорично ответили «нельзя»:
можно иметь имя сначала, не имея «синтаксического мусора» перед именем.
Вы же отвечаете на другую реплику, которую я не писал и которая звучит как «можно обойтись без синтаксического мусора».

Это так же неверно, т.к. двоеточие не имеет никакого отношения к подходу.

Имеет; таким образом список идентификаторов синтаксически отделяется от типа, задавая однозначную грамматику. Это нужно именно при подходе «идентификаторы перед».
Я повторю еще раз тезис, на который вы категорично ответили «нельзя»:
можно иметь имя сначала, не имея «синтаксического мусора» перед именем.

Мне без разницы кто там и что говорил. Я говорил а) в рамках контекста определённым начальным комментом, б) я отвечаю только за свои тезисы.

С чего вдруг вы решили, что вы можете в любой момент подменить начальный тезис и что-то мне предъявлять? Ваши манёвры меня волнуют мало.

Имеет; таким образом список идентификаторов синтаксически отделяется от типа,

В го? К тому же мы говорим про двоеточие в :=, а не о том что вы там себе напридумывали. Этот костыль можно впилить в какой угодно синтаксис — хоть в си. Он вообще никак не привязан ни к чему.

Активно пишу на scala, где аргументы описываются как имя: тип.
На мой взгляд, такой стиль побуждает думать сначала о смысле переменной, а потом уже выбирать подходящий тип.
Допустим пишу функцию "calculate". Например для вычисления баланса по множеству операций. Сначала есть код:
function calculate(
Эта функция принимает в себя множество операций. Добавляю
function calculate(operations:
Какую лучше коллекцию сюда передавать? Сортированный список или set. Продумываю оба варианта и выбираю список. Тогда добавляю в код
function calculate(operations:SortedArray){


Мелочь, но позволяет думать в первую очередь о бизнес-логике, а потом уже о инструментах для ее реализации.

На мой взгляд, такой стиль побуждает думать сначала о смысле переменной, а потом уже выбирать подходящий тип.

Тип и определяет смысл.

множество

Тут ваша логика дала течь. Множество уже тип, вы подумали о типе до.

Опять же, существует два варианта — от данных, либо от операций. От данных — это когда у вас уже есть логика, которая генерирует данные и типы их уже выбраны. Тогда вы в первую очередь должны писать тип.

От операции. Ты вы пытаетесь реализовать какую-то операцию и в процесса выводите тип. Очевидно, что этот процесс находится в теле функции и с какой он находится — неважно. Абсолютно.

Чтобы иметь конструкцию [имя][[: тип][ = значение]].

Странно использовать слово "обычный" в этом контексте. Парсерт непротиворечимой грамматики написать легче в этом случае, только и всего.

Ага, а потом начинается «прелесть»: *(** тип[ ]) имя()[ ]
Эта прелесть никак не связана с темой. Она возникает потому, что в этой языке возможностей куда больше. Нет нет альтернативы, которая бы могла всё тоже, но как-то иначе. Выразительные возможности паскаль-стиля крайне скудные.

В си-стиле выражается void(a, b, c); В паскаль стиле нет. В том же TS приходится эмулировать сишный стиль через (a, b, c) => void, т.е. семантика потекла. Нужно два синтаксис для определения типа и функции.

И таких примеров масса. К тому же не стоит сравнивать скриптуху, где одни ссылочные типы и си. Это разные весовые категории. Это как сравнивать С++-лямбду и js-лямбду.

жс-лямбда мало того, что дырявая(вы не сможете там определить тип возврата), дак ещё и десятой долей функционала не обладает. Конечно, манипулировать и сравнивать несравнимое удобно. Но не стоит так делать.
Так как раз имя: тип очень логичный стиль применяется ещё в Паскале. А С++ стиль тип имя замедляет чтение кода. Обосенно плохо когда описывается сложный тип например
struct building //Создаем структуру!
{ char *owner; //здесь будет храниться имя владельца
char *city;

Мы сначала говорим, что это структура, потом даём имя типа, а потом уточняет.
А логично делать наоборот
building =record и дальше уточнение.
Вообще с порядком в С++ но очень.
Например логично закодировать. Указатель на хрю-хрю как ^hru_hru. Или Хрю-хрю указывает на — hru_hru^. А если сделать обратный порядок, получиться чтение справо налево.
А логично делать наоборот

Почему? К тому же везде и всюду сделано аналогично и здесь:

function update
entity Foo {

И так далее.

Например логично закодировать. Указатель на хрю-хрю как ^hru_hru. Или Хрю-хрю указывает на — hru_hru^. А если сделать обратный порядок, получиться чтение справо налево.

Распарсить это решительно невозможно. Это какой-то набор слов. Напишите что-то более адекватное типа «в крестах так: бла-бла, а нужно так: бла-бла».
К тому же везде и всюду сделано аналогично и здесь:
function update
entity Foo

Это как раз ближе к var foo, потому что слева от имени стоит не тип, а ключевое слово, категория имени (функция, структура или переменная), а тип как раз стоит справа: параметры и возвращаемое значение для функции, список членов для структуры и имя типа для переменной:


category  | name   | domain                  | codomain
-----------------------------------------------------------
function    update   (id: int, data: string) : bool
entity      Foo      {id: int, data: string}
var         foo                              : Foo
Это как раз ближе к var foo

Это какие-то попытки подменить изначальный тезис. Был пример со sturct — я показал, что в этом языке используется такая же форма определения объектов. Она используется везде, в том же тайпскрипте.

потому что слева от имени стоит не тип

Где тут: struct name — стоит слева тип? Нигде.

Начнём с того, что сишный sturct под неё подходит, а говорилось именно о нём. Так же никакое положение в таблице не обосновывается, никак. Т.е. на каком основании "(id: int, data: string)" является «domain», а bool не является. К тому же, ваша табличка игнорирует override method, ref env.

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

Ок, прошу прощения, проглядел пример building = record от nmrulin и почему-то решил, что вы всё ещё про запись "тип имя", так что действительно вышло не в тему.


на каком основании "(id: int, data: string)" является «domain», а bool не является

(id, data) — это "вход" функции, область определений (domain), а bool — выход, область значений (codomain). Запись f(int, string) => bool или f(int, string): bool вполне математична: "f есть отображение множества кортежей типа (int, string) на значение во множестве bool".


А как прочесть запись bool f(int, string) в парадигме "тип имя"? "Функция типа bool с именем f"? Но беда: тип этой функции не bool, а вовсе даже bool (int, string).

А как прочесть запись bool f(int, string) в парадигме «тип имя»? «Функция типа bool с именем f»? Но беда: тип этой функции не bool, а вовсе даже bool (int, string).

У вас дара в логике.: — семантически отделяет тип. Вы игнорируете сей факт и свободно подменяете семантику: во имя подбития реальности под свою модель.

К тому же, вы взяли какую-то логику и каким-то образом определили её за правильную, а далее исходите из того, что всё что иное — неправильное. Ведь любая другая логика — неправильная.

С таким же успехом можно сказать про ref и про override и прочее. Вы говорите о каком-то примитивном обрубке, а не о каких-то общих правилах.

В общих правилах определяющим является имя, а уже далее что-то там из него следует. Но если имя является определяющим, то на каком основании оно должно быть вначале? Да ни по каким — это догмат.

Начнём с того, что сишный синтаксис создан как f(a, b) {} — изначально все типы были auto(из крестов). Правда там не было вывода типов, а универсальный тип просто был интом.

Всё что слева/справа ничего не значит. При этом в си есть прямое разделение на право и лево. Есть тип, а есть объект. То, что написано справа — относится к объекту, а всё что слева — к его типу.

В примитивных языка такого разделения нет — на то они и примитивные. В том же bosque разделение уже появляется — там есть тот же ref, т.е. то, что относится к самому объекту.

Можно, конечно, делать это делать слева до :, как многие и делают. Но, очевидно, что получается полный треш. Всякие там name?: type.

Правда в Си всё не совсем так. Там тип не может быть массивом, потому что массив — это объект. Так же как типом не может быть функция.

Хотя, конечно, в си есть и тип-функция и тип-массив, но только в рамках тайпдефа. Так же, есть (int[]){} — это логика исходит из того же. По такому же принципу работает using в С++.

Если проще. Объект может переменной — это просто тип. Если мы видим просто тип — это тип какого-то объекта/переменной.

Но, в случае с [] — типом будет массив. Объект будет массивом. А типом указывается тип возврата операции/тора [], аналогично и с () — скобочки уже из объекта делают функцию. А всё остальное к делу отношения не имеет. Тип, который слева — это не тип объекта — это тип возвращаемый (). Потому что свободный тип — это всегда объект(какого-либо значение).

Поэтому си читается следующим образом. void f(); f — это идентификатор/имя. Вы без проблем можете писать void f()[] — функция будет возвращать массив. Тоже самое с [][], вы можете написать int arr[10]() — тоже без проблем.

И это бы всё работало круто, но в си есть фундаментальное разделение. Есть объекты как значения(которые могут быть значениями), а есть которые не могут. Вот [] и () значениями быть не могут.

Таким образом сишный синтаксис и его семантика куда строже и логичнее, нежели упомянутая вами. Где вы как угодно трактуете каждую закорючку.

Описать его можно так. Есть база, которой вы даёте тип. Тип задаётся как справа так и слева. Причём есть два типа типов. Тип самого объекта(массив/переменная(значение)/функция), который пишется справа. И всякие расширения — это слева.

f() — это функция, тип объекта. Слева накидываются всякие свойства, свйоства накидываются ИМЕННО на объект(это упомянутая мною база). f тут уже вообще не при делах.

() — расширяется параметрами. Так же, он возвращает какой-то объект. Тип объекта справа не написан — значит это обычный объект/значение. Этот объект является базой. Ему можно задать тип и всякие там квалификаторы.

* — это тип. Никаких «на» там нет. Это просто упрощение. * — такая же база. Правила те же, но она слева и приоритет у неё меньше. Именно для этого там скобочки — они выделяют новую базу.

И теперь, я думаю, вы сами сможете прочитать bool f(int, string)

База по умолчанию — идентификатор. Идентификатор имеет тип-объект функция. f — это функция, () — имеет семантику «аргументы и „возвращаемое для операции () значение“(по-колхозному возвращает значение)». Читаем аргументы. Аргументы типа инт и строка. Далее эта функция что делает? Возвращает значение(справа ничего нет). Далее, слева могут стоять уточняющие, а именно тип значения и его квалификаторы.

Так же там могут стоять «квалификаторы», которые воздействуют на сам базовый объект.

f — функция с аргументами инт и строка, возвращающая(по-колхозному) значения типа bool.
У вас дыра в логике: — семантически отделяет тип

Это скорее у вас дыра в понимании. Семантика двоеточия зависит от контекста: для переменных отделяет тип, для функций — тип возврата. Полный тип может включать в себя больше чем то, что после двоеточия, но правило то же:


  • справа от имени — всё, что про тип, т.е. про область всех возможных значений. Для скаляров — просто имя уже имеющегося типа (встроенного или определённого). Для агрегатов — перечисление типов членов агрегата. Для функций (которые есть мост между двумя областями, входом и выходом) — как типы аргументов, так и тип возращаемого значения.
  • слева от имени — то, что про сам объёкт. Например категория (var/const/enum/function/struct/class), видимость объекта (public/private), модель хранения (static/const/readonly), модель передачи параметра (in/out/ref), модель вызова метода (virtual/static) и прочee. Всё это не является частью типа.

В результате первого правила функции получают настоящий тип, а не несовместимый "тип-объект с расширениями", становятся гражданами первого сорта, могут быть присвоены переменной, проверяются при присваивании как по параметрам, так и по возвращаемому значению, иначе будет ошибка типа.
И, заодно, массивы теперь получают полноценный тип, как и любой другой агрегат или строка (массив символов), а не "тип-объект", чей тип при передаче в функцию внезапно протухает и разлагается до указателя.


Но, очевидно, что получается полный треш. Всякие там name?: type.

Но очевидно, что name?: type — это просто сахар для каноничной записи name: type | undefined, который слишком часто встречается и слишком длинно писать каждый раз. Правило 1 выполняется: ?:type находится справа от name.


всякие расширения — это слева.…
() — расширяется параметрами.

Параметрами тоже слева? Упс, строгая логика поломалась — параметрами расширяем таки справа, т.е. внутри (). И теперь у нас расширения то слева, то справа.


Вы без проблем можете писать void f()[] — функция будет возвращать массив.

Вы уверены? Я плюсовик, не голый сишник, но насколько мне известно, ANSI C не позволяет функциям возвращать массив, только указатель, и объявление будет примерно таким монстриком: void (*f())[N]. В высшей степени интуитивная конструкция.


Претензию про ref и override так и не понял: что конкретно вам не нравится, и как именно они ломают логику?

Это скорее у вас дыра в понимании. Семантика двоеточия зависит от контекста: для переменных отделяет тип, для функций — тип возврата.

С чего вдруг она меняется? Основание.

Полный тип может включать в себя больше чем то, что после двоеточия, но правило то же:

Т.е. двоеточие не имеет никакого отношения к типу. Из этого прямо следует, что тип не только справа от двоеточия, либо только. Третьего не дано. Либо двоеточие ничего не значит.

Что самое интересное — эти манёвры следствие попытки оправдать неоднозначность, которой там, на самом деле, нет. Т.к.: там там же отделяет тип. И типом является именно возврат, ведь тип возврата и определяется. Аналогично работает и для ?:type. Когда? является признаком опциональности и точно так же относится к имени, а не определяет ?:type — новый синтаксис для типа. Потому что тогда нужно было ?type, либо type?..

справа от имени — всё, что про тип, т.е. про область всех возможных значений. Для скаляров — просто имя уже имеющегося типа (встроенного или определённого). Для агрегатов — перечисление типов членов агрегата. Для функций (которые есть мост между двумя областями, входом и выходом) — как типы аргументов, так и тип возращаемого значения.

Вам не нужно мне перечислять те случаи, где его семантика потекла — я и так это знаю. Нужно отвечать на вопрос а) зачем оно нужно. б) почему у него изменяется семантика.

слева от имени — то, что про сам объёкт. Например категория (var/const/enum/function/struct/class), видимость объекта (public/private), модель хранения (static/const/readonly), модель передачи параметра (in/out/ref), модель вызова метода (virtual/static) и прочee. Всё это не является частью типа.

Всё это хорошо, но без интеграции в предыдущие рассуждения — это просто перечисление не относящиеся к теме. Интегрируйте его в изначальную вашу модель. public — это категория? Что это?

К тому же, вы так и не обосновали разделение в таблице. На каком основании часть после двоеточия вынесена, а список параметров остался.

В результате первого правила функции получают настоящий тип

Какие критерии для «настоящий»? Почему меня должен волновать какой-то фентезийный «настоящий тип».
а не несовместимый «тип-объект с расширениями»

У вас опять рассуждения потекли. Вы там забыли про ref/const и прочее. Это такие же «расширители» и без ник никакая аннотация типа не определяет объект, а является лишь частью определения.

, становятся гражданами первого сорта, могут быть присвоены переменной, проверяются при присваивании как по параметрам, так и по возвращаемому значению, иначе будет ошибка типа.

Ну во-первых это наивные манипуляции, когда сравнивается несравнимое. Т.е. берётся скриптуха и её примитивная модель и сравнивается с более сложной моделью, при этом примитивность и её следствия превращаются в следствия синтаксиса/«настоящих типов».

И, заодно, массивы теперь получают полноценный тип, как и любой другой агрегат или строка (массив символов), а не «тип-объект», чей тип при передаче в функцию внезапно протухает и разлагается до указателя.

Опять же. Сравнение примитивной скриптухи и более сложной модели.

Но очевидно, что name?: type — это просто сахар для каноничной записи name: type | undefined, который слишком часто встречается и слишком длинно писать каждый раз. Правило 1 выполняется: ?:type находится справа от name.

Я не понимаю две вещи. На каком основании вы дёргаете куски фраз и отвечаете только на удобное. Зачем вы мне повторяете то, что я уже до вас вам сообщил?

Можно, конечно, делать это делать слева до :, как многие и делают. Но, очевидно, что получается полный треш. Всякие там name?: type.

Здесь именно говорится о том, что ?: — справа от name. И именно поэтому этот пример называется трешем.

При этом это я говорил про этот: [Int, ?:Bool], никакого name тут нет. А вот лево есть. Тут, конечно, можно пытаться задним числом опять изменять семантику для :, но очевидно — что это эквивалент name?:type и значит это не type|undefined, а именно опциональный аргумент. Мне лень читать и искать это в мануале, но любо это дыра в логике языка, либо действительно так.

Параметрами тоже слева?

С чего вдруг? Опять нелепая попытка дёргать фразы. Расширения — это квалификаторы, в разных контекста это понятия значит разное.

Упс, строгая логика поломалась

То, что вы увидели где-то два похожих слова и вам показалось, что вы что-то там нашли — это лишь вам показалось.
— параметрами расширяем таки справа, т.е. внутри (). И теперь у нас расширения то слева, то справа.

С чего вдруг она справа, если они внутри? Отсчёт идут от () — очевидно, что внутри никаким образом не может быть ни справа ни слева.

Вы уверены? Я плюсовик, не голый сишник, но насколько мне известно, ANSI C не позволяет функциям возвращать массив,

Я уверен. К тому же у вас опять какие-то проблемы с восприятием. Мы говорим о синтаксисе, а не о том, что си позволяет/не позволяет делать. Синтаксис это позволяет.
только указатель, и объявление будет примерно таким монстриком

Основания в студию.

: void (*f())[N]. В высшей степени интуитивная конструкция.

Да, куда более интуитивная, чем рандомный набор символов и дыр, который существует в скриптуха-паскаль-языках.

Конечно, куда там этим конструкциями до *[N]void f(); — вот оно, чудо человеческой мысли.

Или это: []int{1000, 2000, 12334} как перепаста с сишного (int[]){1000, 2000, 12334}. struct{f int}{50} — вот оно, удобство.

Претензию про ref и override так и не понял: что конкретно вам не нравится, и как именно они ломают логику?

Я уже обозначил выше проблему — как это интегрируется в вашу табличку.

С чего вдруг она меняется? Основание.

Я же написал: у переменных тип — это одно множество значений, а у функции тип — это два множества: множество входов и множество выходов. Поэтому семантика и разная.


Т.е. двоеточие не имеет никакого отношения к типу.

В принципе, тип можно было бы записывать и без двоеточия, просто var x int = 10 или function foo (a int, b string) bool {}, двоеточие скорее декоративное, чем семантически нагруженное.


Когда? является признаком опциональности и точно так же относится к имени, а не определяет ?:type — новый синтаксис для типа. Потому что тогда нужно было ?type, либо type?..

Нет, ?:type в Typescript означает как раз алгебраический тип type | undefined, что означает "имя определено, но значение может быть не известным". Можно спорить, относится ли опциональность к объекту или типу, но в Typescript это сделано типом, т.е. "значение неопределено" тоже является частью области значений, имеет свою метку, возвращается typeof.


type? мог бы означать type | null как в C#, но в Typescript этого не стали вводить, скорее всего из-за борьбы с null и нежелания облегчать синтаксис для null.


Интегрируйте его в изначальную вашу модель. public — это категория? Что это?

Вроде ясно было написано: public — это область видимости имени/объекта. Она не меняет тип значения объекта, а только доступность имени — значит записывается справа от имени.


ref и override… как это интегрируется в вашу табличку.

Табличка изначально была иллюстрацией к типам (то, что справа от имени), а не про квалификаторы объекта (то, что слева от имени), и в ней указано всего 3 категории имён — свободная функция, свободная переменная и структура. Как вы хотите вкосячить туда ref и override? Это нужно новую таблицу рисовать, со всеми видами объектов. Если у вас есть время и желание, сами нарисуйте себе расширенную табличку, я в вас верю.


Какие критерии для «настоящий»?

Читать умеем? Русским же по фоновому было написано: "функции… могут быть присвоены переменной, проверяются при присваивании как по параметрам, так и по возвращаемому значению, иначе будет ошибка типа".


Вся проверка типов вращается вокруг совместимости переменных разных типов. Тип функции (int,string): bool не совместим по типу с функцией (string, int): bool, хотя возвращаемый тип одинаков. Потому что тип функции — это не только тип возврата, а также и тип и порядок аргументов. Вы не можете переменной одного типа присвоить значение другого типа, и это относится так же к функциональным типам.


Ну во-первых это наивные манипуляции, когда сравнивается несравнимое. Т.е. берётся скриптуха и её примитивная модель и сравнивается с более сложной моделью,

Ну во-вторых, это наивная манипуляция, когда для аргументации одна модель типов беспричинно объявляется "примитивной скриптухой", а другая "более сложной", хотя эта "более сложная" модель была рождена в языке с практически отсутcтующей проверкой типов, а в "примитивной" есть и алгебраические типы, и настоящий null (а не наколенное поделие из #define NULL (0)), и вывод типов.


Как вы любите повторять: где основания вашим словам? Вы тут часто требуете оснований, но сами не брезгуете просто накинуть на вентилятор безо всяких оснований.


Давайте я дальше буду отвечать в вашем же непринуждённом стиле:


Мы говорим о синтаксисе, а не о том, что си позволяет/не позволяет делать. Синтаксис это позволяет.

Синтаксис позволяет, а язык не позволяет. Шизофрения. Обоснуйте.


Да, куда более интуитивная, чем рандомный набор символов и дыр, который существует в скриптуха-паскаль-языках.

Обоснования в студию.


куда там этим конструкциями до *[N]void f(); — вот оно, чудо человеческой мысли.

С чего вдруг? Это лозунги и догматизм какой-то. Где обоснования?


На каком основании вы дёргаете куски фраз и отвечаете только на удобное.

А почему на каком основании вы спрашиваете? Если отвечать на весь трэш и вкусовщину, которые вы тут вываливаете, то я потрачу намного больше времени, чем хотел на вас потратить.

С чего вдруг? Это лозунги и догматизм какой-то. Где обоснования?

Хорошо, поиграем.

только указатель, и объявление будет примерно таким монстриком: void (*f())[N]. В высшей степени интуитивная конструкция.

С чего вдруг? Это лозунги и догматизм какой-то. Где обоснования?

Ну дак что, ответ будет? Или мой оппонент запутался в своей же методичке, сломался и теперь генерирует какие-то рандомные фразы?

Пока что я вижу в вас не оппонента, а нервного адепта С, который бегает и требует у всех обоснований, при этом сам только бросается хлёсткими эпитетами, без оснований. Извините, второго Луговского из вас не получается, а другие тролли мне не интересны.


Для начала обоснуйте, почему void (*f())[N] — это зашибись и красиво, и единственно верно, а всё остальное — дерьмо. Иначе вы точно такой же религиозный догматик, каким всех выставляете.

Для начала обоснуйте

Не, такое не работает. Вы первый начали что-то там болтать про си — обосновывайте. Пока не обоснуете разговаривать с вами нет смысла, т.к. вы болтун.
Луговского из вас не получается, а другие тролли мне не интересны.

Меня мало волнуют заявления кого-то в интернете. Ну и да, тут заметно как адепт пытается, крайне наивно и нелепо, прокладывать путь к отступлению.

Ведь я просто тролль, это не ему ответить нечего, а просто он не будет мне отвечать потому что тролль. А тролль я потому, что он сам так сказал.

а всё остальное — дерьмо.

А тут видно как адепт пытается в очередной раз врать, ведь он нигде не покажет моих подобных тезисов. Все мои тезисы на тему «лучше» имели обоснования и ни этот адепт, ни какой-либо другой их никогда не оспорит.

А вот его тезисы я могу показать и показал выше, как и тезисы подобных ему.

Это базовая методичка болтуна в интернете. Использовать схему «всё говно, кроме того, что я считаю не говном», а когда кто-то приходит оспаривать эти заявления — болтун обвиняет оппонента в том, что делал сам.

Иначе вы точно такой же религиозный догматик, каким всех выставляете.

Это ещё одна тактика болтунов. «иначе вы» — абсолютно неважно кто я, будь я хоть трижды хоть кем — это никак не отменяет ничего. Схема уровня детского садика «а Вася тоже в штаны насрал».

Но самое интересное тут то, что всё эти рассуждения уровня начальной школы не работают, т.к. не я прихожу и не я всем доказываю, что «сишный синтаксис говно» — этим занимаетесь вы. Мне вообще насрать на то, что там у вас и как.

Это у вас есть желание бежать везде и проповедовать. У меня его нет. Я просто вижу «неправильно» и отвечаю на него.

По поводу сравнения. Даже если бы я захотел что-то сравнивать — вы не покажете мне объекта сравнения и его нет. Все сравнения адептов — это сравнение какой-то скриптухи и языков на порядки более сложных и фичастых. За примерами ходить ненужно — рассуждения фанатиков про лямбды.

Хотите, что-бы можно было что-то сравнивать — создайте синтаксис в котором можно выразить аналогичную семантику. Кто же вам не даёт? А я знаю кто не даёт. Потому что тогда нельзя будет врать и выдавать лёгкость более слабого синтаксиса за преимущество перед тяжестью тяжелого.

Запомните раз и навсегда. Си всегда было насрать на все рассуждения маргинальных элементов. Си ненужна защита, его ненужно проповедовать везде и всюду.

Фанатизм, аргументация уровня «у меня лучше синтаксис» — это паскалятская зараза. Именно его адепты постоянно всё засирают и рассказывают всем о том «какой же сишный синтаксис говно».

И почему все адепты паскаля везде бегают и орут — ясно и понятно. Потому что они мечтают сделать свои веру главенствующей. А вот адептам си этого делать ненужно — они итак главенствуют.

Повторю ещё раз. Когда сделаете на паскаль-синтаксисе не-скриптуху. Приходите и поговорим. А пока мне говорить не с кем и сравнивать не с чем.

Хотя даже в этом случае меня это будет волновать мало. Это вам нужно доказывать, что вы не хуже. Моя(условная) вера уже всё доказала.
Вы первый начали что-то там болтать про си

Вы бредите. Я вообще-то начал с того, что стиль "имя тип" ничуть не менее логичный, чем стиль "тип имя" — если конечно понимать что такое тип вообще, а не докапываться до двоеточий и их местоположения, и не триггериться от якобы "синтаксического мусора".


не я прихожу и не я всем доказываю, что «сишный синтаксис говно»

Конечно не вы. Вы пытаетесь доказать, что "паскалевский стиль говно". Ровно с той же степенью обоснованности.


ведь он нигде не покажет моих подобных тезисов.

Т.е. вы не называли паскалеподобный синтаксис мусором?


Я просто вижу «неправильно» и отвечаю на него.

Не обосновывая своё "неправильно" никак, кроме субъективных эпитетов, при этом яростно требуя обоснований и разбрасываясь ad hominem-ами.


Но когда вам указывают на неоднозначности си-подобного синтаксиса, вы просто отмахиваетсь. "Ой, most vexing parse уже починили". Ну да, добавив ещё кучку неоднозначностей с разными видами плохо различимых скобок (int foo{} vs int foo()), разных видов инициализации и т.п.


Я лично не имею ничего против сишного синтаксиса — пусть цветёт сто цветов, я спокойно пишу и на C++, и на C#, и на TS, и уважаю и использую их и их фичи, не забывая о косяках. Но вот вас, похоже, конкретно бомбит по поводу якобы "синтаксического мусора" в других языках, и от критики в сторону C. Это просто комично, вы пытаетесь быть святее K&R, что-ли?


паскалятская зараза. Именно его адепты постоянно всё засирают

Какие сволочи. Ну ничего, если вы будете продолжать кидать в них какашками, они обязательно поймут, как они неправы, и как правы вы.


они мечтают сделать свои веру главенствующей.

Эту теорию вам лучше обсудить с вашим лечащим врачом, он лучше знает, что делать с заговорами пасквилянтов о захвате мира.


Хотите, что-бы можно было что-то сравнивать — создайте синтаксис в котором можно выразить аналогичную семантику.

Чего именно принципиально нельзя выразить в паскалеподобном синтаксисе? Голые указатели на голые указатели на массивы, которые под капотом тоже голые указатели? Ещё в паскакале был оператор ^, но теперь даже в плюсах голый указатель — моветон.


Что ещё?


Когда сделаете на паскаль-синтаксисе не-скриптуху. Приходите и поговорим.

Для вас "не-скриптуха" — это что конкретно? Ручная работа с памятью? Макропроцессор для исправления недостатков встроенного синтаксиса?


Моя(условная) вера уже всё доказала.

Ой, не скромничайте, ваша вера совершенно абсолютна.

Конечно не вы. Вы пытаетесь доказать, что «паскалевский стиль говно». Ровно с той же степенью обоснованности.

Где пруфы? Насколько я понял тот факт, что вы ненавидящий си религиозный паскаль-фанатик вами уже признан? Теперь вы хотите оправдать себя через «а Вася тоже в штаны насрал»? Ну хорошо, пытайтесь. Только пруфы где?

«Ой, most vexing parse уже починили».

Опять адепт врёт. В чём тут суть. Есть некий условный сектант, который вещает «зелёный — плохо, непонятно». Мой ответ звучит так: «с чего вы взяли, что зелёный — это плохо? Это ваши религиозные проблемы и меня ваша классификация не волнует. Да и оно уже давно не только зелёное».

Далее, условный сектант начинает вещать «вы аргументируете то, что „оно уже не только зелёное“», что является враньём. Но.

Что пытается сделать условный сектант? Он пытается разрушить основную линию защиты, как и любого человека, которого атакует какой-то адепт секты — отрицание его классификации и мировоззрения. Он пытается врать и болтать эту чушь именно потому, что из неё прямо следует «ты принял, что зелёный — это плохо», но.

Сектант врёт. Я ничего не принимал. Мне насрать на его классификацию и на то, что где и чем называются адепты какой-то секты.

Ну так вы справо налево читаете все предложения видимо, а теперь прочитайте как все обычные люди слева направо. И расшифруйте выражение "^hru_hru" — так, чтобы каждому обозначению соответствовало слово. А теперь попробуйте сделать это c выражением hru_hru*. У вас это не получиться.

В этом то вся и проблема. Некоторые последователи С++ именно, что могут только «парсить» текст. А забыли, что 99% текст не парсят, а читают. Так вот напоминаю вам что чтением в отличие от «парсения» является процесс восприятия информации слева направо. Поэтому можно написать только лишь предложение «Указатель на переменную хрю-хрю». И это будет для всех текст, только для вас набор слов. И наоброт, предложение «Хрю-хрю на укаказатель переменную » -будет для вас текстом, а для 99% людей набором слов.

И расшифруйте выражение "^hru_hru" — так, чтобы каждому обозначению соответствовало слово.

Дак вы должны это сделать — как я буду читать непонятно какие, придуманные вами, символы?

а теперь прочитайте как все обычные люди слева направо

Как нам разница — как и кто читает? К тому же нужно отличать чтение от понимания. Читать можно как угодно. К тому же, прочитайте мне 123.123. Прочитай мне a + b * (c + d).

Я могу читать как угодно, как и любой другой человек. И все именно так и читают. Читают таблицы сверху вниз, либо таблицы нужно запретить? Ищут ключевые слова в текста. Запоминают контекст.

А теперь попробуйте сделать это c выражением hru_hru*. У вас это не получиться.

Указатель — это тип *, T — это тип возврата операции разыменования. Слева всегда стоит конечный тип. Сишные определения читаются как математические выражения. Вот паста, где я разбирал «как читать».

Паста
// Нужно понять фундаментальную вещь - есть база, это некий контекст который расширяют расширятели типов.

//по дефолту база - это то, что справа. Базой любого типа является определение(имя).


typedef int f_t();//функция. База - имя. () - расширяет имя, делая его функцией. Функция теперь является базой. 
// Для этой коснтрукции с лева пишется тип возврата:

f; //имя 

f0();//функция.
int f1();//функция с типом возврата.

* f2();//функция с типов возврата "указатель".

int * f3();//для int базой является * - определение типа операции *(разименования) у указателя.

typedef int f0_t();//правила аналогичны. Функция. 
//хотим сделать указатель на функцию
typedef int * fptr_t();//базой является функция - определяется тип возврата. Указатель.
//нужно как-то определить базу для *, чтобы она была именем. Ведь имя должно быть не функцией(как сейчас), а указателем.

typedef int (* fptr0_t)();//база для * имя. Далее скобки выступают базой. 
//определяется тип операции * у указателя. Указатель является базой.

typedef int (** fptr1_t)();//мы определил тип операции * для указателя(который слева от fptr1_t).
// Базой является тип операции * для указателя, которая является типом операции * для указателя, который является типом для fptr1_t

typedef int (** fptr2_t[])();//fptr2_t теперь является массивом. Массив - база. Слева у массива определяется тип элемента массива.


typedef int (** fptr3_t[][7])();//здесь можно просто упростить до "fptr3_t - двойной массив". Двойной массив - база. Свйоства аналогичным одинарному.

typedef int * (** fptr4_t[][7])();//базой является функция. Для неё определяется тип возврата. Мы определили тип возврата - указатель. Далее мы уже знаем. int тип операции * для указателя.

typedef int * (** fptr5_t[][7])()[];//базой является функция. Типом определён указатель. Это не то, что мы хотели.

//мы хотели определить тип не для функции, а для типа операции * у указателя. Нам нужно сделать базой указатель.

typedef int (*(** fptr6_t[][7])())[];//база указатель. Типом для базы определяется массив. Массив база - для базы(массива) определяется тип элемента - int


typedef int * (*(** fptr7_t[][7])())[];//база массив. Для массива определяется тип элемента - указатль. Для указателя определяется тип операции *.


//тут можно вывести два правила. Право имеет приоритет. Для лева - базой является то, что справа. Для права - лево.

int a[1];//имя - база. Справа - массив. База массив. Для него определён тип - инт, как тип элемента массива.

int ((a)[1]);//можно руками определить базы, как это делается по-дефолту.

int * b[1];//b - база. Для неё определён массив. Для массива определён тип(элемента) - указатель. Для указателя определён тип операции* - int.
int (*c)[1];//c  - база(имя). Для неё опредён тип - указатель. Для указателя определён тип операции* - массив. Для массива определён тип элемента - int.




В этом то вся и проблема. Некоторые последователи С++ именно, что могут только «парсить» текст.

Лозунги такие лозунги.

А забыли, что 99% текст не парсят, а читают.

Я вам привёл примеры — почитайте их. Не нужно путать чтение и интерпретирование. Читать можно что угодно и как угодно, но понимать вы будите так как нужно.

Так вот напоминаю вам что чтением в отличие от «парсения» является процесс восприятия информации слева направо.

Пустые заявления. Да и расскажите это арабам.

Поэтому можно написать только лишь предложение «Указатель на переменную хрю-хрю».

Вы ничего не знаете о си и эта формулировка — полная чушь. Ну и я жду срывов покровов на тему number[], жду чтения () => {}. Ваши рассуждения глупы и догматичны. Во-первых указатель ни на какие переменные не указывает. На этом уже можно закончить и признать вашу несостоятельность, полную.

И это будет для всех текст, только для вас набор слов.

Вы попросту хейтер, который придумал какую-то чушь и ему кажется, что его объяснения что-то объясняют, но нет. Хейтер просто услышал где-то про «паскаль читается, а си нет» и начал выдумывать чушь. Назвав набором слов всё, начиная от математики заканчивая каким-нибудь тайпскриптом.

И наоброт, предложение «Хрю-хрю на укаказатель переменную » -будет для вас текстом, а для 99% людей набором слов.

Это и есть набор слов. Вы пытаетесь рассуждать на тему, в которой ничего не понимаете, приводя идиотские примеры(это даже не примеры, а полный треш). Я отказываю даже читать этот набор слов пока там не будет нормальных примеров с объяснениями — что вообще этот набор слов значит и как он следует из тех же сишных определений.

Потому что если мы принимает порядок "тип имя" для аргументов функций, то для единообразия придётся применять этот порядок везде: при объявлении переменных, членов структур, возвращаемого типа у функции и т.п. И получаются приколы с неоднозначностью типа most vexing parse. Ну вот, например:


Foo foo();


— это объявление и инициализация переменной foo типа Foo, или объявление функции foo() без параметров, возвращающей значение типа Foo?

то для единообразия

Паскаль-стиль не может быть единобразным — он слишком слабый даже для языков уровня js.

И получаются приколы с неоднозначностью типа most vexing parse.

И в чём проблема?

Расскажите мне про прикол с:

(a, b) => c — что это?
А про [a, b, c]?

К тому же, очень наивно ссылаться на проблему, которая вообще не проблема и которую уже решили. И об этом написано по ссылке.
Тем, что таким образом упрощается парсинг языка и исключаются неоднозначные ситуации, которых в С/С++ предостаточно. Первым всегда идет или ключевое слово или идентификатор. Тоже самое с переносом возвращаемого значения функции в конец и использованием ключевого слова вроде func — упрощает парсинг и делает адекватным использование функций первого порядка. В отличие от упомянутых С/С++, где это пытка сплошная.
Тем, что таким образом упрощается парсинг языка и исключаются неоднозначные ситуации

Кому, кроме студентов, интересна сложность парсинга? Язык должен быть мощным и удобным, а насколько его сложно парсить — никому не интересно.

исключаются неоднозначные ситуации

Пустой лозунг, который я уже опровергал выше.

Первым всегда идет или ключевое слово или идентификатор.

Опять лозунг. Хорошо оно идёт — дальше что?

упрощает парсинг и делает адекватным использование функций первого порядка.

Парсинг никому не интересен. Чем это использование более адекватно? Что вообще это значит. Опять какой-то лозунг без примеров/объяснений.

В отличие от упомянутых С/С++, где это пытка сплошная.

Опять же, в чём заключается пытка?
Кому, кроме студентов, интересна сложность парсинга? Язык должен быть мощным и удобным, а насколько его сложно парсить — никому не интересно.

Всем, кто потом будет работать с инструментами, которые язык парсят и что-то делают с AST. Таких для Go множество и именно благодаря его однозначному и простому синтаксису. Это ускоряет и сам процесс парсинга, что полезно вообще всем.

Пустой лозунг, который я уже опровергал выше.

Никакого опровержения не заметил. Отсутствие неоднозначности в синтаксисе языке несет за собой далеко идущие преимущества. И Go этому яркий пример.

Опять лозунг. Хорошо оно идёт — дальше что?

То, что парсить легко. Дальше логику сами можете достроить.

Опять же, в чём заключается пытка?

В том, что в С/С++ синтаксис указателя на функцию ужасен, нечитабелен, сложен для написания и полностью отличается от того, как функции объявляются. Чего стоит только необходимость включения имени переменной в сам тип вроде int(*foo)(). В Go объявление функции, объявления типа указателя на функцию, передача функции как объекта первого порядка — все это идентичные синтаксически вещи, что значительно упрощает чтение и написание кода. Авторы Go к этому стремились, делая такой синтаксис, и они своего добились. Помимо этого, С++, будучи заложником своей извращенной грамматики, придумал тот ужас, которым называют лямбды в этом языке. Тоже самое в C# том же, хоть и не настолько ужасно.

Вы уперлись в какие-то ваши странные представления о том, какой должен быть язык, не понимая, что С/С++ и им подобные это одни из худших примеров с точки зрения синтаксиса. Поэтому не случайно языки нынче выбирают совершенно иную логику, в том числе «идентификатор: тип», func/fun перед функцией и прочее и прочее. Люди наелись проблем этих языков и не хотят тащить теже самые проблем себе, только потому что все привыкли и вроде как все в порядке уже.
Всем, кто потом будет работать с инструментами, которые язык парсят и что-то делают с AST. Таких для Go множество и именно благодаря его однозначному и простому синтаксису. Это ускоряет и сам процесс парсинга, что полезно вообще всем.

Попросту враньё. Инструментов по статическому анализу С++-кода больше и они куда как мощнее и качественнее, чем для го. Никакой С++ парсить ненужно.

К тому же, это враньё ещё и тем, что в го нужны парсеры потому, что язык крайне примитивен и ничего не может. От того и нужнается в кодогене и тысячах костылях, для обхода отсутствия тех же генериков.

Никакого опровержения не заметил. Отсутствие неоднозначности в синтаксисе языке несет за собой далеко идущие преимущества. И Go этому яркий пример.

Т.е. у вас ничего, кроме лозунгов, нет? Где преимущества, в чём преимущества? Го в сравнении с тем же жаваскриптом/тайпскриптом — пыль. Я уж не говорю про С/С++. Что мне показывает пример го? Да ничего.

То, что парсить легко. Дальше логику сами можете достроить.

Ну то, что ваши тезисы — глупые лозунги я понял уже давно. Вы не на баррикадах и лозунги в данном случае котируются мало.

В том, что в С/С++ синтаксис указателя на функцию ужасен

Примеры. Зачем мне лозунги? Конкретно. Берёте идентичный код и пишите его на го и на С++.

нечитабелен

Опять лозунги?

сложен для написания и полностью отличается от того, как функции объявляются.

Вы ведь ничего не знаете. Функция объявляется так же.

Чего стоит только необходимость включения имени переменной в сам тип вроде int(*foo)().

У вас явно лозунги плывут. Функции в си записывается как int(foo)(); Указатель записывается как int(* foo)(); То, что вы этого не знаете — это проблему. Узнайте/спросите перед тем, как делать далеко идущие заявления.

В Go объявление функции, объявления типа указателя на функцию, передача функции как объекта первого порядка — все это идентичные синтаксически вещи, что значительно упрощает чтение и написание кода.

Опять лозунги. Приведите пример.

Авторы Go к этому стремились, делая такой синтаксис, и они своего добились.

Это настолько нелепые заявления. Синтаксис го не может и 10% того, что может синтаксис си в С++, в том же C#. Зачем сравнивать несравнимое?

Это примерно как рассказывать, что у мышки 3 кнопки, а у клавиатуры 100. Вот ведь какая клавиатура плохая — кнопок много. Авторы мышки стремились сделать такое кол-во кнопок(малое) и они добились этого.

Все ваши рассуждения — пустые общие слова, которые ничего не значат.

Помимо этого, С++, будучи заложником своей извращенной грамматики, придумал тот ужас, которым называют лямбды в этом языке. Тоже самое в C# том же, хоть и не настолько ужасно.

Она извращённая лишь потому, что вы где-то это услышали? Сильная аргументация.

И да, у вас опять лозунг потёк. Покажите мне эквивалент С++-лямбды на го, либо на другом языке.

НЛО прилетело и опубликовало эту надпись здесь
Есть другой подход: compiler as a service, как это сделано в C#/TypeScript.

Именно этим и занимается clang уже 10лет. Да и уже лет 20 есть gcc-xml, которого для базовых вещей вполне хватит. Причём лучше, чем упомянутые выше случаи.

Тут двойной факап. И упоминания С++, который находится в авангарде «compiler as a service» и догматическая уверенность в одном избранном случае.
Ну с С++11 стало проще
function<void(int,float)> func_ptr;
Главная миссия дизайна языка —… чтобы он был прост и понятен как для человека, так и для компьютера.

Паскаль же вроде давно придумали, зачем снова разводить «зоопарк»???
Вообще, симпатичный синтаксис, однако, рекурсия тут задумана как некий «Unsafe» элемент… Стоп, что? Язык, претендующий на функциональность со всеми этими иммутабельностью, пайплайнами, вызовами фильтер/мап/редьюсов в ДжаваВосемь-стиле, только через стрелочки, и этот язык предлагает огромную кодобазу отмечать как рекурсивную, хотя мне не припоминается, чтоб у компиляторов когда-либо были проблемы с распознаванием рекурсивных вызовов в коде, с тех пор как в них добавляли поддержку рекурсивных вызовов.
Крайне занятная задумка со стринг-типами, хотя слишком сыро и конкретно – надо расширить на систему типов по возможности (я вижу отличное применение такому функционалу – он вполне может потеснить костыльнуть Хаскелльные тайпклассы, пусть и работает в другую сторону, так же, как и концепты из С++20).
Также интересно отсутствие UB, но это не гарантирует, что программа будет себя вести, как задумано. Более того, никто ещё не видел ошибки реальных программ, а это очень важно – всегда придерживался и придерживаюсь мнения, что максимум ошибок надо ловить в компайлтайме.

Общее впечатление: симпатичный синтаксис (а больше пока ничего и нет), вангую проприетарный майкрософтовский F# x переRust.
P.S.: Насчёт ссылочности и сохранения иммутабельности, как по мне, всё просто: пример кода в статье на эту тему – негодный и не должен ни компилиться, ни, тем более, запускаться. В сигнатуре функции надо обязать указывать mutable var для изменяемых переменных. При правильно прикрученной системе вывода типов получим синтаксис функции вроде:

function foo(var ref bar/*Тип указан только для второй переменной, в то время, как тип первой выводится*/, ref strategy: Int) /*Тип возвращаемого значения выводится сам*/
{
bar += 1;
//Ошибочный код:
//strategy += 1;
return bar;
}

Что в принципе миленько – возможность контроля типов получаемых и возвращаемых значений функции, как и их модификаторов.

А в чём смысл дублирования слова ref словом var? И почему нельзя написать просто strategy: Int, без ref?

ref – Указание, что принимаемый тип будет ссылочным, а var же указывает на мутабельность.
Я провожу аналогию в меру своих знаний, а именно:

На плюсах можно написать:
/*void foo*/
(int a)
(int& a)
(const int& a)
Что будет значить три разных вещи. 1 – int скопируется новой переменной. 2 – будет передан мутабельный параметр по ссылке. 3 – передастся ссылка на константную (то есть, неизменяемая, она же мутабельная) переменную (константную ссылку на переменную, но не суть).

Имеем:
ref strategy: Int –> const int& strategy
strategy: Int –> const int strategy
var ref bar –> template T& bar
ref bar –> template const T& bar

Почему я использую ref для strategy – привычка, больше скажу, я консты не всегда пишу, и потому всеми конечностями за иммутабельность по умолчанию
Передача по константной ссылке отличается от передачи по значению с точки зрения поведения лишь в одном случае — когда параметр передаётся по константной ссылке и по неконстантной ссылке одновременно. Но такая передача — источник ошибок, и в том же Rust не просто так её запретили.

В том же C++ константные ссылки используются, как правило, для оптимизации; но в современном языке такую оптимизацию лучше поручить компилятору.

Таким образом, константные ссылки — не нужны, и остаётся всего два типа передачи параметра: по значению и по изменяемой ссылке. Именно второй способ и достигается при помощи слова ref.
Мне кажется, вы здесь излишне упрощаете, потому что в С++ константные ссылки используются еще и как гарантия той самой иммутабельности при отсутствии сайд-эффектов от копирования.
Т.е. если у меня на руках «тяжелый» константный объект, который хочется отдать как параметр в функцию, то константные ссылки — это хорошая вещь.
Они работают только в одну сторону — чтобы получатель не изменил что-то по ссылке. А вот получателю нет никаких гарантий, что объект «иммутабельный» внезапно из стула не превратится в верблюда, потому что кто-то снаружи что-то внутри него дернул. По сути, это делает бесполезной всю эту затею, почему давно const модификатор скорее плохим тоном и мусором считается, которые постоянно мешает, чем реально полезным инструментом.
Хм. Интересно, можно сыылки на «плохой тон и мусор»? Я на полном серьезе, любопытно посмотреть.
Ссылки не смогу. Это, так сказать, мое агрегированное мнение после чтения всего и вся. Я тоже не из ненависти какой-то, но много раз встречал в самых разных источниках обсуждение проблемы const, какой от него реально профит или вред. И как-то сложилось мнение, что, действительно, оно того не стоит и больше проблем создает. Модные нынче языки тоже вливаются в это русло, либо полностью исключив подобные костыли, либо внедрив себе полноценную иммутабельность в том или ином виде.
Ни разу не встречал обсуждение «проблемы const», Вами так с лёгкостью окрещённой, однако, могу представить Вам пример полноценной иммутабельности на С++:

int main(void)
{
const int i = 0;
++i;
//Всё как мы и ожидали, ошибка компиляции «expression must be a modifiable value»
}

Const – имхо не самая сложная тема при изучении С-подобных языков.
Я и не говорю, что сложная. Но неоднозначная это точно, особенно в последнее время. Именно в разрезе const модификатора аргументов и функций. const переменная для реально константных выражений это как раз таки хороший тон. Тут даже иммутабельность не при чем уже.
Так с точки зрения вызывающего кода с const и правда никаких проблем, проблемы начинаются у вызываемого кода, получившего константную ссылку…
Из очевидных проблем могу назвать const_cast & mutable. Но что есть — то есть, вот с таким сиплюплюсом мы живем. Имхо, это не делает написание конст-корректного кода бесполезным занятием. А встретив на код-ревью эти попытки обмануть конст, можно смело начинать спрашивать о причинах.
Если во внешнем скоупе объект иммутабельный, то такой проблемы и не будет (бишь, функциональный подход для меня по большей части в этом и заключается), а с неизменяемостью по умолчанию – не придётся вообще писать mutable var.
Ну т.е. это совсем не const решается и не может решаться. Это либо весь язык таким должен быть, либо интерфейс у объектов такой, что они иммутабельны по-умолчанию. А так получается ни туда, ни сюда.
объект «иммутабельный» внезапно из стула не превратится в верблюда, потому что кто-то снаружи что-то внутри него дернул

Вы апеллируете к многопоточному программированию?
В таком случае, это вопрос организации взаимодействия и разделения данных между потоками.
Решил продемонстрировать, как я это вижу:
#include <thread>
#include <chrono>

int func(const int& x)
{
	std::this_thread::sleep_for(std::chrono::seconds(1));
	if (x < 1)
		return -1;
	else return x;

}

int main(void)
{
	/*const*/ int i = 1;
	std::thread thr(foo, i);
	++i;
	thr.join();
}

В такой ситуации закомментированный const как раз снимает вопрос.
Да даже без многопоточного. Достаточно положить объект себе куда-то в поле до лучших времен. Что с ним за это время может натворить мир вокруг никто не знает.
Так идея в том, что если ты получаешь конст-объект, то это ты не должен с ним что-то натворить.
Это уже извращения из стана плюсов. Если мы говорим об иммутабельности, а об этом и начался разговор, то этого недостаточно. Это не иммутабельность и const вроде бы никогда ей не считался. Это модификатор доступа, но не характеристика иммутабельности объекта.
Дело в количестве потоков исполнения и они есть, если я не ошибаюсь, во всех языках общего назначения, а не только в спп:

Если он 1 – то программа выполняется построчно, и пока поток выполнения находится в функции, объект назван его формальным параметром, то есть условно const int& x.

Если же их более, чем 1 – переменная действительно может измениться, ну тут уже смотрите, чтоб не было гонок.

Мы обсуждаем странное понятие иммутабельности – позвольте уточнить, что иммутабельные данные – это не коробка байт, которые не изменятся, даже если подача тока прекратится/коротнёт. Это коробка байт, которую можно открыть и посмотреть, но не трогать байты руками.

Если же мы обсуждаем изменение данных «извне» (напр., тупую ассемблерную подмену данных тем же артмани), то для того, чтоб программа корректно(?!) обрабатывала такие изменения, придётся использовать продвинутые техники.
Иммутабельность это иммутабельность. Это объект, который, единожды созданный, больше не изменяется. По крайней мере в рамках своего внешнего интерфейса. Нужно что-то изменить — вперед, делаем копию с изменением. Вот такая иммутабельность делает асинхронный код безопасным. А const модификатор это ограничение доступа к объекту, который, при этом, может меняться изменяться сколько влезет.

И чего вы к потокам привязались. Потоков может быть один, но код асинхронным. И запросто получишь ситуации, когда у тебя под ногами изменился объект. В современных языках с async/await и всеми этими вашими горутинами это обычное дело.
Асинхронный пример принят, сам как-то не подумал.
Непонятно следующее: каким образом /*фактическая*/ переменная, объявленная со словом const, может быть изменена в процессе выполнения программы?
Большинство современных компиляторов плюсов выдадут ошибку, если в коде её значение попытаться изменить.

Потоки тут ни при чём. Берем функцию add_mul, с сигнатурой void add_mul(big_number &s, big_number const& a, big_number const &b) // s += a*b (на олимпиадах я такую любил, ибо элементарная операция), пишем add_mul(x, x, y) // x += x*y и приплыли. Поток всего один, но это не помогло.

В такой ситуации закомментированный const как раз снимает вопрос.

А хотелось бы ошибку компиляции при "не снятом" вопросе...

Как скоро появятся объявления рекрутёров с фразой «Опыт написания программ на Bosque от года»? ;)
НЛО прилетело и опубликовало эту надпись здесь
«от 5 лет»
Всякий раз, когда очередной язык хотят сделать «более понятным для человека», они просто приближают его синтаксис к чему-то паскалеподобному. Так почему бы просто не взять Паскаль?
Там переменные надо объявлять в отдельном блоке. Есть мазохисты, которым нравится, но остальные сильно против. Форвард-декларации — то же самое. И ещё много моментов, неадекватных с современной точки зрения.
Объявлять переменные в отдельном блоке не очень удобно при написании кода, но читать и понимать такой код потом значительно легче.
Вопрос привычки и используемых инструментов, на самом то деле.
Мне удобней читать когда переменные объявлены рядом с местом их использования.

Не легче. В этом самом отдельном блоке у переменной есть только имя и тип, и никакого контекста.

а тут — перлом попахивает

// 5.15 Merge
var t = @[ 1, 2, 3 ];
t<+(@[5])       //@[1, 2, 3, 5]
t<+(@[3, 5])    //@[1, 2, 3, 3, 5]

var r = @{ f=1, g=2, k=true };
r<+(@{g=5})          //@{f=1, g=5, k=true}
r<+(@{g=3, k=false}) //@{f=1, g=3, k=false}
r<+(@{g=5, h=0)      //@{f=1, g=5, k=true, h=0}

var e = Baz@{ f=1, g=2, k=true };
e<+(@{g=5})          //@{f=1, g=5, k=true}
e<+(@{g=3, k=false}) //@{f=1, g=3, k=false}
e<+(@{g=5, h=0)      //error field not defined
4) Вызов функций можно делать с указанием названия аргументов из сигнатуры функции, например: myfunc(x=1, y=2)
Я правильно понял: вызов myfunc(x=1, y=2) полностью эквивалентен вызову myfunc(y=2, x=1) и вызову myfunc(1, 2), но не вызову myfunc(2, 1)? Кажется такое было в ассемблере OS 360/370 и то в макро. В каких других ЯП есть такое?
НЛО прилетело и опубликовало эту надпись здесь
Мне нравится, как сделано в языке R. Можно произвольно сочетать позиционную и именованную запись. В то время как в большинстве других языков именованные аргументы можно перечислять только после позиционных.
Kotlin? В нём, кстати, почти всё перечисленное в статье уже есть и выглядит весьма органично и дружелюбно, в отличии от.
Чувствуется, MS решили запилить свой K# (как они запилили С# в ответ на Java). По мне — так лучше бы F# развивали, «отвязав» его от необходимости быть «совместимым» с С#.
А если к этому добавить параметры по умолчанию:
 function  myfunc(x: integer=1; y : real=2.0) : real;
то можно сделать вызов
myfunc(y =3.16);
а совсем роскошно будет выглядеть эквивалентный вызов
myfunc(3.16);

для параметра с уникальным типом в данной функции.
Простите, а анонс точно не 1 апреля вышел?
Теперь можно пить шампанское «Боско» и писать на языке «Боско».
Страшен, как образы на картинах Босха.
Все значения в Bosque являются неизменяемыми (immutable)

Ну наконец-то они создали такой язык (F# не в счет).

Напомнило Prolog, там тоже циклов нет, все надо делать рекурсивно
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации