Beta Ziliani 16 Jul 2021

Crystal 1.1.0 is released!

We are releasing the first post-1.0 release, making efforts to keep our promise of making regular releases each 3 months, a bit delayed because of the conference, and with special focus on keeping the language stability. Below we list the most important or interesting changes, without mentioning the several bugfixes. For details visit the release’s notes.

Stats

In this release we included 166 PRs since the 1.0.0 release by 28 contributors. We thank all the effort put into improving the language and its stdlib! ❤️

Language changes

Splats can now be embedded in enumerable literals and in type definitions (#10429). A few examples:

t1 = {1, 'a'}
t2 = {true, *t1} # => {true, 1, 'a'}
typeof(t2)       # => Tuple(Bool, Int32, Char)

def f1(x : {Bool, *{Int32, Char}}); end       # Works in type annotations too
def f2(x : Tuple(Bool, *{Int32, Char})); end

ae = 'a'..'e'
ccae = ['<', *ae, '>'] # => ['<', 'a', 'b', 'c', 'd', 'e', '>']

a = 1..10
b = 5..15

Set{*a, *b} # => Set{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}

The type of a while expression is now the union of all break expressions within the body, plus Nil if the condition isn’t exactly the true literal; the while expression returns nil if the condition fails. The type of a break expression is computed similarly to a break inside a block or a return (Nil if empty, Tuple if multiple values) (#10566).

# First the first non-blank line in STDIN
first_non_blank_line =
  while line = gets
    break line unless line.blank?
  end

puts first_non_blank_line

Macros

It is now possible to access the top level module with the special instance variable @top_level (#10682):

FOO = 1
class Foo
    def bar
       {{@top_level.has_constant?("FOO")}}  # true
    end
end

NumberLiteral now includes a to_number method to obtain the pure number, without any stringification #10802:

{{ p 10_u8.id }}  # => 10_u8
{{ p 10_u8.to_number }}  # => 10

We included a small breaking change, as there was a mismatch between the documentation and the code regarding Path#global?. The former Path#global is now deprecated in favor of Path#global?, whose name better represents it (#10812).

There is a new macro method ASTNode#nil? for querying if an object is the NilLiteral or Nop (#10850, #10616).

Stdlib

There were several changes that are not supposed to have a direct impact on the users. The most important one to note is that to help get better error messages and documentation, several methods were annotated with expected types. Adding typing annotations might break existing code in specific scenarios so, if this happens to you, please let us now. Also, we are growing the native Windows support, requiring several refactors.

Numeric

It is now possible to create numbers from different representations using new, as in Float32.new("1.1", whitespace:false) ((#10422).

We added #positive? and #negative? methods for Number and Time::Span (#10601).

BigFloat and BigDecimal got rounding modes (#10618, #10798).

Collections

Likewise to Set, the Hash class includes now sub/superset checking methods (#7500):

  • Hash#subset_of?(other : Hash)
  • Hash#proper_subset_of?(other : Hash)
  • Hash#superset_of?(other : Hash)
  • Hash#proper_superset_of?(other : Hash)

Also, we generalized Number#step with a new Steppable module, that is included in Char, Number, Time and Time::Span (#10279).

Finally, it is now possible to #truncate and Array, to efficiently remove elements from both ends (#10712).

Crypto

New methods for getting peer certificates and signatures in OpenSSL (#8005).

Files

Now it is possible to use a Path for the methods in FileUtils (#10747).

Networking

OAuth2::Client supports the customization of its HTTP::Client node (10452).

Runtime

The segfault handler is now implemented in Crystal, in practice meaning that the compilation process of Crystal is simpler: it does not require the former external libcrystal. For package maintainers, this means building libcrystal.a (which was part of the make deps recipe) is obsolete now. The C code for this library has been removed and packaging instructions need to be updated. make deps is no longer necessary for building arbitrary Crystal programs; now it only builds llvm_ext.a, only required for linking against LLVM (for example when building the compiler itself).

Serialization

The Yaml parser now supports UUID (#10715).

We have been able to do all of this thanks to the continued support of 84codes, Nikola Motor Company and every other sponsor. To maintain and increase the development pace, donations and sponsorships are essential. OpenCollective is available for that. Reach out to crystal@manas.tech if you’d like to become a direct sponsor or find other ways to support Crystal. We thank you in advance!

We are releasing the first post-1.0 release, making efforts to keep our promise of making regular releases each 3 months, a bit delayed because of the conference, and with special focus on keeping the language stability. Below we list the most important or interesting changes, without mentioning the several bugfixes. For details visit the release’s notes.

Stats

In this release we included 166 PRs since the 1.0.0 release by 28 contributors. We thank all the effort put into improving the language and its stdlib! ❤️

Language changes

Splats can now be embedded in enumerable literals and in type definitions (#10429). A few examples:

t1 = {1, 'a'}
t2 = {true, *t1} # => {true, 1, 'a'}
typeof(t2)       # => Tuple(Bool, Int32, Char)

def f1(x : {Bool, *{Int32, Char}}); end       # Works in type annotations too
def f2(x : Tuple(Bool, *{Int32, Char})); end

ae = 'a'..'e'
ccae = ['<', *ae, '>'] # => ['<', 'a', 'b', 'c', 'd', 'e', '>']

a = 1..10
b = 5..15

Set{*a, *b} # => Set{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}

The type of a while expression is now the union of all break expressions within the body, plus Nil if the condition isn’t exactly the true literal; the while expression returns nil if the condition fails. The type of a break expression is computed similarly to a break inside a block or a return (Nil if empty, Tuple if multiple values) (#10566).

# First the first non-blank line in STDIN
first_non_blank_line =
  while line = gets
    break line unless line.blank?
  end

puts first_non_blank_line

Macros

It is now possible to access the top level module with the special instance variable @top_level (#10682):

FOO = 1
class Foo
    def bar
       {{@top_level.has_constant?("FOO")}}  # true
    end
end

NumberLiteral now includes a to_number method to obtain the pure number, without any stringification #10802:

{{ p 10_u8.id }}  # => 10_u8
{{ p 10_u8.to_number }}  # => 10

We included a small breaking change, as there was a mismatch between the documentation and the code regarding Path#global?. The former Path#global is now deprecated in favor of Path#global?, whose name better represents it (#10812).

There is a new macro method ASTNode#nil? for querying if an object is the NilLiteral or Nop (#10850, #10616).

Stdlib

There were several changes that are not supposed to have a direct impact on the users. The most important one to note is that to help get better error messages and documentation, several methods were annotated with expected types. Adding typing annotations might break existing code in specific scenarios so, if this happens to you, please let us now. Also, we are growing the native Windows support, requiring several refactors.

Numeric

It is now possible to create numbers from different representations using new, as in Float32.new("1.1", whitespace:false) ((#10422).

We added #positive? and #negative? methods for Number and Time::Span (#10601).

BigFloat and BigDecimal got rounding modes (#10618, #10798).

Collections

Likewise to Set, the Hash class includes now sub/superset checking methods (#7500):

  • Hash#subset_of?(other : Hash)
  • Hash#proper_subset_of?(other : Hash)
  • Hash#superset_of?(other : Hash)
  • Hash#proper_superset_of?(other : Hash)

Also, we generalized Number#step with a new Steppable module, that is included in Char, Number, Time and Time::Span (#10279).

Finally, it is now possible to #truncate and Array, to efficiently remove elements from both ends (#10712).

Crypto

New methods for getting peer certificates and signatures in OpenSSL (#8005).

Files

Now it is possible to use a Path for the methods in FileUtils (#10747).

Networking

OAuth2::Client supports the customization of its HTTP::Client node (10452).

Runtime

The segfault handler is now implemented in Crystal, in practice meaning that the compilation process of Crystal is simpler: it does not require the former external libcrystal. For package maintainers, this means building libcrystal.a (which was part of the make deps recipe) is obsolete now. The C code for this library has been removed and packaging instructions need to be updated. make deps is no longer necessary for building arbitrary Crystal programs; now it only builds llvm_ext.a, only required for linking against LLVM (for example when building the compiler itself).

Serialization

The Yaml parser now supports UUID (#10715).

We have been able to do all of this thanks to the continued support of 84codes, Nikola Motor Company and every other sponsor. To maintain and increase the development pace, donations and sponsorships are essential. OpenCollective is available for that. Reach out to crystal@manas.tech if you’d like to become a direct sponsor or find other ways to support Crystal. We thank you in advance!