(Upd. Статья не рекомендована к прочтению, т.к. содержит огромное количество неточностей, является частью большого материала, содержит сугубо личные размышления автора)
Впервые я познакомился с программированием в 6 классе… Тогда это был старинный компилятор borland pascal, который мог запускаться только с помощью эмулирования MS-DOS. С тех пор прошло 6 лет… Маленький мальчик вырос и стал писать более читаемый код, а судьба привела его в один из лучших технических вузов страны. Но те 6 лет не прошли даром. В течение них накапливался огромный пласт противоречий, которые заставляли его искать все более и более совершенный язык… Так появился на свет Ctag — продукт переосмысления достижений человечества.

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

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

  1. С/C++
  2. Java и C#
  3. Python
  4. JavaScript

Теперь разберем подробнее каждый из языков.

Языки С/C++ были разработаны еще в доисторические времена (1970-80 года), но и сегодня их продолжают использовать для реализации высоко производительных систем, потому что их код легко компилируется в код ассемблера без существенной потери производительности. Java и С# являются очень устойчивыми языками по отношению к окружающим их средам. Python радует своей простотой и удобностью при написании кода (хотя, честно сказать, это мой самый нелюбимый язык программирования). Ну и наконец, JavaScript очень удобный язык для реализации работы в браузере (хотя работа с canvas марока еще та...)).

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

  1. Быстродействие
  2. Отказоустойчивость
  3. Удобство
  4. Простота базового освоения
  5. Кроссплатформенность

Также еще желательно:

  • ООП
  • Функциональное программирование
  • Единство работы в разных средах (браузер, ПК, мобильное приложение)
  • Сохранение работоспособности кода для более новых версий языка

Что ж, приступаем к разработке.

Первое, с чего хочется начать мой рассказ — это кроссплатформенность. Наверно не для кого не секрет, что Java и JavaScript компилируются в байт код, а промежуточной стадией работы компилятора/интерпретатора для других языков является ассемблер. В любом случае, если вы пытаетесь сделать кроссплатформенный язык, то у него должна быть стадия компиляции, код в которой максимально приближен к машинному языку, но при этом сохраняет еще свою однообразность для разных платформ. Остается только выбрать между ассемблером и машинным байт кодом. Думаю, что тут будет приоритетнее выбрать язык ассемблера синтаксиса AT&T(см. эту статью) для дальнейшего удобства. Но и его мы немного отредактируем также под однородный стиль, получив таким образом язык у которого стилистика команд будет примерно такой:

(знаковая/беззнаковая) ; команда ; (использующиеся флаги) ; размерность операндов ; операнд 1; операнд 2; ...

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

Глава 1. Привет Мир.


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

Итак, напишем типичную первую программу:

#import print from stdio
function main() -> int(4){
	print("hello world");
	return 0;
}

Странная помесь, которую я пока откажусь комментировать. Примите на веру).

Глава 2. Переменные.


Тут наступает время новых откровений. Дело в том, что Сtag по примеру С# является языком двойной типизации, т.е. позволяет как статические переменные, так и динамические. Всего в языке существует более 10 базовых типов:

1) nil
2) int
3) double
4) register
5) char
6) string
7) function
8) code
9) operator
10) statment
11) bool
11) object

А также еще несколько стандартных типов, как array, set, map,… подключаемые через библиотеки. Теперь подробнее про каждый тип:

1) nil или пустой тип. По умолчанию присваивается любой переменной при объявлении. Также может быть вернут любой функцией как признак ошибки.

int a; print(a) //nil
function f() -> int(4) {return nil;} //не ошибка

2) int. Стандартный тип для работы с целыми числами. Существует две формы объявления:

  • Статическая с параметром — размер.
  • Динамическая.

Если в качестве параметра статического объявления стоит небольшое число(<=8), то «класс» заменяется более дешевым в плане операций эквивалентом. (вы не можете объявить переменную размера <8 не являющегося степенью 2).

int(4) a; //equal to int in C++
int(128) b; //static type int
int c; //dynamic type int

4) register. Специальный тип предназначенный для переменных с большим количеством обращений. Если в качестве имени переменной будет указано настоящее имя одного из регистров, то компилятор попытается выделить вам его. В другом случае компилятор попытается найти место наиболее близкое по скорости к регистровой памяти (регистр или кеш 1 уровня). Имеет один параметр определяющий размер регистра. По умолчанию выбирается наибольшее доступное значение.

register a; //give me some register
register ax; //give me ax
register bx; //give me rbx

5) char. Тип для хранения символа. Имеет один параметр строкового типа, который определяет кодировку символа (ASCII = 1 байт, utf-16 = 2 байта, utf-32 = 4, utf-8 = 4 всегда, для удобства индексации). По умолчанию выбирается utf-8.

char c; //the same to char(utf-8) c; sizeof(c) = 4!!!!
char(ASCII) ch;

6) string. Базовый тип, производный от char. Имеет два параметра. Первый — кодировка. Второй — размер. Оба параметра необязательны. Если не указан второй, то строка считается динамической.

string s1; //charset = utf-8; dynamic string
string(ASCII) s2; //dynamic string of ASCII characters
string(ASCII, 80) buf; //standart C string

7) function. Базовый тип для задания функций. Существуют два объекта данного типа: сырая функция и скомпилированная. Все используемые в программе функции получают этот тип. Без специальных событий не является компилируемым объектом.

function hello;
hello.code = {print("hello world");}
hello.lock() //we can't do anything  with this function in future
hello.compile() //compile function(can't make this without lock) 
hello.run() //it runs faster than without lock

8) code. Базовый тип реализующий сырой код. Является некомпилируемым объектом, если объявлен без спецификатора const. Смысл это типа будет показан в дальнейшем.

code a = {print(x);} //could not compile
const code b = {print(x);} //could compile
fuction print_var(int x) -> nil {b;}

9) operator. Базовый тип способный подменять разные операторы. Вокруг оператора обязательны пробельные символы.

operator op = "<";
if (a op b) ...

10) statment или выражение. Базовый тип призванный скрывать вычисление выражения. Входные данные — любые переменные. Выходной тип — bool.

statment s = (a < b);
int a =10;
int b = 15;
if (s) ...

11) object. Тип предназначенный для динамической типизации. Имеет другой способ объявления — ключевое слово var.

#import readint from stdio
#import print from stdio
function main() -> int(4){
	var a, b;
	a = readint();
	b = readint();
	print(a + b);
}

Ключевые слова и переменные


С помощью нескольких ключевых слов можно изменять видимость переменных. Их всего 3:

  1. global
  2. local
  3. const

1) Ключевое слово global используется для расширения области видимости переменной. Если переменная объявляется внутри функции, то делает ее глобальной переменной. Вне кода функций делает переменную полностью глобальной.

2) Ключевое слово local используется для сужения области видимости переменной. Если переменная объявляется внутри функции, то не взымает воздействия. Примененное к внешним переменным, сужает их область видимости до текущего файла.

Теперь я хотел бы закончить эту статью. Продолжение следует…
Поделиться с друзьями
-->

Комментарии (236)


  1. artemonster
    18.01.2017 14:38
    +6

    Ой… ещё один :D
    Весь мир бежит от nullptr, а вы его добавляете. В чем разница между code & statEment? В чем разница между оператором и функцией?
    Городите велосипед какой-то, да ещё и фу какой :)


    1. int33h
      18.01.2017 20:25

      В изначальных планах, когда задумывался этот язык было сделать его так, чтобы на нем можно было написать хоть Python, хоть С. Т.е. реализовать минимальный набор конструкций языка, чтобы с помощью asm кода и этих инструментов можно было «запрограммировать» парсер кода на добавление новых, других конструкций языка. Но пока я еще очень слабо знаком с разработкой компиляторов, поэтому гарантировать это не могу.


  1. vlreshet
    18.01.2017 14:39
    +5

    ИМХО, пока для языка нет даже компилятора (интерпретатора) — показывать его кому-то нет смысла. Разработать синтаксис может даже школьник, но вся соль в том как потом этот синтаксис потом будет обработан, и во что скомпилирован. Толку от такой вашей «разработки»?


    1. int33h
      18.01.2017 20:29
      +1

      Я хочу понять:
      1)Есть ли язык, который по качеству сравним с моим предложением.
      2)Интерес народа к этому языку.
      3)Возможных помощников и помощь в освоении требуемых инструментах.
      Я безусловно задумываюсь над основными вводимыми символами и способом их реализации, иначе я бы тоже понимал бессмысленность этого языка.


      1. deep_orange
        18.01.2017 23:49
        -1

        Синтаксис — это последнее. Система пакетов, система сборки и конечно же стандартная библиотека. А компилятор с помощью LLVM- или GCC-backend не так уж и сложен. Во всяком случае, гораздо легче чем без.


        Какой смысл от языка, если нет норм. стандартной библиотеки. Питон рулит тем, что http://xkcd.ru/353/


        1. int33h
          19.01.2017 00:29
          +1

          Чтобы это все писать нужно сначала понять нет ли критических ошибок в базовом синтаксисе(безусловно, текущая версия языка еще нуждается в качественной доработке). А питон меня немного подбешивает каждый раз, когда я сажусь писать на нем код. Единственное для чего я его пока использую, так это для работы со строками, которая там очень хорошая. Но в нем есть и много хорошего, и не допустить 20 ошибок в 10 строчках я не могу…


          1. DarkEld3r
            19.01.2017 13:56
            +1

            Чтобы это все писать нужно сначала понять нет ли критических ошибок в базовом синтаксисе

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


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


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


            1. int33h
              19.01.2017 14:45

              В планах борьба с С/C++ по читаемости и удобству(но не размеру) написания, с Python по скорости… Возможно будет еще добавлены какие-нибудь языки в этот список.


  1. claygod
    18.01.2017 14:41
    +5

    Неужели из кучи языков программирования Вам ничего не подошло?


    1. leremin
      18.01.2017 15:31
      -2

      Само наличие этой кучи разве не говорит, что постоянно что-то кому-то не нравится и он начинает создавать новый ЯП?


    1. int33h
      18.01.2017 20:32
      -2

      Да, я читал эту статью и ни в одном языке, кроме совсем старых не нашел прямой компиляции в ассемблерный код. Везде в качестве основы берется С. А насчет Java, достоверно не знаю как она компилирует, но мне кажется что тоже через С. А это большая проблема для max оптимизации.


      1. Googolplex
        18.01.2017 22:10
        +2

        Большинство популярных реализаций JVM используют just-in-time-компиляцию, когда программа из байт-кода преобразуется в нативный код во время выполнения.


      1. Googolplex
        18.01.2017 22:11
        +2

        ни в одном языке, кроме совсем старых не нашел прямой компиляции в ассемблерный код

        Эм. Rust, Go, Swift, Haskell? Да любой язык, который использует LLVM, компилирутся в нативный код.


        1. int33h
          18.01.2017 22:18
          -1

          Через промежуточную стадию — язык С.(насчет Haskell не знаю)


          1. Googolplex
            18.01.2017 22:28
            +3

            Через промежуточную стадию — язык С

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


            1. int33h
              18.01.2017 22:38

              Интересно. Наверно где-то неправильный материал нашел/прочитал. Хорошо посмотрю LLVM в дальнейшем.


      1. DarkEld3r
        19.01.2017 14:00
        +1

        но мне кажется что тоже через С. А это большая проблема для max оптимизации.

        Зато это сильно увеличивает число платформ под которые можно использовать язык. Ну и касательно оптимизаций: есть сомнения, что язык с обилием "динамических фич" будет ставить рекорды.


        1. int33h
          19.01.2017 14:52

          Ускорение выполнения гарантируется только на компилируемую часть кода. Понятно что динамичекские фишки сильно не прооптимизируешь, поэтому там язык будет работать, наверно, сравнимо с Python…
          Отказаться от С я хочу в угоду таких технологий как SSE,… которые в С/C++ не могут быть реализованы напрямую без либо стандартной библиотеки intel со странным синтаксисом, либо asm вставок, которые тоже не так уж и просто добавлять.
          Переход на уровень ниже к ассемблеру позволит во многих случаях улучшить состояние работы с этими технологиями(обратите внимание, что я указываю на свой ассемблер, который потом трансляцией переводится в нормальный ассемблер/машинный код)


          1. lair
            19.01.2017 14:56

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

            MSIL?


            1. int33h
              19.01.2017 15:18

              Нет. Это не то. Предполагается машинно-удобно-читаемый язык, с жесткими(очень правилами) написания команд. Например:
              add cf $4 ax, bx

              складывает два регистра eax и ebx с учетом флага переноса.(adc) А
              add $8 ax, bx

              складывает уже два регистра rax и rbx теперь уже без учета флага.(простая add)
              Вот так вот… Код не сильно различается для моего языка, зато очень сильно разниться в итоговом коде.


              1. lair
                19.01.2017 15:28
                +1

                … и как это поможет оптимизации? Зачем для этого ассемблер? Зачем для этого "очень жесткие" правила написания команд?


                1. int33h
                  19.01.2017 16:05
                  -1

                  Ассемблер самый быстрый язык => на него мы должны пытаться компилировать(экв. байт кода). Потом когда мы запускаем скомпилированное приложение на специальном трансляторе, этот код переводится в код на машине с учетом ее «комплектации». Это скорее для расширяемости языка в дальнейшем(ведь аппаратура не стоит на месте и вместительность регистров тоже увеличивается. (Хотя хороший вопрос надо будет подумать...)


                  1. lair
                    19.01.2017 16:09
                    +1

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


                    1. int33h
                      19.01.2017 16:35

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


                      1. lair
                        19.01.2017 16:43

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

                        А мне кажется, что MSIL удобнее и понятнее.


                        Но, что важнее, зачем новичку вообще туда лазить?


                        1. int33h
                          19.01.2017 16:53

                          Да уж, хороший вопрос… Новичку наверное незачем, но рано или поздно придется.


                          1. lair
                            19.01.2017 16:58

                            Возможно, когда придется, он уже не будет новичком. Ну и да, если мы говорим о чтении кода, надо делать читаемый язык. А вы зачем-то начали с "Ассемблер самый быстрый язык => на него мы должны пытаться компилировать". Разные посылки совершенно.


                            1. int33h
                              19.01.2017 17:07

                              Бывает. Я просто не ожидал, что разразится такая дискуссия по поводу моего поста…


  1. c4boomb
    18.01.2017 14:48
    +3

    1) register глупо называть типом, лучше сделать это ключевым словом которое помещает переменную в регистры процессора
    2) из-за типов code/function прийдется таскать с собой компилятор повсюду

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

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

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


    1. int33h
      18.01.2017 20:37

      1)Да, скорее всего register лучше брать как ключевое слово.
      2)Правило языка очень простое: Если ты можешь полностью скомпилировать код, то ты его можешь собрать в объектный файл и т.д. Если же ты хочешь писать что-нибудь наподобие этого:
      string s;
      read(s);
      in.(#s) //вызов метода класса по переданной строке

      То тут уже ничего не поделаешь.


  1. devpony
    18.01.2017 14:50
    +2

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


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


    1. BelBES
      18.01.2017 15:11

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

      А что это такое? Ну т.е. я видел какие-то упоминания этого термина от ребят из DeepMind, но они внятно н могли объяснить, что же это такое и зачем нужно...


      1. devpony
        18.01.2017 15:16

        Это как tensorflow, только с возможностью рассуждать о графе с позиции типов: доказывать корректность, дифферинцируемость функций, производить оптимизации, распараллеливание и прочее.


        1. BelBES
          18.01.2017 16:00

          Tensorflow + Prolog, не? :-)


          1. devpony
            18.01.2017 16:12

            Скорее уж tensorflow-haskell, но это всего-лишь обёртка с примитивными типами…


            1. BelBES
              18.01.2017 16:36

              Это насколько я понимаю просто биндинг к Haskell? А я говорю про нашлепку поверх tf в виде Prolog'а, анализирующего граф) Ведь выводимость выражений, проверка корректности и тд и тп — это ведь прям логическое программирование, не?


              1. devpony
                18.01.2017 17:42

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


                1. int33h
                  18.01.2017 20:48

                  Это интересно.
                  Насчет оптимизаций и распараллеливания…
                  Расспараллеливание будет автоматически производиться компилятором при возможности(это будет связано со специальными ключевыми словами перед определениями функций), но будет ограничение на max кол-во потоков доступных программе, которая будет определяться через специальный модуль bios(полная конфигурация всего железа, от процессора до жесткого диска).Также можно будет спокойно самому распараллеливать программу с помощью нескольких простых тегов и классов потоков, но следить за их безопасностью.
                  Оптимизации будут производиться на последнем этапе компиляции(из asm в asm), и возможно на начальном этапе, по примеру языка nim, о котором я прочитал из совета ниже…


  1. NeoCode
    18.01.2017 15:15
    +3

    Интересная смесь жабоскрипта с ассемблером :)
    На самом деле толку от register мало -это или подсказка оптимизатор или жесткая привязка к регистру как в C--, но не все сразу.
    Отдельный тип для операторов не нужен т.к. операторы сами по себе это весьма специфические штуки…
    В целом я всегда приветствую разработку новых языков и такие обсуждения но уровень проработки слабый. Говорю так потому что у меня тоже есть такая разработка и с гораздо более высоким уровнем проработки, но я не публикую потому что понимаю что все равно сырое...


    1. zagayevskiy
      18.01.2017 15:27

      Тоже без компилятора?=)


      1. NeoCode
        18.01.2017 15:35
        +1

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


        1. int33h
          18.01.2017 20:53
          +1

          О это я бы хотел почитать. Тоже хотел сначала довести до ума, прежде чем публиковать, но потом решил, что помощь будущего(возможно) сообщества будет кстати. Идея языка max уменьшить важные минусы любой современной программы такие, как скорость работы и поддержка. При этом придется например пожертвовать огромной выделяемой памятью на этапе компиляции(это тоже идея… заставить компилятор работать дольше, но выдавать более качественный код(уменьшить время работы готового за счет времени сбора))


  1. MyFutureIsYou
    18.01.2017 15:18
    +1

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


    1. int33h
      18.01.2017 21:03
      -1

      Да, опыта у меня мало. Поэтому мой первоначальный план реализовать язык более близкий по удобству к Python или JavaScript, но при этом сделать его также и очень быстрым(т.е. покрыть основной недостаток python) за счет более большого спектра специальных слов(Пример оптимизации: написал в начале программы debug тебе будут сыпаться всевозможные ошибки, написал realize и компилятор удаляет все проверки из кода). Эти спец слова предполагается реализовать в виде вышедших их моды высокоуровнего программирования меток(label: в С), и назвать их тегами. Потом, уже ближе к концу своего обучения, я думаю смогу глубже погрузиться в это все…


      1. lair
        18.01.2017 21:59
        +3

        Пример оптимизации: написал в начале программы debug тебе будут сыпаться всевозможные ошибки, написал realize и компилятор удаляет все проверки из кода)

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


        1. int33h
          18.01.2017 22:07
          -1

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


          1. lair
            18.01.2017 22:09
            +1

            Одна строчка в начале программы — это все равно исходники. Не надо их трогать.


            1. int33h
              18.01.2017 22:20
              -1

              Хорошо. Пусть решают другие, как лучше будет.


              1. lair
                18.01.2017 23:07
                +1

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


                1. int33h
                  18.01.2017 23:20
                  -1

                  Я не видел в библиотеках STL, чтобы были внутри функции использованы блоки типа:
                  #ifdef DEBUG
                  if (i >= length) std::cout << «error index out of range»;
                  #endif
                  Я предполагаю такое использование этих слов.


                  1. lair
                    18.01.2017 23:23
                    +1

                    На STL жизнь не заканчивается. В (.net) BCL есть куча кода, помеченного [Conditional("DEBUG")] или [Conditional("TRACE")], а компилятор (и C#, и JIT) в разных режимах использует разные оптимизации.


                    1. int33h
                      18.01.2017 23:45
                      -2

                      С (.net) я вообще не знаком, поэтому исходил из известных мне источников.


                      1. lair
                        19.01.2017 00:00
                        +1

                        Ээээ, так может лучше сначала познакомиться, а уже потом пробовать свое изобретать?


                        1. int33h
                          19.01.2017 00:24
                          -1

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


                          1. lair
                            19.01.2017 00:31
                            +3

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

                            Если у вас нет времени на изучение, то у вас не будет и времени на разработку. И, что важнее, нельзя разрабатывать, не изучив.


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

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


                            Ну вот банально, у вас есть каррирование функций? Частичное применение? Как они выглядят? Как выглядит создание объекта? А с одновременной инициализацией? Анонимные функции? Анонимные объекты?


                            1. int33h
                              19.01.2017 12:30

                              Это должно быть гораздо позже, но если это вас волнует, то могу в следующей статье уже рассматривать функции(судя по всему никому дела до последовательности повествования нет...).
                              Насчет ФП я пока думал только над чем-то простым вроде чистых функций. Но я готов добавлять все хорошие предложения, которые не будут противоречить идеологии языка.
                              (каррирование и частичное применение не кажутся чем-то уж слишком сложным)
                              Создание объекта будет скорее всего будет очень похоже на создание структуры в С(только будет еще сегмент кода) и/или таблиц Lua.
                              Анонимные функции и объекты вопрос сложный, так как на этапе компиляции они все равно будут обязаны получить свое имя(объектам для хранения в таблицах типов, функциям для хранения в таблицах функций).


                              1. lair
                                19.01.2017 12:33
                                +1

                                Насчет ФП я пока думал только над чем-то простым вроде чистых функций.

                                Чистые функции на уровне языка? И как же?


                                каррирование и частичное применение не кажутся чем-то уж слишком сложным

                                Не кажутся? Покажите пример синтаксиса.


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

                                Пример приведите.


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

                                Вы сейчас говорите о реализации. А я говорю о синтаксисе.


                                1. int33h
                                  19.01.2017 13:07

                                  1)Формально каждая функция языка будет чистой, т.е. написав
                                  function add(int a, int b) {..}

                                  Вы получите чистую функцию, которая может работать только с переданными аргументами.
                                  Если же вы хотите использовать внешние переменные или функции с доступом к внешним переменным, то в момент использования придется расширять область видимости до global(тег global:), который компилятор будет как-то интерпретировать исходя из других уже использованных тегов.
                                  (В случае с вводом выводом потребуются теги read: write:)
                                  У некоторых тегов могут быть атрибуты, в частности, у тега global указывается название используемых переменных и функций.
                                  2)Частичное применение если я правильно понимаю:
                                  function abcd(int a, string b, var c, operator d) {..}
                                  function abcd(int a, string b) : function abcd(a, b, nil, '<');

                                  Каррирование: действительно сложно сходу придумать синтаксис.
                                  3)В процессе компиляции в классе определяются несколько блоков:
                                  1.Внутренние данные
                                  2.Внутренние данные с разрешением на чтение извне(read_only)
                                  3.Внешние данные
                                  4.Данные секции protected(не уверен что будет)
                                  дальше идет примерно такой же набор ссылок на функции..:
                                  1.private функции
                                  2.protected функции
                                  3.public функции
                                  Дальше, собранный тип помещается в таблицу типов, через которую он потом используется(т.е. получается что-то типа таблицы c парами <param/func, address>)
                                  4)Не знаю, что даже сказать… Возможно просто будет писаться слово anonym вместо имени, либо перед функцией будет ставиться тег once:, но при этом функции придется давать какое-то имя…


                                  1. lair
                                    19.01.2017 13:18
                                    +1

                                    Формально каждая функция языка будет чистой [...] Если же вы хотите использовать внешние переменные или функции с доступом к внешним переменным, то в момент использования придется расширять область видимости до global(тег global:), который

                                    Значит, уже не каждая функция будет чистой. Более того, вы только что сделали невозможным ООП.


                                    Частичное применение если я правильно понимаю:

                                    Это не частичное применение, а перегрузка функции.


                                    Частичное применение — это, грубо говоря, вот так:


                                    [1;2;3] |> map ((+) 42) // [43; 44; 45]

                                    В процессе компиляции в классе определяются несколько блоков

                                    Это создание класса, а не создание объекта. Ну и да, даже по описанию (которое далеко не синтаксис) — это тихий ужас, показывающий, что вы с удобными ООП-языками и не работали вовсе.


                                    Возможно просто будет писаться слово anonym вместо имени, либо перед функцией будет ставиться тег once:, но при этом функции придется давать какое-то имя…

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


                                    1. int33h
                                      19.01.2017 15:12
                                      -1

                                      Подход к написанию программ сильно зависит от нужд…
                                      1)Если вам нужен функциональный язык программирования, то вам предлагается механизм чистых функций. При этом ввод/вывод также делается не хитрыми функциями по типу show…
                                      2)Если вам нужно ООП, то можно для функций классов можно придумать расширение области видимости до класса.
                                      3)Я понял что вы имеете ввиду под механизмом частичного применения.
                                      Еще в вики написано, что язык с замыканиями может выполнять работу частичного применения => вполне можно обойтись и замыканиями...(я думаю, что язык позволит написать замыкания почти безболезненно)
                                      4)Да, я люблю чистый С и asm). Если вы имеете ввиду как будет работать объект в режиме runtime, то по коду это будет похоже на вызов функции у которой в качестве первого скрытого параметра передается указатель на класс(данные), дальше по таблице типов вычисляются все нужные в программе смещения.
                                      5)Я до конца не готов назвать язык полностью готовым к реализации, но использование ключевого слова anonym мне кажется идеальным решением для неназванных объектов.


                                      1. staticlab
                                        19.01.2017 15:17

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


                                      1. lair
                                        19.01.2017 15:26
                                        +1

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

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


                                        При этом ввод/вывод также делается не хитрыми функциями по типу show…

                                        … которые не являются чистыми.


                                        Если вам нужно ООП, то можно для функций классов можно придумать расширение области видимости до класса.

                                        Ага, придумать… То есть тоже вы об этом не думали. Хотя заметим, в реальности, ничего придумывать не надо, давно уже есть концепция членов класса и их видимостей.


                                        (собственно, это все следствие того, что у вас зачем-то есть модификаторы local и global, никакого смысла в которых, на самом деле, нет)


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

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


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


                                        Если вы имеете ввиду как будет работать объект в режиме runtime

                                        Нет, я этого не имею в виду.


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

                                        Идеальное решение — это то, в котором не нужно лишних ключевых слов (и, кстати, так сделано в C#, F# и Java).


                            1. DmitryMry
                              19.01.2017 18:21

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

                              Здесь ситуация точно такая же: большие амбиции, совершенно «не в теме», избыточный синтаксис и т.д. Собственно, результат предсказуем. Хотя чего уж, наверное, каждый, рано или поздно, проходит через создание собственного языка…


                              1. int33h
                                19.01.2017 18:30

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


                                1. lair
                                  19.01.2017 18:32

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

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


                                  1. int33h
                                    19.01.2017 18:43

                                    Внешний вид мне не оч. понятен. А компиляторов с понятным кодом я пока не находил.


                                    1. lair
                                      19.01.2017 18:45

                                      Внешний вид мне не оч. понятен.

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


                                      Ну и да, на этом фоне то, что вы нам показываете как раз "внешний вид" — это любопытно.


                                      1. int33h
                                        19.01.2017 18:54

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

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


                                        1. lair
                                          19.01.2017 18:56
                                          +1

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


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


                                          1. int33h
                                            19.01.2017 19:02

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


                                            1. lair
                                              19.01.2017 19:03

                                              Сначала их надо попробовать порешать на других языках.


                                              И нет, я не знаю хорошего ресурса с такими задачами.


                                              1. int33h
                                                19.01.2017 19:10

                                                Я пробовал на С, С++, Python, Pascal(в школьные недалекие времена).
                                                Также писал на Lua и совсем чуть-чуть на ассемблере.
                                                Так вот, к сожалению, все языки меня не удовлетворили(дольше всего продержался С, но классы...). Хочу попробовать в ближайшее лето заняться Java и Haskell(может он мне понравится).

                                                Печаль.


                                                1. lair
                                                  19.01.2017 19:12

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


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


                                                  1. int33h
                                                    19.01.2017 19:30

                                                    Для развлечения я писал графическую библиотеку и мышь в старинном borland turbo c 30. Там С хватало с головой для решения всех задач(конечно, ведь MS-DOS), кроме организации перемещений по экрану, когда постоянно приходилось писать hide, а потом show. Потом со временем я стал переходить на codeblocks и более новые компиляторы соответственно.[Для решения олимпиадных задач их базовых возможностей хватало] В вузе я пока я не сталкивался со сложными структурами и алгоритмами(1 курс все же), но на «дополнительных» занятиях я стал натыкаться на кучу статей с очень интересными кодовыми решениями(sse, побег из темницы типов, ...). А при попытках реализовать некоторые свои классы и алгоритмы я понял, что они трудно расширяемы…
                                                    С python дело было худо с самого начала. Я уже писал, что не могу на нем написать адекватный код состоящий хотя бы из 5 строчек, не сделав ни одну ошибку.(может быть, потому что чаще пишу все на С). Хотя его строки я полюбил.
                                                    Еще был Lua с которым я познакомился через игрушку. Он мне очень понравился с первого взгляда своими метатаблицами, но проблема в том, что на нем удобно писать какой-нибудь интеллект, но не низкоуровневый код


                                                    1. lair
                                                      19.01.2017 21:57

                                                      Ну я и говорю: вы еще не писали для решения конкретной задачи, и это хорошо видно. Помогает взять пару курсов (например, Стэнфордский по алгоритмам, в двух частях, и их же по Mining Massive Datasets — первое, что в голову пришло) и решить их языках так на трех. Ну или найти реальную прикладную задачу (я вот делал сайт-каталог), и полностью реализовать. Тоже на нескольких языках. Просветляет.


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

                                                      Может не в питоне проблема, простите за прямоту?


                                                      1. int33h
                                                        19.01.2017 22:06

                                                        Это просто не мой язык.


                                                        1. lair
                                                          19.01.2017 22:18

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


                                                          1. int33h
                                                            20.01.2017 02:10

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


                                                          1. int33h
                                                            20.01.2017 02:44

                                                            Я почитал сейчас немного про python 3.5… Судя по всему, там задумываются над теми же удобствами.(Может эта версия мне уже подойдет)


                                                1. DmitryMry
                                                  19.01.2017 20:46
                                                  +3

                                                  Просто как пример: мне приходилось использовать более 20 разных языков (может и более 25), и это я ещё не сталкивался с функциональными языками (Haskell, Clojure, F# и др) и некоторыми современными (например, Nim и Rust — не нравится синтаксис, Go — не моя область применения). Каким-то из них уделялось много времени (например, ассемблер — около 7-8 лет), каким-то поменьше (Lua — пара лет ежедневной работы), некоторым совсем мало (Python — буквально несколько скриптов) и т.д. Свои языки/компиляторы/интерпретаторы также приходилось делать (там, где не было возможности использовать что-либо существующее). И как-то не возникает желания создавать новый язык. Почему? Потому что есть огромное количество языков, среди которых найти что-то подходящее для решения задачи (инструмент выбирается исходя из задачи) не представляется чем-то невозможным.

                                                  А вы притронулись к верхушке нескольких языков и решили, что нужно писать свой… Это глупо. Сейчас вы максимум, что можете сделать — студенческую поделку, не более того. Для чего-то серьёзного у вас нет ни знаний, ни опыта. Вы не знакомы с современными языками, не знакомы с принципами их разработки, даже серьёзных проектов у вас не было. Как вы будете проектировать язык, если не знаете, какие с ним возникнут проблемы в серьёзных проектах, а так же, что и как поможет решить язык в этих серьёзных проектах? Плюс, не забывайте, что язык — это не только синтаксис. И это не только компилятор. Это и библиотеки, и средства разработки, и различные вспомогательные инструменты.

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

                                                  P.S. Лично для меня любимым (но, к сожалению, не основным используемым) языком стал D, также использую и другие, если есть необходимость (последние годы это в основном Lua, C#, GML).


                                                  1. int33h
                                                    19.01.2017 21:05

                                                    Да. Я тоже думаю, что стоит набраться сначала опыта в больших проектах, но не уверен получится ли(я хотел бы начать сейчас, но не уверен в своих знаниях и где искать)(потом малообщительный человек)… Наверно, пока что отложу в ящик, но потом вернусь.
                                                    Язык D я начинал изучать, но не сильно. Есть ли там что-то сильно отличающееся от C++?


                                                    1. DmitryMry
                                                      20.01.2017 07:50

                                                      Где искать большие проекты — зависит от области ваших интересов. Если нет своих разработок, то, как вариант, просто поучаствовать в опенсорс проектах на гитхабе.

                                                      Про язык D говорят «C++ done right». Достаточно обширная тема, которая уже много раз обсуждалась. Например, есть циклы статей в соответствующем хабе.


                          1. FForth
                            19.01.2017 04:29

                            Посмотрите ещё в сторону Конкатенавных языков


                            1. int33h
                              19.01.2017 12:00

                              Спасибо, обязательно почитаю.


                  1. DarkEld3r
                    19.01.2017 14:09

                    Я не видел в библиотеках STL, чтобы были внутри функции использованы блоки типа:

                    Зато можно найти асерты, что фактически то же самое.


                    1. int33h
                      19.01.2017 15:20

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


                      1. staticlab
                        19.01.2017 15:27

                        Компиляторы давным давно это делают.


                      1. lair
                        19.01.2017 15:29

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

                        Ну посмотрите уже на conditional complation, а?


  1. MrGobus
    18.01.2017 15:26

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

    Вот пример — мечта автора о том, что любой неинициализированной переменной будет присваиваться nil, сразу говорит нам лишь об одном, в языке будет куча и сборщик мусора. Поэтому все разговоры об ассемблере не имеют особого смысла =).В лучшем случае, это будет c-sharp.

    Вообще, изобретать яп отталкиваясь от удобства не самая лучшая идея =)


    1. NeoCode
      18.01.2017 15:40
      +1

      Это говорит о том что все переменные бубну по умолчанию нуллабельны. Такое можно сделать и в низкоуровневом языке… только для низкоуровневом это неестественно: нуллабельность это фига которая добавляется к типу (optional(T)) а не наоборот.


      1. MrGobus
        18.01.2017 16:53

        Задачка на «нуллабельность»

        unsigned char A;
        Занимает 1 байт памяти, имеет значение 0..255.
        Какое значение переменной A будет считаться «нуллабельным»?
        Как foo(A) узнает, что А «нуллабельна»

        Введенное понятие nil говорит о том, что я смогу получить и использовать это состояние во время исполнения а не на этапе компиляции. А с неинициализированными переменными и -Wall в обычном СИ легко справляется без всяких бесполезных типов.


        1. NeoCode
          18.01.2017 18:56
          +2

          Ну о чем и речь.
          unsigned char это базовый тип данных, а чтобы добавить ему нуллабельность его нужно сделать или ссылочным или завернуть в optional, то есть добавить скажем еще байт на хранение признака наличия/отсутствия данных.
          Если бы на заре компьютерных технологий предусмотрели для целочисленных типов «недействительную» битовую комбинацию (например «отрицательный ноль», который сейчас выражается как 0b100...00 и имеет значение минимального отрицательного числа данного типа) то был бы еще вариант. Для типов с плавающей точкой вот предусмотрели NaN, но опять-же философский вопрос — можно ли использовать NaN для float как Optional.None или это разные понятия.


        1. int33h
          18.01.2017 20:11

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


          1. int33h
            18.01.2017 21:15

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


          1. DarkEld3r
            19.01.2017 14:16

            Может не совсем понял, но вот такая ситуация: есть int(размер_указателя) в который положили nil. Формально адрес nil вполне может быть честным значением.


            1. int33h
              19.01.2017 15:24

              Вы не можете положить в int значение nil. Если вам требуется удалить переменную этого типа, то вы должны вызвать функцию(оператор) delete.(после этого ее надо будет объявлять заново) Но в object(var) вы можете спокойно в любой момент указать на nil(nil — элемент таблицы типов(адрес))


              1. lair
                19.01.2017 15:30
                +2

                Вы не можете положить в int значение nil.

                Тогда как же функция (...) -> int может вернуть nil? Чему будет равно i после выполнения следующего примера?


                function f() -> int(4) {return nil;}
                int(4) i = f();


                1. int33h
                  19.01.2017 16:31

                  Скорее всего этот код выдаст ошибку на этапе исполнения. При компиляции компилятор обратит внимание на то, что не всегда функцией возвращается int(4), поэтому сделает обертку в виде object-а а при присвоении проверит совместимость типов и выдаст критическую ошибку. Правильным будет написать:
                  function f() -> int(4) {return nil;}
                  if (f() != nil) int(4) i = f();

                  Предполагается, что nil это специальный тип для object. Поэтому при попытке вернуть nil из функции которая его не должна возвращать, компилятор обязан создать тип object, который будет его оберткой.(т.е. формально можно возвращать любые данные, но при дальнейшем исполнении будет предполагаться, что функция вернула то, что нужно)
                  [Вообще это очень тонкий момент связанный с тем, что мы хотим отказаться от принципа «любая переменная есть указатель» в угоду скорости](int(4) и char мы храним на стеке, a var,string,function всего лишь указатель на некие структуры)


                  1. lair
                    19.01.2017 16:40

                    function f() -> int(4) {return nil;}
                    if (f() != nil) int(4) i = f();

                    Это же адски неудобно (даже если не считать двойного вызова). Вы не слышали про nullable-типы? Про Option[T]? А про то, что для ошибок бывают исключения? Или, если вам не нравятся исключения, Try[T]?


                    (хотя я вот понял, что вы еще ни разу не упомянули про дженерики, и что-то мне кажется, что у вас их тоже нет...)


                    1. int33h
                      19.01.2017 16:57

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


                      1. lair
                        19.01.2017 17:00

                        Как можно слышать про Option[T], но не слышать про дженерики, если Option[T] — это дженерик?


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


                        1. int33h
                          19.01.2017 17:06

                          Не всегда указывают.


                          1. lair
                            19.01.2017 17:08

                            Кто "не всегда указывают"? Куда "не всегда указывают"?


                  1. staticlab
                    19.01.2017 16:49

                    Нет, извините. Здесь двойной вызов функции. А вот я хочу прочитать число int(4) из файла. Получается, по-вашему, что int(4) x = readFromFile(file) работать не будет. И дважды я тоже не могу запросить, потому как функция имеет побочные эффекты. Приведите правильный пример кода, пожалуйста.


                    1. int33h
                      19.01.2017 17:04

                      int(4) x = readFromFile(file) немного не удачный пример, но идею я понимаю. Придется, видимо, оставить эту возможность.

                      Код по вашему запросу
                      read: //желательно тут указывать еще файл, чтобы не блокировался весь диск в многопоточной программе
                      function readFromFile(file) -> int(4) {...}

                      или как в python через var

                      function readFromFile(file) -> var {...}
                      var x = readFromFile()
                      if (x.type == int)…


                      1. staticlab
                        19.01.2017 17:11

                        Ага, то есть у вас получается как раз Nullable/Option[T]. Значит, фактически, функция будет возвращать пару значений: [isNil, result]. Если мы добавим ещё объект ошибки, то придём к чему-то похожему на Rust: Result<T, E>:


                        pub enum Result<T, E> {
                            Ok(T),
                            Err(E),
                        }


                        1. int33h
                          19.01.2017 17:17

                          Есть идея возврата через регистры нескольких параметров… Но тут я опять зажат в тески специальным типом register.
                          Думаю что откажусь в пользу обычных исключений.


                          1. lair
                            19.01.2017 17:29

                            Но тут я опять зажат в тески специальным типом register.

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


                            1. int33h
                              19.01.2017 17:39

                              Ну вообще-то вещь полезная… Через этот тип можно, например, ускорять функции...(передача аргументов через регистр)


                              1. lair
                                19.01.2017 17:52

                                Почему эту оптимизацию не может делать компилятор?


                      1. devpony
                        19.01.2017 17:42
                        +2

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


                        1. int33h
                          19.01.2017 17:57

                          Это зависит от того какими типами пользоваться. int, char, string малых размеров хранятся в стеке. var является своего рода указателем на данные с методами их обработки(таблица типов). И никто не отменял техник метапрограммирования которые серьезно садят производительность.


                          1. devpony
                            19.01.2017 18:02
                            +1

                            Ну вот в вашем примере используется крайне быстрый int размером 4 байта. И… каждый раз при вызове функции выполняется проверка типа возвращаемого значения.

                            Зачем вообще нужна статическая типизация, если она не спасает от ошибок типов во время компиляции?


                            1. int33h
                              19.01.2017 18:04

                              Нет. Так код генерируемый компилятором сильно зависит от стиля написания. Если бы функция не возвращала nil, то компилятор не приводил бы его к object…


                              1. lair
                                19.01.2017 18:05

                                Если бы функция не возвращала nil

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


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


                                1. int33h
                                  19.01.2017 18:12

                                  Признаю. Возможно это не лучшая идея.


  1. zagayevskiy
    18.01.2017 15:26
    +6

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

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


    1. Carzil
      18.01.2017 15:54
      +3

      Изобретение своего языка программирования — не такая уж и бесполезная вещь. Во время этого процесса можно узнать много нового и значительно расширить свой кругозор в области IT: узнать как работают и из чего состоят компиляторы/JIT/интерпертаторы, изучить runtime уже существующих языков, то есть, по-сути, лучше узнать как они работают изнутри :)


      1. c4boomb
        18.01.2017 16:01

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


      1. zagayevskiy
        18.01.2017 16:02
        +5

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


    1. BelBES
      18.01.2017 15:59

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


      1. zagayevskiy
        18.01.2017 16:06
        +1

        Изучение языка подразумевает и хоть какое-то "заглядывание под крышку", имхо.


        1. BelBES
          18.01.2017 16:34
          +1

          Ну вот и много программистов C++ заглядывали под крышку, например, синтаксического парсера для C++?


          1. int33h
            18.01.2017 21:12

            Под крышку парсера я пока не заглядывал, но генерируемый gcc код оптимизировал… Получилось сократить код функции где-то на 3 за счет использования регистров 64 битной системы(r8-r15), который почему-то gcc не использует. Я бы очень хотел посмотреть код компилятора С/C++ написанного во времена Страуструпа, потому что даже в этом замечательном языке, когда я стал программировать в среде более новой, чем turbo c30 я нашел кучу мягко сказать неприятного кода(та же библиотека boost). Поэтому появилась идея найти новый путь в истории языков, чтобы код был понятен на любом этапе погружения.(все-таки я же программист(и физик)), и лень — мое второе я).


            1. Sirikid
              19.01.2017 00:21
              +1

              Как насчет -O[s0123]?


              лень — мое второе я

              Проще нормально научится писать на одном из мейнстримных (или не очень) ЯП.


              1. int33h
                19.01.2017 00:34
                -2

                Я уже пробовал. У меня хорошо идет только ассемблер, диалект С и Lua, которые к сожалению сейчас не очень актуальны.
                Python вызывает дикую ненависть каждый раз когда я пишу на нем код, а С++, Java,… содержат огромное кол-во библиотек, работа которых мне совершенно непонятна, а => адекватный код я написать не могу


                1. FForth
                  19.01.2017 04:37

                  Ненависть к частным языкам программирования и понятие программирования немного ортогональны.


                  1. int33h
                    19.01.2017 11:59
                    -1

                    Я понимаю, когда ошибки в коде действительно существенны и/или понятны, но когда в ходе выполнения программа выдает ошибку из-за ошибочной индексации, но при этом выдает ошибку о не существующем элементе, это вводит меня в то состояние.
                    В том же Lua или С я никогда не встречался с подобного рода ошибками. Всегда ошибка была либо слишком локальной(забыл поставить лишее = в проверке), либо в корне меняющей поведение программы.


                1. DarkEld3r
                  19.01.2017 14:18

                  С++, Java,… содержат огромное кол-во библиотек

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


                  1. int33h
                    19.01.2017 15:27

                    Я так не могу… Простой пример. В Java есть такое понятие как interface. Оно называет объект но не определяет его. А теперь кто-то за нас уже реализовал его. Как теперь понять насколько быстро, например, эта реализация пишет в конец списка(метод push_back)?


                    1. lair
                      19.01.2017 15:32

                      Как теперь понять насколько быстро, например, эта реализация пишет в конец списка

                      Никак. Это называется "инкапсуляция", и это, знаете ли, нормально для программирования.


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


                      1. int33h
                        19.01.2017 16:37

                        Ну да.) А если документации нормальной нет толком? Я парочку раз встречался.


                        1. lair
                          19.01.2017 16:43
                          +1

                          Тогда выкиньте эту библиотеку и возьмите другую. Либо забейте на дурацкие вопросы, на которые вы все равно не получите разумного ответа.


                    1. staticlab
                      19.01.2017 15:33
                      +2

                      Для Java Collections API, C++ STL и прочих подобных библиотек в документации к классам как правило описана алгоритмическая сложность операций.


            1. BelBES
              19.01.2017 00:45

              но генерируемый gcc код оптимизировал

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


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


              1. int33h
                19.01.2017 11:50

                Ну так какими способами в С++ добиваются векторизации вычислений или, например, делегатов?
                Я хочу чтобы, там где это возможно, язык почти автоматически мог добавлять нужные тебе компоненты… И при этом он был бы удобный как снаружи так и внутри(вот, например, как в этой статье… элегантно и красиво)


                1. lair
                  19.01.2017 12:11

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

                  … и на сколько оптимизирующих компиляторов вы уже посмотрели?


                1. BelBES
                  19.01.2017 12:33

                  1) Оптимизирующие компиляторы уже умеют векторизовать вычисления, иногда весьма неплохо (-O3 в помощь ;-) )


                  2) Когда дело доходит до ручного использования SSE/NEON, обычно идет уже экстремальная оптимизация кода, где все эти "почти автоматические" методы только мешаются оптимизатору.


                  1. int33h
                    19.01.2017 12:41

                    1)Я всегда компилирую с -O3, но в gcc векторизации ни разу не заметил. Может быть Сlang и др. это делают.

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


                    1. lair
                      19.01.2017 12:45

                      Во всяком случае я хочу реализовать библиотеку bios, с помощью которой можно будет полностью собрать всю информацию о компьютере и использовать это для оптимизации(но видимо придется в таком случае таскать компилятор с собой).

                      Эмм, ну откройте уже для себя JIT-компиляцию (в том числе — при установке на конкретный компьютер).


                    1. BelBES
                      19.01.2017 13:12

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

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


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


                      1. int33h
                        19.01.2017 13:18
                        -1

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


    1. int33h
      18.01.2017 20:18
      -1

      Среди знакомых мне языков существуют: Pascal, C/C++, Lua, asm, Python(мой самый злейший враг), JavaScript. И немного изучал С# и Java.(может что-нибудь еще… уже не помню). Вопрос в том, что я только студент и хочу, в виде языка, выразить накопившиеся во мне противоречия даже с таким совершенным, на мой взгляд, языком, как С/C++. А с работой над серьезными проектами я мог разбирался только по готовым кодам, например, игр(тот же самый Colobot)


  1. Googolplex
    18.01.2017 16:20
    +2

    Прошу прощения, но кодировки UTF-8 и UTF-16 не имеют фиксированной ширины code unit'а, поэтому вводить типы вроде char(utf-16) или char(utf-8) это нонсенс, совершенная бессмыслица (если под "символом UTF-X" вы понимаете именно code unit; в противном случае я вообще не понимаю, что это такое). Посмотрите, как строки реализованы в Rust, Swift или Go. А ещё почитайте http://utf8everywhere.org/, очень хороший документ.


    1. int33h
      18.01.2017 20:08

      Я же сказал внутри текста, что utf-8 будет фиксированной длины(4 байта — max размер) для удобства его хранения в массивах. А насчет utf-16 действительно моя ошибка.(см. комментарий ниже)
      [«Да, спасибо за уточнение. Хотя в начале этот тип был действительно фиксированного размера(2 байта).»]
      Если вы знаете другой способ реализации хранения данных динамического размера, то я буду рад, хотя, честно говоря, пока мой план, что я буду жертвовать размерами программы в памяти ради скорости


      1. lair
        18.01.2017 22:02
        +2

        Я же сказал внутри текста, что utf-8 будет фиксированной длины(4 байта — max размер) для удобства его хранения в массивах.

        Ну и зачем тогда брать utf-8, если можно взять utf-32?


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


        1. int33h
          18.01.2017 22:27

          1)Насколько мне известно представление символов в кодировках utf-8 и utf-32 различаются, а быстрой индексации строк ну уж очень хочется.)
          2)Как мне кажется, доступ вполне оправдан, ведь если у нас текст только на английском языке, то смысл выделять под его хранение в 4 раза больше места?


          1. Googolplex
            18.01.2017 22:30
            +2

            быстрой индексации строк ну уж очень хочется

            Во-первых, прочитайте http://utf8everywhere.org, вы поймёте, что индексация строк совершенно не так важна, как кажется на первый взгляд, и не так проста, как это можно представить по языкам, которые не работают с юникодом правильно.


            Во-вторых, строки в UTF-8/UTF-16, если это действительно UTF-8/UTF-16, за константное время индексировать нельзя (если, конечно, вы хотите по индексу доставать code point'ы, а не что-то ещё), просто потому, что code point'ы в них переменной длины.


            1. int33h
              18.01.2017 22:36

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


              1. Googolplex
                18.01.2017 22:43
                +1

                Языку полностью по барабану на память, используемую приложением

                Не понял, к чему это, если честно.


                А от строк я хочу добиться индексации за константу

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


                Приве?т ?????? ???????

                Насколько полезно будет индексировать эту строку по code unit'у? Особенно с учётом того, что вы можете попасть на апостроф или другой комбинирующий символ?


                Кроме того, единственный способ добиться индексации за константное время без постоянных накладных расходов в рантайме и при этом не потерять полноценную работу с юникодом, это использовать UTF-32.


                1. int33h
                  18.01.2017 22:48
                  +1

                  Да, наверное соглашусь.


                1. Googolplex
                  19.01.2017 10:22

                  индексировать эту строку по code unit'у

                  code point'у, конечно.


          1. lair
            18.01.2017 23:10

            Насколько мне известно представление символов в кодировках utf-8 и utf-32 различаются, а быстрой индексации строк ну уж очень хочется.

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


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

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


            Ну и да, если взять utf-8, то как раз никакого избыточного выделения не будет.


            1. int33h
              18.01.2017 23:23

              Да мы уже это выяснили с Googolplex в ходе разговора. Признаю.


      1. Googolplex
        18.01.2017 22:08

        utf-8 будет фиксированной длины

        Дело не в удобстве/неудобстве, дело в том что вот в этом вот утверждении первая и вторая части противоречат друг другу. В UTF-8 code point'ы (раньше я написал неправильно, каюсь; это code point, а не code unit, code unit в UTF-18 будет 1 байт) переменной длины; если это не так, то это не UTF-8. Какая раскладка байт в char(utf-8) будет, скажем, у символа Y (ASCII) и Ы (BMP)?


        Такой вопрос: индексация строк у вас есть? Если да, то что эта операция возвращает?


        1. int33h
          18.01.2017 22:33

          Да в utf-8 символы переменной длины, но для удобств индексации нужно чтобы каждый символ хранился строго по определенному смещению от начала строки. Поэтому старшие байты, если символ 1 байтовый, будут содержать всякий мусор(или 0).
          Оператор индексации будет возвращать(тоже не без мусора) тип char(utf-8), т.к. строка является «производным» классом от char.


          1. Googolplex
            18.01.2017 22:35

            Вы понимаете что то, что вы изобрели, это не UTF-8? В UTF-8 строках code point'ы располагаются один за другим. Никакого смысла в представлении, когда code unit'ы паддятся до фиксированной длины, нет вообще! Почему в этом случае не взять UTF-32 и сэкономить на вычислении представления символа в UTF-8?


            1. int33h
              18.01.2017 22:40
              +1

              Хорошо. Возможно не лучшая идея.


  1. zolern
    18.01.2017 19:21
    +2

    А Вы на Nim (nim-lang.org) посмотрите — если не понравится то хоть будет полезно посмотреть как надо новые языки разрабатывать.


    1. int33h
      18.01.2017 20:01

      Да, очень интересный язык. Очень похож по синтаксису на мой язык, судя по краткому ревью…
      Но вот вопрос в том насколько этот язык умеет оптимизировать под современные процессоры. Недавно я читал кучу статей в которых оптимизация производилась с помощью xmm регистров и обработки данных массивным способом.(вот одна из них). Так вот, мне кажется, что язык С уже немного устарел для современного железа, поэтому действительно быстрый код можно написать разработав язык заново с ассеблера. А Nim, к сожалению, не производит ассемблерного кода напрямую, что, как я считаю немного мешает теории идеальной оптимизации).


      1. BelBES
        19.01.2017 00:37

        А чем не угодили интринсики и всякие SSE/AVX/NEON инструкции в C/C++?


        1. int33h
          19.01.2017 11:21

          Они кажутся мне слишком сложными для понимания на базовом уровне. Знание ассемблера меня спасло… А если бы я его не знал?..


      1. deep_orange
        19.01.2017 02:19
        +2

        Си не может устареть. И, кстати, если хотите жизни своему языку, то позаботьтесь об взаимодействии с Си-библиотеками. Например такими как OpenGL, их вам не удастся переписать.


        1. int33h
          19.01.2017 11:32
          -1

          Еще как может. Да, для программирования под системы уровня MS-DOS язык просто прекрасный. Но как только развитие технологий доходит до нового технического уровня(потоки, например) язык потихоньку начинает устаревать. Си возможно и не устареет в использовании для написания маленьких системных программ, но его наследник С++, как мне кажется, уже сдает позиции при выборе в качестве основного для больших проектов(если бы не его производительность)…


  1. om1058
    18.01.2017 19:21

    символ в кодировке utf16 — не всегда 2 байта


    1. int33h
      18.01.2017 19:25

      Да, спасибо за уточнение. Хотя в начале этот тип был действительно фиксированного размера(2 байта).


      1. mwizard
        18.01.2017 22:53

        Вы путаете UCS2 и UTF-16.


        1. int33h
          18.01.2017 22:56

          Возможно.


  1. lair
    18.01.2017 22:05
    +1

    Дело в том, что Сtag по примеру С# является языком двойной типизации, т.е. позволяет как статические переменные, так и динамические.

    А, что? Тип любой переменной в C# статичен.


    1. int33h
      18.01.2017 22:17

      Вроде бы тип object и функции boxing,unboxing позволяют работать с переменными, как в динамической типизации. Но я не очень хорошо знаю С#, потому что дело было давно и недолго. Единственное — относительно недавно, смотрел ролик по этому типу. Подумал, что хорошая идея.


      1. lair
        18.01.2017 23:06
        +1

        Вроде бы тип object и функции boxing,unboxing позволяют работать с переменными, как в динамической типизации.

        Нет. Тип переменной будет тот же, который был указан в декларации.


        1. int33h
          18.01.2017 23:25

          Вам виднее.


  1. Sirikid
    19.01.2017 00:46
    +2

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


  1. staticlab
    19.01.2017 09:54
    +4

    Ctag — продукт переосмысления достижений человечества

    Но пока я еще очень слабо знаком с разработкой компиляторов

    не допустить 20 ошибок в 10 строчках я не могу

    насчет Java, достоверно не знаю как она компилирует

    Да, опыта у меня мало

    С моими нагрузками, только во время экзаменов могу садиться за изучение обширных тем

    Под крышку парсера я пока не заглядывал

    С++, Java,… содержат огромное кол-во библиотек, работа которых мне совершенно непонятна

    Но я не очень хорошо знаю С#, потому что дело было давно и недолго

    Так о каких достижениях человечества вы говорите?


    1. int33h
      19.01.2017 11:42

      Да, с компилированием я слабо знаком. Да, я уже давно не писал код на С#. Да, я плохо разбираюсь в компилировании Java-ой в байт код. И времени у меня тоже немного. Но остальные претензии были недостоверно взяты из контектса.
      1)20 ошибок на 10 строк относятся только к Python
      2)огромное кол-во библиотек, работа которых мне не понятна, я могу спокойно использовать, если обращусь к документации.
      Язык С++ в некоторых своих библиотеках предоставляет иногда просто не читаемый код, а я, к сожалению, не могу писать качественный код, покуда не понимаю все от начала до конца(за это я и полюбил С без классов). Поэтому я хочу сделать язык код которого будет понятен для любого, кто только познакомился со всем языком(без всякой шаблонной магии и проч. ерунды boost)


      1. lair
        19.01.2017 12:12
        +1

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

        Эта задача не имеет решения, потому что пишут код люди, а не язык.


        1. int33h
          19.01.2017 12:33

          Это понятно. Просто в процессе написания люди имеют некоторые ограничения и это сильно влияет на исходный код, чем больше этих ограничений.


          1. lair
            19.01.2017 12:34
            +1

            … вы сторонник того, чтобы ограничений было больше или меньше?


            1. int33h
              19.01.2017 13:13

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


              1. lair
                19.01.2017 13:21
                +2

                Меньше

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


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

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


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


                1. int33h
                  19.01.2017 15:39

                  Насчет читаемости я не уверен. По крайней мере с помощью поисковика можно будет спокойно отследить функции с доступом к вводу-выводу, общим данным и др. Да сам код будет гораздо больше, чем даже в С++, но при этом по определению функции можно будет с уверенностью утверждать, что она, например, не работает с внешними переменными или если она обращается к ним, то к каким…
                  А дальше вступает debug-ер. И находит точную ошибку… Во всяком случае, при попытке написания большого кода(я тогда писал что-то наподобие графического движка для MS-DOS) иногда бывает очень сложно отследить какую-нибудь маленькую ошибку по неаккуратности. А тут тебя ограничивают по полной. Но стоит научиться использовать теги и проблемы отпадают…


                  1. lair
                    19.01.2017 15:46

                    По крайней мере с помощью поисковика можно будет спокойно отследить функции с доступом к вводу-выводу, общим данным и др.

                    Это не читаемость, это статический анализ. Человек — не поисковик.


                    по определению функции можно будет с уверенностью утверждать, что она, например, не работает с внешними переменными или если она обращается к ним, то к каким…

                    Опять нарушение инкапсуляции.


                    А дальше вступает debug-ер. И находит точную ошибку…

                    Каким образом? И как ему в этом помогло то, что по определению функции видно, с какими внешними переменными она работает?


                    (но вообще, конечно, эта проблема — снова — давно решена: в ФП функции не работают с "внешними переменными", в ООП нет функций, а методы работают только с состоянием класса)


                    1. int33h
                      19.01.2017 16:51

                      Так никто и не говорит, что человек — не поисковик. Большинство современных текстовых редакторов поддерживают функцию поиска… Разве этого не достаточно для того чтобы найти функцию по имени, или специальный тег?
                      Работа с классами и функции никак толком не связаны. Внутри класса есть своя область видимости, в которой и находятся все методы. Методы в классе по определению используют расширение видимости до всего класса(тег global повышает видимость на 1, local опускает видимость на 1)(Порядок видимости: 1)все файлы, 2)этот файл, 3) внутренность чего-нибудь ...)
                      Ну debug-ер я изменять не собираюсь… Поставить точку остановки и т.д.


                      1. lair
                        19.01.2017 16:57

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

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


                        Работа с классами и функции никак толком не связаны.

                        То есть метод — это не функция?


                        (Порядок видимости: 1)все файлы, 2)этот файл, 3) внутренность чего-нибудь ...)

                        … и отдельно, конечно, хочется сказать, что оперировать файлами как областями видимости — это тоже бессмысленно.


                        Ну debug-ер я изменять не собираюсь… Поставить точку остановки и т.д.

                        … и как тут помогло то, что по определению функции видно, с какими переменными она работает?


                        1. int33h
                          19.01.2017 17:14

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


                          1. lair
                            19.01.2017 17:29

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

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


                            Метод — это функция с тегом global… Но для формальности пусть будут разными понятиями.

                            Как только они стали разными понятиями, вы потеряли возможность использовать их взаимозаменяемыми (например, передать в map метод класса).


                            А если метод — это функция с тегом global, то все методы — не чистые функции (и все функции с тегом global — не чистые функции, кстати), так что опять боль и печаль.


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

                            Это называется internal, и к файлам отношения не имеет.


                            1. int33h
                              19.01.2017 17:54

                              Слишком много комментариев и куча новой информации… Я начинаю путаться.

                              Все методы по умолчанию принимают в качестве первого параметра указатель на данные(объект класса)[что-то из Lua]. Поэтому тег global обязателен. (применение его в секции public бессмысленно(не работает))

                              Можно и internal.


                              1. lair
                                19.01.2017 17:58

                                Слишком много комментариев и куча новой информации… Я начинаю путаться.

                                … хотя вся эта информация — это, в общем-то, более-менее типовые вещи в современных языках.


                                Все методы по умолчанию принимают в качестве первого параметра указатель на данные(объект класса) Поэтому тег global обязателен.

                                Какая связь?


                                1. int33h
                                  19.01.2017 18:02

                                  Человек не может познать всего сам.

                                  Без понятия. Я не очень хорошо вас понимаю.


                                  1. lair
                                    19.01.2017 18:06

                                    Человек не может познать всего сам.

                                    Для этого, знаете ли, люди учатся. А у вас "времени нет".


                                    1. int33h
                                      19.01.2017 18:17

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


  1. lair
    19.01.2017 13:36
    +1

    Кстати, о простоте. Вот четыре ваших "типа":


    7) function.
    8) code.
    9) operator.
    10) statment.

    Даже если отвлечься от ошибок в их описании/именовании, достаточно легко придти к выводу, что все они легко заменяются одним "типом" — function. Потому что code — это функция (...) -> unit, operator — функция (x, y) -> 'a, а statment — функция (...) -> bool.


    (но какая же фигня у вас там творится с параметрами и замыканиями...)


    1. BelBES
      19.01.2017 13:37

      "Весь мир — Монада" © ;-)


      1. lair
        19.01.2017 13:38

        С этим куда-нибудь к Лейбницу, у меня сугубо практический интерес.


    1. int33h
      19.01.2017 14:33

      Да, возможно вы правы. Но тип code и function сильно различаются, чтобы сделать их одним типом.
      Тип code предполагается в будущем использовать для реализации циклов. А function это полноценная ед. компиляции.


      1. lair
        19.01.2017 14:34

        Тип code предполагается в будущем использовать для реализации циклов. А function это полноценная ед. компиляции.

        И что?.. Содержимое цикла — это тоже полноценная единица компиляции.


        1. int33h
          19.01.2017 17:21

          Конечно). Почти. Сначала идут разные макро подстановки… Потом компиляция с проверкой.


          1. lair
            19.01.2017 17:30

            … вот и нет смысла разделять code и function.


            1. int33h
              19.01.2017 18:00

              Не уверен. code должен иметь возможность использовать переменные окружающей его видимости, в отличии от функции.


              1. lair
                19.01.2017 18:04

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


                Понимаете ли, решение вида


                code = {x = x + y};
                
                var z, x, y;
                code();

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


                1. int33h
                  19.01.2017 18:18

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


      1. staticlab
        19.01.2017 14:43
        +1

        JavaScript (ES5):


        var arr = [1, 2, 3, 4, 5];
        
        arr.forEach(function (item, i) {
            console.log(i, " => ", item);
        });

        Чем это не цикл? А ведь просто функция. И её даже можно отдельно в переменную вынести и передать в forEach().


        1. int33h
          19.01.2017 17:23

          Да, можно и так.


    1. int33h
      19.01.2017 15:47

      Интересный подход на этапе компиляции подменять все функциями. Только code это скорее void(nil) функция, но которая может взаимодействовать с внешней областью видимости. Оператор ведет себя нетипично, поэтому его я думаю стоит оставить. А все остальное пусть действительно станет функциями.


      1. lair
        19.01.2017 15:50

        Только code это скорее void(nil) функция, но которая может взаимодействовать с внешней областью видимости.

        … и в этот момент вы замучаетесь делать это униформно. А, главное, зачем?


        Оператор ведет себя нетипично, поэтому его я думаю стоит оставить

        И что же у него нетипичного?


      1. staticlab
        19.01.2017 16:19

        Некий сферический язык в вакууме:


        Vector<int, 3> a = { 1, 2, 3 };
        Vector<int, 3> b = { 4, 5, 6 };
        
        function sum(Vector<T, N> v, Vector<T, N> u) {
            var res = new Vector<T, N>();
            for (int i = 0; i < N; i++) {
                res[i] = v[i] + u[i];
            }
            return res;
        }
        
        a `sum` b // Haskell-like syntax: sum(a, b) => { 5, 7, 9 }


        1. int33h
          19.01.2017 17:26

          Да вы правильно уловили мысль. Только вместо function написать operator, чтобы компилятор когда встретил слово sum посмотрел на пред. блок как на первый параметр. И можно опустить одинарные кавычки(пробелов достаточно чтобы отделить)


          1. staticlab
            19.01.2017 17:58

            Это уже непринципиально, однако читаемость может сильно пострадать.


    1. int33h
      19.01.2017 17:19

      Да вы правы. В принципе я таким же образом и думал, как их реализовывать. Видимо стоит оставить только function и оператор, из-за своей специфики.


      1. lair
        19.01.2017 17:30

        Какой специфики-то?


        1. int33h
          19.01.2017 18:07

          Некий сферический язык в вакууме:

          Vector<int, 3> a = { 1, 2, 3 };
          Vector<int, 3> b = { 4, 5, 6 };

          function sum(Vector<T, N> v, Vector<T, N> u) {
          var res = new Vector<T, N>();
          for (int i = 0; i < N; i++) {
          res[i] = v[i] + u[i];
          }
          return res;
          }

          a `sum` b // Haskell-like syntax: sum(a, b) => { 5, 7, 9 }

          Да вы правильно уловили мысль. Только вместо function написать operator, чтобы компилятор когда встретил слово sum посмотрел на пред. блок как на первый параметр. И можно опустить одинарные кавычки(пробелов достаточно чтобы отделить)

          Как компилятор при встрече с оператором отделит его от функции, если порядок написания функции и оператора отличаются[func #1 #2; #1 op #2]


          1. lair
            19.01.2017 18:13

            Как компилятор при встрече с оператором отделит его от функции, если порядок написания функции и оператора отличаются[func #1 #2; #1 op #2]

            Это вы зачем-то сказали, что порядок написания функции и оператора отличаются. Хотя это совершенно не обязательно. Но вообще, конечно, это типичная задача разрешения: если в выражении [a b c] a — это функция, которая может принять b и c, то вызываем a(b, c), если нет, и b — это функция, которая может принять a и c — то вызываем b(a, c).


            Но на самом деле, добро пожаловать в Smalltalk или Scala, в которых, упрощая, a eq b — это сообщение eq с параметром b, отправленное объекту a.


            1. int33h
              19.01.2017 18:21

              [Я предполагал, что smalltalk мне пойдет на закуску...]
              Если действительно компилятор сможет отличать оператор от функции, то это будет прекрасно.


              1. lair
                19.01.2017 18:22

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


                1. int33h
                  19.01.2017 18:32

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


                  1. lair
                    19.01.2017 18:34

                    Ну да, без создания операторов.


                    (если быть совсем точным, вам придется все-таки сделать несколько инфраструктурных операторов, навроде присвоения, но их единицы, и их хранить в типе не надо)


                    1. int33h
                      19.01.2017 18:44

                      это как-то неудобно…


                      1. lair
                        19.01.2017 18:45

                        Кому неудобно-то?


                        1. staticlab
                          19.01.2017 18:55

                          Там разве что будет неопределённость: если вдруг будет запись op1 op2 op3, где и op1, и op2 могут принять функции, то компилятор не сможет однозначно понять, что ему делать: op1(op2, op3) или op2(op1, op3). Вероятно по этой причине, например, в хаскелле инфиксный оператор нужно заключать в бэктики: op1 `op2` op3


                          1. lair
                            19.01.2017 18:57

                            Там разве что будет неопределённость: если вдруг будет запись op1 op2 op3, где и op1, и op2 могут принять функции, то компилятор не сможет однозначно понять, что ему делать: op1(op2, op3) или op2(op1, op3).

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


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

                            В Скале, кстати, не надо.


                            1. Sirikid
                              19.01.2017 21:04

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

                              В Скале, кстати, не надо.


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


                              (+) 13 37

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


                              13 `plus` 37


                              1. lair
                                19.01.2017 21:57

                                Вы про скалу или про хаскель?


                                1. Sirikid
                                  19.01.2017 23:07

                                  Хаскель.


                        1. int33h
                          19.01.2017 18:56

                          Мне точно. Ни в одном знакомом мне языке я не встретил такой возможности(вроде бы в haskell есть такая возможность)


                          1. lair
                            19.01.2017 18:58

                            Вам как программисту на этом языке? А что неудобного-то?


                            (не "я никогда так раньше не писал", а именно неудобно)


                            1. int33h
                              19.01.2017 19:04

                              Мне банально было лень писать куча операторов сравнения, когда я писал свой класс строк(я знаю что все операторы выводимы из <, но это не рационально). So…


                              1. lair
                                19.01.2017 19:07

                                … и как вам здесь поможет разделение на операторы и функции?


                                (BTW, задача "кучи операторов сравнения" решается методом CompareTo, возвращающим "равно/больше/меньше/неприменимо(неравно)")


                                1. int33h
                                  19.01.2017 19:13

                                  Так нет же. Использование операторов в функциях разве плохая идея?

                                  Да можно и методом, но разве это всегда работает?


                                  1. lair
                                    19.01.2017 19:17

                                    Так нет же. Использование операторов в функциях разве плохая идея?

                                    Плохая идея — разделять операторы и функции (за исключением примитивных операторов, которые функцией передать нельзя). Если, конечно, мы хотим получить язык, который имеет достаточную мощность расширения.


                                    Да можно и методом, но разве это всегда работает?

                                    В ОО-языках — всегда. Впрочем, все то же самое можно и функцией сделать, если мы про ФП говорим.


                                    1. int33h
                                      19.01.2017 19:33

                                      Стоп. Я не предлагаю разделять операторы и функции. Оператор будет функцией, но для компилятора он будет специально называться оператором.(Как в Lua и Python)


                                      1. lair
                                        19.01.2017 22:14

                                        Как же не предлагаете-то? "Для компилятора будет специально называться", два разных типа в языке...


                                        Вот смотрите:


                                        function sortA(int[], operator(int) cmp);
                                        function sortB(int[], function ((int, int) -> bool) cmp);
                                        
                                        operator x gto y = x > y;
                                        function gtf (x, y) = x > y;
                                        
                                        sortA(data, gto); //так можно
                                        sortA(data, gtf); //а так?
                                        
                                        sortB(data, gtf); //так можно
                                        sortB(data, gto); //а так?
                                        
                                        function sort(int[] data, operator(int) cmp)
                                        {
                                        bool b = data[0] cmp data[1]; //так можно
                                        bool b = cmp(data[0], data[1]); //а так?
                                        }
                                        
                                        //частичное применение
                                        function gtf4 (x) = gtf(x, 4);
                                        
                                        gtf4(2); //false
                                        
                                        //а как использовать частично примененный оператор?
                                        operator gto4 (x) = ?;
                                        gto4 x?
                                        x gto4?

                                        Ну и можно продолжать до бесконечности. Зачем так сложно?


                                        1. int33h
                                          20.01.2017 02:24

                                          1)Описание оператора в функции sortA. Такое представление невозможно для оператора. Я бы написал:
                                          operator((int, int) -> bool) cmp

                                          Если уж брать ваш синтаксис.
                                          2)Определение собственного оператора тоже мне не сильно нравится…
                                          operator gto((int x, int y) -> bool) = x > y;

                                          3)Применение функции там где требуется оператор невозможно, и наоборот.(хотя возможно ситуация когда оператор можно заменить функцией, как в внутри вашей sort показано)
                                          4)Скорее всего логически правильным будет применение оператора в последней форме(x gto4)


                                          1. lair
                                            20.01.2017 11:35

                                            Описание оператора в функции sortA. Такое представление невозможно для оператора.

                                            Не невозможно, а вы не предполагали. Это разные вещи.


                                            operator((int, int) -> bool) cmp
                                            operator gto((int x, int y) -> bool) = x > y;

                                            Ну вот видите. Это функция. И пишете вы ее как функцию.


                                            Применение функции там где требуется оператор невозможно, и наоборот.

                                            Ну и почему? У них, с точки зрения реализации, совершенно идентичное поведение, одна и та же сигнатура.


                                            Скорее всего логически правильным будет применение оператора в последней форме(x gto4)

                                            А если я сделал частичное применение первого операнда (fourGt = 4 gt _), то запись будет fourGt x?


  1. staticlab
    19.01.2017 14:25
    +1

    1) nil или пустой тип. По умолчанию присваивается любой переменной при объявлении. Также может быть вернут любой функцией как признак ошибки.

    Получается, что если объявить переменную int(4) x, то у неё до первого присвоения будет тип nil? И если функция возвращает ошибку, то тоже вернётся "объект" типа nil? То есть, фактически, все типы получаются монадами Maybe (то же, что и Nullable в некоторых языках)?


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


    int(4) x;
    ...
    x = readInt4(file);  // в случае ошибки чтения должен вернуться nil
    ...
    if (x) { ... } // нужно ведь проверить, не так ли? Какой у вас для этого синтаксис?

    Вот сколько в таком случае байт будет требовать переменная x?


    И, наконец, если вернулся nil, то знаем, что произошла ошибка. А какая именно? У вас есть способ, чтобы это определить?


    1. lair
      19.01.2017 14:46
      +1

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


    1. int33h
      19.01.2017 17:37

      Да, таким способом ошибок не наловишь… Если рассматривать этот код с точки зрения возможности возврата nil, то нельзя было бы писать такой код по следующей причине:
      Т.к. функция может вернуть nil, как результат своей работы, то возвращаемый тип — var.
      При попытке присвоить int-у var проверяется соответствие типа хранимого var на равенство «int».
      Если проверка успешна, то выполняется копирование значения
      Иначе выдается ошибка времени выполнения.
      (По умолчанию тип var хранит два указателя: один на таблицу типов, другой на данные.)

      Можно предложить в качестве решения создать тип exception куда складывать ошибку и возвращать return. Но тогда проще уж обработчик ошибок реализовать.(или запретить возврат не того типа)