-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Эта статья представляет собой справочник по языку программирования gg, который следует парадигме функционального программирования на основе лямбда-исчисления и написан на F#. Одной из отличительных черт языка gg является краткость, лаконичность и выразительность, а также то, что все выражения записываются в префиксной форме, в которой операторы располагаются слева от аргументов. Язык программированичя gg поддерживает интерактивную среду для выполнения кода на данном языке - repl, в которой мы можем вводить конструкции на gg, и они будут сразу выполняться.
Для создания первой программы на языке gg потребуется текстовый редактор и фреймворк .NET SDK. Необходимо склонировать репозиторий. Для подключения расширения языка gg в VSCode нужно скопировать директорию gg из данного репозитория в директорию ~/.vscode-server/extensions. Для создания проекта используется команда dotnet new console -lang "F#" -o new_project, которой передается тип проекта. В данном случае мы указываем, что создаваемый проект представляет собой консольное приложение. С помощью флага -o указывается название проекта - new_project. После выполнения данной команды в папке new_project будет создан проект с минимальным набором стандартных файлов и папок:
-
new_project.fproj- главный файл проекта, который описывает его конфигурацию. В него в<ItemGroup>необходимо подключить\src\Main\Main.fsproj; -
program.fs- созданный файл с кодом программы на языке F#. В данной папке необходимо создать файл с расширением.ggдля дальнейшего написания кода.
Для запуска программы на gg в консоли в папке new_project необходимо ввести команду dotnet run <название созданного файла>.gg.
В следующей таблице показан синтаксис для языковых конструкций gg. Фигурные скобки {} заключают определяемые пользователем элементы синтаксиса.
Конструкция языка | Синтаксис -- | -- Блок кода | ( {expr} ) var-привязки | (var a = {expr} ) if | (if {cond} : ( {expr} ) ) if-else | (if {cond} : ( {expr1} ) else : ( {expr2} )) for | (for i [start .. finish] : ) while | (while {cond} : )Оператор позволяет определить значение и связать с данными или действиями. После идентификатора через знак равно указываются связываемые с заданным идентификатором данные или действия.
(var id = expression)
Var применяется для выражения привязки одного конкретного имени. Простейшая форма var выражения привязывает имя к значению. В качестве значения, можно использовать как числа/числовые выражения, так и строки.
(var a = 5)
(var b = (+ 5 1))
(var c = "Hello, world!")
Привязанные имена можно использовать после определения, но не в любом месте после var отображения привязки.
# ERROR: #
(print x)
(var x = 10)
OK:
(var x = 10)
(print x)
Базовый ввод-вывод включает в себя запись данных в консоль, а также чтение из файла и запись в него. Для записи в консоль используется функция print.
( print number)
(print "string")
( print (expr))
Для записи в файл используется функция write, которая добавляет строки в файл, затем закрывает его. Если указанный файл не существует, то функция создает его, записывает туда нужные строки и закрывает его.
(write "./file_path" "input_text")
Параметр ./file_path - путь к файлу, который находится в текущей директории, input_text - строки, которые добавляются в файл. Для чтения из файла используется функция read, которая открывает заданный файл и считывает построчно всю информацию, содержащуюся в нем, которая сохраняется в строковую переменную и выводится в консоль.
(print(read "./file_path"))
Параметр ./file_path - путь к файлу, который находится в текущей директории.
1) if Выражение выполняет ветвь кода и вычисляет значение, если заданное логического выражение истинно.
(
if (boolean_expression) :
(
expression_body
)
)
2) if-else Выражение выполняет ветви кода и вычисляет различные значения в зависимости от заданного логического выражения.
(
if (boolean_expression) :
(
expression_body_1
)
else :
(
expression_body_2
)
)
В предыдущем синтаксисе expression_body_1 выполняется, когда логическое выражение принимает значение true, в противном случае - expression_body_2. Типы значений, создаваемых в каждой ветви, должны совпадать.
Язык поддерживает использование операторов kill и continue, позволяющих завершать циклы досрочно, либо продолжать их выполнение, пропуская при этом одну итерацию. 1) Выражения for Используются для прохода по циклу над диапазоном значений переменной цикла.
(
for identifier [start .. finish] :
(
expression_body
)
)
Тип идентификатора выводится из типа выражения начала и окончания цикла. Правая граница диапазона не включается. 2) Выражения while Выражение используется для выполнения итеративного цикла, пока значение заданного условия истинно.
(
while (condition) :
(
expression_body
)
)
Вычисляется condition. Если оно истинно, то выполняется выражение expression_body. Затем condition проверяется заново. Если оно ложно, то цикл завершается на текущей итерации.
Функции в языке gg имеют имя, параметры, тело. Определяются с помощью ключевого слова func. Могут быть рекурсивными (функции, вызывающие сами себя). Вызвать функцию можно, указав её название и подаваемое через пробел значение (аргумент функции).
(
func function_name {parameters} :
(
function_body
)
)
Элемент function_name является идентификатором, который представляет функцию. Элемент parametrs состоит из последовательных параметров, разделенных пробелами. Явный тип для каждого параметра не указывается, а компилятор определяет его автоматически из тела функции. Элемент function_body - выражение, представляющее тело функции Оно состоит из нескольких выражений, которые в результате дают итоговое выражение, являющееся возвращающим значением. Простое определение функции выглядит следующим образом:
(
func func_example {x} :
(
if (> x 0) :
(
x
)
else :
(
0
)
)
)
(func_example 5)
В данном примере func_example является именем функции, x - аргументом, имеющим тип float. Условие if-elseпредставляет собой тело функции. Возвращаемое значение имеет тип float. В языке gg функции могут возвращать другие функции.
(
func sum {x1 x2} :
(
(var rez = (+ x1 x2))
rez
)
)
(
func multiply {x1 x2} :
(
(var rez = (* x1 x2))
rez
)
)
(
func f {x1 x2 x3} :
(
(if (<= x1 0) :
(print(multiply x1 x2))
else :
(print(sum x2 x3))
)
)
)
(f 3 4 5)
Здесь функция f принимает 3 параметра. В зависимости от значения первого возвращает одну из функций: sum или multiply. Причем все возвращаемые функции имеют один и тот же тип.
Документация: справочник по языку GG
Эта статья представляет собой справочник по языку программирования gg, который следует парадигме функционального программирования на основе лямбда-исчисления и написан на F#. Одной из отличительных черт языка gg является краткость, лаконичность и выразительность, а также то, что все выражения записываются в префиксной форме, в которой операторы располагаются слева от аргументов. Язык программированичя gg поддерживает интерактивную среду для выполнения кода на данном языке - repl, в которой мы можем вводить конструкции на gg, и они будут сразу выполняться.
Компиляция и запуск программы
Для создания первой программы на языке gg потребуется текстовый редактор и фреймворк .NET SDK. Необходимо склонировать репозиторий. Для подключения расширения языка gg в VSCode нужно скопировать директорию gg из данного репозитория в директорию ~/.vscode-server/extensions. Для создания проекта используется команда dotnet new console -lang "F#" -o new_project, которой передается тип проекта. В данном случае мы указываем, что создаваемый проект представляет собой консольное приложение. С помощью флага -o указывается название проекта - new_project. После выполнения данной команды в папке new_project будет создан проект с минимальным набором стандартных файлов и папок:
new_project.fproj - главный файл проекта, который описывает его конфигурацию. В него в необходимо подключить \src\Main\Main.fsproj; program.fs - созданный файл с кодом программы на языке F#. В данной папке необходимо создать файл с расширением .gg для дальнейшего написания кода. Для запуска программы на gg в консоли в папке new_project необходимо ввести команду dotnet run <название созданного файла>.gg.
Синтаксис
В следующей таблице показан синтаксис для языковых конструкций gg. Фигурные скобки {} заключают определяемые пользователем элементы синтаксиса.
Конструкция языка Синтаксис Блок кода ( {expr} ) var-привязки (var a = {expr} ) if (if {cond} : ( {expr} ) ) if-else (if {cond} : ( {expr1} ) else : ( {expr2} )) for (for i [start .. finish] : ) while (while {cond} : ) Типы
Базовые типы, определенные в языке gg:
Тип Описание Принимаемые значения bool Логический true/false float Вещественный 64-битные числа с плавающей точкой string Строковый строка символов Unicode в двойных кавычках Символы комментариев
Однострочные и многострочные комментарии в языке обозначаются с помощью двойных знаков решетки #comment#.
Арифметические операторы
Оператор Описание
- При использовании в качестве бинарного оператора складывает левую и правую части, а при использовании в качестве унарного обозначает положительное число
- При использовании в качестве бинарного оператора вычитает из левой части правую, а при использовании в качестве унарного обозначает отрицательное число
- При использовании в качестве бинарного оператора перемножает левую и правую части, а при использовании в качестве унарного обозначает положительное число / При использовании в качестве бинарного оператора делит левую часть на правую, а при использовании в качестве унарного возвращает обратное число Логические операторы
Оператор Описание & Вычисляет логическое значение операции “И” | Вычисляет логическое значение операции “ИЛИ” Операторы сравнения и присваивания
Оператор Описание = Присваивает левой части значение правой == Возвращает true, если левая часть равна правой, в противном случае - false < Возвращает true, если левая часть меньше правой, в противном случае - false
Возвращает true, если левая часть больше правой, в противном случае - false <= Возвращает true, если левая часть меньше или равна правой, в противном случае - false => Возвращает true, если левая часть больше или равна правой, в противном случае - false Оператор var. Привязка значений
Оператор позволяет определить значение и связать с данными или действиями. После идентификатора через знак равно указываются связываемые с заданным идентификатором данные или действия.
(var id = expression) Var применяется для выражения привязки одного конкретного имени. Простейшая форма var выражения привязывает имя к значению. В качестве значения, можно использовать как числа/числовые выражения, так и строки.
(var a = 5)
(var b = (+ 5 1))
(var c = "Hello, world!") Привязанные имена можно использовать после определения, но не в любом месте после var отображения привязки.
(print x) (var x = 10)
(var x = 10) (print x) Базовые операторы ввода-вывода
Базовый ввод-вывод включает в себя запись данных в консоль, а также чтение из файла и запись в него. Для записи в консоль используется функция print.
( print number) (print "string") ( print (expr)) Для записи в файл используется функция write, которая добавляет строки в файл, затем закрывает его. Если указанный файл не существует, то функция создает его, записывает туда нужные строки и закрывает его.
(write "./file_path" "input_text") Параметр ./file_path - путь к файлу, который находится в текущей директории, input_text - строки, которые добавляются в файл. Для чтения из файла используется функция read, которая открывает заданный файл и считывает построчно всю информацию, содержащуюся в нем, которая сохраняется в строковую переменную и выводится в консоль.
(print(read "./file_path")) Параметр ./file_path - путь к файлу, который находится в текущей директории.
Условные выражения
- if Выражение выполняет ветвь кода и вычисляет значение, если заданное логического выражение истинно.
( if (boolean_expression) : ( expression_body ) ) 2) if-else Выражение выполняет ветви кода и вычисляет различные значения в зависимости от заданного логического выражения.
( if (boolean_expression) : ( expression_body_1 ) else : ( expression_body_2 ) ) В предыдущем синтаксисе expression_body_1 выполняется, когда логическое выражение принимает значение true, в противном случае - expression_body_2. Типы значений, создаваемых в каждой ветви, должны совпадать.
Циклы
Язык поддерживает использование операторов kill и continue, позволяющих завершать циклы досрочно, либо продолжать их выполнение, пропуская при этом одну итерацию. 1) Выражения for Используются для прохода по циклу над диапазоном значений переменной цикла.
(
for identifier [start .. finish] :
(
expression_body
)
)
Тип идентификатора выводится из типа выражения начала и окончания цикла. Правая граница диапазона не включается. 2) Выражения while Выражение используется для выполнения итеративного цикла, пока значение заданного условия истинно.
( while (condition) : ( expression_body ) ) Вычисляется condition. Если оно истинно, то выполняется выражение expression_body. Затем condition проверяется заново. Если оно ложно, то цикл завершается на текущей итерации.
Функции
Функции в языке gg имеют имя, параметры, тело. Определяются с помощью ключевого слова func. Могут быть рекурсивными (функции, вызывающие сами себя). Вызвать функцию можно, указав её название и подаваемое через пробел значение (аргумент функции).
( func function_name {parameters} : ( function_body ) ) Элемент function_name является идентификатором, который представляет функцию. Элемент parametrs состоит из последовательных параметров, разделенных пробелами. Явный тип для каждого параметра не указывается, а компилятор определяет его автоматически из тела функции. Элемент function_body - выражение, представляющее тело функции Оно состоит из нескольких выражений, которые в результате дают итоговое выражение, являющееся возвращающим значением. Простое определение функции выглядит следующим образом:
( func func_example {x} : ( if (> x 0) : ( x ) else : ( 0 ) ) )
(func_example 5) В данном примере func_example является именем функции, x - аргументом, имеющим тип float. Условие if-else представляет собой тело функции. Возвращаемое значение имеет тип float. В языке gg функции могут возвращать другие функции.
( func sum {x1 x2} : ( (var rez = (+ x1 x2)) rez ) )
( func multiply {x1 x2} : ( (var rez = (* x1 x2)) rez ) ) ( func f {x1 x2 x3} : ( (if (<= x1 0) : (print(multiply x1 x2)) else : (print(sum x2 x3)) )
)
)
(f 3 4 5) Здесь функция f принимает 3 параметра. В зависимости от значения первого возвращает одну из функций: sum или multiply. Причем все возвращаемые функции имеют один и тот же тип.