一种具有Ruby风格的语法的快速编程语言
什么啊
Crystal是一种新的,优雅的,多范式的编程语言,可以高效且快速地进行。 它具有Ruby启发的R̶u̶b̶y's语法,并可以编译为本机代码。 实际上,这种语言与Ruby的相似程度是不现实的。
该语言将高效的代码与开发人员的生产力相结合,添加了完整的OOP,出色的并发模型和可助您一臂之力的编译器。
本文旨在为您提供简短的概述,将其与Ruby进行直接的性能比较,并展示一些使其与众不同的东西。 建议您在继续阅读之前至少了解一些Ruby。
从有趣的东西开始-一个出色的例子
让我们实际了解一下Crystal的性能如何。
我用Crystal和Ruby编写了AA树 。
注意:代码质量可能不是一流的。 故意编写一些Crystal代码行
我们将运行以下代码来对每个实现进行基准测试:
这实际上是将数字添加到树中(内部对其进行排序),然后逐个删除每个数字。 我们还检查每次添加/删除两次树是否包含给定的数字。
上面的代码片段实际上是Crystal代码。
就像我说的那样,这些语言乍一看是相同的。 从Crystal到Ruby重写代码使我对360行文件总共进行了50行更改 。 27如果你很贪心
值得注意的是,这些更改只是删除了.as()方法调用和类型注释。
好的,它们看起来一样,但是Crystal快了多少?
让我们构建可执行文件并开始测试
> enether$ crystal build AA_Tree.cr -o crystal_tree — release
# 100 elements
> enether$ ./crystal_tree 100
Time it took: 0.0006560 seconds.
> enether$ ruby AA_Tree.rb 100
Time it took: 0.00172 seconds.
# 10K elements
> enether$ ./crystal_tree 10000
Time it took: 0.0044000 seconds.
> enether$ ruby AA_Tree.rb 10000
Time it took: 0.288619 seconds.
# 100K elements
> enether$ ./crystal_tree 100000
Time it took: 0.0498230 seconds.
> enether$ ruby AA_Tree.rb 100000
Time it took: 3.414404 seconds.
# 1 million elements
> enether$ ./crystal_tree 1000000
Time it took: 0.5007820 seconds.
> enether$ ruby AA_Tree.rb 1000000
Time it took: 39.370083 seconds.
# 10 million elements
> enether$ ./crystal_tree 100000000
Time it took: 5.6283920 seconds.
> enether$ ruby AA_Tree.rb 100000000
# Still running
如您所见,如果我们以一百万个元素的例子来判断,它运行在Ruby周围,并被证明快了80倍。
Ruby的怪癖和差异
尽管有很多相似之处,但与Ruby还是有很大的不同,在这里我们将重点介绍最明显和最有趣的地方。
类型,类型检查和类型联合
最明显的区别是,Crystal使用并主要对变量执行类型。 它具有出色的类型推断功能-如果您未明确定义变量的类型,则编译器会自行计算出来。
这种语言的打字方式是静态打字和动态打字之间的一种混合。 它允许您更改变量的类型
但它也允许您强制执行变量的类型
类型联合
您是否想知道上面的错误消息中的(Int32 | String)类型是什么?
这是所谓的类型联合,它是多个类型的集合。
如果我们要强制a作为Int32和String的并集,则编译器将允许我们将变量的任意一种分配给该变量,因为它知道这两种变量都期望。
类型推断和类型检查
在大多数情况下,编译器可以自己弄清楚变量的类型。 类型推断算法是专门为在读者看不到变量的类型并且不会深入研究特定类型而构建的。
在可能存在多个条件的情况下,编译器会将联合类型放在变量上。 如果可能的类型不支持在其上调用的给定方法,则Crystal代码不会编译 。
这是编译器保护您避免类型不匹配的愚蠢错误的一种方式,这在动态语言中确实很常见。 就像拥有自己的编程助手一样!
编译器足够聪明,可以找出变量何时明显来自给定类型
有多种方法可以确保编译器设置了适当的类型。 puts a.as(String).camelcase
这将检查a变量是否为字符串,如果不是,则抛出错误。
强制类型
如前所述,我们可以选择强制变量的类型或使其为任意类型。
方法的参数也是如此。
通常最好的做法是不强制使用变量,因为它会导致使用更通用的代码。
并发
它的并发模型受Go的启发,即CSP (通信顺序处理)。
它使用轻量级线程(称为光纤),其执行由运行时调度程序而不是操作系统管理。 所述线程之间的通信通过通道进行,通道可以是缓冲的或不缓冲的。
Crystal当前在单线程中运行,但他们的路线图打算实现多线程。 这意味着它当前不支持并行性(进程分叉除外),但是可能会有所变化。
因为目前只有一个线程在执行您的代码,所以访问和修改不同光纤中的变量就可以了。 但是,一旦以该语言引入了多个线程,它可能会中断。 这就是为什么推荐的数据通信机制是通过渠道的原因。
元编程
Crystal对通过宏进行元编程提供了良好的支持。 宏是在编译过程中将代码粘贴到文件中的东西。
让我们定义我们自己的Ruby attr_writer版本
调用attr_writer(foo, Int32)将评估为
def foo(foo : Int32)
@foo = foo
end Crystal宏支持迭代和条件,并且可以访问常量。
杂
Crystal吸收了其他语言的许多出色功能,并提供了各种语法糖,真是太好了!
直接在方法中初始化类实例变量
def initialize(@name, @age, @gender, @nationality)
等于
def initialize(name, age, gender, nationality)
@name = name
@age = age
@gender = gender
@nationality = nationality
end
def initialize(name, age, gender, nationality)
@name = name
@age = age
@gender = gender
@nationality = nationality
end
隐式对象符号
switch语句支持在给定对象上调用方法,而无需重复指定其名称。
外部关键字参数
我个人最喜欢的-Crystal允许您以一种外部方法和一种方法主体的方式命名函数的参数
编译器
如您先前所见,该语言被编译为可执行文件。 无论如何,它仍然具有类似于REPL之类的东西,事实证明它与我们心爱的irb类似irb : //github.com/crystal-community/icr
您还可以通过crystal命令直接运行文件,而无需编译然后运行。
> enether$ crystal AA_Tree.cr 200000
Time it took: 0.536102 seconds.
这会慢一些,因为我们没有利用- release build标志带来的优化。
C绑定
有一种在Crystal中编写性能库的方法,您可以在Ruby代码中运行该库。 执行此操作的方法是将Crystal绑定到C,这允许您从Ruby使用它。
我并没有对此做过深入的研究,但是显然这很容易,您无需编写C即可完成此操作。 太棒了!
结论
如果您编写Ruby,那么接手Crystal是很自然的事,并且可以很快发现自己正在其中编写对性能至关重要的软件。 我认为它具有很大的潜力,并且可以为我们的社区以及非红宝石程序员带来很多好处,因为语法太容易传递了。 编写它是一种乐趣,并且运行起来非常快,这是一种独特的组合,很少有语言可以吹嘘。
希望我通过这些简短的例子激发了您的兴趣! 我强烈建议您亲自了解一下该语言,如果我错过了一些东西,请通知我。
这里有一些资源需要进一步阅读:
Google群组
聊天室
IRC
Subreddit
通讯
From: https://hackernoon.com/crystal-the-ruby-youve-never-heard-of-57bad2efac9c