Академичность головного мозга на примере Swift, Golang, Rust и Kotlin
UPD: Немного стыдно за этот пост. В течение последних трех лет я сильно поменял свое мнение, это был долгий процесс и за эти годы я получил массу дополнительного опыта. Я перестал считать C-style declaration чем-то более лучшим. Учитывая, что конструкции типа let x: u32 = 5
облегчают жизнь компилятору (парсинг грамматики происходит куда проще) и к ним быстро привыкаешь, я все меньше и меньше стал предпочитать С-подобный синтаксис. Тем более, что современные языки программирования хорошо умеют в вывод типов, а линтер вам и так подсветит выведенный тип. Go, правда, все еще выглядит стремно. Ну и возвращаемый тип функции в конце иногда мешает читаемости еще сильнее, особенно в Rust с кучей Dyn/Box.
Знаете, у меня есть одно интересное правило, которого я придерживаюсь последние 3 года. Выглядит оно так:
Если я хочу посмотреть новый язык программирования, то я начинаю писать на нем эмулятор. Простенький, типо CHIP-8.
Почему? Потому что это лучший "бенчмарк" языка по многим параметрам: I/O, работа с файлами, работа с графическими библиотеками и звуком, типы данных, классы/структуры, циклы, и все-все-все.
Написав простенький эмулятор ты сразу для себя закрываешь огромное число вопросов уровня "а как тут делать что-то?".
Мне часто советуют всякие новые языки, и сам я интересуюсь развитием Rust, к примеру. Я часто гляжу на Go, Swift, Kotlin, Crystal, Nim и другие интересные для меня ЯП, слежу за их развитием и прочим.
И знаете, я выделил для себя один очень странный тренд, который я не могу объяснить: если кто-то может, то скажите и объясните.
Вы никогда не задумывались, почему вы пишете именно так, как вы пишете? Почему существуют стили синтаксиса?
Новые языки создаются удобными и лаконичными. Тогда почему в этих новых языках я встречаю убогие и не лаконичные конструкции времен Паскаля? Почему эти языки уже на фундаментальном уровне пытаются выглядеть неудобно?
Объясню на простом примере синтаксиса Golang и других языков.
Присваивание
var i int = 2 //явно var i = 2 //неявно вне функции i := 2 //неявно, но только в функциях
Swift (тут вообще полный пиздец)
var myVariable = 42 //обычная переменная myVariable = 50 //обычная переменная (???) let myConstant = 42 //константа let explicitDouble: Double = 70 //константа с явным типом var myVariable: String = "Hello" //переменная с явным типом
let x = 5; //константа let x: i32 = 5; //константа с явным типом let mut x = 5 //изменяемая переменная
val c: Int = 5 //явно, неизменяема val c = 5 //неявно, неизменяема var c = 5 //неявно, изменяема
Да, Rust безопасный язык, и я не говорю, что mut — это плохо. Плохо излишнее let и тип данных в конце. Зачем? Зачем Golang и var, и int в одной строке? Зачем Swift вообще существует с таким переусложненным объявлением переменных?
Ведь можно сделать это аккуратно и лаконично — и не надо ничего изобретать. Обычное присваивание переменной с указанием типа:
int i = 2 //явно var i = 2 //неявно
Константа и изменяемое (для Rust)
const i = 2 //неявно const int i = 2 //явно mut i = 2 //невяно, изменяемо mut int i = 2 //явно, изменяемо
Сравните сами два примера и их читаемость
var i: Float = 5.0 // Swift float i = 5.0 //классический C-style
Да, у константы букв больше, но читаемость намного лучше. Сразу видно и тип данных, и изменяем он или нет.
У Golang, в принципе, все еще не так плохо, но избыточность прослеживается. Зачем она здесь нужна, чем так плох C-style? Почему все современные языки хотят казаться такими элитными и пытаются следовать неудобному академическому стилю?
Что интересно, все выдумывают максимально уебанские конструкции и умудряются соединять в одном языке var и val (Kotlin, привет).
Кто вообще додумался писать тип переменной после ее имени, а вначале еще и var/val/let добавлять?
Зато у Swift можно использовать ЭМОДЖИ
let 🐶🐮 = "dogcow"
Функции
О да, сейчас вы просто охуеете, если еще нет. Без прелюдий сразу в пекло.
func sqrt(x float64) string { if x < 0 { return sqrt(-x) + "i" } return fmt.Sprint(math.Sqrt(x)) }
func вначале, после скобок возвращаемое значение. Аргументы в порядке "имя -> тип переменной".
func greet(person: String, day: String) -> String { return "Hello \(person), today is \(day)." }
-> -> -> смотри сюда и не пропусти возвращаемое значение, ты же такой тупой <- <- <-
fn add_one(x: i32) -> i32 { x + 1 }
fun double(x: Int): Int { return 2 * x }
Заметили, как их уебищный синтаксис похож? Это ключевые слова func, fun, fn, лишь бы ты не перепутал функцию с чем-то еще (когда, блять, такая проблема вообще была?) и возвращаемое значение после скобок, убогие типы данных через двоеточие.
Давайте напишем простую функцию в C-style, который эти замечательные языки послали нахуй ради АКАДЕМИЧНОСТИ.
int double(int x){ return 2*x }
func double(x: Int) -> Int { return 2*x }
Лаконично, ничего не скажешь, ебать.
Кстати, вы никогда не задумывались, насколько вам удобно набирать -> каждый раз при написании функции?
Массивы
Напоследок покажу вам ебаный ад
var a [2]string //пустой массив primes := [6]int{2, 3, 5, 7, 11, 13} //создаем и инициализируем
var someInts = [Int]() //пустой массив let oddNumbers = [1, 3, 5, 7, 9, 11, 13, 15] //создаем и инициализируем неявно (статический) let oddNumbers: [Int] = [1, 3, 5, 7, 9, 11, 13, 15] создаем и инициализируем явно (статический) var shoppingList: [String] = ["Eggs", "Milk"] //создаем массив и инициализируем два значения через литералы
let array: [i32; 3] = [0; 3]; //создаем массив и три раза вносим значние 0
val x: IntArray = intArrayOf(1, 2, 3) //эту ебалу я даже комментировать не хочу
Посмотрим, что так не понравилось уникальным АКАДЕМИЧЕСКИМ языкам в классическом C-style
int balance[5]; //просто создаем int balance[5] = {1000, 2, 3, 70, 50}; //создаем и инициализируем int balance[] = {1000, 2, 3, 70, 50}; //можно даже так
Сравним с великолепием, которое предлагает Swift (для удобства сравнивайте последнюю строчку верхнего блока с нижней).
let balance: [Int] = [1000, 2, 3, 70, 5] //создаем и инициализируем
Я сначала хотел написать код для статического массива, чтобы точно сравнить с C-style, но я с удивлением для себя обнаружил, что Swift не дает возможности создать массив фиксированного размера. Зато мы всегда можем использовать эмоджи 😂😂😂😂😂😂😂😂😂😂😂
Не понимаю
Не понимаю, нахуя они это делают. Что это за хипстерский тренд — выкинуть отличный и лаконичный C-style, который может быть намного лаконичнее, что я показал выше.
Возможно, что я консервативен, но я искренне не понимаю, почему нам твердят о большей читаемости и лаконичности кода, и суют такие монструозные конструкции с избыточными словами?
Я лишь вижу одну причину такого дрочева: это попытка сделать свой язык каким-то особенно-крутым, мол, гляньте, у нас академический синтаксис и присваивание как в математике (let идет из математики, как и тип после имени переменной).
Да, математика — это большая часть мира IT, но, блять, математические конструкции не созданы для программистских задач — удобного чтения и повышенной продуктивности.
Я писал пост о том, каким ужасом и отвратительным чудовищем стал C++, в котором за более чем 30 лет развития смешались несколько стилей, концепций, миллиард костылей и обратных совместимостей. Эти же языки создают изначально уебищный синтаксис, который можно было бы сделать куда более аккуратным и не потерять ни в читаемости, ни в понимании.
И я ни в коем случае не хочу сказать, что эти языки плохие. Нет, я всего лишь пытаюсь обсудить синтаксис, который, как мне кажется, идет в разрез с заявлениями о чистоте и аккуратности языков.