Путаница с назначением контейнера списка

Я могу страдать от угасания мозгов, но, согласно документам, касающимся назначения предметов и списков (https://docs.raku.org/language/variables#Item_and_list_assignment),

Назначение контейнеру списка (список-контекст) всегда запускает назначение списка.

Однако это, похоже, противоречит тому, что я получаю из кода (здесь воспроизведено в ответе raku).

> my %syns-by-name = %(Bq => ["Bq", "becquerel", "becquerels"], C => ["C", "coulomb", "coulombs"],)
    {Bq => [Bq becquerel becquerels], C => [C coulomb coulombs]}
> my Str @res = %syns-by-name{'Bq'};
    Type check failed in assignment to @res; expected Str but got Array (["Bq", "becquerel", ...) in block <unit> at <unknown file> line 1
> my Str @res = [|%syns-by-name{'Bq'}];
    [Bq becquerel becquerels]

Это ошибка, или я неправильно понимаю цель...?

Welcome to 𝐑𝐚𝐤𝐮𝐝𝐨™ v2020.10.
Implementing the 𝐑𝐚𝐤𝐮™ programming language v6.d.
Built on MoarVM version 2020.10.
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
11
0
157
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

TL;DR Если неродной элемент можно изменить с помощью присваивания, это Scalar. Назначение списка не сглаживает Scalar элементы. [1]

намек

Рассмотрим этот код:

my %map = :a;
%map<a> = 42;
say %map<a>; # 42

Задание работает, потому что:

say %map<a>.VAR.WHAT; # (Scalar)

"задание по списку"

Рассмотрим этот код:

my $scalar = 1,2;       # Useless use of constant integer 2
say $scalar;            # 1

my @list1 = 1,2;        # "list assignment", so RHS is iterated
say @list1;             # [1 2]

Так что это одно различие между назначением элемента и списка.

my @list3 = [1,2];      # Again, RHS is iterated
say @list3;             # [1 2]

my @list2 = (1,2);      # Again, RHS is iterated
say @list2;             # [1 2]

my @list4 = 1,(2,3);    # Again, RHS is iterated. Second element stays as a `List`.
say @list4;             # [1 (2 3)]

my @list5 = 1,[2,3];    # Again, RHS is iterated. Second element stays as an `Array`.
say @list5;             # [1 [2 3]]

Если в RHS указан только один элемент, и это не Scalar, присвоение списка сглаживает его. Но во всех других сценариях назначение списка не выравнивает элементы.

my @list6 = $[1,2];     # RHS is a `Scalar`. So it doesn't get flattened.
say @list6;             # [[1 2]]

Я ооочень запутался!

Разбираем ситуацию в вопросе:

my Str @res = %( :a[42,99] )<a>;

Это дает такую ​​же ошибку.

Потому что:

say .VAR.WHAT given :a[42,99]<a>;       # (Array)
say .VAR.WHAT given (% = :a[42,99])<a>; # (Scalar)

Сноски

[1] Когда предположение приводит к удивлению, и вы превращаете его в обучение, вы осознаете и идеализируете свои инвестиции в ERNing.

«(i) Array, сохраненное как значение Hash, содержится в Scalar». Любое значение, сохраненное как значение Hash, по умолчанию хранится в Scalar. То же самое верно даже для так называемых неизменяемых Maps. (Но, я полагаю, не будет вообще, по умолчанию или иным образом, с грядущими полностью неизменяемыми Dicts.) Но любое значение может быть привязано к устранению Scalar, например say .VAR.WHAT given (% := :a[42,99])<a>; # (Array).

raiph 26.12.2020 21:26

Итак, чтобы проверить мое понимание, в раку, когда у вас есть массив в качестве значения хэша, он представляется обратно как скаляр при доступе?

librasteve 26.12.2020 21:27

«(ii) вам нужно дважды декантировать его, если вы хотите получить список». (Я бы посоветовал придерживаться строчной буквы «список», а не «список», потому что это не связано с типом List, а просто списками в самом общем смысле и, в частности, «назначением списка».) Никогда не нужно несколько deconts (например, постфикс <>s) в любом коде Raku, потому что внутри Scalar никогда не может быть Scalar. Так что, если вам когда-нибудь понадобится деконтаминация, одной деконтаминации всегда достаточно.

raiph 26.12.2020 21:28

Упс - удалил свои первые ответы - извиняюсь. Мне ясно - ценю руководство!! Не стесняйтесь удалять/изменять свои ответы на мои ответы - отложу до завтра.

librasteve 26.12.2020 21:38

«Итак, чтобы проверить мое понимание, в раку, когда у кого-то есть массив как значение хэша, он представляется обратно как скаляр при доступе «если нет Scalar» (например, как показано в конце моего комментария о «(i) . .."), то это Array, чистое и простое. Нет Scalar, содержащего Array. Но если Array (или любое другое значение) содержится в Scalar (что вы можете проверить, вызвав для него .VAR.WHAT), то функции, которые проверяют VAR.WHAT объекта (я думаю, это просто сглаживание?), обнаружат, что это Scalar, и сработают. соответственно. Для других функций Scalar даст значение, которое оно содержит.

raiph 26.12.2020 21:41

@ p6steve Я буду спать на этом, но я думаю, что, вероятно, включу дополнительное обучение, которое происходит для нас обоих из-за нашего обмена, здесь, в комментариях, в ответ, а затем удалю свои комментарии. Я, вероятно, также уберу ERN из сноски, потому что это просто прихоть и плохо подходит для того, что я действительно хочу передать, потому что ERN на самом деле касается двигательной реакции в сочетании с умственной активностью, что здесь не применимо, тогда как то, что я хочу подчеркнуть, - это комбинация предположения => неожиданности (см. DWIM / WAT), которую я научил себя всегда получать и превращать в возможность обучения.

raiph 26.12.2020 21:48

Привет @raiph - это все круто - я узнал немного больше, ценю диалог!!

librasteve 27.12.2020 11:57

Примечание: вы не ошибетесь, прочитав ответ @raiphs. Тем не менее, я попытаюсь объяснить, что здесь происходит, и предложить возможные решения.

В Раку контекст - это все. Это означает, что разные контексты запускаются в разных контекстах, что подразумевает разные функции упаковки или распаковки структуры данных, с которой вы работаете.

Давайте посмотрим на это

my %syns-by-name = %(Bq => ["Bq", "becquerel", "becquerels"], C => ["C", "coulomb", "coulombs"],)

Мы знаем, что находимся в «ассоциативном» контексте, потому что проценты отмечают обе стороны знака равенства. Нам даже не понадобится это с правой стороны:

my %syns-by-name = Bq => ["Bq", "becquerel", "becquerels"], C => ["C", "coulomb", "coulombs"]

потому что, глядя на левый, это все еще ассоциативный, так что мы знаем, что у нас в руках. Тот же самый код rhs в этом контексте:

my @list-of-signs = Bq => ["Bq", "becquerel", "becquerels"], C => ["C", "coulomb", "coulombs"] # [Bq => [Bq becquerel becquerels] C => [C coulomb coulombs]]

Выдаст список пар. Итак, мы проверяем, что вы упомянули в своем ОП:

Назначение контейнеру списка (список-контекст) всегда запускает назначение списка.

правдиво. Это контейнер «список», мы превращаем rhs в список только по контексту. Здесь нет никакой двусмысленности: правая часть — это список, разделенный запятыми, левая — позиционный. Так вот.

Ситуация немного отличается в вашем коде. Возможно, это станет немного яснее, если мы будем использовать 2020.12.

 my %syns-by-name = Bq => ["Bq", "becquerel", "becquerels"], C => ["C", "coulomb", "coulombs"]
my Str @res = %syns-by-name{'Bq'};
# Type check failed in assignment; expected Positional[Str] but got Array ($["Bq", "becquerel", ...)

На первый взгляд разницы не видно, поэтому я выделю ее здесь:

Ошибка проверки типа при привязке; ожидал Positional[Str], но получил Array ($["Bq", "becquerel", ...)

Это показывает, что массив детализирован, он упакован так, чтобы его можно было вписать в скалярную вещь, такую ​​​​как значение хэш-ключа. По умолчанию значения хэша являются скалярными, и это включено в их определение:

role Associative[::TValue = Mu, ::TKey = Str(Any)] { }

Итак, то, что вы упомянули, остается в силе: назначение списка запускается, как в «контексте списка». Однако отдельный элемент можно преобразовать в список только одним способом: сделав его единственным элементом в списке. Если вы внимательно посмотрите на отчет об ошибке, то увидите, что он говорит: эй, ты сказал мне, что собираешься дать мне список Strs. Это не то! Это список (детализированных) массивов! Это работает:

my List @res = %syns-by-name{'Bq'};
# [(Bq becquerel becquerels)]

Что нам нужно сделать, так это «распаковать» эту штуку, то есть получить массив, который населяет скаляр. Очень просто:

my Str @res = %syns-by-name{'Bq'}<>;
# [Bq becquerel becquerels]

Оператор de-cont (который, возможно, следует называть оператором «unbox», «de-Scalarize» или «de-itemize») делает то, что нужно для вас. Однако это, вероятно, не то, что вы хотите. Вы хотите, чтобы ваши массивы были массивами. Однако это оказалось немного сложнее, и мне понадобится еще один вопрос SO, чтобы решить его.

Спасибо @JJ - я очень ценю объяснение. Это хороший, последовательный дизайн, чтобы значение хэша всегда было скаляром. Просто нужно знать, что массив будет назначен как один элемент, если вы не хотите сглаживать (|) или распаковывать (<>).

librasteve 28.12.2020 20:21

Другие вопросы по теме