Интерполировать без создания контекста String в Raku?

Если у меня есть переменная my $a = True, я получаю этот вывод из следующего кода:

say «a list of words foo $a bar baz».raku; 
# OUTPUT: ("a", "list", "of", "words", "foo", "True", "bar", "baz")

То есть, даже если результатом является List, элемент True преобразовывается в строку перед включением в список - список содержит "True", а не True. Есть ли способ избежать этой строковой обработки при использовании интерполяции?

Был бы способ сделать это, если бы $a был классом, который я определил (и, следовательно, мог бы написать метод Str), а не Bool?

(Я знаю, что могу написать более подробный ("a", "list", "of", "words", "foo", $a, "bar", "baz") или «a list of words foo».Slip, $a, «bar baz».Slip, но я спрашиваю, есть ли способ по-прежнему использовать интерполяцию).


person codesections    schedule 15.03.2021    source источник
comment
У меня есть две причины задать этот вопрос, хотя я считаю, что ответ отрицательный, это невозможно. Во-первых, я могу ошибаться - как это было раньше, , когда я думал, что Раку что-то не может сделать. Во-вторых, наличие SO-ответов, в которых говорится, что это невозможно, может избавить других пользователей от необходимости искать правильный синтаксис для выполнения чего-то, что никогда не будет работать. (А перечисление вещей, которые Раку не может делать, плохо подходит для документации.) Пожалуйста, дайте мне знать, если вас раздражают такие вопросы; если нет, я могу спросить несколько в следующие несколько дней.   -  person codesections    schedule 15.03.2021
comment
когда я думал, что Раку что-то не может сделать. Раку не может изменить законы физики, но без этого никакой PL не может сделать больше, чем Раку. Он содержит полную GPL Тьюринга. Единственные ограничения - это когда, насколько эффективно и легко он делает то, что делает. Raku поддерживает MSP, так что Raku может делать это во время компиляции, что бы это ни было. Стандартный Raku уже поставляется с функциями, упрощающими некоторые задачи MSP. RakuAST и инструменты, созданные на его основе, значительно упростят практически все задачи MSP ier, включая MSP как для удобства, так и для производительности.   -  person raiph    schedule 16.03.2021
comment
Пожалуйста, дайте мне знать, если такой вопрос вас раздражает; если нет, я могу спросить несколько в ближайшие несколько дней. Я думаю, что сто ваших вдумчивых вопросов по этому поводу было бы замечательно, хотя я призываю вас разложить их, подождав, пока отправленный вами вопрос не получит ответ, который вы приняли, или, по крайней мере, не пройдет N дней ( где N = 2 кажется правильным) без принятого ответа перед отправкой следующего.   -  person raiph    schedule 16.03.2021
comment
Я призываю вас разложить их, подождав, пока на отправленный вами вопрос не будет получен ответ, который вы приняли, или пока не пройдет как минимум N дней (где N = 2 кажется примерно правильным) без принятого ответа, прежде чем отправлять следующий один. Согласовано 100%   -  person codesections    schedule 16.03.2021
comment
›Ни один PL не может сделать больше, чем Раку. Он содержит полную GPL Тьюринга. Я имею в виду, что это технически правильно. Но для довольно разумного значения Raku и не может, я бы сказал, что есть уловки, которые Raku в настоящее время не может делать (хотя гораздо больше, что он может!). Например, Raku в настоящее время не может знать, что sub f(--> Int) { 'Oops' } недействителен во время компиляции. Я не имею в виду, что для Raku невозможно написать статический анализатор; очевидно, что это не так. И я не имею в виду, что Раку никогда не сможет этого сделать. Я просто имею в виду, что сейчас не может.   -  person codesections    schedule 16.03.2021
comment
. @ codesections Конечно. Хотя прямо сейчас вы можете написать BEGIN { f }, и результатом будет ошибка времени компиляции. Чтобы было ясно, я понял и понимаю, чем вы были и что говорите. Мой комментарий был адресован не вам лично, а в первую очередь для более поздних читателей, которые могут неверно истолковать, что можно, а что нельзя. Некоторые PL никогда не смогут дать разработчикам возможность переводить вещи из времени выполнения во время компиляции, но Raku уже делает это, и скоро появятся новые возможности. Как вы говорите, разработчики могут написать статический анализатор, и, как заметил jnthn, часть ближайшего плана развития позволяет реализовать средства проверки типов в виде модулей.   -  person raiph    schedule 16.03.2021
comment
Действительно ли это вопрос «рано» или «поздно»? Вы можете представить себе, что на некоторых языках интерполяция задерживается (но, возможно, не в контексте представленного вами примера цепочки методов). Но действительно могут быть другие языки, которые (например) обнаруживают логическое значение или значение NA и сохраняют его как есть (т.е. не преобразовывают в строку во время интерполяции).   -  person jubilatious1    schedule 26.03.2021


Ответы (2)


Интерполяция помещает вещь в строку.

"a b c $thing d e f"

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

В основном это компилируется в этот код:

infix:<~>( 「a b c 」, $thing.Str, 「 d e f」 )

« a b c $thing »

Это сокращение от:

Q :double :quotewords « a b c $thing d e f »

То есть использовать Quoting DSL, включить :double семантику кавычек (“”) и включить :quotewords.

:quotewords - это функция, которая разделяет строку на отдельные части. Это происходит только после того, как он превратился в струну.

Представьте, что это компилируется в:

Internals::quotewords( infix:<~>( 「 a b c 」, $thing.Str, 「 d e f 」 ) )

Есть другой способ получить желаемое, кроме использования .Slip или префикса |.

flat «a list of words foo», $a, «bar baz»

Вся цель цитируемого DSL состоит в том, что он производит строку.

При этом :words, :quotewords и :val все меняют его так, чтобы он возвращал что-то отличное от одной строки. И идея их в том, что они изменяют DSL.

Итак, МОЖЕТ вы могли бы убедить достаточное количество людей, что такое изменение того стоит. Это большое возможно.

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

person Brad Gilbert    schedule 15.03.2021
comment
Или, что еще лучше, просто создайте специализированный DSL ^ _ ^ (который напоминает мне вернуться к написанию моих практических рекомендаций по DSL на основе опыта с binex, который в настоящее время приостановлен до RakuAST) - person user0721090601; 15.03.2021
comment
Спасибо, что все имеет смысл и было о том, о чем я подозревал; очень полезно получить подтверждение. В основном это компилируется в этот код: infix:<~>( 「a b c 」, $thing.Str, 「 d e f」 ). Я подумал о таком коде, когда спросил, могу ли я избежать строкового преобразования $thing, если это тип под моим контролем - в конце концов, я мог бы теоретически написать .Str метод, который не возвращает Str . Но теперь, когда вы указываете способ использования infix:<~>, этот путь кажется маловероятным - если он что-то сделает, это, вероятно, просто нарушит интерполяцию. - person codesections; 16.03.2021

То, что здесь происходит, не имеет ничего общего с цитированием, а больше связано с context < / а>. Как указал @ brad-gilbert, все, что происходит, проходит через размещение ~ впереди, что переводит переменную в контекст String.

Но это дает ответ на ваш второй вопрос:

Был бы способ сделать это, если бы $ a был классом, который я определил (и, следовательно, мог бы написать метод Str), а не Bool?

Теоретически должно работать примерно так:

class A { 
    has Bool $.foo;
    method Str { $.foo }
};
my $a = A.new( :foo(True) );
say «a b $a».raku

Увы, это возвращает «No such method 'WORDS_AUTODEREF' for invocant of type 'Bool'␤, поэтому, вероятно, нужно немного поработать (или я мог столкнуться с какой-то ошибкой). Так что на данный момент, и для вашего точного примера, это безответчик. На самом деле этот метод есть только у Strs, поэтому я думаю, что на данный момент, и если вы не потрудитесь создать этот специализированный метод для класса, это будет сложно сделать.

person jjmerelo    schedule 16.03.2021