24 декабря 2023 г. Архивач восстановлен после серьёзной аварии. К сожалению, значительная часть сохранённых изображений и видео была потеряна.
Подробности случившегося. Мы призываем всех неравнодушных
помочь нам с восстановлением утраченного контента!
Информации пока что очень мало, язык еще очень свежий и нестабильный. Есть лишь paper от Марка Марона и дока в начальной стадии написания.
Давайте попробуем рассмотреть некоторые особенности языка.
1) Все значения в Bosque являются неизменяемыми (immutable), чтобы каждый блок кода не содержал никаких сайд-эффектов. По мнению авторов языка это полезно как для человека, так и для компьютера.
При этом, как ни странно, чуть далее по тексту рассказывается, что можно объявить изменяемую переменную ключевым словом var!. И это не просто сахар для более удобной инициализации иммутабельной переменной, это действительно настоящая переменная.
Ладно, допустим, это некий компромисс, и в локальном скоупе так сделали. Но дальше идет упоминание о еще не реализованной фиче языка — передаче аргументов функции по ссылке
function internString(ref env: Map<String, Int>, str: String): Int {
if(env.has(str)) { //use the ref parameter
return env.get(str);
}
env = env.add(str, env.size()); //update the ref parameter
return env.size();
}
Может я чего-то не понимаю, но странная какая-то иммутабельность в языке, если мы можем передать Map по ссылке, и фунция ее намутирует.
2) В языке нет циклов for, while и т.д. Вообще никаких нет. Вместо этого есть коллекции и пайплайны. Другими словами, вместо циклов нужно использовать более высокоуровневые штуки типа map, filter и т.д.
3) Строки можно делать разных типов. Т.е., например, можно сделать строку-имя или строку-zipcode, и для type-чекера это будут две разные строки. Если вы в аргументе функции ожидаете zipcode, а вам по ошибке туда пихают имя, то компилятор это не проглотит. Синтаксис такой: String[Zipcode].
Тоже сомнительная штука, почему не просто ZipCode. Один раз объявить, что ZipCode — это строка и везде в сигнатурах это писать. И почему именно для строк эта типизация сделана, а не для интов, например.
4) Вызов функций можно делать с указанием названия аргументов из сигнатуры функции, например: myfunc(x=1, y=2)
5) В стандартной библиотеке есть различные коллекции, и с коллекциями можно работать по разному. Можно просто по цепочке вызывать map, потом filter и т.д., а можно работать через пайплайны.
var v: List[Int?] = List@{1, 2, none, 4};
//Chained - List@{1, 4, 16}
v->filter(fn(x) => x != none)->map[Int](fn(x) => xx)
//Piped none filter - List@{1, 4, 16}
v |> filter(fn(x) => x != none) |> map[Int](fn(x) => xx)
//Piped with noneable filter - List@{1, 4, 16}
v |??> map[Int](fn(x) => xx)
//Piped with none to result - List@{1, 4, none, 16}
v |?> map[Int](fn(x) => xx)
6) рекурсия считается злом, которое может усложнить программу, поэтому рекурсивные фунции надо помечать словом rec
7) программы на Bosque являются детерминированными. Другими словами в языке нет неопределенного поведения. Например, нельзя использовать переменные, пока они не были определены; алгоритмы сортировки только стабильные и т.д. Если программа выдала какой-то результат, то такой же результат будет и потом, никаких сюрпризов
8) Вместо классов и интерфейсов в языке есть понятия entity и concept.
concept Bar {
field f: Int;
}
entity Baz provides Bar {
field g: Int;
field h: Bool = true;
}
var y = Baz@{f=1, g=2, h=false}; //Create a Baz entity with the given field values
var x = Baz@{f=1, g=2}; //Create a Baz entity with default value for h