Хобрук: Ваш путь к мастерству в программировании

Perl6: получение ссылки на массив для модуля Perl5

Я пытаюсь написать блокнот Excel на Perl6, используя Excel :: Writer :: XLSX.

Я использую Inline :: Perl5 через use Excel::Writer::XLSX:from<Perl5>

В частности, я хочу написать строку, как в Perl5:

$worksheet -> write_row(0,0, \@line);

но это дает ошибку

Чтобы передать массив, хэш или подпрограмму функции в Perl 6, просто передайте его как есть. Для других применений оператора ref Perl 5 рассмотрите вместо этого привязку с :: =. Заключите в скобки (...), если вы намеревались захватить одну переменную.

поэтому я пробую advice1:

$worksheet.write_row(0,0, @line)

что дает ошибку

Не ссылка на массив в вызове write_row () в -e строке 0.

совет2:

$worksheet.write_row(0,0, ::=@line);

Не ссылка на массив в вызове write_row () в -e строке 0.

$worksheet.write_row(0,0, (@line));

что дает те же ошибки.

Как я могу записать массив в строку с помощью Excel :: Writer :: XLSX в Perl6?

18.02.2019

  • Привет, кон. Пожалуйста, попробуйте $worksheet.write_row(0,0, $@line). Если это сработает, я напишу ответ. 18.02.2019
  • @raiph, который действительно работает. Я приму твой ответ, как только он будет написан 18.02.2019
  • @raiph \(@line) генерирует ту же ошибку, что и другие методы 18.02.2019

Ответы:


1

Решение - написать $@array вместо \@array:

$worksheet.write_row(0,0, $@line)

Остальная часть этого ответа представляет собой краткое руководство по написанию кода с использованием установленных адаптеров иностранного языка и решению любых возникающих проблем. Я предполагаю, что это будет общий ресурс, ответ, который выходит далеко за рамки этого конкретного вопроса.

Он начинается с очевидного вопроса «Почему $@foo?», Обсуждает, как успешно использовать адаптеры иностранного языка, и заканчивается объяснением, почему предупреждающее сообщение было бесполезным.

Почему $@foo?

Запись $@foo для передачи @foo в качестве ссылки на массив P5 - это простое и естественное использование существующей функции P6.

Тем не менее, пользователям не нужно понимать эту $ особенность P6, и им не нужно знать, как Inline::Perl5 ее использует, чтобы делать то, что они хотят (чтобы написать код P6, который передает ссылку на массив функции из P5 модуль).

Итак, главный ответ на вопрос "почему $@foo?" в том, что вы так пишете, и это работает. \ o /

Откуда следует знать магические заклинания?

Я получил решение для передачи ссылки на массив из Inline :: Perl5 README:

Ссылки HASH и ARRAY создаются автоматически, если объекты Perl 6 помещены в контейнер:

$p5obj.takes-an-array:      [<a b c>];
$p5obj.takes-an-array-ref: $[<a b c>];

(Слово «контейнерный» относится к концепции P6, которую lizmat хорошо объясняет тем, кто знает P5 в ее Контейнеры в статье P6. Но контейнеровоз на самом деле технически не имеет отношения к почему $@foo означает ссылку на массив в P5 при использовании Inline::Perl5. Да, это работает. Нет, не должно быть таким.)

Почему $@foo в P6 означает ссылку на массив в P5?

Причина, по которой написание $@foo является правильным, заключается не в том, что язык P6 или компилятор говорят, что это так.

Это подходящая функция P6, но причина, по которой это правильно, заключается в том, что так говорит niner (автор Inline::Perl5).

Почему Найнер выбрал $@foo?

Предположительно потому, что это:

  • Легко писать для новичков;

  • Будет иметь смысл для этой цели, когда кто-то узнает P6;

  • Легко задокументировать;

  • Легко преобразовать из его значения P6 (Array в Scalar) в целевое значение P5 (ссылка на массив P5) эффективным способом.

Чего ожидать при использовании адаптеров для иностранных языков

Inline::Perl5 - один из нескольких языковых адаптеров. Эти адаптеры позволяют коду P6 встраивать код, написанный на этих иностранных языках, и / или использовать модули, написанные на этих иностранных языках.

Когда компилятор Rakudo P6 видит :from<Perl5> в операторе use, он неявно вызывает ранее установленный модуль P6 с именем Inline::Perl5.

Inline::Perl5 устанавливает код маршалинга, который автоматически сопоставляет код P6 с кодом P5 и обратно, так что P6 и P5 могут работать вместе с минимальными усилиями.

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

  • Хотя очевидной вещью для сопоставления 42 в P6 на всех без исключения иностранных языках является их значение, представляющее целое число 42, сопоставление не всегда так просто для структур данных более высокого уровня, функций, ссылок и т. Д. Иногда удивительно, что можно написать код P6 (вы можете создать класс P6, который является подклассом класса P5, написав его точно так же, как если бы это был обычный код P6!), но иногда вам нужно следовать правилу (как в этом случае как передать массив P6 в P5 в качестве ссылки на массив). См. Раздел Документация адаптера ниже.

  • Язык P6 и компилятор не знают, что отображение происходит. Поэтому любые отображаемые ими сообщения об ошибках или предупреждениях могут быть бесполезными и даже вводить в заблуждение. Кроме того, ошибки адаптера отделены от ошибок в P6, в его компиляторах и в используемых модулях на иностранном языке. См. Раздел Предупреждения и ошибки ниже.

Автоматическое сопоставление, выполняемое адаптерами иностранных языков, далеко не автоматическое. Талантливые разработчики должны написать код адаптера, который выполняет всю маршалинг данных, исключений и т. Д.

Учитывая достаточное количество прошедшего времени (лет), адаптер может приблизиться к идеалу, в котором вам никогда не придется думать о существовании адаптера, если вы просто хотите использовать модули или код этого языка в P6. Вы просто используете его, и он всегда работает так же, как и на иностранном языке.

Один из способов быстрее приблизиться к этому идеалу для вас, дорогой читатель, и для всех нас - это использовать сторонние модули через существующие адаптеры и писать SO-вопросы и проблемы с файлами, когда определенные функции кажутся неработающими. Спасибо @con, niner и всем, кто делает это возможным.

Документация по адаптеру

Единственный способ узнать наверняка, какой код P6 вы должны написать, чтобы использовать модуль иностранного языка, который вы использовали через :from<...>, - это:

  • Прочтите документацию к модулю иностранного языка, чтобы узнать, чего он ожидает; а потом

  • Прочтите документацию адаптера, чтобы узнать, как написать соответствующий код P6, который дает иностранному языку и модулю иностранного языка то, что они ожидают.

В этом случае, когда мы говорим об использовании :from<Perl5>, адаптер - Inline::Perl5. В настоящее время его документация представляет собой репозиторий проекта github README. Итак, чтобы увидеть, что вы должны написать, чтобы дать P5 и модулю P5 то, что они ожидают, прочтите этот документ.

У каждого адаптера будет своя собственная документация; ссылку можно найти в его списке на modules.perl6.org.

Предупреждения и ошибки

Если что-то пойдет не так при использовании модуля иностранного языка в P6 (что не произойдет при использовании того же кода непосредственно на этом иностранном языке), тогда:

  • Убедитесь, что вы прочитали соответствующую документацию адаптера;

  • Если вы получили предупреждение или сообщение об ошибке, обязательно обратитесь к документации адаптера и его очереди проблем, чтобы увидеть, проливает ли он свет на это конкретное сообщение;

  • Если вы считаете, что есть ошибка в том, как что-то работает (или не работает) в P6 при использовании модуля иностранного языка, который отлично работает при использовании непосредственно на этом иностранном языке, обратитесь к очереди задач адаптера. Например, если вы используете :from<Perl5>, обратитесь к очереди задач Inline::Perl5. Если вы решите что-то опубликовать, напишите здесь, если вы не уверены, что это ошибка, или в очередь задач адаптера, если да.

Поскольку язык P6 и компилятор не осведомлены о том, что происходит сопоставление, предупреждения и сообщения об ошибках могут вводить в заблуждение в контексте обучения использованию любых аспектов адаптера иностранного языка, которые включают следующие правила, такие как правило $@foo этого SO.

В случае проблем с P5 это может усугубиться тем, что P6 пытается помочь кодировщикам P5, пишущим код P6, и пытается дать обратную реакцию при использовании Inline::Perl5. Пример в вопросе является хорошим примером:

To pass an array, hash or sub to a function in Perl 6, just pass it as is.

P6 считает, что вы могли использовать префикс \ для написания ссылок на массивы. Он думает, что вы могли не знать, что вам не нужно писать косую черту в P6. Он не понимает, что вы пытаетесь настоять на получении ссылки на массив, которую P5 поймет через Inline::Perl5.

For other uses of Perl 5's ref operator consider binding with ::= instead.

P6 думает, что вы пытаетесь сделать то, что в P5 обычно делается с \, не потому, что вы хотите работать с P5, а потому, что вы знаете P5, хотите что-то сделать в P6 без участия P5, и надеются, что будет работать тот же синтаксис.

(Кстати, совет ::= определенно не помог - потому что ::= еще не реализован!)

Parenthesize as (...) if you intended a capture of a single variable.

P6 не думает, что вы пытаетесь заставить функцию P5 работать со ссылкой на массив. Он думает, что вы пытаетесь создать Capture P6.

Его совет должен интерпретироваться как предлагающий вам написать \(@foo) вместо \@foo для создания Capture, содержащего @foo.

Он предупредил об использовании \@foo для обозначения Capture именно потому, что разработчики P5 могут написать это, думая, что это создаст ссылку на массив.

Таким образом, P6 не знает, что Inline::Perl5 существует, или что он собирается что-то делать с вашим кодом. Вместо этого его совет представляет собой попытку перевести синтаксис и концепции P5, которые, по его мнению, вы используете, в соответствующий синтаксис и концепции P6. Это не попытка посоветовать, как написать код P6, подходящий для отображения на P5 через Inline::Perl5.

С учетом всего сказанного, я предполагаю, что разработчики адаптеров и разработчики ядра P6 однажды изменят предупреждения и сообщения об ошибках, связанные с P5, в свете проблем с удобством использования, таких как были подняты этим SO.

19.02.2019

2

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

Компилятор жалуется, потому что вы пишете код, который выглядит как Perl5, а не Perl6. Он не знает, чего вы на самом деле пытаетесь достичь.


В Perl5 \ создает ссылку. В Perl6 такого нет.

use v5.12;

my @a;
my $a = \@a;
say ref $a; # ARRAY
say ref \$a; # REF

В Perl6 \ используется для создания Capture.

use v6.d;

my @a;
my $a = \(@a);
say $a.^name; # Capture

Поскольку Perl5 не имеет Capture, а Perl6 не имеет REF, уровень интерфейса переводит Capture в REF для использования с Perl5.

Массив в Perl6 уже является своего рода ссылкой, поэтому \(@a) в Perl6 похож на \\@a в Perl5.


В качестве способа тестирования я собираюсь использовать Scalar :: Util :: reftype.

use v6.d;

use Scalar::Util:from<Perl5> <reftype>;

my @a;
say reftype @a; # ARRAY

say reftype \(@a); # REF

Первый работает только потому, что reftype имеет прототип, который принимает единственный аргумент. У большинства подпрограмм в Perl5 нет прототипа. Даже когда они это делают, вызовы методов игнорируют прототипы.


В Perl5 массивы обычно сводятся к внешним спискам.

use v5.12;

my @a = 3,2,1;
my @b = 5,4,@a;

say for @b;
# 5
# 4
# 3
# 2
# 1

Чтобы сделать вызов кода Perl5 более похожим на Perl5, массивы сглаживаются.

use v6.d;
use Inline::Perl5;

my $p5 = Inline::Perl5.new;
$p5.run( 'use v5.12; sub fubar { say for @_ }' );

$p5.call( 'fubar', 1,2,3,[4,5] );
# 1
# 2
# 3
# 4
# 5

Один из способов предотвратить сглаживание в Perl6 - сделать его элементом.

use v6.d;

my @a = 1,2,3;
.say for @a;
# 1
# 2
# 3
.say for $@a;
# [1,2,3]

Так что давайте попробуем это при вызове Perl5.

use v6.d;
use Inline::Perl5;

my $p5 = Inline::Perl5.new;
$p5.run( 'use v5.12; sub fubar { say for @_ }' );

$p5.call( 'fubar', 1,2,3,$[4,5] );
# 1
# 2
# 3
# ARRAY(0x55cedda35300)

$p5.call( 'fubar', 1,2,3,[4,5].item );
# 1
# 2
# 3
# ARRAY(0x55ceddbcfc38)

$p5.call( 'fubar', 1,2,3,\[4,5] );
# 1
# 2
# 3
# REF(0x55ceddbcfb90)

Итак, $(…) и .item оба работают для предотвращения сглаживания массивов при вызове кода Perl5 без получения на него двойной ссылки, как это делает \(@).

19.02.2019
Новые материалы

Мой начальный путь к микросервисам с Spring Boot
Почему мы используем микросервисы? Микросервисы — это шаблон проектирования программного обеспечения, который включает создание большого приложения в виде набора небольших независимых..

Уменьшите количество шаблонов при запуске тестов Kotlin
Используя изящный трюк Kotlin, вы можете сделать свои тесты чистыми и простыми для понимания и обслуживания. Тестирование должно быть легким. Если ваши тесты слишком сложны и сложны в..

Понимание React.js: гармоничная симфония компонентов и модульность в стиле LEGO
Понимание React.js: гармоничная симфония компонентов и модульность в стиле LEGO Представляем искусство и науку, лежащую в основе строительных блоков React.js, React Components, которые помогают..

Почему я, журналист, в отчаянии создал сетевое приложение B2B
Почему я, журналист, в отчаянии создал сетевое приложение B2B Итак, вот верхняя линия. Я построил OnGreentech, сеть для индустрии возобновляемых источников энергии. Если вам интересно,..

Ограниченные машины Больцмана (RBM)
Практическое руководство по обучению RBM.pdf Задний план RBM использовались в качестве генеративных моделей для многих различных типов данных, включая помеченные и немеченые. В их условной..

Обнаружение маски или без маски с YOLO😷
Это руководство по созданию пользовательской модели обнаружения объектов для обнаружения людей, носящих или не носящих маски в общественных местах, созданной с использованием YOLO v3. Модель..

Управление приборами в чистом PHP
Этот пост дополняет эти: E2e тестирование Работа с несколькими средами . Мы разработали это решение для базы данных MariaDB, оно может отличаться, если вы используете другую базу..