Create an object/Native demonstration

Here we use delegation to handle all the normal hash methods that we don't need to override to define our new class.

class FixedHash {
        has $.hash handles *;
        method new(*@args) { self.bless: hash => Hash.new: @args }
        method AT-KEY(FixedHash:D: $key is copy) is rw {
                $!hash.EXISTS-KEY($key) ?? $!hash.AT-KEY($key) !! Failure.new(q{can't store value for unknown key});
        }
        method DELETE-KEY($key) { $!hash.{$key} = Nil }
}

# Testing
my $fh = FixedHash.new: "a" => 1, "b" => 2;
say $fh<a b>;   # 1 2
$fh<b>:delete;
say $fh<a b>;   # 1 Nil
$fh<b> = 42;
say $fh<a b>;   # 1 42
say $fh<c>;     # Nil
$fh<c> = 43;    # error

Output:

(1 2)
(1 (Any))
(1 42)
can't store value for unknown key
  in block <unit> at native-demonstration.p6:17

Actually thrown at:
  in block <unit> at native-demonstration.p6:17

By defining FALLBACK any class can handle undefined method calls. Since any class inherits plenty of methods from Any our magic object will be more of a novice conjurer then a master wizard proper.

class Magic {
        has %.hash;
        multi method FALLBACK($name, |c) is rw { # this will eat any extra parameters
                %.hash{$name}
        }

        multi method FALLBACK($name) is rw {
                %.hash{$name}
        }
}

my $magic = Magic.new;
$magic.foo = 10;
say $magic.foo;
$magic.defined = False; # error

Output:

10
Cannot modify an immutable Bool
  in block <unit> at native-demonstration.p6:15