Learning Raku from Ruby, in a nutshell: what do I already know?
This page attempts to index the high-level differences in syntax and semantics between Ruby and Raku. Whatever works in Ruby and must be written differently in Raku should be listed here (whereas many Raku features and idioms won't be).
Hence this should not be mistaken for a beginner tutorial or overview of Raku; it is intended as a technical reference for Raku learners with a strong Ruby background.
Ruby detects the end of most statements with a newline (and a few exceptions), as long as the expression is complete. It is common break up a long expression by leaving an operator dangling at the end of a line to ensure that the parsing will continue:
foo + # In Ruby a trailing operator means parsing should continuebar +baz
In Raku you must explicitly terminate statements with a ;
, which allows for better feedback and more flexibility in breaking up long lines. Two exceptions not needing an explicit ;
are the last statement in a block, and after the closing curly brace of the block itself (if there is nothing else on that line):
my ;...;if 5 < < 10# No ; required after closing } because of the newlinesay "Done!"; # The ; is not required here if nothing follows
Ruby allows a surprising amount of flexibility in the use of whitespace, even with strict mode and warnings turned on:
# unidiomatic but valid Rubyputs"Hello "+(people [ i]. name) . upcase+"!"if[i]<1
Raku also endorses programmer freedom and creativity, but balanced syntactic flexibility against its design goal of having a consistent, deterministic, extensible grammar that supports single-pass parsing and helpful error messages, integrates features like custom operators cleanly, and doesn't lead programmers to accidentally misstate their intent. Also, the practice of "code golf" is slightly de-emphasized; Raku is designed to be more concise in concepts than in keystrokes.
As a result, there are various places in the syntax where whitespace is optional in Ruby, but is either mandatory or forbidden in Raku. Many of those restrictions are unlikely to concern much real-life Perl code (e.g. whitespace being disallowed between an array variable and its square brackets), but there are a few that will unfortunately conflict with some Ruby hackers' habitual coding styles:
No space allowed before the opening parenthesis of an argument list.
foo (3, 4, 1); # Not right in Ruby or Raku (in Raku this would# try to pass a single argument of type List to foo)
foo(3, 4, 1); # Ruby and Rakufoo 3, 4, 1; # Ruby and Raku - alternative parentheses-less style
Space is required immediately after keywords
if(a < 0); ...; end # OK in Ruby
my ; ...;if ( < 0) # Rakuif < 0 # Raku, more idiomatic
while(x > 5); ...; end # OK in Ruby
my ; ...;while ( > 5) # Rakuwhile > 5 # Raku, more idiomatic
No space allowed before a postfix/postcircumfix operator (including array/hash subscripts).
seen [ :fish ] = 1 # Ruby, not idiomatic but allowed
< fish > = 1; # Raku, no space allowed after 'seen'
Space required before an infix operator if it would conflict with an existing postfix/postcircumfix operator.
n<1 # Ruby (in Raku this would conflict with postcircumfix < >)
< 1; # Raku
.
Method calls, .public_send
Method call syntax uses a dot just like Ruby:
person.name # Ruby
my ; ...;.name # Raku
To call a method whose name is not known until runtime:
object.public_send(methodname, args); # Ruby
my ; my Str ; my ; ...;."$methodname"(); # Raku
If you leave out the quotes, then Raku expects $methodname
to contain a Method
object, rather than the simple string name of the method.
In Ruby, variables use sigils primarily to indicate scope. $
for global scope, @@
for class scope, @
for instance scope, and no sigil for local variables (including parameters). The &
sigil is also used to indicate method references. Symbols are prefixed with :
, but they are not variable and so not really sigils.
In Raku sigils are primarily used to indicate a role that the contained value implements, indicating the type (or at least the interface) of the value. The sigils are invariant, no matter how the variable is being used - you can think of them as part of the variable's name.
The scope of a variable is instead indicated by the declaration itself (my
, has
, our
, etc).
For local variables, Ruby uses implicit variable declaration upon assignment and limited to the current block. In Ruby the content of an if
or while
built-in construct is not a block or scope.
Raku uses explicit scope indicators, and never creates variables implicitly. Every place you see { ... }
is a scope, including the body of a conditional or loop. The commonly used scope declarations:
foo = 7 # Ruby, variable scope is defined by first assignment and# extends to the end of the current block
my = 7; # Raku, lexical scoped to the current blockour = 7; # Raku, package scopedhas = 7; # Raku, instance scoped (attribute)
$
ScalarThe $
sigil is always used with "scalar" variables (e.g. $name
). These are single-value containers.
This is the most general-purpose variable type, with no restrictions on its contents. Note that you can still address/use its contents, like $x[1]
, $x{"foo"}
, and $f("foo")
.
@
ArrayThe @
sigil is always used with "array" variables (e.g. @months
, @months[2]
, @months[2, 4]
for an array slice). Variables using the @
sigil can only contain things that do the Positional
role, indicating positional indexing and slicing capabilities.
Indexing
puts months[2]; # Ruby
say [2]; # Raku
Value-slicing
puts months[8..11].join(',') # Ruby
say [8..11].join(',') # Raku
%
HashThe %
sigil is always used with "hash" variables (e.g. %calories
, %calories<apple>
, %calories<pear plum>
). Variables using the %
sigil can only contain things that do the Associative
role.
Ruby uses square brackets to access values for both Arrays and Hashes. Raku uses curly braces for hashes instead. The angle brackets version is available which always autoquotes its contents (strings without quotes):
Adverbs can be used to control the type of slice.
Indexing
puts calories["apple"] # Ruby
say ; # Raku
puts calories["apple"] # Rubyputs calories[:apple] # Ruby, symbols for keys are common
say <apple>; # Raku - angle brackets instead of single-quotessay «"$key"»; # Raku - double angles interpolate as double-quotes
Value-slicing
puts calories.values_at('pear', 'plum').join(',') # Rubyputs calories.values_at((pear plum)).join(',') # Ruby, pretty?
say .join(','); # Rakusay <pear plum>.join(','); # Raku (prettier)my = 'pear plum';say « ».join(','); # Raku, interpolated split
Key/value-slicing
puts calories.slice('pear', 'plum') # Ruby >= 2.5
say :kv.Hash; # Raku - use :kv adverbsay <pear plum>:kv.Hash; # Raku (prettier version)
&
SubThe &
sigil is used very similarly to Ruby's &
to refer to the function object of a named subroutine/operator without invoking it, i.e. to use the name as a "noun" instead of a "verb". Variables using the &
sigil can only contain things that do the Callable
role.
add = -> n, m { n + m } # Ruby lambda for an addition functionadd.(2, 3) # => 5, Ruby invocation of a lambdaadd.call(2, 3) # => 5, Ruby invocation of a lambda
my = -> , ; # Raku addition function(2, 3); # => 5, you can keep the sigiladd(2, 3); # => 5, and it works without it
def foo...endfoo_method = method(:foo); # Ruby
sub foo ;my = ; # Raku
some_func() # Ruby pass a function reference
sub some_func ;some_func() # Raku passes function references the same way
Often in Ruby we pass a block as the last parameter, which is especially used for DSLs. This can be an implicit parameter called by yield
, or an explicit block prefixed with &
. In Raku a Callable
parameter is always listed and called by the variable name (instead of yield), and there are a variety of ways of invoking the function.
# Ruby, declare a method and call the implicit block argumentdef fyield 2end# Ruby, invoke f, pass it a block with 1 argumentf do |n|puts "Hi #"end
# Raku, declare a method with an explicit block argumentsub f(:($))# Raku, invoke f, pass it a block with 1 argument# There are several other ways to do thisf(-> ); # Explicit argumentf -> ; # Explicit argument, no parenthesis# Additionally, if 'f' is a method on instance 'obj' you can use ':'# instead of parenthesismy ; ...;.f(-> ); # Explicit argument.f: -> ; # Explicit argument, no parenthesis
*
Slurpy params / argument expansionIn Ruby you can declare an argument to slurp the remainder of the passed parameters into an array using a *
prefix. It works similarly in Raku:
def foo(*args); puts "I got # args!"; end # Ruby
sub foo(*) # Raku
The Raku version above is slightly different in that when it slurps in the arguments into @args, one level of nesting, if any, is automatically removed:
sub foo(*)foo([1, [2, 3], 4], 5, [6, 7]); # [1, [2, 3], 4, 5, 6, 7]
To preserve the structure of the arguments, you can use **
:
sub foo(**)foo([1, [2, 3], 4], 5, [6, 7]); # [[1, [2, 3], 4], 5, [6, 7]]
You might want to expand an array into a set of arguments. In Raku this is done using a Slip |
:
args = (a b c) # Rubyfoo(*args)
sub foo(, , ) ;my = <a b c>; # Rakufoo(|);
Raku has many more advanced ways of passing parameters and receiving arguments, see Signatures and Captures.
Raku additionally uses "twigils", which are further indicators about the variable and go between the sigil and the rest of the variable name. Examples:
Variable | Description |
---|---|
$foo | Scalar with no twigil |
$!foo | Private instance variable |
$.foo | Instance variable accessor |
$*foo | Dynamically scoped variable |
$^foo | A positional (placeholder) parameter to a block |
$:foo | A named (placeholder) parameter to a block |
$=foo | POD (documentation) variables |
$?FILE | Current source filename. The ? twigil indicates a compile-time value |
$~foo | Sublanguage seen by parser, uncommon |
Though each of these examples use the $
sigil, most could use @
(Positional) or %
(Associative).
:
SymbolsRaku generally uses strings in the places where Ruby uses symbols. A primary example of this is in hash keys.
address[:joe][:street] # Typical Ruby nested hash with symbol keys
my ; ...;<joe><street> # Typical Raku nested hash with string keys
Raku has colon-pair syntax, which can sometimes look like Ruby symbols.
:age # Ruby symbol
# All of these are equivalent for Raku:age ;# Raku pair with implicit True value:age(True) ;# Raku pair with explicit True valueage => True ;# Raku pair using arrow notation"age" => True ;# Raku pair using arrow notation and explicit quotes
You could probably get away with using a colon-pair without an explicit value and pretend that it is a Ruby symbol a lot of the time, but it isn't idiomatic Raku.
Many operators have a similar usage in both Ruby and Raku:
,
List Separator
+
Numeric Addition
-
Numeric Subtraction
*
Numeric Multiplication
/
Numeric Division
%
Numeric Modulus
**
Numeric Exponentiation
! && ||
Booleans, high-precedence
not and or
Booleans, low-precedence
You may use $x++
instead of x += 1
as a shortcut for incrementing a variable. This can be used as a pre-increment ++$x
(increment, return new value) or post-increment $x++
(increment, return old value).
You may use $x--
instead of x -= 1
as a shortcut for decrementing a variable. This can be used as a pre-decrement --$x
(decrement, return new value) or post-decrement $x--
(decrement, return old value).
== != < > <= >=
ComparisonsComparisons in Raku are separated between numeric and string to avoid common errors.
== != < > <= >=
Comparisons
eq ne lt gt le ge
String comparisons
For example, using ==
tries to convert the values to numbers, and eq
tries to convert the values to strings.
<=>
Three-way comparisonsIn Ruby, the <=>
operator returns -1, 0, or 1. In Raku, they return Order::Less
, Order::Same
, or Order::More
.
<=>
forces numeric context for the comparison.
leg
("Less, Equal, or Greater?") forces string context for the comparison.
cmp
does either <=>
or leg
, depending on the existing type of its arguments.
~~
Smartmatch operatorThis is a very common matching operator which is similar to ===
in Ruby. Here are some examples:
my ; ...;say "match!" if ~~ /bar/; # Regex matchsay "match!" if ~~ "bar"; # String matchsay "match!" if ~~ :(Int, Str); # Signature match (destructure)
An equivalent in Ruby would be
= 'bar';puts "match 1!" if /bar/ === ; # Regex matchputs "match 2!" if === "bar"; # String matchputs "match 3!" if String === ; # Class match
Please note that, in this case, ===
is not symmetric; in the first and last case, the variable has to be in the right-hand side. There is no equivalent to the signature class in Ruby, either.
See S03/Smartmatching for more information on this feature.
& | ^
Numeric bitwise ops& | ^
Boolean opsIn Raku, these single-character ops have been removed, and replaced by two-character ops which coerce their arguments to the needed context.
# Infix ops (two arguments; one on each side of the op)+& +| +^ And Or Xor: Numeric~& ~| ~^ And Or Xor: String?& ?| ?^ And Or Xor: Boolean# Prefix ops (one argument, after the op)+^ Not: Numeric~^ Not: String?^ Not: Boolean (same as the ! op)
&.
Conditional chaining operatorRuby uses the &.
operator to chain methods without raising an error if one invocation returns nil. In Raku use .?
for the same purpose.
<< >>
Numeric shift left, right ops, shovel operatorReplaced by +<
and +>
.
puts 42 << 3 # Ruby
say 42 +< 3; # Raku
Note that Ruby often uses the <<
operator as the "shovel operator", which is similar to .push
. This usage isn't common in Raku.
=>
and :
Key-value separatorsIn Ruby, =>
is used in the context of key/value pairs for Hash literal declaration and parameter passing. :
is used as a shorthand when the left side is a symbol.
In Raku, =>
is the Pair operator, which is quite different in principle, but works the same in many situations.
If you are using =>
in a hash literal, then the usage is very similar:
hash = # Ruby, though symbol keys are more common
my = ( AAA => 1, BBB => 2 ); # Raku, uses ()'s though {} usually work
? :
Ternary operatorIn Raku, this is spelled with two question marks instead of one question mark, and two exclamation points instead of one colon. This deviation from the common ternary operators disambiguates several situations and makes the false-case stand out more.
result = ( score > 60 ) ? 'Pass' : 'Fail'; # Ruby
my ; ...;my = ( > 60 ) ?? 'Pass' !! 'Fail'; # Raku
+
String concatenationReplaced by the tilde. Mnemonic: think of "stitching" together the two strings with needle and thread.
= 'grape' + 'fruit' # Ruby
my = 'grape' ~ 'fruit'; # Raku
In Ruby, "#{foo}s"
deliminates a block embedded in a double-quoted string. In Raku drop the #
prefix: "{$foo}s"
. As in Ruby, you can place arbitrary code into the embedded block and it will be rendered in string context.
Simple variables can be interpolated into a double-quoted string without using the block syntax:
# Rubyname = "Bob"puts "Hello! My name is #!"
# Rakumy = "Bob";say "Hello! My name is $name!"
The result of an embedded block in Ruby uses .to_s
to get string context. Raku uses .Str
, or .gist
for the same affect.
if
elsif
else
unless
This work very similarly between Ruby and Raku, but Raku uses { }
to clearly delineate the blocks.
# Rubyif x > 5puts "Bigger!"elsif x == 5puts "The same!"elseputs "Smaller!"end
# Rakumy ; ...;if > 5elsif == 5else
Binding the conditional expression to a variable is a little different:
if x = dostuff(); ...; end # Ruby
sub dostuff() ;if dostuff() -> # Raku, block-assignment uses arrow
The unless
conditional only allows for a single block in Raku; it does not allow for an elsif
or else
clause.
case
-when
The Raku given
-when
construct is like a chain of if
-elsif
-else
statements, and its direct analog is Ruby's case
-when
construct. Just as Ruby uses the ===
(case equality) operator for each condition in a case
-when
expression, Raku, likewise, uses the smartmatch ~~
operator with given
-when
.
It has the general structure:
given EXPR
In its simplest form, the construct is as follows:
my ; ...;given
This is simple in the sense that a scalar value is matched in the when
statements. More generally, the matches are actually smartmatches on the input value such that lookups using more complex entities such as regexps can be used instead of scalar values.
while
until
Mostly unchanged; parentheses around the conditions are optional, but if used, must not immediately follow the keyword, or it will be taken as a function call instead. Binding the conditional expression to a variable is also a little different:
while x = dostuff(); ...; end # Ruby
sub dostuff ; ...;while dostuff() -> # Raku
for
.each
for
loops are rare in Ruby, instead we typically use .each
on an enumerable. The most direct translation to Raku would be to use .map
for both .each
and .map
, but we typically use a for
loop directly.
# Ruby for loopfor n in 0..5puts "n: #"end# Ruby, more common usage of .each(0..5).each do |n|puts "n: #"end
# Rakufor 0..5 -># Raku, misusing .map(0..5).map: ->
In Ruby, the iteration variable for .each
is a copy of the list element, and modifying it does nothing to the original list. Note that it is a copy of the REFERENCE, so you can still change the values to which it refers.
In Raku, that alias is read-only (for safety) and thus behaves exactly like Ruby, unless you change ->
to <->
.
cars.each # Ruby; read-only reference
my ; ...;for -> # Raku; read-onlyfor <-> # Raku; read-write
Same as Ruby:
next
redo
break
This is last
in Raku.
Regular expressions in Raku are significantly different, and more powerful, than in Ruby. By default whitespace is ignored and all characters must be escaped, for example. Regexes can be easily combined and declared in ways to build efficient grammars.
There are many powerful features of Raku regexes, especially defining entire grammars using the same syntax. See Regexes and Grammars.
.match
method and =~
operatorIn Ruby, regex matches can be done against a variable using the =~
regexp match operator or the .match
method. In Raku, the ~~
smartmatch op is used instead, or the .match
method.
next if line =~ /static/ # Rubynext if line !~ /dynamic/; # Rubynext if line.match(/static/) # Ruby
my ; ...;next if ~~ /static/; # Rakunext if !~~ /dynamic/ ; # Rakunext if .match(/static/); # Raku
Alternately, the .match
and .subst
methods can be used. Note that .subst
is non-mutating. See S05/Substitution.
.sub
and .sub!
In Raku you typically use the s///
operator to do regex substitution.
fixed = line.sub(/foo/, 'bar') # Ruby, non-mutating
my ; ...;my = .subst(/foo/, 'bar') # Raku, non-mutating
line.sub!(/foo/, 'bar') # Ruby, mutating
my ; ...;~~ s/foo/bar/; # Raku, mutating
Move any options from the end of the regex to the beginning. This may require you to add the optional m
on a plain match like /abc/
.
next if =~ /static/i # Ruby
my ; ...;next if ~~ m:i/static/; # Raku
In order to aid in readability and reusability, whitespace is not significant in Raku regexes.
/this is a test/ # Ruby, boring string/this.*/ # Ruby, possibly interesting string
/ this " " is " " a " " test /; # Raku, each space is quoted/ "this is a test" /; # Raku, quoting the whole string/ this .* /; # Raku, possibly interesting string
There are many cases of special matching syntax that Raku regexes support. They won't all be listed here, but often instead of being surrounded by ()
, the assertions will be surrounded by <>
.
For character classes, this means that:
[abc]
becomes <[abc]>
[^abc]
becomes <-[abc]>
[a-zA-Z]
becomes <[a..zA..Z]>
[[:upper:]]
becomes <:upper>
[abc[:upper:]]
becomes <[abc]+:Upper>
For look-around assertions:
(?=[abc])
becomes <?[abc]>
(?=ar?bitrary* pattern)
becomes <before ar?bitrary* pattern>
(?!=[abc])
becomes <![abc]>
(?!=ar?bitrary* pattern)
becomes <!before ar?bitrary* pattern>
(?<=ar?bitrary* pattern)
becomes <after ar?bitrary* pattern>
(?<!ar?bitrary* pattern)
becomes <!after ar?bitrary* pattern>
(Unrelated to <> syntax, the "lookaround" /foo\Kbar/
becomes /foo <( bar )> /
(?(?{condition))yes-pattern|no-pattern)
becomes [ <?{condition}> yes-pattern | no-pattern ]
In Raku regexes, |
does Longest Token Match (LTM), which decides which alternation wins an ambiguous match based off of a set of rules, rather than about which was written first in the regex.
To avoid the new logic, change any |
in your Ruby regex to a ||
.
Both Ruby and Raku make it easy to read all of the lines in a file into a single variable, and in both cases each line has the newline removed.
lines = File.readlines("file") # Ruby
my = "file".IO.lines; # Raku, create an IO object from a string
Reading the entire file into memory isn't recommended. The .lines
method in Raku returns a lazy sequence, but assigning to an array forces the file to be read. It is better to iterate over the results:
# RubyFile.foreach("file") do |line|puts lineend
# Rakufor "file".IO.lines ->
Classes are defined similarly between Ruby and Raku, using the class
keyword. Ruby uses def
for methods, whereas Raku uses method
.
# Rubydef greet(name)puts "Hi #!"endend
# Raku
In Ruby you can use an attribute without declaring it beforehand, and you can tell it is an attribute because of the @
sigil. You can also easily create accessors using attr_accessor
and its variants. In Raku you use a has
declaration and a variety of sigils. You can use the !
twigil for private attributes or .
to create an accessor.
# Rubyattr_accessor :age # Declare .age as an accessor method for @agedef initialize= 'default' # Assign default value to private instance varendend
# Raku
Creating a new instance of the class uses the .new
method. In Ruby you must manually assign instance variables as needed inside initialize
. In Raku you get a default constructor that accepts key/value pairs of accessor attributes, and can do further setup in the TWEAK
method. Like with Ruby, you can override new
itself for more advanced functionality, but this is rare.
# Rubyattr_accessor :name, :agedef initialize(attrs)= attrs[:name] || 'Jill'= attrs[:age] || 42= Time.now.year -endendp = Person.new( name: 'Jack', age: 23 )
# Rakumy = Person.new( name => 'Jack', age => 23 )
Private methods in Raku are declared with a !
prefixed in their name, and are invoked with a !
instead of a .
.
# Rubydef visibleputs "I can be seen!"hiddenendprivatedef hiddenputs "I cannot easily be called!"endend
# Raku
An important note is that in Ruby child objects can see parent private methods (so they are more like "protected" methods in other languages). In Raku child objects cannot call parent private methods.
Here are a few examples of metaprogramming. Note that Raku separates the metamethods from the regular methods with a caret.
# Rubyperson = Person.newperson.classperson.methodsperson.instance_variables
# Raku;...my = Person.new;.^name; # Raku, returns Person (class).^methods; # Raku, using .^ syntax to access metamethods.^attributes;
Like Ruby, in Raku, everything is an object, but not all operations are equivalent to .public_send
. Many operators are global functions that use typed multi-dispatch (function signatures with types) to decide which implementation to use.
5.public_send(:+, 3) # => 8, Ruby
&[+](5, 3) # => 8, Raku, reference to infix addition operator&[+].^candidates # Raku, lists all signatures for the + operator
See Metaobject Protocol for lots of further details.
In Ruby, one of the environment variables to specify extra search paths for modules is RUBYLIB
.
$ RUBYLIB="/some/module/lib" ruby program.rb
In Raku this is similar, you merely needs to change the name. As you probably guessed, you just need to use RAKULIB
:
$ RAKULIB="/some/module/lib" raku program.raku
As with Ruby, if you don't specify RAKULIB
, you need to specify the library path within the program via the use lib
pragma:
# Ruby and Rakuuse lib '/some/module/lib';
In Ruby there is no built-in way to selectively import/export methods from a module.
In Raku you specify the functions which are to be exported by using the is export
role on the relevant subs and all subs with this role are then exported. Hence, the following module Bar
exports the subs foo
and bar
but not baz
:
unit ; # remainder of the file is in module Bar { ... }sub foo() is exportsub bar() is exportsub baz()
To use this module, simply use Bar
and the functions foo
and bar
will be available:
use Bar;foo(1); #=> "foo 1"bar(2); #=> "bar 2"
If you try to use baz
an "Undeclared routine" error is raised at compile time.
Some modules allow for selectively importing functions, which would look like:
use Bar <foo>; # Import only foofoo(1); #=> "foo 1"bar(2); # Error!
OptionParser
, parsing command-line flagsCommand line argument switch parsing in Raku is done by the parameter list of the MAIN
subroutine.
# Rubyrequire 'optparse'options =OptionParser.new do |opts|opts.banner = 'Usage: example.rb --length=abc'opts.on("--length", "Set the file") do |length|raise "Length must be > 0" unless length.to_i > 0options[:length] = lengthendopts.on("--filename", "Set the file") do |filename|options[:file] = filenameendopts.on("--verbose", "Increase verbosity") do |verbose|options[:verbose] = trueendend.parse!puts options[:length]puts options[:filename]puts 'Verbosity ', (options[:verbose] ? 'on' : 'off')
ruby example.rb --filename=foo --length=42 --verbose42fooVerbosity onruby example.rb --length=abcLength must be > 0
# Rakusub MAIN ( Int : where * > 0, : = 'file.dat', Bool : )
raku example.p6 --file=foo --length=42 --verbose42fooVerbosity onraku example.p6 --length=abcUsage:example.p6 [--length=<Int>] [--file=<Any>] [--verbose]
Note that Raku auto-generates a full usage message on error in command-line parsing.
See https://modules.raku.org/, where a growing number of Raku libraries are available along with the tools to manage them.
If the module that you were using has not been converted to Raku, and no alternative is listed in this document, then its use under Raku may not have been addressed yet.
You can experiment with Inline::Ruby to call existing Ruby code from your Raku programs. This uses an embedded instance of the ruby
interpreter to run Ruby code called from your Raku script. Note that this is an EXPERIMENTAL library. You can similarly call other language's libraries with Inline::Perl5, Inline::Python, and others.