В течение нескольких лет я разрабатывал язык программирования и на этой неделе опубликовал его на GitHub.
Язык называется Erg, считайте его Python-версией TypeScript (но более элегантной, чем TS, как мне кажется).
Python — широко используемый язык, но его динамическая типизация затрудняет крупномасштабную разработку. Моя цель — решить эту проблему с помощью Erg.
- Особенности:
- 1. Надежность
- 2. Простота
- 3. Функциональный & объектно-ориентированный
- 4. Интероперабельность
- ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ
- В: Если Erg является type-inferrable, как можно вызывать функции Python?
- В: Является ли Erg транспилируемым языком?
- В: Вы говорите, что она совместима с Python, но синтаксис, похоже, не совместим.
- В: Присоединение к процедуре знака ! делает синтаксис уродливым. Почему вы выбрали такой синтаксис?
- В: Могу ли я вызывать API, такие как TensorFlow и NumPy, из Erg?
Особенности:
Примечание: некоторые функции еще не реализованы.
1. Надежность
Erg имеет умную и мощную систему типов. Например, Erg может выполнять проверку нуля (тип Option), деление на ноль и адреса вне диапазона в массивах во время компиляции.
rand = pyimport "random"
l = [1, 2, 3]
assert l in [Nat; 3] # type checking
assert l in [1..3; 3] # more detailed
l2 = l.push(rand.choice! 0..<10)
assert l2 in [0..9; 4]
assert l2 + [3, 5, 7] in [0..9; 7]
# This causes an IndexError, Erg can detect it at compile time
l2[10] # IndexError: `l2` has 7 elements but was accessed the 11th element
2.times! do!:
print! "hello, ", end: ""
# => hello, hello,
-2.times! do!:
print! "hello, ", end: ""
# TypeError: `.times!` is a method of `Nat` (0 or more Int), not `Int`
2. Простота
Erg состоит из очень простого синтаксиса, что позволяет значительно сократить объем кода по сравнению с другими языками. Однако его функциональность не уступает им.
Поскольку система вывода типов очень мощная, вы можете писать код как на динамически типизированном языке.
fib 0 = 0
fib 1 = 1
fib n = fib(n - 1) + fib(n - 2)
assert fib(10) == 55
В Erg очень мало вещей, которые рассматриваются как особые; нет зарезервированных слов.
Даже выражения for
и while
являются просто одной из подпрограмм, так что это возможно.
loop! block = while! True, block
# equals to `while! True, do! print! "hello"`
loop! do!:
print! "hello"
3. Функциональный & объектно-ориентированный
Erg — это чистый объектно-ориентированный язык. Все является объектом; типы, функции и операторы — все это объекты. С другой стороны, Erg также является функциональным языком.
Erg требует размещения некоторых видов маркеров на коде, который вызывает побочные эффекты или изменяет внутреннее состояние, что может локализовать сложность кода. Это значительно улучшит сопровождаемость вашего кода.
# Functional style (immutable), same as `sorted()` in Python
immut_arr = [1, 3, 2]
assert immut_arr.sort() == [1, 2, 3]
# Object-oriented style (mutable)
mut_arr = ![1, 3, 2]
mut_arr.sort!()
assert mut_arr == [1, 2, 3]
i = !1
i.update! old -> old + 1
assert i == 2
4. Интероперабельность
Erg может использовать API Python без особых затрат. Кроме того, они хорошо типизированы!
# using a built-in Python module
rand = pyimport "random"
print! rand.randint!(0, 10) # 7
print! rand.randint!(0, 1.0) # TypeError: the type of rand.randint!::b is mismatched:
# expected: Int
# but found: {%v16: Float | %v16 == 1.0}
И еще больше функций планируется реализовать.
ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ
В: Если Erg является type-inferrable, как можно вызывать функции Python?
A: В Erg есть функция assert casting
, которая откладывает непроверяемые при компиляции решения о типе до времени выполнения (это то же самое, что declare
в TypeScript, но более мощное).
o = eval("1 + 1")
print! Typeof(o) # Object
assert o in Int # From this point on, o can be regarded as Int.
print! Typeof(o) # Int
print! o + 1 # 3
Функции, аргументы которых изменяют возвращаемый тип, типизируются с помощью or type
(Union).
parse_int(x: Str): Int or IntParseError
В Erg также есть система структурных типов, поэтому нежелательные функции, которые получают доступ к атрибутам своих аргументов «из коробки» без утверждений, также могут быть типизированы.
get_name(named: Structural {.name = Str}): Str =
named.name
Используя эти возможности, можно типизировать большинство функций Python.
Несколько функций, таких как exec
, все еще в принципе не типизируемы (я говорю, что легкие вызовы к ним являются плохой практикой и должны быть запрещены), но ограниченная версия функций eval
доступна без ущерба для безопасности типов.
Встроенные функции Python специально типизированы компилятором и могут быть вызваны с нулевой стоимостью. Функции из встроенной библиотеки будут поддерживаться со временем.
В: Является ли Erg транспилируемым языком?
О: На данный момент — да. Мой первоначальный план состоял в том, чтобы разработать даже процессор Python (VM) и создать статически типизированный совместимый с восходящим Python язык (именно поэтому там есть грамматика владения, и мы планировали сделать его GC/GIL-less). ВМ будет называться «Dyne» и будет разрабатываться как подпроект.
В: Вы говорите, что она совместима с Python, но синтаксис, похоже, не совместим.
О: Синтаксической совместимости, как в JS/TS, нет (хотя я постарался сделать ее достаточно похожей для простоты перехода). Как упоминалось в предыдущем вопросе, я имею в виду совместимость систем обработки.
В: Присоединение к процедуре знака !
делает синтаксис уродливым. Почему вы выбрали такой синтаксис?
О: Если вы так считаете, то вы правы и именно это я и имел в виду.
Большое количество !
в коде — это то, что называется запахом кода. Скорее всего, код имеет много побочных эффектов и низкую сопровождаемость.
В: Могу ли я вызывать API, такие как TensorFlow и NumPy, из Erg?
О: Я планирую сделать так, чтобы их можно было типизировать и вызывать на стороне Erg, как DefinitelyTyped
в TS.
Если вам нравится этот проект, пожалуйста, пометьте его на GitHub.