Почему этот пример документации не работает? Является ли мой обходной путь приемлемым эквивалентом?

При изучении задокументированного примера, поднятого в этом вопросе о perl6,, который недавно был задан здесь, я обнаружил, что последний вариант реализации (моя интерпретация примера состоит в том, что он предоставляет три разных способа что-либо сделать) - не работает. Запуск этого;

class HTTP::Header does Associative {
    has %!fields handles <iterator list kv keys values>;

    sub normalize-key ($key)   { $key.subst(/\w+/, *.tc, :g)         }
    method EXISTS-KEY ($key)   { %!fields{normalize-key $key}:exists }
    method DELETE-KEY ($key)   { %!fields{normalize-key $key}:delete }
    method push (*@_)          { %!fields.push: @_                   }


    multi method AT-KEY (::?CLASS:D: $key) is rw {
        my $element := %!fields{normalize-key $key};

        Proxy.new(
            FETCH => method () { $element },

            STORE => method ($value) {
                $element = do given $value».split(/',' \s+/).flat {
                    when 1  { .[0] }    # a single value is stored as a string
                    default { .Array }  # multiple values are stored as an array
                }
            }
        );
    }
}

my $header = HTTP::Header.new;
say $header.WHAT;  #-> (Header)

$header<Accept> = "text/plain";
$header{'Accept-' X~ <Charset Encoding Language>} = <utf-8 gzip en>;
$header.push('Accept-Language' => "fr");    # like .push on a Hash

say $header<Accept-Language>.perl;          #-> $["en", "fr"]

... дает ожидаемый результат. Обратите внимание, что третья последняя строка с мета-оператором X назначает литеральный список (составленный с помощью угловых скобок) хеш-срезу (с учетом гибкого определения «хеша»). Насколько я понимаю, это приводит к трем отдельным вызовам метода AT-KEY, каждый с одним строковым аргументом (кроме self) и, следовательно, не задействует предложение default оператора given. Это правильно?

Когда я придумываю вариант использования, в котором задействована эта часть кода, кажется, что он терпит неудачу;

... as above ...
$header<Accept> = "text/plain";
$header{'Accept-' X~ <Charset Encoding Language>} = <utf-8 gzip en>;
$header{'Accept-Language'} = "en, fr,    cz";

say $header<Accept-Language>.perl;          #-> ["en", "fr", "cz"] ?? 

# outputs
(Header)
This Seq has already been iterated, and its values consumed
(you might solve this by adding .cache on usages of the Seq, or
by assigning the Seq into an array)
  in block  at ./hhorig.pl line 20
  in method <anon> at ./hhorig.pl line 18
  in block <unit> at ./hhorig.pl line 32

Сообщение об ошибке дает прекрасное объяснение - тема представляет собой последовательность, созданную разделением, и теперь она потрачена, и поэтому на нее нельзя ссылаться в предложениях when и / или default.

Правильно ли я «поднял» и реализовал пример? Является ли мой изобретенный вариант использования нескольких языковых кодов в одной строке неправильным или приведенный пример кода неверен / устарел? Я говорю «устаревший», поскольку, насколько я помню, Seq появился довольно поздно в процессе разработки perl6 - так что, возможно, этот код работал раньше, но не сейчас. Может кто уточнить / подтвердить?

Наконец, с учетом сообщения об ошибке появляется следующий код для решения проблемы;

       ... as above ...
       STORE => method ($value) {
            my @values = $value».split(/',' \s+/) ;
            $element = do given @values.flat {
                when 1  { $value  }   # a single value is stored as a string
                default { @values }   # multiple values are stored as an array
            }
        }

... но является ли это точным эквивалентом?


person Marty    schedule 26.04.2016    source источник
comment
Присваивать массиву не нужно, просто добавьте .List в конец: $value».split(/',' \s+/).flat.List   -  person    schedule 09.04.2018


Ответы (1)


Этот код работает сейчас (Rakudo 2018.04) и печатает

$["en", "fr", "cz"]

как предполагалось. Вероятно, это была ошибка, которую в конечном итоге решили.

person jjmerelo    schedule 14.05.2018