Язык программирования Crystal.

Sorcus

Команда форума
Moderator
Сообщения
8
Симпатии
30
Баллы
151
Crystal - это компилируемый, объектно-ориентированный язык программирования общего назначения со статической типизацией, спроектированный и разработанный Ary Borenszweig, Juan Wajnerman, Brian Cardiff и другими.

Синтаксис​

На синтаксис Crystal сильное влияние оказал язык программирования Ruby.
Благодаря этому код легко пишется и читается, а порог вхождения очень низкий для Ruby разработчиков с опытом.
Ruby:
# A very basic HTTP server
require "http/server"

server = HTTP::Server.new do |context|
  context.response.content_type = "text/plain"
  context.response.print "Hello world, got #{context.request.path}!"
end

puts "Listening on http://127.0.0.1:8080"
server.listen(8080)

Система типов​

В Crystal используется статическая проверка типа и соответственно любые ошибки типов будут отловлены компилятором, не допуская падения в рантайме.
Так же Crystal имеет встроенный вывод типов, что позволяет не указывать большинство типов, делая язык более читабельным.
Ruby:
def shout(x)
  # Notice that both Int32 and String respond_to `to_s`
  x.to_s.upcase
end

foo = ENV["FOO"]? || 10

typeof(foo) # => (Int32 | String)
typeof(shout(foo)) # => String

Проверка нулевых указателей​

Все типы в Crystal являются ненулевыми, а все нулевые переменные представлены как объединение между типом и nil.
В итоге компилятор выполнит автоматическую проверки на нулевые указатели, избавляя от ужасных последствий.
Ruby:
if rand(2) > 0
  my_string = "hello world"
end

puts my_string.upcase
Запустив этот код, компилятор выдаст ошибку
Код:
$ crystal hello_world.cr
Error in hello_world.cr:5: undefined method 'upcase' for Nil (compile-time type is (String | Nil))

puts my_string.upcase
               ^~~~~~

Макросы​

Для метапрограммирования Crystal предлагает мощную систему макросов, от базового шаблонизатор и испектирования AST, до испектирования типов и запуска любых внешних программ.
Ruby:
class Object
  def has_instance_var?(name) : Bool
    {{ @type.instance_vars.map &.name.stringify }}.includes? name
  end
end

person = Person.new "John", 30
person.has_instance_var?("name") #=> true
person.has_instance_var?("birthday") #=> false

Многопоточная модель​

Crystal использует зелёные потоки (green threads), называемые волокнами (fibers), для получения многопоточности.
Fiber-ы общаются друг с другом с помощью каналов, как в Go или Clojure, не прибегая к разделяемой памяти или блокировкам.
Ruby:
channel = Channel(Int32).new
total_lines = 0
files = Dir.glob("*.txt")

files.each do |f|
  spawn do
    lines = File.read_lines(f)
    channel.send lines.size
  end
end

files.size.times do
  total_lines += channel.receive
end

puts total_lines

Привязки к C библиотекам​

Crystal предлагает специальный синтаксис для работы с нативными библиотеками, избавляя от необходимости переизобретать низкоуровневые примитивы.
Ruby:
# Fragment of the BigInt implementation that uses GMP
@[Link("gmp")]
lib LibGMP
  alias Int = LibC::Int
  alias ULong = LibC::ULong

  struct MPZ
    _mp_alloc : Int32
    _mp_size : Int32
    _mp_d : ULong*
  end

  fun init_set_str = __gmpz_init_set_str(rop : MPZ*, str : UInt8*, base : Int) : Int
  fun cmp = __gmpz_cmp(op1 : MPZ*, op2 : MPZ*) : Int
end

struct BigInt < Int
  def initialize(str : String, base = 10)
    err = LibGMP.init_set_str(out @mpz, str, base)
    raise ArgumentError.new("invalid BigInt: #{str}") if err == -1
  end

  def <=>(other : BigInt)
    LibGMP.cmp(mpz, other)
  end
end

Зависимости​

Библиотека Crystal упаковываются в осколки (shards) и распространяются с помощью Git, не нуждаясь в централизованном репозитории.
Встроенные команды позволяют указывать зависимости в YAML файле и получать их из указанных источников.
YAML:
name: my-project
version: 0.1
license: MIT

crystal: 0.21.0

dependencies:
  mysql:
    github: crystal-lang/crystal-mysql
    version: ~> 0.3.1

Если тебе понравилась данная статья, хочешь больше статей по Crystal и есть желание изучить его, ставь лайк :wink::blush2:
 
Паттерны для примера хорошие, но без Hello World пример не полный.
 
Назад
Верх