=begin pod :kind("Language") :subkind("Language") :category("migration")

=TITLE JavaScript (Node.js) to Raku - nutshell

=SUBTITLE Learning Raku from Node.js, in a nutshell

This page attempts to provide a way for users experienced in Node.js to learn
Raku. Features shared between the two languages will be explained here, as
well as major differences in syntax and features.

This is not a tutorial for learning Raku; this is a reference for users who
are already at an intermediate to advanced skill level with Node.js.

=head1 Basic syntax

=head2 "Hello, world!"

Let's start with the typical first program when learning new languages. In
Node.js, a hello world program would be written like this:

=begin code :lang<javascript>
console.log('Hello, world!');
=end code

Here are a couple ways to write this in the same way in Raku:

=begin code
say('Hello, world!');
say 'Hello, world!';
=end code

Parentheses are optional for function calls in Raku. While semicolons are,
for the most part, optional in Node.js, they are mandatory for expressions in
Raku.

Now that we've greeted the world, let's greet our good friend, Joe. We'll
start with Node.js again:

=begin code :lang<javascript>
let name = 'Joe';
console.log('What\'s up,' + name + '?');
console.log(`What's up, ${name}?`);
console.log("What's up, ", name, "?");
=end code

Since he didn't hear us, let's greet him again, this time in Raku:

=begin code
my $name = 'Joe';
say 'What\'s up, ' ~ $name ~ '?';
say "What's up, $name?";
say "What's up, ", $name, "?";
=end code

Here, there are only a couple differences: most variables in Raku have what
are called sigils, which are what the C<$> in front of its name is, and string
concatenation uses the C<~> operator instead of C<+>. What the two languages
share in common here is support for string interpolation.

Now that the basic examples are out of the way, let's explain the similarities
between the two languages in greater detail.

=head2 Variables

Variables in Node.js can be defined like this;

=begin code :lang<javascript>
var   foo = 1;  // Lexically scoped with functions and modules
let   foo = 1;  // Lexically scoped with blocks
const foo = 1;  // Lexically scoped with blocks; constant

// No equivalent to Raku dynamic variables exists.

global.foo = 1; // Globally scoped
foo = 1;        // Ditto, but implicit; forbidden in strict mode
=end code

In Raku there is no equivalent to C<var>. An important note to make is that
there is no variable hoisting in Raku; variables are defined and assigned
at the line they're on, not defined at the top of its scope and later assigned
at that line.

In addition to regular variables, in Raku there are what is known as dynamic
variables. Dynamic variables are looked up using the caller's scope, rather
than the outer scope. This is what the equivalent variable declarations look
like in Raku:

=for code
my $foo = 1; # Lexically scoped
our $foo = 1; # Package scoped

=for code
my constant foo = 1; # Lexically scoped; constant

=for code
constant foo = 1; # Package scoped; constant

=for code
my  $*foo = 1; # Dynamic variable; lexically scoped
our $*foo = 1; # Dynamic variable; package scoped

GLOBAL::<$foo> := 1; # Globally scoped

Use C<my> where you'd use C<let>, C<our> for variables you'd define in the
outermost scope needed, and C<constant> where you'd uses C<const>.

You may have noticed the C<$> and C<$*> symbols placed before variable names.
These are known as sigils and twigils respectively, and define what container
the variable has. Refer to the documentation on
L<variables|/language/variables> for more information on sigils, twigils, and
containers.

Variables in Node.js can override others from outer scopes with the same name
(though linters will usually complain about it depending on how they're
configured):

=begin code :lang<javascript>
let foo = 1;
function logDupe() {
    let foo = 2;
    console.log(foo);
}

logDupe(2);       // OUTPUT: 2
console.log(foo); // OUTPUT: 1
=end code

Raku also allows this:

=begin code
my $foo = 1;
sub log-dupe {
    my $foo = 2;
    say $foo;
}

log-dupe; # OUTPUT: 2
say $foo; # OUTPUT: 1
=end code

=head2 Operators

=head3 Assignment

The C<=> operator works the same across both languages.

The C<:=> operator in Raku binds a value to a variable. Binding a variable
to another variable gives them the same value and container, meaning mutating
attributes of one will mutate the other's as well. Bound variables cannot be
reassigned with C<=> or mutated with C<++>, C<-->, etc. but they can be bound
to another value again:

=begin code
my %map;            # This is a hash, roughly equivalent to a JS object or map
my %unbound = %map;
my %bound := %map;
%map<foo> = 'bar';
say %unbound;       # OUTPUT: {}
say %bound;         # OUTPUT: {foo => bar}

%bound := %unbound;
say %bound;         # OUTPUT: {}
=end code

=head3 Equality

Node.js has two equality operators: C<==> and C<===>.

C<==> is the loose equality operator. When comparing operands with the same
type, it will return true if both operands are equal. However, if the
operands are different types, they are both cast to their primitives before
being compared, meaning these will return true:

=begin code :lang<javascript>
console.log(1 == 1);   // OUTPUT: true
console.log('1' == 1); // OUTPUT: true
console.log([] == 0);  // OUTPUT: true
=end code

Similarly, in Raku, both operands are cast to Numeric before comparison if
they don't share the same type:

=begin code
say 1 == 1;       # OUTPUT: True
say '1' == 1;     # OUTPUT: True
say [1,2,3] == 3; # OUTPUT: True, since the array has three elements
=end code

The inverse of C<==> is C<!=>.

Raku has another operator similar to C<==>: C<eq>. Instead of casting operands
to Numeric if they're different types, C<eq> will cast them to strings:

=begin code
say '1' eq '1'; # OUTPUT: True
say 1 eq '1';   # OUTPUT: True
=end code

The inverse of C<eq> is C<ne> or C<!eq>.

C<===> is the strict equality operator. This returns true if both operands are
the same value. When comparing objects, this will I<only> return true if they
are the exact same object:

=begin code :lang<javascript>
console.log(1 === 1);   // OUTPUT: true
console.log('1' === 1); // OUTPUT: false
console.log({} === {}); // OUTPUT: false

let obj = {};
let obj2 = obj;
console.log(obj === obj2); // OUTPUT: true;
=end code

In Raku, the operator behaves the same, with one exception: two objects that
have the same value, but different containers, will return false:

=begin code
say 1 === 1;                    # OUTPUT: «True␤»
say '1' === 1;                  # OUTPUT: «False␤»
say 'ayy lmao' === 'ayy lmao';  # OUTPUT: «True␤»
say {} === {};                  # OUTPUT: «False␤»

my \hash = {};
my %hash = hash;
say hash === %hash; # OUTPUT: False
=end code

In the last case it's the same object, but containers are different, which is
why it returns False.

The inverse of C<===> is C<!==>.

This is where Raku's other equality operators are useful. If the values have
different containers, the C<eqv> operator can be used. This operator can be also
be used to check for deep equality, which you would normally need to use a
library for in Node.js:

=begin code
say {a => 1} eqv {a => 1}; # OUTPUT: True

my \hash = {};
my %hash := hash;
say hash eqv %hash; # OUTPUT: True
=end code

In the case you need to check if two variables have the same container and
value, use the C<=:=> operator.

=begin code
my @arr = [1,2,3];
my @arr2 := @arr;   # Bound variables keep the container of the other variable
say @arr =:= @arr2; # OUTPUT: True
=end code

=head3 Smartmatching

Raku has one last operator for comparing values, but it is not exactly an
equality operator. This is C<~~>, the smartmatch operator. This has several
uses: it can be used like C<instanceof> in Node.js, to match a regex, and to
check if a value is a key in a hash, bag, set, or map:

=begin code
say 'ayy lmao' ~~ Str; # OUTPUT: True

my %hash = a => 1;
say 'a' ~~ %hash; # OUTPUT: True

my $str = 'abc';
$str ~~ s/abc/def/; # Mutates $str, like foo.replace('abc', 'def')
say $str;           # OUTPUT: def
=end code

While we are talking about C<instanceof>, the equivalent to the C<constructor>
property on Node.js objects in Raku is the C<WHAT> attribute:

=begin code :lang<javascript>
console.log('foo'.constructor); // OUTPUT: String
=end code

=begin code :ok-test<WHAT>
say 'foo'.WHAT; # OUTPUT: Str
=end code

=head3 Numeric

Node.js has C<+>, C<->, C</>, C<*>, C<%>, and (in ES6) C<**> as numeric
operators. When the operands are different types, similarly to the equality
operators, are cast to their primitives before following through with the
operation, making this possible:

=begin code :lang<javascript>
console.log(1 + 2);   // OUTPUT: 3
console.log([] + {}); // OUTPUT: [object Object]
console.log({} + []); // OUTPUT: 0
=end code

In Raku, again, they are converted to a Numeric type, as before:

=begin code
say 1 + 2;        # OUTPUT: 3
say [] + {};      # OUTPUT: 0
say {} + [1,2,3]; # OUTPUT: 3
=end code

In addition, Raku has C<div> and C<%%>. C<div> behaves like C<int> division in
C, while C<%%> checks if one number is cleanly divisible by another or not:

=begin code
say 4 div 3; # OUTPUT: 1
say 4 %% 3;  # OUTPUT: False
say 6 %% 3;  # OUTPUT: True
=end code

=head3 Bitwise

Node.js has C<&>, C<|>, C<^>, C<~>, C«<<», C«>>», C«>>>», and C<~> for bitwise
operators:

=begin code :lang<javascript>
console.log(1 << 1);  // OUTPUT: 2
console.log(1 >> 1);  // OUTPUT: 0
console.log(1 >>> 1); // OUTPUT: 0
console.log(1 & 1);   // OUTPUT: 1
console.log(0 | 1);   // OUTPUT: 1
console.log(1 ^ 1);   // OUTPUT: 0
console.log(~1);      // OUTPUT: -2
=end code

In Raku, there is no equivalent to C«>>>». All bitwise operators are
prefixed with C<+>, however bitwise negation uses C<+^> instead of C<~>:

=begin code
say 1 +< 1; # OUTPUT: 2
say 1 +> 1; # OUTPUT: 0
            # No equivalent for >>>
say 1 +& 1; # OUTPUT: 1
say 0 +| 1; # OUTPUT: 1
say 1 +^ 1; # OUTPUT: 0
say +^1;    # OUTPUT: -2
=end code

=head3 Custom operators and operator overloading

Node.js does not allow operator overloading without having to use a Makefile or
build Node.js with a custom version of V8. Raku allows custom operators and
operator overloading natively! Since all operators are subroutines, you can
define your own like so:

=begin code
multi sub infix:<||=>($a, $b) is equiv(&infix:<+=>) { $a || $b }

my $foo = 0;
$foo ||= 1;
say $foo; # OUTPUT: 1
=end code

Operators can be defined as C<prefix>, C<infix>, or C<postfix>. The
C<is tighter>, C<is equiv>, and C<is looser> traits optionally define the
operator's precedence. In this case, C<||=> has the same precedence as C<+=>.

Note how C<multi> is used when declaring the operator subroutines. This allows
multiple subroutines with the same name to be declared while also having
different signatures. This will be explained in greater detail in the
L<Functions|#Functions> section. For now, all we need to know is that it allows
us to override any native operator we want:

=begin code
# Using the `is default` trait here forces this subroutine to be chosen first,
# so long as the signature of the subroutine matches.
multi sub prefix:<++>($a) is default { $a - 1 }

my $foo = 1;
say ++$foo; # OUTPUT: 0
=end code

=head2 Control flow

=head3 if/else

You should be familiar with how C<if>/C<else> looks in JavaScript:

=begin code :lang<javascript>
let diceRoll = Math.ceil(Math.random() * 6) + Math.ceil(Math.random() * 6);
if (diceRoll === 2) {
    console.log('Snake eyes!');
} else if (diceRoll === 16) {
    console.log('Boxcars!');
} else {
    console.log(`Rolled ${diceRoll}.`);
}
=end code

In Raku, C<if>/C<else> works largely the same, with a few key differences.
One, parentheses are not required. Two, C<else if> is written as C<elsif>.
Three, the if clause may be written I<after> a statement:

=begin code
my Int $dice-roll = ceiling rand * 12 + ceiling rand * 12;
if $dice-roll == 2 {
    say 'Snake eyes!';
} elsif $dice-roll == 16 {
    say 'Boxcars!';
} else {
    say "Rolled $dice-roll.";
}
=end code

Alternatively, though less efficient, this could be written to use C<if> after
statements:

=begin code
my Int $dice-roll = ceiling rand * 12 + ceiling rand * 12;
say 'Snake eyes!'        if $dice-roll == 2;
say 'Boxcars!'           if $dice-roll == 16;
say "Rolled $dice-roll." if $dice-roll != 2 && $dice-roll != 16;
=end code

Raku also has C<when>, which is like C<if>, but if the condition given is
true, no code past the C<when> block within the block it's in is executed:

=begin code
{
    when True {
        say 'In when block!'; # OUTPUT: In when block!
    }
    say 'This will never be output!';
}
=end code

Additionally, Raku has C<with>, C<orwith>, and C<without>, which are like
C<if>, C<else if>, and C<else> respectively, but instead of checking whether
their condition is true, they check if it's defined.

=head3 switch

Switch statements are a way of checking for equality between a given value and
a list of values and run some code if one matches. C<case> statements define
each value to compare to. C<default>, if included, acts as a fallback for when
the given value matches no cases. After matching a case, C<break> is typically
used to prevent the code from the cases that follow the one matched from being
executed, though rarely this is intentionally omitted.

=begin code :lang<javascript>
const ranklist = [2, 3, 4, 5, 6, 7, 8, 9, 'Jack', 'Queen', 'King', 'Ace'];
const ranks    = Array.from(Array(3), () => ranklist[Math.floor(Math.random() * ranks.length)]);
let   score    = 0;

for (let rank of ranks) {
    switch (rank) {
        case 'Jack':
        case 'Queen':
        case 'King':
            score += 10;
            break;
        case 'Ace';
            score += (score <= 11) ? 10 : 1;
            break;
        default:
            score += rank;
            break;
    }
}
=end code

In Raku, C<given> can be used like switch statements. There is no equivalent
to C<break> since C<when> blocks are most commonly used like C<case>
statements. One major difference between C<switch> and C<given> is that a value
passed to a C<switch> statement will only match cases that are exactly equal to
the value; C<given> values are smartmatched (C<~~>) against the C<when> values.

=begin code
my     @ranklist = [2, 3, 4, 5, 6, 7, 8, 9, 'Jack', 'Queen', 'King', 'Ace'];
my     @ranks    = @ranklist.pick: 3;
my Int $score    = 0;

for @ranks -> $rank {
    # The when blocks implicitly return the last statement they contain.
    $score += do given $rank {
        when 'Jack' | 'Queen' | 'King' { 10                      }
        when 'Ace'                     { $score <= 11 ?? 10 !! 1 }
        default                        { $_                      }
    };
}
=end code

If there are multiple C<when> blocks that match the value passed to C<given>
and you wish to run more than one of them, use C<proceed>. C<succeed> may be
used to exit both the C<when> block it's in and the given block, preventing any
following statements from being executed:

=begin code
given Int {
    when Int     { say 'Int is Int';     proceed }
    when Numeric { say 'Int is Numeric'; proceed }
    when Any     { say 'Int is Any';     succeed }
    when Mu      { say 'Int is Mu'               } # Won't output
}

# OUTPUT:
# Int is Int
# Int is Numeric
# Int is Any
=end code

=head3 for, while, and do/while

There are three different types of for loops in JavaScript:

=begin code :lang<javascript>
// C-style for loops
const letters = {};
for (let ord = 0x61; ord <= 0x7A; ord++) {
    let letter = String.fromCharCode(ord);
    letters[letter] = letter.toUpperCase();
}

// for..in loops (typically used on objects)
for (let letter in letters) {
    console.log(letters[letter]);
}
# OUTPUT:
# A
# B
# C
# etc.

// for..of loops (typically used on arrays, maps, and sets)
for (let letter of Object.values(letters)) {
    console.log(letter);
}
# OUTPUT:
# A
# B
# C
# etc.
=end code

Raku C<for> loops most closely resemble C<for..of> loops, since they work on
anything as long as it's iterable. C-style loops are possible to write using
C<loop>, but this is discouraged since they're better written as C<for> loops
using ranges. Like C<if> statements, C<for> may follow a statement, with the
current iteration being accessible using the C<$_> variable (known as "it").
Methods on C<$_> may be called without specifying the variable:

=begin code
my Str %letters{Str};
%letters{$_} = .uc for 'a'..'z';
.say for %letters.values;
# OUTPUT:
# A
# B
# C
# etc.
=end code

C<while> loops work identically between JavaScript and Raku. Raku also has
C<until> loops, where instead of iterating until the given condition is false,
they iterate until the condition is true.

C<do/while> loops are known as C<repeat/while> loops in Raku. Likewise with
C<while>, C<repeat/until> loops also exist and loop until the given condition
is false.

To write infinite loops in Raku, use C<loop> rather than C<for> or C<while>.

In JavaScript, C<continue> is used to skip to the next iteration in a loop, and
C<break> is used to exit a loop early:

=begin code :lang<javascript>
let primes = new Set();
let i      = 2;

do {
    let isPrime = true;
    for (let prime of primes) {
        if (i % prime == 0) {
            isPrime = false;
            break;
        }
    }
    if (!isPrime) continue;
    primes.add(i);
} while (++i < 20);

console.log(primes); # OUTPUT: Set { 2, 3, 5, 7, 11, 13, 17, 19 }
=end code

In Raku, these are known as C<next> and C<last> respectively. There is also
C<redo>, which repeats the current iteration without evaluating the loop's
condition again.

C<next>/C<redo>/C<last> statements may be followed by a label defined before an
outer loop to make the statement work on the loop the label refers to, rather
than the loop the statement is in:

=begin code
my %primes is SetHash;
my Int $i = 2;

OUTSIDE:
repeat {
    next OUTSIDE if $i %% $_ for %primes.keys;
    %primes{$i}++;
} while ++$i < 20;

say %primes; # OUTPUT: SetHash(11 13 17 19 2 3 5 7)
=end code

=head3 do

C<do> is not currently a feature in JavaScript, however a proposal has been made
to L<add it to ECMAScript|https://github.com/tc39/proposal-do-expressions>.
C<do> expressions evaluate a block and return the result:

=begin code
constant VERSION        = v2.0.0;
constant VERSION_NUMBER = do {
    my @digits = VERSION.Str.comb(/\d+/);
    :16(sprintf "%02x%02x%04x", |@digits)
};
say VERSION_NUMBER; # OUTPUT: 33554432
=end code

=head2 Types

=head3 Creating types

In JavaScript, types are created by making a class (or a constructor in ES5
and earlier). If you've used TypeScript, you can define a type as a subset of
other types like so:

=begin code :lang<typescript>
type ID = string | number;
=end code

In Raku, classes, roles, subsets, and enums are considered types. Creating
classes and roles will be discussed in
L<the OOP section of this article|#Object-oriented_programming>. Creating an ID
subset can be done like so:

=begin code
subset ID where Str | Int;
=end code

See the documentation on L<subset|/language/typesystem#subset> and
L<Junction|/type/Junction> for more information.

TypeScript enums may have numbers or strings as their values. Defining the
values is optional; by default, the value of the first key is 0, the next key,
1, the next, 2, etc. For example, here is an enum that defines directions for
extended ASCII arrow symbols (perhaps for a TUI game):

=begin code :lang<typescript>
enum Direction (
    UP    = '↑',
    DOWN  = '↓',
    LEFT  = '←',
    RIGHT = '→'
);
=end code

Enums in Raku may have any type as their keys' values. Enum keys (and
optionally, values) can be defined by writing C<enum>, followed by the name
of the enum, then the list of keys (and optionally, values), which can be done
using L«< >|/language/quoting#Word_quoting:_<_>»,
L<« »|/language/quoting#Word_quoting_with_interpolation_and_quote_protection:_«_»>,
or L<( )|/language/operators#term_(_)>. C<( )> must be used if you want to
define values for the enum's keys. Here is the Direction enum as written in
Raku:

=begin code
enum Direction (
    UP    => '↑',
    DOWN  => '↓',
    LEFT  => '←',
    RIGHT => '→'
);
=end code

See the documentation on L<enum|/language/typesystem#enum> for more information.

=head3 Using types

In TypeScript, you can define the type of variables. Attempting to assign a
value that doesn't match the type of the variable will make the transpiler
error out. This is done like so:

=begin code :lang<typescript>
enum Name (Phoebe, Daniel, Joe);
let name: string = 'Phoebe';
name = Phoebe; # Causes tsc to error out

let hobbies: [string] = ['origami', 'playing instruments', 'programming'];

let todo: Map<string, boolean> = new Map([
    ['clean the bathroom', false],
    ['walk the dog', true],
    ['wash the dishes', true]
]);

let doJob: (job: string) => boolean = function (job: string): boolean {
    todo.set(job, true);
    return true;
};
=end code

In Raku, variables can be typed by placing the type between the declarator
(C<my>, C<our>, etc.) and the variable name. Assigning a value that doesn't
match the variable's type will throw either a compile-time or runtime error,
depending on how the value is evaluated:

=begin code :skip-test<compile-time error>
enum Name <Phoebe Daniel Joe>;
my Str $name = 'Phoebe';
$name = Phoebe; # Throws a compile-time error

# The type here defines the type of the elements of the array.
my Str @hobbies = ['origami', 'playing instruments', 'programming'];

# The type between the declarator and variable defines the type of the values
# of the hash.
# The type in the curly braces defines the type of the keys of the hash.
my Bool %todo{Str} = (
    'clean the bathroom' => False,
    'walk the dog'       => True,
    'wash the dishes'    => True
);

# The type here defines the return value of the routine.
my Bool &do-job = sub (Str $job --> Bool) {
    %todo{$job} = True;
};
=end code

=head3 Comparing JavaScript and Raku types

Here is a table of some JavaScript types and their equivalents in Raku:

=begin table
JavaScript | Raku
=============================
Object     | Mu, Any, Hash
Array      | List, Array, Seq
String     | Str
Number     | Int, Num, Rat
Boolean    | Bool
Map        | Map, Hash
Set        | Set, SetHash
=end table

C<Object> is both a superclass of all types in JavaScript and a way to create
a hash. In Raku, L<Mu|/type/Mu> is a superclass of all types, though usually
you want to use L<Any|/type/Any> instead, which is a subclass of C<Mu> but also
a superclass of nearly every type, with L<Junction|/type/Junction> being an
exception. When using C<Object> as a hash, L<Hash|/type/Hash> is what you want
to use. One key difference between C<Object> and C<Hash> is that C<Object>
preserves the order of its keys; C<Hash> does not by default.

There are three types equivalent to C<Array>. L<Array|/type/Array> is most
similar to C<Array>, since it acts as a mutable array. L<List|/type/List> is
similar to C<Array>, but is immutable. L<Seq|/type/Seq> is used to create lazy
arrays.

C<String> and L<Str|/type/Str> are for the most part used identically.

There are several different types in Raku equivalent to C<Number>, but the
three you'll most commonly see are L<Int|/type/Int>, L<Num|/type/Num>, and
L<Rat|/type/Rat>. C<Int> represents an integer. C<Num> represents a
floating-point number, making it the most similar to C<Number>. C<Rat>
represents a fraction of two numbers, and is used when C<Num> cannot provide
precise enough values.

C<Boolean> and L<Bool|/type/Bool> are for the most part used identically.

C<Map> has both a mutable and an immutable equivalent in Raku.
L<Map|/type/Map> is the immutable one, and L<Hash|/type/Hash> is the mutable
one. Don't get them mixed up! Like C<Map> in JavaScript, C<Map> and C<Hash> can
have any type of key or value, not just strings for keys.

Like C<Map>, C<Set> also has both a mutable and an immutable equivalent in Raku.
L<Set|/type/Set> is the immutable one, and L<SetHash|/type/SetHash> is the
mutable one.

=head2 Functions

=comment TODO

# TBD

=head1 Object-oriented programming

=comment TODO

# TBD

=head1 Asynchronous programming

=comment TODO

# TBD

=head1 The networking API

=head2 Net

In Raku, there are two APIs for dealing with networking: C<IO::Socket::INET>
(for synchronous networking), and C<IO::Socket::Async> (for asynchronous
networking).

C<IO::Socket::INET> currently only supports TCP connections. Its API resembles
that of C's socket API. If you're familiar with that, then it won't take long
to understand how to use it. For example, here's an echo server that closes the
connection after receiving its first message:

=begin code
my IO::Socket::INET $server .= new:
    :localhost<localhost>,
    :localport<8000>,
    :listen;

my IO::Socket::INET $client .= new: :host<localhost>, :port<8000>;
$client.print: 'Hello, world!';

my IO::Socket::INET $conn = $server.accept;
my Str $msg               = $conn.recv;
say $msg; # OUTPUT: Hello, world!
$conn.print($msg);

say $client.recv; # OUTPUT: Hello, world!
$conn.close;
$client.close;
$server.close;
=end code

By default, C<IO::Socket::INET> connections are IPv4 only. To use IPv6 instead,
pass C<:family(PF_INET6)> when constructing a server or a client.

In contrast, C<IO::Socket::Async> supports both IPv4 and IPv6 without the need
to specify which family you wish to use. It also supports UDP sockets. Here's
how you would write the same echo server as above asynchronously (note that
C<Supply.tap> is multithreaded; if this is undesirable, use C<Supply.act>
instead:

=begin code
my $supply = IO::Socket::Async.listen('localhost', 8000);
my $server = $supply.tap(-> $conn {
    $conn.Supply.tap(-> $data {
        say $data; # OUTPUT: Hello, world!
        await $conn.print: $data;
        $conn.close;
    })
});

my $client = await IO::Socket::Async.connect('localhost', 8000);
$client.Supply.tap(-> $data {
    say $data; # OUTPUT: Hello, world!
    $client.close;
    $server.close;
});

await $client.print: 'Hello, world!';
=end code

The equivalent code in Node.js looks like this:

=begin code :lang<javascript>
const net = require('net');

const server = net.createServer(conn => {
    conn.setEncoding('utf8');
    conn.on('data', data => {
        console.log(data); # OUTPUT: Hello, world!
        conn.write(data);
        conn.end();
    });
}).listen(8000, 'localhost');

const client = net.createConnection(8000, 'localhost', () => {
    client.setEncoding('utf8');
    client.on('data', data => {
        console.log(data); # OUTPUT: Hello, world!
        client.end();
        server.close();
    });
    client.write("Hello, world!");
});
=end code

=head2 HTTP/HTTPS

Raku doesn't natively support HTTP/HTTPS. However, CPAN packages such as
L<Cro|https://cro.services/> help fill the gap.

=head2 DNS

Raku does not currently support the majority of the features that Node.js's DNS
module implements. C<IO::Socket::INET> and C<IO::Socket::Async> can resolve
hostnames, but features like resolving DNS records and reverse IP lookups are
not implemented yet. There are some modules that are a work in progress,
such as L<Net::DNS::BIND::Manage|https://github.com/tbrowder/Net-DNS-BIND-Manage-Perl6/>,
that aim to improve DNS support.

=head2 Punycode

Punycode support is available through the L<Net::LibIDN|https://github.com/Kaiepi/p6-Net-LibIDN>,
L<Net::LibIDN2|https://github.com/Kaiepi/p6-Net-LibIDN2>, and
L<IDNA::Punycode|https://github.com/FROGGS/p6-IDNA-Punycode> modules on CPAN.

=head1 The filesystem API

=comment TODO

# TBD

=head1 Modules and packages

=comment TODO

# TBD

=end pod

# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6
