Added article about raku

This commit is contained in:
qorg11 2021-12-09 14:16:47 +01:00
parent b65b7bbabb
commit e86d8d173d
No known key found for this signature in database
GPG Key ID: 343FC20A4ACA62B9
1 changed files with 168 additions and 0 deletions

View File

@ -0,0 +1,168 @@
# Raku rocks
Raku (formerly Perl 6) is a programming language which, despite its
former name, it's a very different language from perl. Altough if you
already know Perl, learning Raku will be relatively easy.
Raku introduces (or makes usable) concepts that perl didn't have (or
had but were useless and discouraged) in Perl such as Threads,
promises, lazy evaluation, and grammars.
Sigils in Raku make sense unlike in Perl, for example:
~~~
# Perl:
my %hash = (key1 => "value", key2 => "value2");
$hash{key1} # value;
# Raku:
my %hash = (key1 => "value", key2 => "value2");
%hash{"key1"} # Value
~~~
If a hash is a hash, it is a hash, it won't be converted to a scalar
when you want to retrieve data from that hash. Unlike in Perl.
Raku, unlike perl is a typed programming language, by default all
variables you declare are of the type "Any", which means that variable
can have any time and can be converted to other type. Nevertheless you
can specify which type you want the variable to be:
~~~
my Int $n = 3;
my Str $s = "hello world";
~~~
There is a type hierarchy, which means types are based on other
types. All types are based on the type `Mu`[fn:1].
For example, the type `atomicint`, and `bool` derives from the type
`Int` which derives from `Cool` which derives from `Any` which derives
from `Mu`. All roads lead to Rome and all types lead to `Mu`.
Raku also has a decent Object Oriented interface:
~~~
Class Socket {
has Int $.sockfd;
method new ($path) {
my $mfd = create_socket();
connect_socket($mfd,$path);
self.bless(sockfd => $mfd);
}
method send($str) {
my $len = $str.chars;
write_to_sock(self.sockfd, $str, $len);
}
}
my $sock = Socket.new("path/to/socket");
$sock.write("hello from raku!");
~~~
Calling C functions from Raku is stupidly easy, to do this only use
the [NativeCall](https://docs.raku.org/language/nativecall) module
which is included in the standard library, consider the following:
file.c:
~~~
#include <stdio.h>
int
print_string(const char *s)
{
puts(s);
return 0;
}
~~~
You have to compile it so it's a shared library:
`gcc -fpic -shared file.c -o libfile.so`
file.raku:
~~~
use NativeCall;
# Libpath, raku will add the lib and the .so automatically so you don't
# have to put libfile.so
constant LIBPATH = "$*CWD/file";
# Takes a Str as argument and returns and int32 (which is just an alias to Int)
sub print_string(Str --> int32) is native(LIBPATH) { * }
print_string("C function running in raku");
~~~
It will output:
`C function running in raku`
Which was expected. Obviously you can import syscalls and any kind of
functions you can run in C. Which is useful for doing stuff that is
not in the Raku standard library but it's in the C stdlib, such as
creating sockets which all the flags you want, or calling `fork()`
(which is discouraged as you can use threads and async functions
really easily, but if you *really* want to call `fork()` you can call
`fork()`.
## Concurrency in Raku
Async functions in raku are something very easy. The [language
website](https://raku.org) give us this example:
~~~
start { sleep 1.5; print "hi" }
await Supply.from-list(<A B C D E F>).throttle: 2, {
sleep 0.5;
.print
}
# OUTPUT: ABCDhiEF
~~~
the `start` block is called asyncronously, so it sleeps 1.5 seconds
and then prints "hi" while the other part prints 2 letters every 0.5
seconds. so after printing ABCD, 1.5 seconds have passed, so it will
print the "hi" form the `start {}` block.
Raku also has promises:
~~~
sub counter(Int $n) {
for 0..$n -> $i {
if $i == 21474834 {
return "There";
}
}
}
my $promise = start {
counter(21474834);
};
$promise.then({say .result}); # Will print "There" after finishing.
say "I'm doing other stuff";
say "Blah, blah";
sleep(1000); # Simulate stuff-doing
~~~
the `.then` method takes as parameter a block of code, which will be
executed after finishing the process. In that code I use `sleep(1000)`
to simulate stuff-doing, but if you finished all the stuff you have to
do and need the promise to finish, you only do
`$promise.result`. Which will wait until it finishes. This is like
joining a thread.
## Rakudo
Rakudo is the main implementation of the Raku programming language. It
compiles Raku code to be run in MoarVM or, if wanted, the JVM[fn:2].
[fn:1]: Haha discordian reference!
[fn:2]: MoarVM is the most used because it's the fastest raku implementation. But you can compile Rakudo to use the JVM if you really want to.