- PVSM.RU - https://www.pvsm.ru -
мнение автора может не совпадать с вашим мнением, добро пожаловать в комментарии.
В доисторические времена высокопроизводительные Web-приложения можно было писать, в основном, на C или C++. Поддерживать такие приложения было не просто дорого, а очень дорого.
Потребность в среде программирования, в которой удобно писать, читать и изменять высокопроизводительные приложения, появилась давно.
В первую очередь термины "производительность" и "надежность" относятся к Erlang. В своей нише он великолепен, но синтаксис заставляет желать лучшего. Собственно, именно поэтому появился Elixir [1], но речь сейчас не об этой экосистеме.
Если же немного снизить планку надежности, то здесь перед нами широкий выбор, включая Node [2], Go [3], Nim [4] и Crystal [5]. Можно взглянуть на типичные сравнительные данные по производительности [6], включая более [7] обширные [8].
Все эти среды программирования предлагают сборщик мусора, что уменьшает сложность поддержки кода.
При это Node предлагает всем понятный язык программирования (и вариации на тему), но динамическая типизация снижает производительность в несколько раз относительно других претендентов.
Если нам нужно больше запросов в секунду, то выбор на сегодня — Go. Эта среда программирования обладает великолепными характеристиками производительности, поддержку со стороны крупных компаний и немалое число активных проектов.
Так почему же Crystal?
Crystal предоставляет фронтэнд для инфраструктуры LLVM, позволяя компилировать код под все поддерживаемые платформы (x64, ARM, Web Assembly etc.).
Crystal способен в большинстве случаев сам вывести типы используемых данных.
Например, мы где-то отправляем в метод speak в одном случае строку, в другом случае целое число.
В таком случае Crystal на этапе компиляции знает, что метод speak принимает параметр выведенного типа String | Int32.
Мы можем написать такой код:
speak(15)
speak("Whatever")
def speak( thing )
thing.say_every # Ошибка компиляции, у переменной thing тип (Int32 или String), а у него нет метода say_every
# Здесь можно пользоваться методами класса Object, а также всех классов, общих предков String и Int32
if thing.is_a?(String)
# здесь Crystal гарантирует нам, что у переменной thing тип String, и можно пользоваться его методами.
return thing.sub(/Athes+/, "")
elsif thing.responds_to?(:to_s)
# Здесь Crystal гарантирует нам, что у thing есть метод to_s, и его можно вызвать
return thing.to_s
end
end
Важно отметить, что все значения являются объектами, включая числа и строки. Цена всеобъектности — нулевая, ибо операции над объектами определены на этапе статического анализа в компиляторе.
В общем случае специальная проверка в коде на пустое значение не требуется. Например, в этом примере попытка передачи пустого значения приведет к ошибке компиляции, так как my_string имеет тип (String или Nil), а у типа Nil нет метода upcase:
if rand(2) > 0
my_string = "hello world"
end
puts my_string.upcase
Crystal поддерживает зеленые потоки, каналы, и опцию SO_REUSEPORT — аналогично Go. В настоящее время идёт работа [9] над качественной поддержкой многопоточности на уровне операционной системы, что приведет к эффективным приложениям на нескольких процессорных ядрах.
В Crystal фактически встроен свой менеджер зависимостей — Shards [10].
Функциональность аналогична ruby bundler, perl carton etc. При этом зависимости описываются в shards.yml проекта.
BDD, общий интерфейс по работе с РСУБД и прочие приятности включены в стандартную библиотеку [11].
Я не стану упоминать различные библиотеки для анализа данных и прочая, для этого есть список Awesome Crystal [12].
Из того, что не входит в стандартную поставку, но полезно для web-приложений:
require "kemal"
# Matches GET "http://host:port/"
get "/" do
"Hello World!"
end
# Creates a WebSocket handler.
# Matches "ws://host:port/socket"
ws "/socket" do |socket|
socket.send "Hello from Kemal!"
end
Kemal.run
PG_DB.query_one("select ARRAY[1, null, 3]", &.read(Array(Int32?))
# => [1, nil, 3]
PG_DB.query_one("select '{hello, world}'::text[]", &.read(Array(String))
# => ["hello", "world"]
require "remarkdown"
Remarkdown.to_html("Hello **world**")
Надо сказать, что изучил Crystal я на этих выходных, успев выпустить один проект (благодаря сходству синтаксиса с Ruby). И эта статья является точкой зрения новичка в мире Crystal.
Автор: akzhan
Источник [14]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ruby/254895
Ссылки в тексте:
[1] Elixir: http://elixir-lang.org
[2] Node: https://nodejs.org/
[3] Go: https://golang.org
[4] Nim: https://nim-lang.org/
[5] Crystal: https://crystal-lang.org
[6] сравнительные данные по производительности: http://blog.seraum.com/crystal-lang-vs-nodejs-vs-golang-vs-http-benchmark
[7] более: https://github.com/kostya/benchmarks
[8] обширные: https://www.techempower.com/benchmarks/
[9] идёт работа: https://github.com/crystal-lang/crystal/wiki/Roadmap#concurrency
[10] Shards: https://github.com/crystal-lang/shards
[11] стандартную библиотеку: https://crystal-lang.org/api/0.22.0/
[12] Awesome Crystal: http://awesome-crystal.com
[13] Kemal: http://kemalcr.com/
[14] Источник: https://habrahabr.ru/post/328364/
Нажмите здесь для печати.