Implementing AT-POS to return an object instead of a list of things

The AT-POS method is intended to let an object act as a Positional object. This is not what you appear to want. You want object[slice] DWIM.

The best way to achieve that, is to create a postcircumfic:<[ ]> (multi) candidate for your object:

class A {
    method slice(@_) {
        say @_;  # just to show the principle
    }
}
sub postcircumfix:<[ ]>($object, *@indices) {
   constant &slicer = &postcircumfix:<[ ]>;
   $object ~~ A
     ?? $object.slice(@indices)
     !! slicer($object, @indices)
}

A.new[1,2,4,5];  # [1 2 4 5]

my @a = ^10;     # check if foo[] still works
say @a[1,2,4,5]; # (1 2 4 5)

To make sure that the common behaviour of @a[] is kept, we save the value of the system's postcircumfix:[ ]> at compile time (with a constant). Then at runtime, when the object is not of the right class, invoke the original version of postcircumfix:<[ ]> with the given parameters.


Building on Liz's guidance:

class Names {
    has @.names;                                      # Make public so [] can access.
    method new (*@names) { nextwith :@names }         # Positional .new constructor.
    submethod BUILD (:@!names) {}                     # Called by nextwith'd Mu new.
    multi sub postcircumfix:<[ ]>                     # Overload [] subscript.
      ( Names $n, $index, *@indices )                 # Why `$index, *@indices`?
      is default is export                            # And why `is default`?
      { Names.new: |$n.names[ |$index, |@indices ] }  # Why? See my comment 
    method gist { @!names.join(', ') }                # below Liz's answer.
}
import Names;

my $original = Names.new: <jonathan joseph jotaro josuke giorno>;
my $sliced-off = $original[0..2];

say $original.^name;   #=> Names
say $original;         #=> jonathan, joseph, jotaro, josuke, giorno
say $sliced-off.^name; #=> Names
say $sliced-off;       #=> jonathan, joseph, jotaro

PLMK if the code or explanation is inadequate.

Tags:

Object

Slice

Raku