Perl 6: доступ для записи многомерного индекса с помощью AT-POS - PullRequest
0 голосов
/ 16 декабря 2018

Вы можете легко разрешить доступ к своим собственным классам с помощью индекса AT-POS:

class Foo
{
    has @.grid;

    method AT-POS($x) is rw { return-rw @!grid[$x] }
    method Str { '<' ~ @!grid.join(' ') ~ '>' }
    method gist { self.Str }
}

my $foo = Foo.new(:grid(<a b c d e>));
say $foo;
say $foo[2];
$foo[3] = 'z';
say $foo;

output:

<a b c d e>
c
<a b c z e>

Но мне нужен двумерный доступ к индексам.Я понял, как заставить эту работу работать на чтение, но она умирает при записи:

class Bar
{
    has @.grid;

    method AT-POS($y, $x) is rw { return-rw @!grid[$y;$x] }
    method Str { '<' ~ @!grid».join(' ').join("\n ") ~ '>' }
    method gist { self.Str }
}

my $bar = Bar.new(:grid(<a b c d e>, <f g h i j>, <k l m n o>));
say $bar;
say $bar[1;2];
$bar[2;3] = 'z';
say $bar;

output:

<a b c d e
 f g h i j
 k l m n o>
h
Too few positionals passed; expected 3 arguments but got 2
  in method AT-POS at ./p6subscript line 25
  in block <unit> at ./p6subscript line 33

Есть ли способ заставить эту работу работать?

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Мое решение будет (при условии, что у нас есть только 2 измерения):

class Bar {
    has @.grid;

    method TWEAK() { $_ .= Array for @!grid }
    method AT-POS(|c) is raw { @!grid.AT-POS(|c) }
    method Str { '<' ~ @!grid».join(' ').join("\n ") ~ '>' }
    method gist { self.Str }
}

TWEAK преобразует любые списки, которые были переданы массивам, если они еще не были.is raw на AT-POS - это все, что нужно: return-rw - очень окольный способ сделать это.

0 голосов
/ 16 декабря 2018

Почему-то метод AT-POS не вызывается. документация упоминает об использовании ASSIGN-POS вместо этого, поэтому здесь мы идем:

class Bar
{
    has @.grid is rw;

    method AT-POS($y, $x) is rw { say "AT-POS $y, $x"; return-rw @!grid[$y;$x] }
    method ASSIGN-POS($y, $x, $new) { say "ASSIGN-POS $y, $x"; @!grid[$y;$x] = $new }
    method Str { '<' ~ @!grid».join(' ').join("\n ") ~ '>' }
    method gist { self.Str }
}

my $bar = Bar.new(:grid(<a b c d e>, <f g h i j>, <k l m n o>));
say $bar;
say $bar[1;2];
$bar[2;3] = 'z';
say $bar;

Что, что интересно, приводит к еще одной ошибке:

Cannot modify an immutable List ((k l m n o)) in method ASSIGN-POS at semilist-so.p6 line 8 in block <unit> at semilist-so.p6 line 16

Итак, проблема не в синтаксисе, а в том, что вы работаете с неизменяемыми списками.Вы должны использовать Array s, которые являются изменяемыми, и вы сможете это сделать.

class Bar
{
    has @.grid is rw;

    method AT-POS($y, $x) is rw { return-rw @!grid[$y;$x] }
    method ASSIGN-POS($y, $x, $new) { @!grid[$y;$x] = $new }
    method Str { '<' ~ @!grid».join(' ').join("\n ") ~ '>' }
    method gist { self.Str }
}

my $bar = Bar.new(:grid([<a b c d e>], [<f g h i j>], [<k l m n o>]));
say $bar;
say $bar[1;2];
$bar[2;3] = 'z';
say $bar;
...