У каждого программиста есть мечта — создать свой язык программирования. Самый лучший и самый удобный, конечно же — не то что существующие. Лично для меня идеей-фикс было создание языка, в котором совершенно не будет бойлерплейта, который будет максимально краток, но при этом чрезвычайно красноречив. В течение двух лет я делал попытки добиться желаемого результата, но с чего бы я не начинал, в конце концов после отсечения всего лишнего у меня всегда получался Lisp. И тогда мне в голову пришла гениальная мысль — взять Lisp, и усовершенствовать его в соответствие с моими идеями. В честь первой попавшейся мне на глаза вещи, проект был назван Sova.
Чтобы язык из коробки работал и на сервере, и в вебе, и на мобильных платформах я решил сделать компиляцию в Javascript, который по-моему мнению без шуток является одним из лучше всего спроектированных языков нашего времени и что гораздо более важно обладает мощнейшей экосистемой npm, Node.js, React и React Native.
И перед началом нашего путешествия, чтобы сразу вызвать интерес к дальнейшему прочтению статьи, вот вам пример одного файла Express-приложения на Sova:
=-> './database' database
=-> 'express' express
= application express ()
application.get '/'
-> (request response) (response.sendStatus 200)
application.get '/user/:id'
-> (request response) (response.send (database.getUserById request.params.id))
application.listen 8080
-> () (console.log 'Application is listening on port 8080')
Ну что ж, начнем...
Шаг 1: Вырываем с корнем скобочки из Lisp с помощью индентации Python
Хоть этот комикс и вызывает у меня улыбку каждый раз, как я на него смотрю, я совершенно не согласен с основным его утверждением. Скобочки — это не элегантно, скобочки — это бойлерплейт.
Поэтому первым делом в своем чудесном языке я решил избавится от скобочек. Лучшим решением стала имеющая значение индентация, прямо как в Python. Возьмем, к примеру, такой кусок кода на lisp:
(* 2 (+ 1 2) (- 4 (/ 2 1)))
Конечно, это выражение можно разнести по разным строкам, но от забористости из засоряющих глаз скобочек это нас не избавляет.
(* 2
(+ 1 2)
(- 4 (/ 2 1)))
А теперь посмотрим, как элегантно и воздушно можно написать это же выражение на Sova с помощью имеющей значение индентации:
* 2
+ 1 2
- 4 (/ 2 1)
То есть в Sova выражение a (b c) (d (e f))
равнозначно выражению:
a
b c
d
e f
Шаг 2: Делаем язык лаконичным
Что мне не нравилось в большинстве языков программирования, так это засоренность синтаксиса ничего не значащим, но занимающим место на экране бойлерплейтом — лишними ключевыми словами, бессмысленными знаками препинания и многим другим. Даже в common lisp вместо простых и всем понятных символов часто используются слова для обозначения простейших операций, вроде того же defn
.
Объявление констант
Возьмем к примеру объявление константы в Javascript:
const a = 1
Sova — язык исключительно функциональный и в нем все переменные иммутабельны, поэтому не нужно указывать дополнительное ключевое слово const, а пишется все просто:
= a 1
Функции
Основным элементом любого языка являются функции. Вот так минималистично они выглядят в Sova:
= addOne -> number
+ number 1
= doubleAndAddOne -> number
= doubled (* number 2)
addOne doubled
console.log (doubleAndAddOne 2)
Как и в любых функциональных языках последнее выражение в теле функции является возвращаемым. То есть код выше в скомпилированном JavaScript будет выглядеть как:
const addOne = number => {
return number + 1
}
const doubleAndAddOne = number => {
const doubled = number * 2
return addOne(doubled)
}
console.log(doubleAndAddOne(2))
Сравнения и условия
У условного выражения в Sova может быть как два так и один аргумент.
Вот примеры условий, имеющих два аргумента:
console.log
? true 1 0
console.log
? (> 2 1) 'Greater' 'Less'
console.log
? (> 2 1)
? (> 1 2) 'x' 'y'
'z'
А вот тут например в функции checkNumber мы возвращаем значения по условию:
= checkNumber -> number
? (=== number 1) (<- 'One')
? (=== number 2) (<- 'Two')
? (<= number 9) (<- 'From three to nine')
'Ten or more'
console.log (checkNumber 1)
console.log (checkNumber 4)
console.log (checkNumber 11)
В скомпилированном JavaScipt это выглядит как:
const checkNumber = number => {
if (number === 1) return 'One'
if (number === 2) return 'Two'
if (number <= 9) return 'From three to nine'
return 'Ten or more'
}
console.log(checkNumber(1))
console.log(checkNumber(4))
console.log(checkNumber(11))
Коллекции
Array
Основной коллекцией любого языка является массив. Вот так объявление и деконструкция массива выглядят в Sova:
= list | 1 2 3 4
console.log list
console.log
list.map (-> x (+ x 1))
= (| first second) list
console.log first
console.log second
В скомпилированном JavaScript это будет выглядеть как:
const list = [1, 2, 3, 4]
console.log(list)
console.log(list.map(x => x + 1))
const [first, second] = list
console.log(first)
console.log(second)
Object
Второй самой важной коллекцией является хешмапа. В Sova объявление и деконструкция мапы выглядит так:
= map :
a 1
b 2
c :
d 3
e 4
f 'Hello'
console.log map
= (: a (c (: d e))) map
console.log a
console.log d
console.log e
В скомпилированном JavaScript это выглядит так:
const map = { a: 1, b: 2, c: { d: 3, e: 4 }, f: 'Hello' }
console.log(map)
const { a, c: { d, e }} = map
console.log(a)
console.log(d)
console.log(e)
Если мы хотим вызвать у объекта метод, то есть два способа это сделать. Мы можем вызвать его как object.method parameter1 parameter2
либо как .method object parameter1 parameter2
. Второй способ позволяет нам создавать цепь вызовов методов.
Импорт и экспорт модулей
Импорт
Импортировать в Sova код можно модули как из других .sv
файлов, так и из .js
файлов. Например, в данном примере, импортируются два модуля — data/index.js
и handler/index.sv
:
=-> './data' (: greeting name)
=-> './handler' handle
handle greeting name
В скомпилированном JavaScript это выглядит так:
const { greeting, name } = require('./data')
const handle = require('./handler')
handle(greeting, name)
Импорт как JavaScript, так и Sova модулей дает возможность по чуть-чуть внедрять Sova в существующий Javascript проект.
Экспорт
В данном примере, из модуля экспортируется функция:
<-= -> (greeting name)
console.log greeting
console.log name
В скомпилированном JavaScript это выглядит так:
module.exports = (greeting, name) => {
console.log(greeting)
console.log(name)
}
Примеры использования
Чтобы увидеть всю красоту, воздушность и лаконичность Sova, нужно посмотреть на более менее крупную программу. Например, вот программа вычисляющая средний возраст людей и находящая имя человека, чей возраст наиболее близок к среднему возрасту.
=-> 'lodash' _
= people |
: (name 'Alice') (age 24)
: (name 'Bob') (age 15)
: (name 'Chris') (age 46)
: (name 'Daniel') (age 35)
: (name 'Elisabeth') (age 29)
: (name 'Fred') (age 52)
= averageAge /
.reduce (.map people (-> man man.age))
-> (x y) (+ x y)
0
.length people
= manWithClosestToAverageAge _.minBy
.map people (-> man (: (name man.name) (distance (Math.abs (- averageAge man.age)))))
'distance'
console.log averageAge
console.log manWithClosestToAverageAge.name
Благодаря тому что язык компилируется в JavaScript, становится возможной разработка под любые платформы. Например, вот небольшой пример React-приложения под веб-браузеры:
=-> 'react' React
=-> 'react-dom' ReactDOM
=-> './styles' styles
= (: createElement:e) React
= App -> ((: name))
e 'div' (: (style styles.container))
e 'div' (: (style styles.hello)) 'Hello'
e 'div' (: (style styles.name)) name
ReactDOM.render (e App (: (name 'John'))) (document.getElementById 'root')
Так же в репозитории есть примеры Express-сервера и React Native приложения под мобильные платформы.
Заключение
Таким образом, язык Sova вобрал в себя лучшее из нескольких других языков:
- простота и мощь Lisp
- чистота индентации Python
- рантайм и экосистема JavaScript
Код компилятора с примерами использования языка лежит тут https://github.com/sergeyshpadyrev/sova. Буду рад увидеть звезды на репозитории от всех тех, кому понравилась концепция языка и кто хотел бы, чтобы работа над ним продолжилась. Но сразу предупрежу, что пока что это исключительно proof of concept, и даже поиграться с языком из-за отсутствия документации и некоторых возможностей крайне трудно. Например, в языке пока что отсутствует обработка исключений, классы и другие необходимые вещи. И под Windows запустить его вряд ли получится.
Следующими шагами я планирую дополнить и стабилизировать синтаксис, переписать парсер, написать тесты на парсер и транслятор, написать документацию. А пока, спасибо за внимание и до новых встреч.
Комментарии (101)
abar
20.05.2019 10:00+5Работа интересная, придумывать свой ЯП — это всегда здорово и хороший опыт для программиста. Без сарказма.
Но. Использовать обратную польскую нотацию и утвержать, что язык простой и чистый — попахивает издевательством.
К тому же на том же Котлине задачу «найти средний возраст записей из списка и найти наиболее близкую к среднему запись» можно решить в три строки, после чего код компилируется хоть под JS, хоть под Джаву, хоть ещё куда.staticlab
20.05.2019 10:05Использовать обратную польскую нотацию
Это не обратная нотация. Это вполне себе префиксная, как и в Лиспе. В обратной нотации было бы ещё больше ада :)
abar
20.05.2019 10:11+2Да, точно. Почему-то всегда так получается когда хочется понтануться умным словом в разговоре и забываю перепроверить, что точно помню о чем говорю :(
staticlab
20.05.2019 10:03= App -> ((: name)) e 'div' (: (style styles.container)) e 'div' (: (style styles.hello)) 'Hello' e 'div' (: (style styles.name)) name
И то же самое в CoffeeScript:
App = ({ name }) -> e 'div', style: styles.container, [ e 'div', style: styles.hello, 'Hello' e 'div', style: styles.name, name ]
prostofilya
20.05.2019 10:08+2Если лучший язык в какой-то определённой нише ещё можно найти/создать, то лучший язык в вакууме — нет.
BasicWolf
20.05.2019 10:08SergioShpadi, с почином!
Но есть несколько замечаний :)
Скобки же в Лиспе не от балды. Их смысл как раз таки в том, что любое валидное выражение в Лиспе можно прочесть как программу, а можно как список. Таким образом мы получаем обалденную систему макросов.
По-поводу иммутабельности — имеется ввиду иммутабельность значений? Или всего лишь иммутабельность связки символ-значение?v_m_smith
20.05.2019 17:41А еще скобки легко читать редактору кода, чтобы выполнять текущий блок из любого места, или там скакать к концу-началу. Насколько легко это с индентацией — не понятно.
Надеюсь автор сделал скобки опциональными, а не вообще от них отказался.
Guitariz
20.05.2019 11:04У каждого программиста есть мечта — создать свой язык программирования.
Ойвей, не надо так за всех.
Посмотрел ваши примеры — очень вкусовая наркомания. Не отрицаю, возможно кому-то такое заходит, но с точки зрения длительной разроботки в команде, пожалуй, я выберу что-то более очевидное в плане понимания.
tundramani
20.05.2019 11:05+1Про JS иногда говорят что это Лисп в шкуре Си
JS — это и есть лучший в мире ЯП
И я не понимаю, зачем усложнять си-подобный синтаксис?evocatus
20.05.2019 14:33Про «JS — это LISP» здесь подробно разобрано:
journal.stuffwithstuff.com/2013/07/18/javascript-isnt-scheme
tuxi
20.05.2019 11:17+2Поздравляю с реализацией мечты :)
Но язык должен быть читаемым легко и всеми «с ходу», тогда его ждет успех, а не мизерная маргинальная ниша внутри академического сообщества, имхо.
Таки возможность самодокументации кода — это супер фишка.Arlekcangp
20.05.2019 17:05Прежде всего цель должна быть, которую на этом яп можно достичь проще, быстрее, более понятным способом. Тогда язык займет нишу. Вот, например, скрипты в браузере — js: интерпретируемый с динамической типизацией, прототипный ООП и элементы функциональных языков. Или параллельное программирование на серверной стороне — Go (не люблю его, но т к его все знают — привожу в качестве примера): компилируемый, строгая типизация, поддержка из коробки таких сложных абстракций как CSP. Ну очевидно, что можно писать на js на сервере и наоборот — на go в браузере. Вот только так делают отдельные извращенцы. И в обратную сторону справедливо — если язык "слишком универсален" — в нем есть все и куча лишнего одновременно. И со временем эти фичи ещё и расширяются и вступают в конфликт в конечном итоге. Учитывая количество ЯП сейчас, нет смысла делать новый, если он не решает какую то специфическую задачу, которую его предшественники решают не идеально. Ну только для обучения если.
tuxi
20.05.2019 18:00ну JS сначала таки занял нишу и только потом появились вкусные плюшки, псевдо ООП и функциональщина прочая. А сначала же он был простой, с простым синтаксисом и ява-подобный. То есть читабельный.
assembled
21.05.2019 15:52ява-подобный
Не смешите меня, где вы там ява-подобность увидели? Вы Java то хоть раз видели?
Разработчики JavaScript просто примазались к популярному в то время бренду.tuxi
21.05.2019 17:57Я на 1.1-1.3 начинал писать и на JS во времена нетскейпа. Уж позвольте не согласиться с Вами :)
assembled
21.05.2019 19:19Из схожего у них только основная часть синтаксиса выражений и управляющих конструкций, что унаследовано ими от C, как и у большинства современных языков, прямо или косвенно. Собственно, на этом сходства и заканчиваются. Конкретно чего-то от Java в JavaScript'е нет и не было.
tuxi
21.05.2019 21:05А сначала же он был простой, с простым синтаксисом и ява-подобный. То есть читабельный.
Я ровно тоже самое и написал. Синтаксис на старте был читаемым даже для неподготовленного человека (чего не скажешь например про С). Поэтому в начале нулевых, при поддержке развития интерактивного веба он и выстрелил так хорошо.assembled
21.05.2019 21:57+1Возможно мне не удалось правильно распарсить ваш коммент, слова о простоте не выглядят относящимися к словам о «ява-подобии» :).
читаемым даже для неподготовленного человека
Ну, скорее для тех, кто уже знаком с каким-либо си-подобным языком.
VIkrom
20.05.2019 11:24+3У каждого программиста есть мечта — создать свой язык программирования.
Нет.
lair
20.05.2019 11:55так это засоренность синтаксиса ничего не значащим, но занимающим место на экране бойлерплейтом — лишними ключевыми словами
[...]
= checkNumber -> number ? (=== number 1) (<- 'One') ? (=== number 2) (<- 'Two') ? (<= number 9) (<- 'From three to nine') 'Ten or more'
Ну и зачем в этом примере слово
number
четыре раза?
let checkNumber = function | 1 -> "One" | 2 -> "Two" | x when x > 2 && x <= 9 -> "From three to nine" | _ -> "Ten or more"
(и немедленно получаем warning "значения от нуля и вниз не покрыты")
Ну и да, говорить о "лучшем в мире языке программирования" и вообще не упомянуть типизацию?
SergioShpadi Автор
20.05.2019 12:04-3Все верно. Типизация не делает код лучше, но сильно замедляет разработку. На языках с динамической типизацией разработка идет в разы быстрее.
Я сам получил прививку от любви к типам поработав некоторое время со Scala. Сначала мне это нравилось, но в конце концов я понял, что большую часть времени занимаюсь не разработкой, а ублажением компилятора.Guitariz
20.05.2019 12:08+1Типизация не делает код лучше
Пожалуйста, остановитесь. Такие заявления должны же строиться на чем-то большем, чем просто заявления.
Замедляет разработку отсутствие прямоты рук у разработчика. А типизация, например, ускоряет отладку (аж на этапе компиляции) и упрощает дальнейшую поддержку. Но это все например, я не буду утверждать, что делает код лучше и или хуже — это все субъективщина.
Я так понимаю, разработка идет быстрее, потому что компилятор даст вам по рукам за ошибки в коде. Это безусловно, влияет на скорость разработки.
Только, я надеюсь, вам известно, зачем же все таки введены такие ограничения и чем типизация и компиляция полезна и отличается от динамических интерпретируемых языков?SergioShpadi Автор
20.05.2019 12:16Никакой корреляции между статической типизацией и количеством багов нет. Вот советую почитать хороший пост на эту тему (https://ru.hexlet.io/blog/posts/the-broken-promise-of-static-typing)
Про ускорение отладки это смешно, учитывая что в лиспоподобных языках, да и многих динамических есть REPL. Но большинство не используют его, потому что проще просто перезапустить код и сразу увидеть изменение без всякой перекомпиляции.
Aingis
20.05.2019 13:14+3Пожалуйста, остановитесь. Такие заявления должны же строиться на чем-то большем, чем просто заявления.
Ну, вообще-то бремя доказательство тут, наоборот, лежит на доказывании утверждения пользы типизации. И — увы! — несмотря на десятки лет исследований надёжности ПО, польза типизации не доказана. Есть практики с доказанной пользой: такие как код-ревью и тесты. Типизация к ним не относится.
А типизация, например, ускоряет отладку (аж на этапе компиляции) и упрощает дальнейшую поддержку.
Вот это как раз и требуется доказать. Ещё никто не смог привести подтверждающие цифры. С учётом того, что всё это происходит после многих часов ублажения компилятора, польза весьма сомнительна и не превышает накладных расходов.
Guitariz
20.05.2019 13:51+1Типизация есть во всех языках, вопрос про статическую и динамическую вариацию. Так что наброс не засчитан.
Ублажения компилятора происходят у тех, кто не знаком со стандартом языка.Aingis
20.05.2019 15:24-6- Шланг засчитан.
- Как только вы начнёте писать программу посложнее Hello World с динамическими структурами и рекурсией, вы быстро обнаружите, что типами это описать это очень сложно, если не невозможно. Известный факт, что некоторые подходы ФП не описываются статической типизацией.
lair
20.05.2019 15:27+1Как только вы начнёте писать программу посложнее Hello World с динамическими структурами и рекурсией, вы быстро обнаружите, что типами это описать это очень сложно
Ну писал я сложные программы с "динамическими структурами и рекурсией", на статически типизированном языке. Ну да, надо подумать иногда. Но ничего невозможного я не видел.
Известный факт, что некоторые подходы ФП не описываются статической типизацией.
А можно пример?
Guitariz
20.05.2019 15:35+3Ой ой, как только Hello world закончился, сразу динамические структуры поперли во все щели и рекурсия, рекурсия, аж через край льется.
Как я только умудряюсь одни хелловорлды писать на работе, ума не приложу.
Я понял, что диалога нет. Вы видимо не видели, какие штуки на статически типизированых языках пишут.Aingis
21.05.2019 15:07Диалога и вправду нет. Вы так и не привели обоснований утверждения о пользе типизации с цифрами. Типичное поведение слепо верующих фанатиков: отбрехаться, не предоставляя реальные факты.
Guitariz
21.05.2019 15:13-1Статическая типизация работает быстрее, т.к. операции приведения к типу происходит на этапе компиляции, а не в рантайме, присущие динамической типизации.
Польза очевидна — в производительности.
Ну и да, статическая типизация сама по себе убирает необходимость тестирования на приведение типов.
Жаль, что приходится ссылки на википедию прикреплять, но видимо, без этого никак.
retran
21.05.2019 16:22А на мой вопрос сможете ответить?
Вот этот — habr.com/en/post/451422/#comment_20176348Guitariz
22.05.2019 01:42Я — Понятия не имею. Но и вопрос динамической тиизации не в скорости, она тоже нужны для определенных задач, по любому придется чем то пожертвовать.
0xd34df00d
20.05.2019 16:22+1Как только вы начнёте писать программу посложнее Hello World с динамическими структурами и рекурсией
Типизация, кстати, позволяет статически доказывать, что рекурсия завершима (или, обобщая, что комплюктер производит полезную работу за конечное число шагов, если мы говорим о потенциально бесконечно работающих программах вроде серверов).
Как вы это тестами докажете?
0xd34df00d
20.05.2019 16:20+2Есть практики с доказанной пользой: такие как код-ревью и тесты. Типизация к ним не относится.
Типизация — это такой подвид тестов. От выразительной силы типизации зависит то, какие «тесты» с её помощью вы можете написать.
И типизация может гарантировать выполняемость утверждений с квантором всеобщности, в отличие от тестов.
Aingis
20.05.2019 16:29-3Типизация — это подвид хреновых тестов. Тех, которые проверяют детали реализации, а не ожидаемое поведение. Хорошие тесты позволяют вам переписать реализацию без переписывания тестов. Типизация же требует изменений на каждый чих. При этом ловит только тривиальные ошибки, которые при хороших тестах и так будут отловлены.
0xd34df00d
20.05.2019 16:33+2Почему?
Если у меня есть функция
sort
с типом(xs : List a) -> (ys : List a ** Sorted xs ys)
(или функцияsort : List a -> List a
и рядомsortTheorem : (xs : List a) -> Sorted xs (sort xs)
, это чуть более модульный подход), то она проверяет, что функция возвращает сортированный список. Без деталей реализации.
Если у меня есть функция с типом
a -> b
, иb
не имеет видIO b'
(и ещё пару подобных вариантов), то функция не лезет в сеть и на диск, не майнит биткоины на вашем компьютере и не утягивает ключи от биткоин-кошельков. Успехов проверить это тестами.
И нет, на каждый чих ничего менять не надо. Зачем вам менять тип функции, если поменялась только её реализация? А внутри функции у вас никаких аннотаций типов нет, тайпчекер всё сам выводит.
А если я существенно меняю логику, то я наоборот хочу, чтобы тайпчекер мне указал на все места, на которые надо обратить внимание.
lair
20.05.2019 16:33+1Типизация же требует изменений на каждый чих.
Это утверждение настолько же обосновано, как и "тесты требуют изменений на каждый чих".
Guitariz
20.05.2019 16:39+1Нормальная типизация позволяет вам тестировать бизнес логику, а не кастовать данные (причем здесь приложение, если проверяем данные) во что угодно, считать количество переданных параметров и убеждаться, что вам пришел не null — а потом называть это тестированием.
lair
20.05.2019 12:12Типизация не делает код лучше
А ничего, что у любого языка есть "типизация"? Но вы просто игнорируете этот факт, вы закрываете на его глаза — а потом немедленно вводите костыли в виде
number
в вашем коде.
сильно замедляет разработку.
… или нет. Я вот на языках со статической типизацией (типа C#) пишу быстрее, чем на языках с динамической (типа python), потому что мне проще увидеть, когда я запихиваю "не то не туда".
На языках с динамической типизацией разработка идет в разы быстрее.
Во-первых, это заявление неплохо бы подтвердить ссылкой на авторитетные источники. Во-вторых, после этого неплохо бы сравнить аналогичные источники по стоимости поддержки такого кода.
0xd34df00d
20.05.2019 16:19А ничего, что у любого языка есть "типизация"?
Смотря что называть типизацией.
Классическая задача типов — статически гарантировать, что программы удовлетворяют определённым требованиям. Смешивать это с наличием рантайм-меток и рантайм-проверок — можно, конечно, и это, увы, достаточно общепринятая точка зрения, но она неконструктивна и не имеет смысла.
Guitariz
20.05.2019 16:44Это вы про статическую типизацию. Само поняте типизации гораздо шире и в программировании присутствует всегда
0xd34df00d
20.05.2019 16:48То есть, если я буду рассуждать исключительно в терминах пары из
void*
и некоторого тега, описывающего семантику значения по этому указателю, и предварять любые операции проверками этого тега, то у меня получится типизация?
Не, ну можно так говорить, но как-то, ИМХО, неправильно называть настолько принципиально разные вещи одним термином, различая их лишь неприметным прилагательным.
Guitariz
20.05.2019 16:56Это прилагательное и несет в себе смысл. Сама типизация никуда не девается.
Простой пример — для операции «1» + «1» вам все равно придется объяснить, складываете вы строки или числа. «Сам» язык программирования не выбирает, он либо приоритет имеет, либо ошибку вам выкинет. Самостоятельно «догадаться» он не в состоянии.
Это как раз именно про типизацию в принципе.0xd34df00d
20.05.2019 17:00Это потому что тут перегрузка операторов есть. Если у меня будет отдельно функция
addInt
и отдельноconcatStr
, то ничего никому выбирать не придётся.
Чистое лямбда-исчисление (тьюринг-полное, кстати) вполне себе нетипизировано. Там даже нолик как false выглядит в Church encoding, и один можно использовать вместо другого вообще без всяких мыслей о типах.
Собственно, да, хороший пример. Где типы в untyped lambda calculus?
Guitariz
20.05.2019 17:11Вопрос в том, что операция над статической типизацией имеет малое процессорное время выполнения и выдает ошибку в случае нарушения правил.
Динамическая типизация (в 99% случаев) так же скатывается в стандартные процессорные инструкции, дополнительно проведя все касты в рантайме. Вы же не написали собственное сложение а используете предоставленное языком?
Это занимает больше времени, но позволяет писать по парадигме динамической типизации.
Я не берусь утверждать, что лучше. Методы имеют разное применение, да и юзайте, что вам подходит.0xd34df00d
20.05.2019 17:37Не, я-то апологет статической типизации, причём, ну, очень ортодоксальный апологет.
У рантайм-проверок и смысл другой, и предназначение другое, и выразительная мощность другая (статические типы заведомо консервативны — для любой типизации существует семантически корректная программа, которая меж тем нетипизируема).
Ну да ладно, видимо, стоит уж мне прекратить пропагандировать различение этих двух разных ситуаций.
Скрытый текстХотя ко мне вчера на stackoverflow чувак справедливо придрался, что я использовал термин «доказательство от противного» в неправильном контексте, так что хз.
tuxi
20.05.2019 12:45Собеседование на должность секретаря. Директор спрашивает:
— Какая у вас скорость печати?
— 100 знаков в минуту!
— Спасибо, Вы нам не подходите! Следующая!
— Какая у вас скорость печати?
— 200 знаков в минуту!
— Спасибо, Вы нам не подходите! Следующая!
— Какая у вас скорость печати?
— 3000 знаков в минуту!!!
— Так много???!!!
— Ага! Правда все время такая ерунда получается...
retran
20.05.2019 15:05+3Типизация не делает код лучше
Расскажите, пожалуйста, как должен быть устроен эффективный по производительности и памяти рантайм с динамической типизацией (меня интересуют аллокации на стеке и хипе, data locality, расходы на сборку мусора, etc).
И, нет, компьютеры все еще недостаточно быстрые, чтобы все могли на это забить.
0xd34df00d
20.05.2019 16:17+2Вот ведь забавно, я окончательную прививку от динамической типизации получил, поработав с хаскелем. Сначала мне это выворачивало мозги, но в конце концов я понял, что большую часть времени я занимаюсь не отладкой, а разработкой. И в разы быстрее, да.
namikiri
21.05.2019 08:30Сначала вам типизация мешает, потом компиляция, и в результате мы получаем очередной браузер размером под сто мегабайт в качестве текстового редактора. Нет, спасибо, оставьте себе.
GarfieldX
22.05.2019 12:32+1Про замедление разработки из-за наличия статической типизации смешно читать. Такое ощущение, что прям очередной гений стиля «херак-херак и в продакшн». Вспоминаются всякие чудики из интернета, по словам которых они каждую свободную минуту могут монетизировать и все из себя такие крутые, что, буквально, матери подать стакан воды уже убыток. Только не понятно что они на форумах интернета забыли. Это еще больше разработку замедляет ведь :)
Ну вот никогда за мои 15 лет опыта никакая типизация никак не влияла на скорость. Зато на скорость влияет куча говнокода после таких вот кодеров за которыми приходится разгребать авгиевы конюшни.
Статическая типизация учит порядку в мышлении и однозначно делает код лучше. И уж точно никогда и никак не мешала, разве что генерировать говнокод. Не стоит этим прикрывать свои недостатки.
Динамическая же типизация возникла там, где это было необходимо.fireSparrow
22.05.2019 13:06-1+1.
Когда только начинаешь учить язык с нормальной типизацией, постоянно спотыкаешься о типы, и кажется, что это компилятор придирается на пустом месте, что можно было бы обойтись без всего этого, что это какой-то лишний бойлерплейт, который только мешает. Но достаточно быстро вырабатывается привычка, об этом уже не надо задумываться — мозг за всем на автомате следит.
Но многие делают выводы о языке и забрасывают его ещё до этого.
SergioShpadi Автор
20.05.2019 12:11Вообще, поработав на достаточно большом количестве проектов, я понял, что никакими методологиями и техническими приблудами сделать код более легко изменяемым, надежным и чистым нельзя. Ни типизация, ни eslint, ни юнит тесты не помогают. Да полезный эффект от них есть и чаще всего он достаточно велик, но основной затык всегда — это прямота рук программистов. Если программисты оверинжинирят на ровном месте, не изучают мануалов до того, как использовать библиотеку и проектируют кривую архитектуру приложения, то ничего не поможет
lair
20.05.2019 12:12+1Ни типизация, ни eslint, ни юнит тесты не помогают.
Кому не помогают? Вам не помогают? Ну да, верю. Мне — помогают.
Guitariz
20.05.2019 12:19это все дураки придумали, наверно, или проклятые менеджеры, чтобы разводить заказчика на лишние траты. Я вот накодил и сразу в прод лью</sarkasm off>
lair
20.05.2019 12:23Вот у вас точно самый лучший в мире язык программирования, раз такое позволяет.
Guitariz
20.05.2019 13:12+1По моему если автор спорит о том, что лучше — статическая или динамическая типизация, дальше конструктивно можно даже не пытаться.
В мире приняты несколько тем, запрещенных для обсуждения — политика, религия, сексуальная ориентация.
Для разработчиков надо сюда внести еще «динамическая или статческая типизация», «фп или ооп», «множественное или одиночное наследование».
SergioShpadi Автор
20.05.2019 12:24Мне в наследство часто доставались репозитории с отборным еле-работающим говнокодом, прекрасно проходящим проверку линтером, с наличием кучи юнит-тестов и flow-типами.
Эти инструменты могут сделать хороший код надежней, чище и лучше. Но плохой код плох не потому что не использует линтер или типы, а потому что криво написан. И можно хоть сколько угодно танцевать вокруг этого кода с линтером и чем угодно, добиться значимого улучшения без тотального переписывания не удастся.
igormich88
20.05.2019 13:13Я правильно понимаю что у вас не предполагается полноценных объектов, а только хэшмапы?
v_m_smith
20.05.2019 17:32если переменные иммутабельны, то почему вы продолжаете называть их переменными, а не постоянными например?
FForth
20.05.2019 19:32-1Автор, не смотрели при изобретении своего языка на целую группу конкатенативных языков
и в частности Factor язык, который был изобретён разработчиком его при отказе от использования Java?assembled
21.05.2019 16:29Настоящие программисты не пишут на лиспах и фортах. Их используют лишь сосунки.
Ни постфиксные ни префиксные языки не нужны, вы не понимаете, ни что не держит мозг в тонусе лучше, чем необходимость помнить 20 уровней приоритетов операторов и ассоциативность каждого.FForth
21.05.2019 16:37Да, чем больше размышляешь, тем больше приходишь к выводу, что языки программирования разделяет вопрос об отношении к скобкам.
Forth на Лурк
, а мозг и без них может обойтись, что и подтвердил автор данного поста заменив их пробелами в Питон варианте. :)
Vahman
20.05.2019 21:21+2когда же это закончится. хайп драйвен девелопмент и борьба с ветряными мельницами.
Автор хочет красивый и выразительный язык, и предлагает следующее для описания вычислений:
А теперь посмотрим, как элегантно и воздушно можно написать это же выражение на Sova с помощью имеющей значение индентации:
* 2 + 1 2 - 4 (/ 2 1)
Думаю нужно пойти дальше, и записывать в такой манере математические статьи, и литературу. Это же прекрасно, отлично читается.
Если честно, я надеюсь, что автор шутит. Просто после всех таких статей, и прочих, где рассказывают, например, как копипаста на go становится более изящным решением, чем generic в C#, например, я начинаю сомневаться в будущем программирования.
ПС: На самом деле имеющая значение индентация — это тоже бойлерплэйт, нажимать на таб или на пробелы — все тоже, что эти скобки кошмарные ставить. Надо писать код в одну строку, а scope сообщать силой мысли напрямую компилятору.
Sirikid
20.05.2019 22:02Таким образом, язык Sova вобрал в себя лучшее из нескольких других языков:
А макросы у тебя где?
- простота и мощь Lisp
DexterHD
20.05.2019 22:33-1У каждого программиста есть мечта — создать свой язык программирования.
Нет
zim32
21.05.2019 13:16+1Нормально так, для увеличения чсв сойдёт. Я тоже думал написать язык, но во время понял что я не самый умный в этом мире.
FForth
21.05.2019 13:40Теперь осталось на своём языке создать уникальное ПО или технологию для оправдания сего действия.
YemSalat
22.05.2019 07:59У меня знакомый работает в компании, которая так и сделала.
Написали свой язык толи для принтеров, толи еще для какой-то периферии и теперь продают его и курсы по нему в разных странах. (Как сам язык называется к сожалению не помню)
assembled
21.05.2019 14:42+1Такой синтаксис называется I-expressions, придуман давно и даже в каком-то диалекте лиспа был реализован (вроде Scheme).
Почитайте ещё про M-expressions.
GarfieldX
21.05.2019 22:45Что за чушь. Никогда даже не возникало такой мысли. Такое свойственно либо начинающему программисту в стадии зазнайства "все вокруг идиоты, один я весь в белом", либо идеалисту.
0xd34df00d
22.05.2019 05:17Нет, ну почему. Мне было бы интересно сделать свой язык программирования, хотя я вроде как не совсем зазнайка и не идеалист. Даже несколько языков программирования, с разными идеями:
- Что, если отказаться от parametricity для зависимых типов-сумм, где первый элемент в зависимой паре — тип?
- Можно ли попробовать интернализировать тотальность функций и как-то формализовать это понятие, а не выносить это на уровень метаязыка?
- Можно ли работать с отношениями эквивалентности как-то изящнее, чем так?
Ну это так, сходу.
Sirikid
22.05.2019 18:333. Сложно воспринимать код на SO, это про сетоиды?
0xd34df00d
22.05.2019 18:35Да.
Sirikid
22.05.2019 18:46Тогда ответ можно. Берешь HoTT и
быстро вилкойпутями и интервалами работаешь с этими эквивалентностями.0xd34df00d
22.05.2019 18:48Язык-то где, где это все уже готовое?
Не кок плз, люблю видеть свои термы.
GarfieldX
22.05.2019 19:10В принципе, если есть избыток свободного времени, то имея подобный интерес можно и поиграться. В академических целях. Но рассчитывать всерьез, что это панацея, да еще и удастся продвинуть — явно не стоит.
Самому же реально такая мысль не разу не посещала, даже мимо не пробегала. Всегда было интересно решить задачу, а язык — всего лишь средство. Тех что напридумывали уже с избытком хватает для самых разных нужд.0xd34df00d
22.05.2019 20:10Именно, исключительно академический интерес.
Который, впрочем, можно сделать работой и решить проблему со свободным временем, если устроиться, наконец, в кокодемию.
YemSalat
22.05.2019 07:48Статья интересная, и парсер у вас довольно мило написан.
Но сам язык в текущем виде, особой пользы не представляет нa мой взгляд. Тот же пример с экспрессом почти ничем не отличается от такого же кода на js. Как уже выше написали, чтобы язык имел шанс на востребованность — у него должна быть своя ниша. Просто новым языком (особенно с весьма спорными фичами) пользоваться никто не будет.
vlreshet
*Автор*
*Тоже автор*Ну правда, я чего-то не понимаю, или в какой-то вселенной читается действительно проще и удобнее чем ?
alexesDev
Есть ещё более читаемые варианты в языках типа ruby
hakell
dom1n1k
Чем перевёрнутое с ног на голову условие удобнее?
Если A то B — естественный порядок.
B если A — странный.
lair
Да оба они, на самом деле, "естественны".
alexesDev
Может буть чуть чуть. Но если развернуть целиком, то такая запись совсем обычная.
B только если A
dom1n1k
Естественно сначала понять ситуацию, а уже потом действие в ней.
v_m_smith
clojure
zagayevskiy
Заменить :else на T и будет просто Лисп.
FreeBa
Для лисперов обратная польская/префиксная запись проще и очевиднее класической. Это стоит учитывать.
alexesDev
Это обычная запись, если воспринимать оператор как имя функции.
То, что там скобки по другому устроены — особенность языка. В Haskell это
т.е. целиком фишка языка