# A very basic HTTP server
require "http/server"
server = HTTP::Server.new do |context|
context.response.content_type = "text/plain"
context.response.print "Hello, Crystal!"
end
address = server.bind_tcp(8080)
puts "Listening on http://#{address}"
server.listen
def add(a, b)
a + b
end
add 1, 2 # => 3
add "foo", "bar" # => "foobar"
Static Typing
Type safety
Feels dynamic
def add(a, b)
a + b
end
add 1, 2 # => 3
add "foo", "bar" # => "foobar"
add "foo", 2 # Error: instantiating 'add(String, Int32)
# Error: expected argument #1 to 'String#+'
# to be Char or String, not Int32
Static Typing
ary = [1, 2, 3]
ary.class # => Array(Int32)
ary << 4
typeof(ary[0]) # Int32
ary << "foo" # Error: expected argument #1 to 'Array(Int32)#<<'
# to be Int32, not String
[] # Error: for empty arrays use '[] of ElementType'
[] of String
# or
Array(String).new
Static Typing
instance variables
class Foo
@bar = 123
def initialize(@baz : String)
end
end
Compilation
$ crystal build src/hello.crb
$ ls -sh hello
2,0M hello-world
$ file hello
hello: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d7768fdb368d11e8e08c9bcaea7cc1a629914f04, for GNU/Linux 3.2.0, with debug_info, not stripped
$ ./hello
Hello, Crystal!
Compilation
Runtime is embedded into the binary
LLVM backend generates efficient code
Limited dynamic language features
Metaprogramming: macro
Code that writes other code at compile time
macro getter(var)
# macro body
end
getter foo
Macro expansion:
# macro body
Metaprogramming: macro
Code that writes other code at compile time
macro getter(var)
def {{ var.id }}
@{{ var.id }}
end
end
getter foo
Macro expansion:
def foo
@foo
end
Metaprogramming: def
class Foo
def ==(other)
{% for ivar in @type.instance_vars %}
return false unless @{{ivar.id}} == other.@{{ivar.id}}
{% end %}
true
end
end
Macro expansion:
# macro expansion of method body with ivars @bar and @baz
return false unless @baz == other.@baz
return false unless @bar == other.@bar
true
Concurrency
channel = Channel(Int32).new
3.times do |i| # i = 0, 1, 2
spawn do # concurrently do...
3.times do |j|
sleep rand(100).milliseconds # add non-determinism for fun
channel.send 10 * (i + 1) + j
end
end
end
9.times do
puts channel.receive
end