Язык программирования Ü. Введение, мотивация к созданию, цели

    Введение


    С 2016-го года (с перерывами) я разрабатываю собственный язык программирования. Название данного языка — «Ü». Почему Ü? Потому, что хотелось однобуквенного названия, а все буквы из набора A-Z уже заняты.

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

    Зачем нужен ещё один язык?

    Я рассмотрел ряд существующих статически-типизированных компилируемых более-менее известных языков, и пришёл к выводу, что ни один из них меня вполне не устраивает. У всех них есть «фатальные» недостатки.

    Конкретно по пунктам:

    • C — слишком низкоуровневый и небезопасный
    • C++ — по наследству получил много недостатков низкоуровневости, появились новые способы выстрелить себе в ногу, отсутствие рефлексии
    • D — сборщик мусора, отдельные ссылочные типы
    • Java — сборщик мусора, все композитные типы ссылочные, сильная завязанность на виртуальную машину. Многое и этого применимо и к языках на основе JVM.
    • C# — недостатки во многом аналогичны Java
    • Rust — необходимость явного взятия ссылок и явного их разыменования, (субъективно) опасность подхода, когда всё есть выражение и возвращает результат, наличие явного указания соответствия протоколу, отсутствие наследования
    • Go — сборщик мусора, отсутствие шаблонов
    • Swift — ссылочные типы, необходимость явного указания соответствия протоколу

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

    Общее сведения


    Ü — компилируемый, статически-типизированный язык со строгой типизацией. Язык содержит свободные функции, структуры, классы, методы для структур и классов. Существующие виды типов — фундаментальные, структурные (структуры, классы), массивы константного размера, кортежи, перечисления, указатели на функции. Классы могут участвовать в наследовании и иметь виртуальные функции. Язык поддерживает шаблоны, есть шаблоны классов и структур, псевдонимов типов, функций и методов. Присутствует перегрузка функций и операторов (с некоторыми ограничениями).

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

    Что уже есть


    Реализован компилятор на основе LLVM. Компилятор поддерживает все платформы, что поддерживает LLVM. Чисто исполняемые файлы компилятор создавать пока что не умеет, но умеет порождать объектные файлы, ассемблерный код, бинарный или текстовый llvm-код. Есть возможность связи с C кодом, есть утилита, позволяющая упростить написание Ü-заголовков для C библиотек.

    Цели и задачи


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

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

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

    Итак, давайте рассмотрим, какие моменты есть в Ü, которые соответствуют заявленным целям.

    Система типов


    В отличие от C++, в Ü не существует указателей и ссылок как типов. Указателей нету вообще, ссылки есть, но только как стековые ссылки, ссылочные аргументы функций, ссылочные поля. Также модификаторы mut/imut не являются частью типа, а являются частью переменной, ссылки, аргумента функции, поля.

    Благодаря такому упрощению повышается понимание того, где какой тип, особенно в шаблонном коде. Отсутствуют сомнения, будет ли объявлена ссылка или переменная, сомнения в результате typeof (аналог decltype из C++), сомнения в константности/неконстантности.

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

    Инициализаторы


    Невозможно объявить какую-то переменную и не инициализировать её. Любой байт объявленной переменной должен быть инициализирован.

    Фундаментальные (и некоторые другие) типы требуют обязательной инициализации:

    var i32 x= 22, y(12345);

    Требуют инициализации поля классов и структур:

    struct Vec{ f32 x; f32 y; }
    ...
    var Vec v{ .x= -56.1f, .y= 42.0f };
    var Vec v_uninit; // Будет ошибка

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

    struct Vec
    {
    	f32 x; f32 y;
    	fn constructor()
    	( x= 0.0f, y= 0.0f )
    	{}
    }
    ...
    var Vec v; // позовётся конструктор

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

    Кстати, инициализатор поля:

    struct Vec
    {
    	f32 x= 0.0f;
    	f32 y= 0.0f;
    }

    Другие виды типов имеют свои инициализаторы, для массивов и кортежей нужен инициализатор [] с количеством элементов, равным количеству элементов в массиве или кортеже:

    var [ i32, 4 ] a[ 1, 1, 3, 4 ];
    var tup[ i32, f32 ] t[ 8, 0.5f ];
    var [ f32, 16 ] a_uninit; // Ошибка, члены массива неконструируемы по умолчанию.
    var[ i32, 3 ] aa[ 0, 1 ]; // Ошибка, мало инициализаторов

    В отличие от C++, элементы структуры нельзя инициализировать просто передав инициализаторы в определённом порядке, обязательно указывать имя поля. Это предотвращает проблемы, когда структуру поменяли, а инициализаторы — нет.

    Язык поддерживает конструкторы и список инициализации для конструкторов. При инициализации членов через список инициализации отслеживается, какие поля уже проинициализированы, а какие — ещё нет. Также из списка инициализации недоступен this, а значит нельзя позвать какие-либо методы/функции, передав им недоинициализированные данные:

    struct Vec
    {
    	f32 x; f32 y;
    	fn constructor()
    	( x= y, y= 0.0f ) // Ошибка,  «y» ещё не инициализирован
    	{}
    
    	fn constructor( f32 val )
    	( x= val, y= x ) // Нормально. «x» уже инициализирован и его можно использовать для инициализации «y»
    	{}
    }

    Отслеживание ссылок


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

    Простейший пример:

    var i32 mut x= 0;
    var i32 &mut ref0= x;
    ++x; // Ошибка, для инкремента нужно создать ещё одну изменяемую ссылку
    var i32 &imut ref1= x; // Ошибка, неизменяемую ссылку создать нельзя, т. к. уже есть одна изменяемая

    Другой пример:

    var i32 mut x= 0;
    var i32 &imut ref0= x;
    var i32 &mut ref1= x; // Ошибка, нельзя создать изменяемую ссылку, если уже есть неизменяемые ссылки

    Однако можно так:

    var i32 mut x= 0;
    var i32 &mut ref0= x;
    var i32 &mut ref1= ref0; // Так можно, т. к. изменяемая ссылка указывает не на саму переменную, а не другую изменяемую ссылку

    Ссылки учитываются при вызове функций:

    fn Mutate( i32 &mut x, i32 &mut y );
    ...
    var i32 mut x= 0;
    Mutate( x, x ); // Ошибка, создаём две изменяемые ссылки на одну и ту же переменную

    Данный механизм позволяет отлавливать типичные ошибки доступа к памяти. Пример на C++

    std::vector<int> vec;
    vec.push_back(1);
    int& ref= vec.front();
    vec.push_back(2); // Беда, ссылка ref после этого может указывать на неправильный участок памяти

    В Ü подобного рода проблемы поймаются на этапе компиляции:

    var ust::vector</i32/> mut vec;
    vec.push_back(1);
    var i32 &imut ref= vec.front();
    vec.push_back(2); // Ошибка, создание изменяемой ссылки на переменную vec, на которую уже есть неизменяемые ссылки

    Наследование


    Участвовать в наследовании могут только классы (не структуры). В наследовании участвуют только полиморфные классы — помеченные как polymorph, interface, abstract или имеющие предков. Унаследоваться от неполиморфного класса нельзя. Полиморфные классы имеют виртуальный деструктор, явно не объявленный виртуальным деструктор всё равно будет виртуальным.

    Виды полиморфных классов:

    • Интерфейсы. Могут иметь только интерфейсных предков, не могут иметь полей, не могут иметь реализаций виртуальных функций.

      Пример:

      class A interface
      {
      	fn virtual pure Foo(this);
      }
    • Абстрактные классы. Могут иметь одного неинтерфейсного предка и несколько интерфейсных предков. Могут не иметь реализаций у некоторых виртуальных функций. Могут иметь конструкторы, но в конструкторах не доступен полностью this, а значит нельзя звать методы, в т. ч. виртуальные. Тем самым ликвидируется проблема abstract call, которая есть, к примеру, в C++.

      Пример:

      class A abstract
      {
      	fn virtual pure Foo(this);
      	fn virtual Bar(this){}
      	i32 x= 0;
      }
    • Просто полиморфные классы. Могут иметь одного неинтерфейсного предка и несколько интерфейсных предков. Требуется реализация всех виртуальных функций. Если какая-то виртуальная функция не реализована, будет порождена ошибка.

      Пример:

      class A interface
      {
      	fn virtual pure Foo(this);
      }
      class B : A
      {
      	fn virtual override Foo(this){}
      }
    • Финальные полиморфные классы. Такие же, как обычные полиморфные классы, но от них нельзя наследоваться.

    Только полиморфные классы имеют право иметь виртуальные функции. Для виртуальных функций требуется явно указывать вид виртуальности.

    fn virtual pure Foo(this); // Объявление чистой виртуальной функции. Если предок уже имеет подобное объявление, или имеет объявление такой функции с наличием реализации, будет порождена ошибка.
    
    fn virtual Foo(this){} // Объявление виртуальной функции с реализацией. Будет порождена ошибка, если функция перекрывает виртуальную функцию предка.
    
    fn virtual override Foo(ths){} // Объявление виртуальной функции, перегружающей функцию предкового класса. Если у предкового класса нету объявления этой виртуальной функции, будет порождена ошибка.
    
    fn virtual final Foo(this){} // Объявление виртуальной функции, окончательно перегружающей функцию предкового класса. Если у предкового класса нету объявления этой виртуальной функции, будет порождена ошибка. Если класс-потомок попробует перегрузить данную функцию, будет порождена ошибка.

    Контроль потока выполнения


    Возможно в 2019—м году это уже банальщина, но тем не менее, в Ü есть проверка верности потока управления. При обнаружении недостижимого кода порождается ошибка. В функциях, которые должны возвращать значение, порождается ошибка, если не доказано, что оно возвращается всегда.

    Пример:

    fn Foo( i32 mut x ) : i32
    {
    	while(x  < 100 )
    	{
    		x+= 10;
    		continue;
    		x+= 20; // Ошибка, недостижимый код
    	}
    	return x;
    	++x; // Ошибка, недостижимый код
    }

    Ещё пример:

    fn Foo( i32 x ) : i32
    {
    	if( x < 10 ) { return 0; }
    	else if( x > 100 ) { return 1; }
    	// Ошибка, функция не всегда возвращает значение
    }

    Пример выше можно исправить или добавив безусловный else с возвратом, или же добавив return в конце.

    Для случаев, когда поток управления куда-то заходить не должен, предусмотрен оператор halt (см ниже). Этот оператор считается терминальным, что означает, что после него код не допустим, а ветвь потока управления учитывается в проверке наличия return.

    Многопоточность


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

    К примеру:

    struct CallableObject
    {
    	i32 &mut x;
    	op()( mut this )
    	{
    		++x;
    	}
    }
    ...
    var i32 mut x= 0;
    var CallableObject mut obj{ .x= x };
    auto thread= ust::thread_create( move(obj) );
    ++x; // Ошибка, изменение переменной «x», на которую есть уже изменяемая ссылка в «thread»
    ++ obj.x; // Аналогичная ошибка

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

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

    Однако, что если надо иметь возможность доступа на чтение и запись для одних и тех же данных из разных потоков? Для этого существуют специальные библиотечные классы разделяемых указателей с блокировкой — shared_ptr_mt и прочие. Поток, которому нужна запись, вызывает метод lock_mut() у класса указателя чтобы получить доступ на запись или lock_imut(), если нужен доступ на чтение. Данные методы блокирующие и гарантируют соблюдения правила «одновременно позволено существование или одной изменяемой ссылки, или нескольких неизменяемых».

    Пример:

    struct Incrementer
    {
    	ust::shared_ptr_mt_mut</ i32 /> ptr;
    	op()( mut this )
    	{
    		auto mut lock= ptr.lock_mut(); // Разрушение объекта «lock» снимет блокировку
    		++lock.get_ref();
    	}
    }
    ...
    var ust::shared_ptr_mt_mut</ i32 /> ptr(0);
    var size_type mut i(0);
    var ust::vector</ ust::thread</Incrementer/> /> mut threads;
    while( i < size_type(64) )
    {
    	var Incrementer incrementer{ .ptr= ptr };
    	threads.push_back( ust::thread_create(incrementer) );
    	++i;
    }
    threads.clear(); // Дожидаемся выполнения потоков в вызове деструкторов.
    halt if( ptr.lock_imut().get_ref() != 64 ); // Проверяем, что результат тот, что надо

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

    Глобальные переменные


    Изменяемых переменных нет. Позволены только глобальные константы, при этом не любые, а только constexpr типов. Как следствие, значения всех констант вычисляются на этапе компиляции и нету проблем с порядком инициализации.

    Если глобальное изменяемое состояние нужно, реализовывать его придётся не на Ü, а на чём-то другом, например на C.

    Операторы


    В отличие от C++, операторы присваивания (=, +=, *= и т. д.) не возвращают никакого значения и более того, синтаксически являются утверждениями, а не выражениями. Аналогично и с операторами ++ и –.

    Примеры ниже даже не будут синтаксически верными:

    if( x = 0 ) {}
    x++; // ошибка Можно только префиксный ++
    x += x += x; // ошибка, второй += не опознан
    x+= x++ + ++x; // и уж тем более нельзя так

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

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

    auto a = select( condition ? x : y );

    ключевое слово select и скобки являются частью оператора.

    Исключения


    Их нет. Совсем нет. И не будет. Никогда не будет.

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

    • Потенциальная возможность возникновения исключения в каждой строчке программы. Из-за этого сложнее сохранять консистентность данных, требуются как затраты времени программиста на решение проблем консистентности, так и затраты производительности на её реализацию.
    • Нарушение уровней абстракции. Фундаментальная возможность пробросить исключение через несколько уровней стека вызовов порождает проблему нарушения абстракций. Какой-нибудь NullPointerException малоинформативен где-нибудь наверху, где его поймают при попытке выполнить какую-то высокоуровневую операцию. Проблему отчасти могло бы решить принуждение к обработке исключений конкретной функции в месте вызова, но тогда теряется смысл механизма исключений, т. к. то же самое поведение можно было бы реализовать через механизм возврата.
    • Неоднозначность трактовки понятия исключения. Как следствие, в общем случае непонятно, где нужно кидать исключение, а где возвращать значение. Из-за этого в одной и той же программе может быть принято по-разному реализовывать по сути один и тот же код, если над программой работают более одного человека. Как следствие, ухудшается восприятие кода.
    • Проблема обработки исключения при обработке исключения. За тем, чтобы такого не возникло, надо следить вручную.

    Кто, если не Что, если не исключения?

    В случае, когда функция не может вернуть т. н. «ожидаемый» результат, надо возвращать результат или признак неудачи, наподобие std::optional/std::variant из C++ или Option/Result из Rust.

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

    Модульность


    Как таковых модулей пока что нету, но всё-же есть импортирование содержимого из другого файла. Исходный файл, указанный после директивы import, зачитывается и компилируется, после чего объявления из него можно использовать. В отличие от C++, это полноценная компиляция отдельного файла, без учёта имён предыдущих импортированных файлов.

    Пока что нету ограничения видимости содержимого импортируемого файла. Но можно разбивать модули на заголовочную и внутреннюю части, аналогично *.cpp и *.hpp из C++.

    Заключение


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

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

    Ссылки


    Репозиторий с проектом

    Пример сборочного скрипта, чтобы было понятно, как собрать проект.

    → Примеры кода можно увидеть в тестах и в стандартной библиотеке.

    Документации пока что нету, т. к. пока рано её создавать, да и руки до неё не дошли.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

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

      +4
      А какую смысловую нагрузку несёт ключевое слово var?
      var i32 x=0;
      или
      i32 x=0;
        +7
        Ключевое слово необходимо для упрощения синтаксического разбора. В Ü грамматика контекстно-свободная, а значит по ходу выяснить, что i32 это имя типа, а не что-то ещё, не возможно.
          0
          Почему тогда не сделать как в большинстве языков var x:i32 = 0?
            +5
            Для объявления нескольких переменных одного и того же типа:
             var i32 x= 0, y= 1, z= 2;

            В вашем примере потребовалось бы для каждой переменной указывать тип, ну или не указывать и выводить тип из инициализатора, но тогда пострадает читаемость.
              +1
              Не очень понятное решение. Это довольно редкий случай, когда нужны _сразу_ несколько переменных одного типа. Да и даже в том случае, может быть более читаемо объяивить каждую переменную на своей строке. Да и если захочется сделать указание типа опциональным, то будет странно.
              0
              Большинстве? Где нибудь есть список? очень хочу найти идеальный для себя, а знаю только недоделанный zig.
                +1
                От Паскаля и до ML-подобных языков, включая Scala. Только Haskell выпендрился, там не одно ":", а два.
              +3
              Ключевое слово необходимо для упрощения синтаксического разбора.

              Одна из самых больших ошибок при разработке ПО, когда делают упущения ради простоты реализации. Как мне кажется, новый ЯП должен не только покрывать недостающий в других ЯП функционал, но и упрощать синтаксис, уменьшать уровень входа для разработчиков.
              Я бы пошел по пути groovy / dart / etc, сделав указание типа опциональным и добавив автовыведение типов, т.е.
              int[] num1 = [ 123 ];
              var num2 = [ 123, 456 ]; // int[]
              


              Названия типов я бы взял из java, да кому-то нравятся сокращения, но неужели f64 более понятен, чем double?

              Для часто используемых конструкций добавил бы литералы – массивы/коллекции [], множества {}, хэш-таблицы {:},

              Из новых операторов я бы добавил null-safe оператор obj?.attr, может быть cascade оператор… как в dart'е, elvis-оператор ?:.

              Систему типов взял бы из java – все методы виртуальные, т.к. в большинстве случаев это и ожидается в ООП, а для статичных методов, пожалуйста, static. Так же добавил бы в систему типов trait'ы.
              На уровне класса оперировал понятиями свойств (как c#, groovy, dart) – доступ к значению поля через автогенерируемые getter / setter, но с возможностью переопределить эти методы.

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

              Для синхронизации потоков стоит или на уровне ЯП определить конструкции типа synchronized блоков / volatile, либо добавить в sdk семафоры / мютексы / атомики, которые бы обеспечивали корректную модель памяти.

              В конечном счете, чем больше ЯП вы проанализируете, тем более точное представление о проблемах получите. В текущем виде ваш ЯП больше поход на среднее между rust/c++, думаю, вы не этого изначально добивались.
                0
                упущения ради простоты реализации
                Данное упрощение ещё и читаемость кода упрощает, глаз сразу видит, где объявление переменной, а где что-то другое.
                добавил бы литералы
                Можно, но это пока не в приоритете.
                null-safe оператор
                Есть встроенный макрос if_var(){}, который достаёт из опционального значения объект, если он там есть, и выполняет содержимое блока для него. Возможно, это не так изящно, но суть примерно та-же.
                Систему типов взял бы из java – все методы виртуальные
                Все фунцкии виртуальнуе — это ущерб производительности, это противоречит заявленным целям.
                ля синхронизации потоков стоит или на уровне ЯП определить конструкции
                в язык такое, без должной необходимости, лучше не тащить. Но вот в стандартной библиотеке такое можно.
                  0
                  Одна из самых больших ошибок при разработке ПО, когда делают упущения ради простоты реализации.

                  Следствием этого обычно являются хорошие сообщения об ошибке, а не "вы пропустили точку с запятой" когда на самом деле закрывающая скобка не там.


                  Я бы пошел по пути groovy / dart / etc, сделав указание типа опциональным и добавив автовыведение типов, т.е.

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


                  Названия типов я бы взял из java, да кому-то нравятся сокращения, но неужели f64 более понятен, чем double?

                  Конечно. Или вот в расте сделали тип i128, какое для него будет очевидное название? i32 — это int, long или DWORD?


                  Для часто используемых конструкций добавил бы литералы – массивы/коллекции [], множества {}, хэш-таблицы {:},

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


                  Хотел продолжить разбор комментария, но обратил внимание на некоторые высказывания


                  Названия типов я бы взял из java
                  Систему типов взял бы из java
                  Для синхронизации потоков стоит или на уровне ЯП определить конструкции типа synchronized блоков

                  Вы в свою очередь предлагаете сделать еще одну джаву.

                    0
                    Вы в свою очередь предлагаете сделать еще одну джаву

                    Причем а том числе в местах, где в Java очевидно плохо (например virtual по умолчанию)

                      0
                      Приведите пример, когда виртуальные методы это плохо, когда происходит вызов не актуальной реализации метода (программист зачем-то же переопределял метод), а реализации, определяемой типом указателя / ссылки?
                        0

                        Бывают даже protected методы, по своей природе не предназначенные для перекрытия. А уж среди public методов таких большинство. Но из-за того, что такие методы виртуальные, у программиста, пишущего наследника, имеется возможность ошибочно их перекрыть и получить конструкцию, неработоспособную в edge cases, но на первый взгляд вполне корректную.

                      0
                      Вы в свою очередь предлагаете сделать еще одну джаву.

                      В своем комментарии я приводил примеры из java, groovy, dart, php, c#, js, но вы увидели только первое.
                      Скажите, какой цели вы добивались, создавая пост: получить замечания и критику, указания на недочеты и неудобство? или чтобы потешить свое самолюбие, глядите какой я молодец, сделал еще один c/rust?
                        0

                        Вы немного промахнулись веткой :)


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

                          0
                          Если забыть о jvm, gc, наследии java 1.1 и прочей мишуре, в чем вы видите проблемы java касательно языковых конструкций, системы типов и т.п.?
                          Не холивара ради, просто мне интересен взгляд со стороны.
                    0
                    ты тогда просто зарезервируй i32 и т.п. как кодовые слова, чтобы криворукие не обьявляли так переменные, что создаст только головную боль.
                  +19
                  Поругать C и написать что-то на него похожее, а что — вариант! )
                    –5
                    От C в Ü только некоторые синтаксические элементы, ключевые слова. В остальном Ü как раз и не содержит тех элементов, за которые ругают C.
                    +5
                    А что вам мешало подсветить синтаксис в статье почти всех примеров?
                    Например, rust очень даже ничего так справляется
                    fn Foo( i32 x ) : i32
                    {
                    	if( x < 10 ) { return 0; }
                    	else if( x > 100 ) { return 1; }
                    	// Ошибка, функция не всегда возвращает значение
                    }
                      +2
                      Да, действительно, так лучше. У Ü много ключевых слов, таких же как в Rust.
                        +10
                        Видимо это не случайно :) Синтаксис практически 1-1 как в rust. Да и отслеживание ссылок тоже оттуда, только тема не так полно раскрыта

                        P.S. Моё знакомство с Rust ограничено 8 часов работы с tutorial. Но и после этого совершенно непонятно зачем нужен Ü при живом Rust
                        +2
                        А вот захочется Вам поработать с оперативной памятью, Винапи, файлами, и т.д. Как Вы сможете это реализовать без указателей-то?
                          0
                          Указателей не то чтобы нету, их нету как составной части языка. Есть библиотечный шаблонный класс для сырых указателей, для всяких низкоуровневых вещей его можно использовать. Но это только для unsafe кода.
                          При работе с WinAPI, файлами, сетью можно (отчасти) обойтись ссылками. Там где обойтись ссылками будет нельзя, придётся писать свои биндинги.
                          Вообще, взаимодействие с кодом на других языках это отдельная тема, которую я раскрою позже.
                          +29
                          А читается название языка как «ЪУЪ»?
                            +5
                            Почему конвенцию именования переменных не используют при именовании языков?..
                              +45
                              Ü

                              image

                                +5

                                это логотип языка?

                                  +4
                                  Маскот.
                                  +1
                                  Это из Мольера?
                                  Заголовок спойлера
                                  MAÎTRE DE PHILOSOPHIE: La voix u se forme en rapprochant les dents sans les joindre entièrement, et allongeant les deux lèvres en dehors, les approchant aussi l'une de l'autre sans les rejoindre tout à fait: u.
                                  MONSIEUR JOURDAIN: U, u. Il n'y a rien de plus véritable: u.
                                  MAÎTRE DE PHILOSOPHIE: Vos deux lèvres s'allongent comme si vous faisiez la moue: d'où vient que si vous la voulez faire à quelqu'un, et vous moquer de lui, vous ne sauriez lui dire que: u.

                                  («У» в русском переводе не совсем точно передаёт гримасу:
                                  Учитель философии. Чтобы произнести звук У, нужно приблизить верхние зубы к нижним, не стискивая их, однако ж, а губы вытянуть и тоже сблизить, но так, чтобы они не были плотно
                                  сжаты: У.
                                  Г-н Журден. У, У. Совершенно справедливо! У.
                                  Учитель философии. Ваши губы при этом вытягиваются, как будто вы гримасничаете. Вот почему, если вы пожелаете в насмешку над кем-либо состроить рожу, вам стоит только сказать: У.
                                  )
                                    –1
                                    Вы сделали мой день! :)
                                    0

                                    Видео как произносить название языка: Kung Pow — Wii-U

                                      0
                                      Наверняка, как «Ю» в слове «мюсли» или «Мюнхен».
                                      +18

                                      Под ваши нужды могли бы подойти: Crystal, Nim, Zig. Они, конечно, не такие популярные, как Си \ Rust \ Go, но все же живые, и человекочасов в них вложено на порядок больше, чем вы в одиночку сможете вложить в свой проект. Поэтому ваша аргументация с недостатками существующих языков неубедительна — скажите честно, что одолела жажда велосипедостроения. Это нормально :)

                                        +1
                                        Действительно, жажда велосипедостроения у меня присутствует, скрывать не стану.
                                        На счёт перечисленных вами языков: о Nim я немного читал, обнаружил в нём сборщик мусора. Это противоречит моим представлениям об идеальном языке. С Crystal и Zig не знаком, обращу на них внимание.

                                          +2
                                          В nim можно обойтись без сборщика мусора. Но есть небольшая сложность с некоторыми стандартными типами.
                                          Подробности тут:
                                          forum.nim-lang.org/t/3801
                                          0
                                          +1

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

                                          Потенциальная возможность возникновения исключения в каждой строчке программы.
                                          Это нормально. К счастью, вам не нужно ловить исключение на каждой же строчке.
                                          Из-за этого сложнее сохранять консистентность данных
                                          Пруфы, пожалуйста. Не забываем, что программа без исключений также может упасть в любой момент по собственной вине (halt), по вине операционки или просто выключения питания.
                                          Нарушение уровней абстракции.
                                          Никакого нарушения тут нет. Наоборот, исключения можно обрабатывать на том уровне, где это осмысленно, не замусоривая остальной код рутинными проверками с возвратом.
                                          Неоднозначность трактовки понятия исключения.
                                          Это глобальная проблема семантики и наличие Result вместо исключений ее не решает — например, можно вернуть Some(null).
                                          Проблема обработки исключения при обработке исключения.
                                          Это следствие из первого пункта. В крайне редком случае, когда возникло исключение при обработке исключения и его никто не поймал выше, будет ровно то же, что у вас происходит в любой ситуации с halt.
                                            0
                                            вам не нужно ловить исключение на каждой же строчке.
                                            Не нужно ловить там, где после каждой строчки состояние будет валидным. Если же переход из валидного состояния A в валидное состояние B требует выполнения операций i, j, k, и во время выполнения операции j возникло исключение, то возникнет невалидное состояние. Чтобы такого не было в среде с исключениями, надо ловить исключения каждой промежуточной операции и откатывать состояние до валидного.
                                            исключения можно обрабатывать на том уровне, где это осмысленно
                                            Я бы даже сказал не просто можно, а нужно. У нужный уровень это тот, на котором происходит вызов. Получается, исключения, которые пролетают несколько уровней стека вызовов, не нужны.
                                            можно вернуть Some(null)
                                            Вот именно, «вернуть». На счёт выбора механизма уже нету сомнений. Есть сомнения в типе, но так и с исключениями есть такие сомнения.
                                              +1
                                              Не нужно ловить там, где после каждой строчки состояние будет валидным.
                                              Если у вас нет глобального состояния, то после любого исключения будет уничтожен текущий scope (читай — часть стека) и состояние останется валидным. Если глобальное состояние есть (например, внешняя БД) — то в обоих случаях придется писать дополнительную логику (например, отката транзакций). Таким образом, ваш подход с явным возвратом ситуацию никак не улучшает.
                                              У нужный уровень это тот, на котором происходит вызов.
                                              Нужный уровень — это тот, на котором есть достаточно данных для принятия решения (сделать retry, залогировать, пробросить выше, показать ошибку и т.д.). На промежуточных уровнях проверки — это лишний boilerplate, из-за которых код распухает и становится менее понятным и поддерживаемым.
                                                0
                                                будет уничтожен текущий scope
                                                Это не отменяет изменений в изменяемых переменных. Чтобы отменяло, надо сильно заморочиться.
                                                Нужный уровень — это тот, на котором есть достаточно данных для принятия решения
                                                Больше всего данных для принятия решения по месту возникновения ситуации. Выше по стеку вызовов данных становится всё меньше.
                                                  +1
                                                  Это не отменяет изменений в изменяемых переменных.
                                                  Локальное состояние (переменные на стеке) отменится, глобальное внутреннее состояние (глобальные переменные) — признак говнокода, глобальное внешнее состояние (базы, API, прочее) — при исключениях обработать можно, при глобальном halt'е будет «ой».
                                                  Выше по стеку вызовов данных становится всё меньше.
                                                  Окей, элементарный пример: представьте клиент для мессенджера. Пользователь отправляет сообщение, а если оно не отправилось — нужно показать ошибку и предложить попробовать еще раз. Запрос на отправку проходит через три слоя: UI, менеджер сообщений и обертку над API конкретной библиотеки, и падает в самой глубине из-за недоступности сети. На каком из слоев, по-вашему, должна быть логика показа сообщения и выполнения повтора?
                                                    0
                                                    ИМХО, где то в коде libcurl :)
                                                      +2
                                                      Пользователь отправляет сообщение, а если оно не отправилось — нужно показать ошибку и предложить попробовать еще раз.

                                                      Не нужно.
                                                      Если не отправилось — автоматически повторяем попытки, пока не отправится. У пользователя при этом будет меняться статус сообщения («отправляется» — «падажжи, бяка какая-то» — «отправилось» — «прочитано» — «с той стороны стучат по кнопкам, набирая ответ»).

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

                                                      Показ — в УИ, перепосылка и смена статусов сообщения — в слое менеджера сообщений.
                                                  0
                                                  Если же переход из валидного состояния A в валидное состояние B требует выполнения операций i, j, k, и во время выполнения операции j возникло исключение, то возникнет невалидное состояние. Чтобы такого не было в среде с исключениями, надо ловить исключения каждой промежуточной операции и откатывать состояние до валидного.

                                                  А как отсутствие исключений решит эту проблему?

                                                    0

                                                    Потому что когда вы видите строчку var a = Foo() вы не знаете, хотел ли автор этого кода прокинуть ошибку наверх или он просто забыл написать try catch. Если у вас раньше была функция, возвращающая результат, а теперь она бросает эксепшн, вы не знаете, какие флоу у вас от этого сломались. Исключения в многопоточной среде тоже привносят свои приколы. Ну и так далее.

                                                      0

                                                      Нет, а вот проблему "у нас было изменение состояния в i и j, но потом злобный k бросил исключение, надо теперь обратить i и j" — как решит отсутствие исключений?
                                                      Разве отсутствующие исключения не позволят таких ситуаций создавать? Да вроде нет, для этого всего-то надо мутабельное состояние, и в языке оно есть — более того, в языке есть вообще бич любых попыток что-то откатить — переприсваивание значений локальных переменных, переданных по ссылке внутрь j, когда вы уже и не знаете даже, менялось там хоть что-то или нет (мы ведь о чёрных ящиках рассуждаем, раз уж я не могу заглянуть в Foo, или проследить, какие потоки вызовов ведут ко мне извне).


                                                      Если у вас раньше была функция, возвращающая результат, а теперь она бросает эксепшн

                                                      Вот прямо вдруг бросает? Хорошо, а если я так же вдруг поменяю тип возвращаемого значения на Either<a, b>, но в коде не обработан случай с b (ну, написано там Foo().left, ну так вот) — это разве такой же проблемы не вызовет?

                                                        0
                                                        Нет, а вот проблему "у нас было изменение состояния в i и j, k бросил исключение, надо теперь обратить состояния i и j" — как решит отсутствие исключений?

                                                        Я буду видеть, что j всегда завершается успешно, а k завершается с ошибкой. Если вдруг после рефакторинга k станет тоже всегда успешным то весь код-обработчик ошибочной ситуации можно будет обрать.


                                                        Разве отсутствующие исключения не позволят таких ситуаций создавать?

                                                        Во всех местах мне будет подсказывать компилятор. Любой рефакторинг — и вам либо надо добавить обработку ошибки, либо убрать ту, которая никогда не вызовется, чтобы не замусоривать код. По сути это ровно то же самое, что null vs Option, в одном случае вы всегда знаете, что у вас может быть или не быть значение, а в другом вы в рандомных местах проверяете на null и наедетесь, что не проверяете, где не надо, и проверяете где надо.



                                                        Ну и да, мой вопрос остается. Если человек написал var a = Foo() а функция Foo кидает эксепшн, вы никогда не узнаете, ошибся он и забыл обработчик написать, или надо тут эксепшн обрабатывать. Причем как я уже говорил, сегодня Foo не кидает ошибку, а завтра кидает. А правильно обработать весь коллстек до main без поддержки компилятора не такая уж простая задача. Спросите любого, кто пробовал изменить синхронный метод на асинхронный где-нибудь внизу дерева вызовов.

                                                          –1
                                                          j всегда завершается успешно

                                                          Простите, но это — фантастика в языке с командой "а теперь, детишки, падаем в корку" (i.e. halt). В конце концов, f может попытаться выделить память, которой ему не дали — и что, будем везде иметь как возвращаемое значение гигатип Result, одним из вариантов которого будет Result::OOM? И возвращаемое значение конструктора типа T канонически запишем как
                                                          Either<T, Result::OOM>?


                                                          Если человек написал var a = Foo() а функция Foo кидает эксепшн, вы никогда не узнаете, ошибся он и забыл обработчик написать, или надо тут эксепшн обрабатывать

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

                                                            0
                                                            Простите, но это — фантастика в языке с командой "а теперь, детишки, падаем в корку" (i.e. halt)

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

                                                              0

                                                              Я по-прежнему думал, что мы там обсуждаем проблему консистентности данных, старый я дурак, а не синтаксические конструкции, которые заставят разработчика обработать исключительные ситуации (а пустой Option это такое же исключение, только вы ещё и не знаете, почему так произошло, пока код не запустите на точно тех же самых данных). Потому что так-то в языках с исключительными ситуациями тоже можно заставить разработчика обработать ваше исключение — и он иногда даже сделает настоящую обработку, основываясь на данных, которые возможно получить из "формы" объекта исключения. То есть, всё то же самое, что и с различными return-кодами, типа Option, Try, и проч.
                                                              Так вот, исходя из проблемы консистентности данных любая форма такого Halt это куда хуже так нелюбимых нынче исключений.

                                                                0

                                                                Я говорил исключительно про то, что процитировал. Если f попытается выделить память, а при нехватке будет вызываться halt, то Result::OOM возвращать и обрабатывать не надо.

                                                                  0

                                                                  Я думаю, многие программы всё же вполне могут обработать OOM собственными силами, (хоть и не на уровне условного f, можно ведь и какой-нибудь LRU-кэш почистить где-нибудь в соседнем модуле). Потому, как раз не надо делать halt если память закончилась, а если и делать, то давать программе возможность это действие обратить и "попытаться снова", и вообще очень много подобных оговорок. Но я не уверен, что такое получится применить в языке без механизма исключений. Разве что не иметь исключений в safe-коде, но иметь его или его аналог в unsafe.

                                                    0
                                                    требует выполнения операций i, j, k, и во время выполнения операции j возникло исключение, то возникнет невалидное состояние

                                                    Да, в таком случае вам надо оборачивать каждую операцию. Но на практике, если i, j и k так сильно меняют состояние, то это скорее всего будут семантически отдельные операции, например, обособленные процедурами. Или же состояние системы (на каком она шаге) можно точно выяснить в ходе обработки единого блока исключения и откатить куда надо.
                                                  +7

                                                  Как гуглить? Копипастить букву Ü с голландских сайтов?

                                                    +3
                                                    На Linux: ctrl+shift+u, появится u, набрать dc и пробел. На Windows: alt+0220
                                                      +2

                                                      У меня укороченная клавиатура без нумпада. Так шо часть разработчиков оказывается за бортом )

                                                        +5

                                                        Афигеть какое удобное это "однобуквенное" название )

                                                          0
                                                          Заголовок спойлера

                                                          Зачем такие сложности? Compose+"+U же.


                                                          UPD: Я буду читать комментарии перед отправкой своего.

                                                          0
                                                          В голландском такой буквы нет, так что придётся копипастить с турецких.
                                                            0
                                                            Действительно в турецком алфавите есть такая буква :)
                                                            … А еще в азербайджанском.
                                                            0
                                                            X.Org: Compose-u-" (или Compose-"-u)
                                                              0

                                                              Ещё способ с включенной Compose Key: Compose,",U.

                                                                0
                                                                на маке option-u, появятся две точки сверху, а после этого u
                                                                üÜ
                                                                  0
                                                                  На маке на любой раскладке с латиницей просто держать долго U пока не появится выбор какой из вариантов ввести — Ü.
                                                                  +14
                                                                  Название данного языка — «Ü».

                                                                  Помнится, в книжке некого т-ща Кларка «Talk to the Snail» есть пассаж, удивительно подходящий к ситуации. Цитирую по памяти, так что могу ошибаться:
                                                                  «Собственно, само название языка — Français — с этим их крючком под буквой ç — намекает нам на причину, по которой французский никогда не станет языком мирового общения».

                                                                  Ӥ кстӓтӥ, кӓкӧё рӓсшӥрёнӥё бӱдёт ӱ ӥсхӧднӹх фӓйлӧв? :)
                                                                    0
                                                                    На счёт проблем с печатью на английской клавиатуре названия языка — да, есть такое. Но, пока что, особой проблемы я в этом не вижу, т. к. гуглить по этому языку пока что нечего.
                                                                    А когда (и если) язык станет хоть немного извесным, я убеждён, что можно будет каким-то способом эту проблему побороть.
                                                                    Ӥ кстӓтӥ, кӓкӧё рӓсшӥрёнӥё бӱдёт ӱ ӥсхӧднӹх фӓйлӧв?
                                                                    Сейчас используется "*.u". Но завязки на расширение в компиляторе нету, можно как угодно файлы именовать, компилятор их в любом случае попытается скомпилировать.
                                                                      +3

                                                                      Расширение по идее должно быть .ue. Это вроде стандартный способ портирования этого звука в английский. Например: Überauth — https://github.com/ueberauth/ueberauth

                                                                        0
                                                                        Это вообще не про английский. Это из свежих веяний в немецкой орфографии.
                                                                          +1
                                                                          Совсем не из свежих: наоборот, умлаут появился как сокращённая запись e.
                                                                        0
                                                                        Сделайте нормальное неоднобуквенное латинское название:) На самом деле и Си-то некоторое время назад не запросто гуглился.
                                                                          0
                                                                          Взять пример с Go. И назвать You
                                                                        +6
                                                                        Ü => u-'point'-'point' => .upp
                                                                        Сравним с C++ => .cpp

                                                                          +5
                                                                          upp — это u-plus-plus.
                                                                          А Ü — это u-dot-dot (.udd).
                                                                          Или вообще «u with diaeresis» — .uwd. Главное — не спутать с diarrhea. :)
                                                                            +3

                                                                            У дот дот — отлично, вот и название языка Удод. Или 2 удода.


                                                                            Кстати красивая птичка

                                                                            0

                                                                            .uyo

                                                                            +3
                                                                            Ӥ кстӓтӥ, кӓкӧё рӓсшӥрёнӥё бӱдёт ӱ ӥсхӧднӹх фӓйлӧв?

                                                                            Тут просто напрашивается вариант *.uuml.

                                                                              0
                                                                              Это немцам зайдет хорошо, остальным сложно будет запомнить
                                                                                0
                                                                                Немцам лучше зайдет .ue
                                                                                До меня только сейчас дошло, что .uuml — это «u — Umlaut», а не разновидность UML.
                                                                                  0
                                                                                  Вот-вот, именно умляут (понял что нужно было это пояснить дополнительно), поэтому и говорю что это только немцам зайдет потому-что остальные юзеры реально не поймут что за uml в расширении
                                                                              0

                                                                              Про lingua franca, естественно, автор не слыхал.

                                                                                +1
                                                                                panzerschrek@u:~/dev/u_samples$ ls
                                                                                hello_world..u i_hate..u
                                                                                +1
                                                                                Может проще название писать нажав только одну клавишу пробела?

                                                                                — Как в передать по значению?
                                                                                — А где взять для либу(обёртку) под gl?
                                                                                — Кто подскажет, что лучше учить первым C# или?
                                                                                  0
                                                                                  в смысле?
                                                                                    +2
                                                                                    название языка — пробел :)
                                                                                      0
                                                                                      Ну хоть не символ каретки ^H.
                                                                                  –1
                                                                                  И опять эти точки с запятой.
                                                                                  Причём непонятно, почему в этом случае они используются:
                                                                                  fn virtual pure Foo(this);

                                                                                  А в этом нет:
                                                                                  fn virtual Bar(this){}


                                                                                  почему нужно это дублирование конца строк? Неужели недостаточно символов CrLF, которые вставляет любой редактор по нажатию на Enter?
                                                                                    +3
                                                                                    Это разделители инструкций (statements). Если обходиться только концами строк, придется либо вводить ограничение «одна строка — одна инструкция», либо придумывать какой-то маркер переноса длинных инструкций на новую строку. В C перенос можно сделать где угодно, а в JavaScript и Python (языки без обязательных разделителей инструкций) уже другие правила.
                                                                                      –1
                                                                                      Очевидно, что случаев «одна строка — одна инструкция» намного больше, чем мешанина инструкций в одной строке, поэтому в исходном коде будет намного больше синтаксического мусора в виде точек с запятой.
                                                                                      Отдельный оператор‐разделитель инструкций в этом случае уберёт мусор в конце каждой строки.
                                                                                        0
                                                                                        В некоторых языках statements рассматриваются как выражения, возвращающие значение. В этом случае оператор «точка с запятой» становится чем-то вроде оператора «запятая» из С/С++, освобождая саму запятую для других целей.
                                                                                        +2

                                                                                        В Scala; нужно ставить только если вы хотите несколько выражений написать в пределах одной строки, а в остальном хватает просто переноса.

                                                                                          +4
                                                                                          опыт яваскрипта показывает, что такой подход порой порождает неоднозначности
                                                                                            +3
                                                                                            Только потому, что JS — слабо типизированный динамический язык. В Go точки с запятой тоже ставятся крайне редко — без каких-либо неоднозначностей.
                                                                                              +2
                                                                                              В Go их вообще их «ставит» компилятор поэтому никакой неоднозначности нет
                                                                                                +1
                                                                                                дело не в типизированности.
                                                                                                в js в некоторых случаях концом будет перенос строки.
                                                                                                несколько странно, как и многое другое в js
                                                                                                  +1

                                                                                                  Не поэтому. Типизированность языка никак не влияет на использование разделители) Нужно только понимать, является ли следующая строка выражением, продолжающее выражение в текущей.

                                                                                                  +1

                                                                                                  Опыт показывает, что неоднознасности больше порождает плохая структура решения, чем код без ;


                                                                                                  В js есть несколько правил, определяющий будет ли выражение перенесено на след строку в отсутствии ;. Учатся за полчаса.

                                                                                                    0
                                                                                                  0
                                                                                                  поразительно, уже 2019 год в завершающей фазе, а кому-то всерьез в языке программирования нужны
                                                                                                  — инструкции
                                                                                                  — возможность писать несколько инструкций в одной строке

                                                                                                  мир прекрасен и удивителен

                                                                                                  p.s. на всякий случай поясню: я считаю, что: 1. инструкций быть не должно, это лишнее, если есть выражения и функции; 2. запись несколько *инструкций* в одной строке ухудшает читаемость и понимаемость исходника. Но я тут мимо проходил, у меня уже есть свой «идеал языка программирования», а даже не один ;)))
                                                                                                    +1

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

                                                                                                      0
                                                                                                      Конечно, императивные языки доминируют, потому, что очень просто записать последовательности действий.

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

                                                                                                      На счет «переноса длинных строк», уж простите за моё старпёрство, но если у вас выражение больше 72 символов (да-да, очень стар по нынешним меркам, и на самом деле у меня во всяких линтерах правая граница строки 120 символов), то нет никаких проблем записать это выражение в виде двух, трёх, десяти. Сделать несколько функций, подумать еще пол часа, и «вообще не делать так длинно».

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

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

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

                                                                                                        Учитывая ваш богатый опыт, было бы странным предположить, что вы не видели функций, принимающих несколько аргументов. Имена этих функций могут быть достаточно длинными. Аргументов может быть больше, чем 3 и вообще эти функции могут оказаться частью API сторонней библиотеки. Да, вы правы, часто можно записать все в несколько отдельных строк. Но с моим неидеальным и многословным C++, не все удается вместить в 80-90 символов и перенос на следующую строку бывает неплохим компромиссом.

                                                                                                          0
                                                                                                          длинные функции с множеством аргументов?

                                                                                                              # например такие?
                                                                                                              very_long_named_python_func(
                                                                                                                  first_argument,
                                                                                                                  second_argument,
                                                                                                                  third=named_argument
                                                                                                              )
                                                                                                          
                                                                                                      0
                                                                                                      — возможность писать несколько инструкций в одной строке

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

                                                                                                      +1

                                                                                                      Мне в js нравится писать без ;


                                                                                                      К, сожалению, редко встречаешь людей кому это тоже нравится. Поэтому в команде пишу; и не жужу.


                                                                                                      Но это опциональность языка. Хочешь учи правила переноса и не ставь точкусзапятой. Хочешь не учи и не парься и так и так работает

                                                                                                        0
                                                                                                        Не обязательно. В Lua например можно делать переносы строк где угодно, без точек с запятой, и это не порождает неоднозначностей. Во многих языках реализовать такое нельзя из-за мешанины в операторах и statements, как например в C++, но в данном случае такой проблемы нет.
                                                                                                        0
                                                                                                        Первый случай — объявление функции, но без тела. pure функции не могут иметь тела.
                                                                                                        Второй случай — функция с пустым телом.
                                                                                                          +1
                                                                                                          Какая разница — есть тело у функции или нет, это же законченная конструкция кода, которая должна заканчиваться точкой с запятой.
                                                                                                            0

                                                                                                            Закрывающая скобка действует как точка с запятой. Из Rust:


                                                                                                            struct Empty;
                                                                                                            struct NotEmpty {
                                                                                                                field: String,
                                                                                                            }

                                                                                                            (с функциями в типажах также, но лень писать)

                                                                                                        0
                                                                                                        Мне почти все нравится. Предложу убрать ust::. В С++ это введено из-за наследия, классов с такими же именами как в std наделали до std, а у вас нет наследия, просто зарезервируйте побольше слов-названий, и пишите анонсы того что войдет из зарезервированного в понимаемое компилятором, если не все сразу делать (хотя можно классы-заглушки-пустышки).
                                                                                                        И, возможно, убрать auto, потому что чтобы понять программу, ее компилируешь в голове, и в этом известность результирующего типа нередко помогает.

                                                                                                        Имхо ваш язык отличный кандидат чтобы занят пустую нишу языка мощного (компилируемого в нативный код, без GC), простого (доступного новичкам и старичкам), поддерживающего ООП. С++ ушел из этой ниши и не так важно куда он идет, как занять то святое место, которое он оставил пустым. Именно на таком языке должны бы быть написаны и десктопные приложения типа офиса или CAD, именно на таком надо бы писать тем, кого государство могло бы нанимать для написания нужных ему программ, вовлекая в этот процесс широкие круги, примерно как в open source, но за зарплату и хостя самостоятельно.
                                                                                                          0
                                                                                                          Предложу убрать ust::
                                                                                                          Надо подумать, нет ли очевидных минусов у данного решения.
                                                                                                          убрать auto
                                                                                                          Совсем убрать нельзя, в шаблонах без него тяжело будет. Злоупотребление auto пока что останется на совести автора кода.
                                                                                                          С++ ушел из этой ниши и не так важно куда он идет, как занять то святое место, которое он оставил пустым
                                                                                                          Такого хотелось бы конечно, буду работать над этим.
                                                                                                            0
                                                                                                            Совсем убрать нельзя, в шаблонах без него тяжело будет. Злоупотребление auto пока что останется на совести автора кода.

                                                                                                            Вы заставляете пользователя вашего языка использовать его так как задумано, прямым путем, и одновременно ограждаете его ошибок где можете, одна система учета ссылок чего стоит. И это концептуально правильно, массовый язык должен защищать от ошибок. Имея это в виду, посмотрите что творится в шаблонах С++, как выглядит код ATL, насколько он удобен в использовании (не говоря о модификации развитии) не сильно искушенному в шаблонах программисту. Мало удобен, надеюсь, Вы знаете это. А многие идеи Александреску, прекрасно зашедшие в С++, и породившие использование системы типов для решения разных задач, но не создания экземпляров порожденных шаблонных типов в привычном для «С с классами» смысле. Не ищите такого использования шаблонов, массовый пользователь ЯП и метапрограммирование — вещи противолежащие. Простота ЯП, быстрота понимания его программ, это и защищенность от ошибок и эффективность работы на нем.
                                                                                                          –1
                                                                                                          в Ü есть проверка верности потока управления. При обнаружении недостижимого кода порождается ошибка

                                                                                                          Почему не предупреждение? Иногда в процессе отладки хотелось быстро влепить return в свежий метод, но Java отказывалась запускать код и приходилось городить «if (true) return;»
                                                                                                            0
                                                                                                            Предупреждений, пока что нету, только ошибки. Как мне кажется, лучше немного затруднить написание отладочных конструкций, чем оставлять лазейки безопасности.
                                                                                                            +1
                                                                                                            Почему выбор пал на обязательное использование оператора return вместо значения последнего выражения?
                                                                                                            Почему реализация на C++? Есть же более надежные языки, тот же Rust для компилятора подходит лучше.
                                                                                                              +6
                                                                                                              Чукча, всмысле автор, конечно не читатель, но я б все равно рекомендовал, прежде чем писать новый модный язык, ознакомиться с языками последних лет 40. Т.е это от лиспов, хаскелей и эрлангов до форта. И с концепциями, в них представленными. Потом много много подумать. И только потом что то писать, если это делать не расхочется.
                                                                                                                +6

                                                                                                                Почему Вы считаете отсутствие наследования структур в Rust "фатальной" ошибкой?

                                                                                                                  +1
                                                                                                                  Конкретно это не фатальная ошибка, но существенная потеря, в сравнении с другими языками, где наследование есть. В языках с наследованием довольно просто осуществляется динамическая диспетчеризация за счёт механизма виртуальных функций, в Rust же надо использовать Trait Object, что, как мне кажется, не совсем изящно.
                                                                                                                  +1
                                                                                                                  Почему Ü? Потому, что хотелось однобуквенного названия, а все буквы из набора A-Z уже заняты.

                                                                                                                  Может я плохо гуглил, но I, Y, P, G и др. не нашел.
                                                                                                                  C — слишком низкоуровневый и небезопасный

                                                                                                                  А почему это он небезопасный?

                                                                                                                  Panzerschrek, язык у вас назван немецкой буквой, ваш никнейм тоже на немецкий манер, подумал вы увлекаетесь немецким языком. Зашел в репозиторий на гитхаб а там в коммитах везде транслитом русские слова. Почему так?
                                                                                                                  UPD даже не латиницей(пример: Podderžka kortežej v parametrah signatury šablonov klassov i v parame…)
                                                                                                                    +1
                                                                                                                    Да, вы верно подметили, немецким языком увлекаюсь.
                                                                                                                    там в коммитах везде транслитом русские слова
                                                                                                                    Использую такое для личных целей. Нужно это затем, чтобы не переключать часто раскладку клавиатуры. Символы с диакритикой есть в моей раскладке клавиатуры, отчасти поэтому у меня не вызывает проблем напечатать название языка.
                                                                                                                      +1
                                                                                                                      Не хочу навязывать, но мне кажется если вы чем-то делитесь(как в данном случае) то все надо привести к единому виду понятному всем, иначе это тормозит популяризацию продукта.
                                                                                                                      Символы с диакритикой есть в моей раскладке клавиатуры

                                                                                                                      А у других может и не быть
                                                                                                                      +4

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


                                                                                                                      (субъективно) опасность подхода, когда всё есть выражение и возвращает результат

                                                                                                                      А в чем собственно опасность? Я вот 100 лет ждал возможность написать код в стиле


                                                                                                                      let result = if condition { DoExpensiveStuff(); 10 } else { 0 };

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


                                                                                                                      наличие явного указания соответствия протоколу

                                                                                                                      Это что за зверь?


                                                                                                                      отсутствие наследования

                                                                                                                      Мне казалось, даже гиганты от ООП вроде фаулера говорили "используйте композицию, а не наследование". От наследования реализации обычно больше проблем нежели достоинств.


                                                                                                                      Что касается вашего языка, то во-первых отсутствие ссылок немного смущает, немного смахивает на го, где в генерики можно только авторам языка, а остальным нельзя, а во-вторых странный выбор синтаксиса:


                                                                                                                      fn Foo( i32 x ) : i32

                                                                                                                      Тип то слева, то справа. Сравните с той же скалой:


                                                                                                                      def Foo(x: i32): i32

                                                                                                                      Намного чище и логичнее

                                                                                                                        0
                                                                                                                        Я вот 100 лет ждал возможность написать код в стиле
                                                                                                                        Читать такое бывает сложно.
                                                                                                                        Это что за зверь?
                                                                                                                        Ну это когда надо писать impl SomeTrait for SomeStruct{}. Мне больше нравится подход из C++ шаблонов — соответствие требованиям к типу определяются по необходимости, скажем, если вызвали std::sort, то будет использован operator<, и не обязательно наследовать тип от какого-нибудь Ordered.
                                                                                                                        От наследования реализации обычно больше проблем нежели достоинств
                                                                                                                        Действительно, можно перемудрить с наследованием. Но мне кажется, достоинства от наличия наследования всё же перекрывают недостатки от возможности его неправильно использовать.
                                                                                                                        отсутствие ссылок немного смущает
                                                                                                                        Ссылки есть. Нету ссылочных типов.
                                                                                                                        странный выбор синтаксиса
                                                                                                                        В начале разработки так и было, тип аргумента функции указывался после двоеточия. Но потом я пришёл к выводу, что двоиточие тут лишнее и не несёт особой смысловой нагрузки, а если двоеточие убрать, то логичнее будет указывать на первом месте тип аргумента, а имя на втором.

                                                                                                                          +2
                                                                                                                          если вызвали std::sort, то будет использован operator<
                                                                                                                          вот так просто будет взят и использован, без задней мысли? Отсортирует как-нибудь, как ему вздумается, а ты потом думай, почему так странно получается.
                                                                                                                          В остальном, вы пытаетесь сделать ещё один раст с кажущимися вам необходимыми фичами — уже проще форкнуть то, что есть. Также обратите внимание на /rfc/ и /issues/ раста — многое из того, что вам кажется очевидно-необходимым там так или иначе было отсеяно (очень многое было перед этим реализовано в nightly) как раз из-за возможной неоднозначности/небезопасности.
                                                                                                                            0
                                                                                                                            Читать такое бывает сложно.

                                                                                                                            Так альтернативы (если условное выражение не expression) заведомо сложнее.


                                                                                                                            Зачем, кстати, темплейты? Мы же в 2019 живем, а не в 80-х, уже давно все умеют нормальный параметрический полиморфизм.

                                                                                                                          0
                                                                                                                          Танкоужас, вроде есть еще свободные однобуквенные имена.
                                                                                                                            0

                                                                                                                            То есть в мире уже существует язык U?)
                                                                                                                            Спасибо, рванул гуглить)

                                                                                                                              +3
                                                                                                                              Зашел на github автора. Теперь понятно откуда такая любовь к букве Ü.
                                                                                                                              Test na ctenije kompilätorom putej s Junikodom.
                                                                                                                                0
                                                                                                                                Проверялся ли компилятор на больших проектах? Предполагается ли самокомпиляция?
                                                                                                                                  0
                                                                                                                                  Чтобы проверить компилятор на больших проектах, нужны большие проекты. Ну хотя бы какие-то проекты. Но таких пока нету.
                                                                                                                                  Самокомпиляции в ближайшее время не будет, т. к. во-первых, для этого надо переписать весь компилятор, а во-вторых, надо будет написать биндинги для llvm.
                                                                                                                                  +4
                                                                                                                                  А много тут нас таких, кто сейчас делает свой язык? Признавайтесь :)
                                                                                                                                  (Нужен бы опрос, но и отметиться неплохо)
                                                                                                                                    0
                                                                                                                                    Я уже давно чем-то подобным занимаюсь (правда не постоянно). Накопил огромный массив идей для своего языка, примерно половину структурировал, и параллельно понемногу изучаю исходники компилятора D, которые я взял за основу своего проекта, занимаюсь рефакторингом, написал загрузку синтаксического дерева в GUI, чтобы было удобнее смотреть, и пытаюсь подобраться к основной задаче — трансформации всего этого в то, что мне нужно.
                                                                                                                                      0
                                                                                                                                      GUI, чтобы было удобнее смотреть
                                                                                                                                      Можете показать?
                                                                                                                                        0
                                                                                                                                        Для совершенно простой программы на D, которая выглядит как-то так (ничего особенного, просто сделанное на скорую руку нагромождение синтаксических конструкций, единственное требование к которому — быть самодостаточным для компиляции, т.е. не требовать никаких зависимостей)
                                                                                                                                        Заголовок спойлера
                                                                                                                                        module Hello.World;
                                                                                                                                        
                                                                                                                                        this() 
                                                                                                                                        {
                                                                                                                                        }
                                                                                                                                        
                                                                                                                                        alias void *HANDLE;
                                                                                                                                        alias HANDLE HWND;
                                                                                                                                        alias char CHAR;
                                                                                                                                        alias const(CHAR)*  LPCCH, LPCSTR, PCCH, PCSTR;
                                                                                                                                        alias uint UINT;
                                                                                                                                        alias ushort WORD;
                                                                                                                                        
                                                                                                                                        version (Windows) {
                                                                                                                                        extern (Windows) {
                                                                                                                                        nothrow {
                                                                                                                                        @nogc
                                                                                                                                        {
                                                                                                                                        int MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
                                                                                                                                        }
                                                                                                                                        }}}
                                                                                                                                        
                                                                                                                                        struct Soo {
                                                                                                                                        	int x, y;
                                                                                                                                        };
                                                                                                                                        
                                                                                                                                        int foo(int x, int y)
                                                                                                                                        {
                                                                                                                                         return x+y;
                                                                                                                                        }
                                                                                                                                        
                                                                                                                                        int main()
                                                                                                                                        {
                                                                                                                                        	int i = 12Lu;
                                                                                                                                        	Soo s;
                                                                                                                                        	if(i>10) {
                                                                                                                                        		int j = i;
                                                                                                                                        		s.x = foo(50,50);
                                                                                                                                        	}
                                                                                                                                        	MessageBoxA(cast(void*)0, "test", "hello world", 0);
                                                                                                                                            return 0;
                                                                                                                                        }
                                                                                                                                        


                                                                                                                                        маленький кусок дерева выглядит вот так
                                                                                                                                        Заголовок спойлера


                                                                                                                                        На самом деле ничего особенного, просто я навесил самодельную рефлексию на все структуры синтаксического дерева, чтобы их можно было как-то смотреть в удобном виде.
                                                                                                                                      0
                                                                                                                                      Написал компилятор Паскаля; есть смутные помыслы превратить его в компилятор собственного более удобного паскалеподобного языка. Если затея получит развитие, буду использовать и критически переосмыслять идеи из C и Оберона. ООП не интересует.
                                                                                                                                        –1

                                                                                                                                        Кушать захочется — заинтересует :)

                                                                                                                                          +1
                                                                                                                                          По-моему, в наше время почти любой компилятор, написанный одиночкой, пишется для удовольствия, а не от голода. С другой стороны, язык C даёт пример того, как можно, не имея ООП, вот уже 40 лет неизменно оставаться в первой тройке языков.
                                                                                                                                        0

                                                                                                                                        Изучаю VHDL, так что делаю свой процессор…

                                                                                                                                          0
                                                                                                                                          Я для себя сделал на Go простой скриптовый язык — github.com/gentee/gentee.
                                                                                                                                            0
                                                                                                                                            Помнится, он был на Си. Зачем переписали?

                                                                                                                                            А я этот язык когда-то учил (наткнулся на интерпретатор на какой-то файлопомойке), это был мой первый си-подобный язык (си я тогда не осилил). Перестал заниматься, потому что проект мне показался заброшенным.
                                                                                                                                              0

                                                                                                                                              От того языка имя только сохранилось да похожий синтаксис. Этот заточен под написание скриптов — более простой и легкий.

                                                                                                                                            0

                                                                                                                                            С точки зрения ФП любая программа это свой язык + абстрактный интерпретатор :)

                                                                                                                                            0
                                                                                                                                            Биндинги для Godot будут?
                                                                                                                                              +2
                                                                                                                                              Придумать язык просто, сложнее описать его в виде грамматики и реализовать соответствующий компилятор. Да, даже если это и велосипед — это очень хорошая возможность понять как работает все изнутри, разобраться на совершенно другом уровне. Мой респект.
                                                                                                                                                –2
                                                                                                                                                C++ — по наследству получил много недостатков низкоуровневости, появились новые способы выстрелить себе в ногу, отсутствие рефлексии
                                                                                                                                                Вот бы жаловаться на язык, на котором написано почти всё, что в нем чего то не хватает для решения задач =) Появились новые способы, зато убралось гораздо больше старых…
                                                                                                                                                D — сборщик мусора, отдельные ссылочные типы
                                                                                                                                                Можно жить и без сборщика, но бедненько. Можно и без ссылочных типов (классов).
                                                                                                                                                Rust — необходимость явного взятия ссылок и явного их разыменования, (субъективно) опасность подхода, когда всё есть выражение и возвращает результат, наличие явного указания соответствия протоколу, отсутствие наследования
                                                                                                                                                Это совсем не главные проблемы Раста, и кстати разыменование ссылок там неявное
                                                                                                                                                Go — сборщик мусора, отсутствие шаблонов
                                                                                                                                                Шаблоны там и не нужны (м.б.нужны дженерики, ждем 2.0). Специально так сделано: простой язык — простые решения для энтерпрайза

                                                                                                                                                P.S. Чтобы понять, чего стоит язык, нужно сначала попробовать написать что-либо практическое, хотя бы после набора юниттестов стандартной библиотеки. На этом многие ломаются.
                                                                                                                                                  +1
                                                                                                                                                  Фундаментальные (и некоторые другие) типы требуют обязательной инициализации:

                                                                                                                                                  var i32 x= 22, y(12345);

                                                                                                                                                  А давайте провозгласим, что фундаментальные типы всегда инициализированы, но если мы просто пишем
                                                                                                                                                  var i32 x, y;
                                                                                                                                                  то переменные будут проинициализированы строго определенным значением по умолчанию (которое 0 для целых, false для булевских, пустая строка для строк и т.д). Удобнее же будет — инициализация каким-то конкретным значением нужна заметно реже чем нулем.
                                                                                                                                                    +1
                                                                                                                                                    Я тут исхожу из принципа, что все значения фундаментальных типов равозначны, а значит нельзя выбрать какое-то значения для умолчательной инициализации. Поэтому программисту явно надо указать, какое начальное значение ему нужно.
                                                                                                                                                    На счёт удобства — спорно. ак подсказывает мой опыт, чаще всего переменные объявляются сразу с инициализатором, где инициализатор это не просто какое-то число (вроде нуля) а значение сложного выражения, результат вызова функции и т. д. Случаи, когда мы объявляем переменную и только потом в неё что-то записываем редки, в основном это случай с аккумулятором для цикла.
                                                                                                                                                    +1
                                                                                                                                                    Зачем нужно было вводить ключевые слова fn и var? Вы хотели сделать паскалеподобный синтаксис, но постеснялись, и замаскировали его конструкциями из С? Если уж вводить ключевое слово var, то и тип переменной лучше указывать после имени, например:
                                                                                                                                                    var a: i32;

                                                                                                                                                    Сейчас в вашем языке всё вразнобой: объявления переменных начинается с типа, как в С, а тип возвращаемого значение функции указывается после, через двоеточие, как в Pascal.
                                                                                                                                                    Имена числовых типов зачем-то сделали трудночитаемыми — одна буква, намекающая на тип, и разрядность после. Чем вам не угодили простые и понятные char (byte), short, int, long, вместо i8, i16, i32, i64? Не понимаю этой тяги к минимизации и сокращению ключевых слов, в ущерб читаемости исходного текста.
                                                                                                                                                      +1
                                                                                                                                                      Уже где-то отвечали. Когда конструкция начинается с ключевого слова, парсить ее гораздо проще (нет неоднозначностей) и быстрее. Причем это касается не только компилятора, но и например среды разработки, в которой нужно «на лету» распарсить буфер редактора, раскрасить его, загрузить в разные деревья списки функций и классов и и т.д.

                                                                                                                                                      А объявления переменных кстати в таком формате («КлючевоеСлово Тип СписокОбъектов») лучше всего смотрятся. К тому же, в С++ есть например «const int x = 100», это ведь никого не смущает.

                                                                                                                                                      Имена числовых типов — наверное так однозначнее; ведь Си знаменит тем, что там int и char могут быть разных размеров для разных платформ. Хотя олдскульные имена типов тоже неплохи, если жестко задать им размерность в байтах.
                                                                                                                                                        0
                                                                                                                                                        А объявления переменных кстати в таком формате («КлючевоеСлово Тип СписокОбъектов») лучше всего смотрятся.
                                                                                                                                                        А объявление функций при этом в совершенно другом формате… Здесь так, а там этак. Язык не смотрится целостным.

                                                                                                                                                        Си знаменит тем, что там int и char могут быть разных размеров для разных платформ
                                                                                                                                                        Для Си это наследие прошлого. А вот к примеру в D типы (u)byte, (u)short, (u)int, и (u)long одинаковы для всех платформ, и читаются не в пример лучше чем что-то вроде «i16».
                                                                                                                                                        +1
                                                                                                                                                        Выше уже отметил, что тип пишется после var, чтобы можно было объявить несколько переменных с одним типом.
                                                                                                                                                        Тип возвращаемого значения после описания аргументов функции, как мне кажется, более логичен.
                                                                                                                                                        имена фундаментальных типов специально включают разрядность, для наглядности, чтобы не вспоминать, сколько там байт в каких-нибудь shot, long.
                                                                                                                                                          0

                                                                                                                                                          В nim можно объявить несколько переменных одного типа как
                                                                                                                                                          var a, b, c: int

                                                                                                                                                            +1

                                                                                                                                                            Основное преимущества написания типа "в конце" — возможность опустить его вообще, когда происходит вывод типов.

                                                                                                                                                              0
                                                                                                                                                              Здесь есть некий конфликт с объявлением параметров функций и полей структур — там обычно тип все равно в начале.
                                                                                                                                                              Можно конечно пойти по пути C/C++/C#/Java и просто принять, что если есть два идентификатора, разделенные пробелами — то первый это всегда тип, второй — объект. Но в этом случае нужно очень аккуратно подходить к синтаксису, чтобы не нагородить неоднозначностей.
                                                                                                                                                                +2
                                                                                                                                                                там обычно тип все равно в начале

                                                                                                                                                                Go — в конце, Rust — в конце, Pascal — в конце. Где именно "обычно" тип в начале?

                                                                                                                                                                  0
                                                                                                                                                                  Да, вы правы. Мне кажется, я где-то видел такой гибридный синтаксис, но совершенно не помню где. Добавлю, что Scala — в конце, Kotlin — в конце, Nemerle — в конце, Swift — в конце, Nim — в конце, Zig — в конце…
                                                                                                                                                                  +1
                                                                                                                                                                  Здесь есть некий конфликт с объявлением параметров функций и полей структур — там обычно тип все равно в начале.

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


                                                                                                                                                                  И да, один из самых мейнстрим языков с нотацией "в конце" — это тайпскрипт. И конечно же структуры там объявляются точно так же:


                                                                                                                                                                  class Greeter {
                                                                                                                                                                      greeting: string;
                                                                                                                                                                      constructor(message: string) {
                                                                                                                                                                          this.greeting = message;
                                                                                                                                                                      }
                                                                                                                                                                      greet() {
                                                                                                                                                                          return "Hello, " + this.greeting;
                                                                                                                                                                      }
                                                                                                                                                                  }
                                                                                                                                                                    0
                                                                                                                                                                    Спасибо! Там у них и про баг с более низким приоритетом битовых операторов относительно операторов сравнения написано!
                                                                                                                                                                    0
                                                                                                                                                                    Можно конечно пойти по пути C/C++/C#/Java и просто принять, что если есть два идентификатора, разделенные пробелами — то первый это всегда тип, второй — объект.

                                                                                                                                                                    В C/C++ всё далеко не так просто: a * b; — это операция умножения, или объявление переменной-указателя?
                                                                                                                                                                    На этапе синтаксического разбора это определить невозможно.
                                                                                                                                                                +2

                                                                                                                                                                В приведенных вами "простых и понятных" типах char (byte) — знаковый или беззнаковый? А какую разрядность имеет long? Мне всегда казалось, что различные системы типов решают различные задачи.


                                                                                                                                                                Например, при реализации низкоуровневых примитивов очень важно, чтобы некоторые переменные были именно беззнаковыми 32-разрядными (uint32_t), другие, например, беззнаковыми 64-разрядными (uint64_t), а третьи — тоже беззнаковыми, но неопределенной разрядности (size_t). Код, который эти переменные использует, может, например, рассчитывать на конкретное поведение в случае переполнения (wrapping underflow/overflow).


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


                                                                                                                                                                Поэтому, опять же, на мой взгляд, в удобном и при этом универсальном языке программирования окажутся и те, и другие типы. При этом я совсем не против забирать определения более специфичных типов из отдельных заголовочных файлов (модулей, пакетов, etc.), но совсем выкидывать их из языка мне кажется неправильным.

                                                                                                                                                                  0
                                                                                                                                                                  А ведь можно было бы вообще взять буквы из алгебры:
                                                                                                                                                                  N — натуральные (без знаковые)
                                                                                                                                                                  Z — знаковые
                                                                                                                                                                  Q — с плавающей запятой
                                                                                                                                                                  N16bit, Z32bit… Но программисты не любят в алгебру…
                                                                                                                                                                  И почему так мало языков вводят возможность определять числа большие чем 256 bit? Q64Kbit
                                                                                                                                                                    +1

                                                                                                                                                                    Q — рациональные числа, IEEE 754 ассоциировать с каким-то алгебраическим множеством неразумно.


                                                                                                                                                                    И почему так мало языков вводят возможность определять числа большие чем 256 bit? Q64Kbit

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

                                                                                                                                                                      0
                                                                                                                                                                      Я считаю что создание литералов длинных чисел должно поддерживаться в языке. А уж как их использовать — это вопрос библиотек.
                                                                                                                                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                                                                                  +1

                                                                                                                                                                  Чем V не подошел?

                                                                                                                                                                    +1

                                                                                                                                                                    "Java — сборщик мусора, все композитные типы ссылочные, сильная завязанность на виртуальную машину. Многое и этого применимо и к языках на основе JVM."


                                                                                                                                                                    Здесь перечислены достоинства, а не недостатки

                                                                                                                                                                      0

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

                                                                                                                                                                        0
                                                                                                                                                                        Очевидно, что halt надо использовать в крайнем случае, а в библиотечном коде так вообще, стараться воздерживаться от его использования.
                                                                                                                                                                        С исключениями в C++ проблема схожая тоже присутствует, все вызовы к сторонним библиотекам в try-catch мало кто заворачивает, а значит, если оттуда прилетит исключение, его могут и не поймать, что закончится std::abot.
                                                                                                                                                                          0

                                                                                                                                                                          Нет, его просто не надо использовать. Использование таких вещей — признак плохого дизайна. Это ещё хуже, чем исключения

                                                                                                                                                                        0
                                                                                                                                                                        А какими фатальными недостатками обладает язык ADA с точки зрения автора статьи?

                                                                                                                                                                          0
                                                                                                                                                                          С языком ADA я не знаком. Предположу, что в виду его древности в нём нету ряда концепций, считающихся сейчас строго необходимыми.
                                                                                                                                                                        +1
                                                                                                                                                                        Конечно, удачи автору в создании языка программирования. Не совсем ясно по мотивации… но не важно («выстрелить себе в ногу» теоретически можно на любом языке — даже на «Ü»). Однако я не уверен, что возможно одному человеку под силу реализовать такой проект, что бы он при этом отвечал всем современным требованиям. Сам иногда делаю синтаксические анализаторы по данному описанию грамматики на C/C++ — для приложений — вроде иногда это нужно заказчику для специфических задач. Но я рассуждаю с точки зрения обычного человека (не обладающего уникальными способностями), поэтому в мире наверное все возможно.
                                                                                                                                                                          0
                                                                                                                                                                          www.e-reading.club/chapter.php/1002058/30/Mayers_-_Effektivnoe_ispolzovanie_CPP.html

                                                                                                                                                                          Здесь один из примеров скрытых особенностей языка, которые по-хорошему должен знать каждый программист — пользователь языка, но мало в какой книжке по языку о подобном пишут, и обычно из таких особенностей получаются грабли, которые рано или поздно проявляются. И сам факт наличия таких граблей говорит о плохой реализации языка. В плюсах таких моментов слишком много. И других языков, с усложнениями всех видов, много, поэтому актуальна потребность в простом языке, но эффективном.
                                                                                                                                                                          И вообще неправильно это, создавать скрытую особенность языка, замаскированные грабли, потому что не удается сделать нормальную реализацию. Надо добиваться нормальной реализации сразу, и всячески избегать замаскированных граблей. Чтобы программист при переносе объектной модели в язык программирования не получал мин замедленного действия, на которых подорвутся пользователи.
                                                                                                                                                                            –3
                                                                                                                                                                            Возможности развития текстовых языков приближаются к своему пределу. Пора программировать в графике. Я сейчас работаю над прототипом графической среды программирования Metaprog.

                                                                                                                                                                            Подробности и ссылка на скачивание здесь. Это всего лишь прототип, но он должен быть интересен тем, кого интересует новый этап развития языков программирования.
                                                                                                                                                                              +3
                                                                                                                                                                              Весьма неосторожные заявления.
                                                                                                                                                                              • В чём заключается «предел развития» текстовых языков?
                                                                                                                                                                              • Чем «новый этап развития» отличается от заявленной ещё в 70-е годы концепции «языков программирования четвёртого поколения», давшей нам Matlab/Simulink и LabView, но не заменившей текстовых языков?
                                                                                                                                                                              • Функция трансляции схемы в код на C издавна была в Simulink. Чем отличается ваш подход?
                                                                                                                                                                              • Где вообще спецификация вашего языка? Или языка и вовсе нет, а есть только трансляция в C один к одному?

                                                                                                                                                                                +1

                                                                                                                                                                                Автор назвал язык в честь самого себя — как по мне, это уже достаточная характеристика для языка :)

                                                                                                                                                                                  +4
                                                                                                                                                                                  Будем полагать, что он себя назвал в честь языка :)
                                                                                                                                                                                    +1
                                                                                                                                                                                    Я взял ник в честь своей среды программирования.
                                                                                                                                                                                    +5

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

                                                                                                                                                                                      0
                                                                                                                                                                                      Да не, это ИИ притворяется человеком.
                                                                                                                                                                                    –2
                                                                                                                                                                                    В чём заключается «предел развития» текстовых языков?
                                                                                                                                                                                    Низкоуровневые сложны (как Си), а высокоуровневые тоже непростые в обучении и требут толстых рантаймов. Мое разочарование в софте. Софте, написанном на текстовых языках.
                                                                                                                                                                                    Чем «новый этап развития» отличается от заявленной ещё в 70-е годы концепции «языков программирования четвёртого поколения», давшей нам Matlab/Simulink и LabView, но не заменившей текстовых языков?
                                                                                                                                                                                    Тем, что код не пишешь, а собираешь из боков и соединяешь проводками. По этой теме уже есть LabVIEW, но область его применения очень ограниченная, не говоря уже о том, что оно пропиетарное, с закрытым кодом и дорогой лицензией. Метапрог будет опенсорсным и, самое главное, он претендует на универсальность. Он может все, что может Си. Кстати, прототип уже опенорсный, правда пока что требует Лабвью для запуска и просмотра кода (но это временно).
                                                                                                                                                                                    Функция трансляции схемы в код на C издавна была в Функция трансляции схемы в код на C издавна была в Simulink. Чем отличается ваш подход?.. Чем отличается ваш подход?
                                                                                                                                                                                    Тем, что Метапрог универсальный. Можно делать низкоуровщину сишного уровня, используя функции Си и вставки сишного кода, оперировать указателями. В графике, а не тексте. И Метапрог опенсорсный, в отличие от Simulink.
                                                                                                                                                                                    Где вообще спецификация вашего языка?
                                                                                                                                                                                    Метапрог пока существует только в виде LabVIEW-прототипа и еще не устаканен окончательно. И это не обычный текстовый язык, который можно запросто описать текстовыми спецификациями. Основная часть работы с Метапрогом — в графическом интерфейсе, как в компьютерной игре. Где вы выдели игры с отдельно лежащими интсрукциями/спецификациями? Я могу вспомнить только Герои 3, в большей части игр есть встроенная обучалка. И в прототип Метапрога я тоже встроил интерактивную обучалку и справочную систему, а если этого мало — можно консультироваться со мной в личке или «Метапрог онлайн».
                                                                                                                                                                                      +1
                                                                                                                                                                                      • Совершенно непонятно, чем ваш язык должен быть проще, если в нём должны быть как минимум те же возможности, что и в текстовых языках. Программу вычисления факториала на Питоне или Паскале поймёт даже тот, кто почти не программировал. Вашу программу я не понимаю.
                                                                                                                                                                                      • В Simulink схема точно так же рисуется, как и у вас. Если речь о деньгах, то аналогичный редактор схем есть в бесплатном SciLab. Про возможности LabView судить не возьмусь.
                                                                                                                                                                                      • Язык программирования — это не игра, и публикация почти любого нового языка — это публикация его спецификации. Без неё я не понимаю даже того, существует ли вообще некий ваш язык, или есть только трансляция схемы в C. Мне всё больше кажется, что нам просто предлагается «C в картинках».
                                                                                                                                                                                        –1
                                                                                                                                                                                        Программу вычисления факториала на Питоне или Паскале поймёт даже тот, кто почти не программировал. Вашу программу я не понимаю
                                                                                                                                                                                        Даже не знающий слово «for»? Есть входы и выходы цикла и жесткие последовательности. Пожалуй, кое в чем вы правы: когда напишу пост о Метапроге, наделаю скринов с описаниями базовых элементов диаграмм.
                                                                                                                                                                                        аналогичный редактор схем есть в бесплатном SciLab
                                                                                                                                                                                        Он не текстовый?
                                                                                                                                                                                        Мне всё больше кажется, что нам просто предлагается «C в картинках».
                                                                                                                                                                                        Си с графическими плюшками.
                                                                                                                                                                                          +2
                                                                                                                                                                                          Даже не знающий слово «for»?
                                                                                                                                                                                          Сейчас трудно оставаться таким отшельником, чтобы совсем не видеть английского языка (кстати, слово for было чуть ли не первым английским словом, которое я узнал). А вот разноцветные квадратики с редкими подписями по-украински мне мало что объясняют.
                                                                                                                                                                                          Он не текстовый?
                                                                                                                                                                                          Редактор схем — разумеется, графический. Он задумывался как бесплатная альтернатива Simulink.

                                                                                                                                                                                          А вообще, посмотрите Википедию. Там обширнейший список визуальных языков программирования. Если соберётесь писать пост, вам придётся объяснять, чем ваш проект отличается от всех перечисленных. И конечно, советую воздержаться от громких слов о «пределе развития» и «новом этапе».
                                                                                                                                                                                            –1
                                                                                                                                                                                            А вообще, посмотрите Википедию. Там обширнейший список визуальных языков программирования.

                                                                                                                                                                                            Есть ли из них хоть один, на котором можно, скажем, делать и декстопный софт, и мобильный софт, и ядра ОС под х86 и ARM, и прошивки на микроконтроллеры (любые, а не только фирменные)? Википедия меня встретила скрином со Scratch — это все равно, что если б в статье со списком текстовых языков программирования первым примером показать Brainfuck.
                                                                                                                                                                                            Лучшее из того что я знаю — это LabVIEW. Оно, опять же, весьма ограниченное по возможностям и сфере применения, но все же позволило мне сделать прототип Метапрога, не обращаясь к текстовым языкам. Все что вы видите на видео (интерфейс, работа с диаграммами, сетевой функционал) сделано исключительно из графических схем. Си там — только сущность, которой оперирует транслятор, на самом Си я почти ничего не писал.
                                                                                                                                                                                            разноцветные квадратики с редкими подписями по-украински мне мало что объясняют.
                                                                                                                                                                                            Примерно так же не-программист (особенно не знающий английский) видит текстовый код. Когда напишу пост про Метапрог — постараюсь сделать понятные скрины с базовыми элементами. А насчет украинского — так есть русская локализация, даже на видео видно.
                                                                                                                                                                                              +1
                                                                                                                                                                                              Насколько я понимаю, генерация кода под разные платформы — это в любом случае не ваша заслуга, а создателей компилятора C. Так что вопрос придётся переформулировать: «Есть ли языки с поддержкой трансляции схем в C?». Есть. Simulink — точно, насчёт остальных предоставляю выяснять вам (я не знаток визуальных языков и говорю только о том, с чем работал). В общем, перед вами непростая задача доказать ценность вашего проекта, если будете готовить пост.
                                                                                                                                                                                                –1
                                                                                                                                                                                                «Есть ли языки с поддержкой трансляции схем в C?». Есть. Simulink — точно, насчёт остальных предоставляю выяснять вам
                                                                                                                                                                                                И импорт сишных функций, и работа с указателями тоже? Насколько я знаю, ничего лучше Лабвью нет.
                                                                                                                                                                                                генерация кода под разные платформы — это в любом случае не ваша заслуга, а создателей компилятора C
                                                                                                                                                                                                Так кто же спорит? Или у вас стоит цель потешить собственное ЧСВ, принизив мои заслуги? Моя заслуга в том, что я выбрал Си, как наиболее кроссплатформенный и при этом низкоуровневый язык, имеющий кучу готовых библиотек. И сделал реально работающий прототип Метапрога на Лабвью. И даже выложил его код для всех желающих ознакомиться с ним. Если хотите — могу попробовать и в ехешник скомпилировать (правда стабильность не гарантирую, прототип как-никак:)).
                                                                                                                                                                                                  +1
                                                                                                                                                                                                  В общем, напишите обстоятельный пост и объясните нам, в чём реально состоят ваши заслуги. Пока это непонятно.
                                                                                                                                                                                            +1
                                                                                                                                                                                            Если вам так хочется почитать мотивацию автора, можете ознакомиться с его постами на ЛОРе и комментами там же) Боюсь, вы слишком оптимистичны.
                                                                                                                                                                                              –2
                                                                                                                                                                                              ЛОР — тот еще обезьянник. Там обливают говном даже успешно работающий много лет софт (например, systemd, реально ускоряющий загрузку системы). Что уж говорить о прототипе новой визуальной среды программирования?
                                                                                                                                                                                                +1
                                                                                                                                                                                                Эм, что? О_о. Я предложил комментатору если уж не терпится, ознакомиться с ВАШИМИ постами и ВАШИМИ комментариями (вообще максимально тактично не упоминая про обсёр вас, с которым, кхм, я даже местами согласен, простите). Чего уж вы завелись про облив говна, я хз.
                                                                                                                                                                                                Про умерить оптимизм — я вот именно попытался охладить пыл, что там еще нечего сравнивать со зрелыми продуктами, это именно прототип и относиться надо соответствующе.
                                                                                                                                                                                                  –4
                                                                                                                                                                                                  Прототип есть прототип. Хорошо что вы это понимаете, в отличие от немалой части тамошней публики (с которой мне порой приходится общаться в соответствующей манере). Но к чему тут пессимизм? Разработка идет, еще полгода назад я только мечтать мог о том, что прототип уже умеет. Впереди еще очень много работы, и мне, кстати, не помешали бы желающие присоединиться к опенсорсному проекту.