Archived messages from: gitter.im/red/Russian from year: 2020

bubnenkoff
10:12Объясните зачем нужен /local у функций? Как понимаю он указывает что нужно локальное значение брать. Но зачем его указывать при перечислении аргументов самой функции?

9214
15:41@bubnenkoff что ты имеешь в виду под локальным значением?
DVL333
19:17@bubnenkoff После /local указываются слова, которые требуется сделать локальными в рамках контекста рассматриваемой функции. Т.е. после выхода из функции эти слова будут недоступны в рамках глобального контекста. Иначе, если так не сделать, они станут доступны глобально.
При этом следует иметь в виду, что в Red имеются несколько функций для создания функций: уточнение /local актуально для функции func, а то время как для function все слова, объявленные внутри нее, по умолчанию будут локальными (а еще есть does и has, но с их помощью объявляются функции, не требующие аргументов).
9214
19:31> Иначе, если так не сделать, они станут доступны глобально.

Нет, они останутся привязаны к своему старому контексту, который может быть (а может и не быть) глобальным. /local привязывает слова внутри тела функции к контексту данной функции. Без понимания со стороны @bubnenkoff'а что такое "слово", "привязка" и "контекст" объяснять это ему смысла нет.

> уточнение /local актуально для функции func, а то время как для function все слова, объявленные внутри нее, по умолчанию будут локальными

Нонсенс. /local может быть указан в спецификации любой функции. function автоматически собирает только set-word!ы и word!ы используйщиеся как аргументы foreach и repeat. has локализует все слова в данном тобой блоке.

DVL333
08:32Объяснять есть смысл всегда, потому что здесь не экзаменационная комната и если даже если человек что-то пока не знает, то как раз повод ему в этом помочь. Мне не влом сделать это по мере моих сил и знаний, если вы заняли такую непримиримую позицию.
Во-вторых, если уж и докапываться до слов, то и /local сам по себе ничего ни к чему не привязывает - он лишь указывает, что как надо будет привязывать.
Ну и в третьих, по поводу "нонсенса", то я сказал об актуальности, а не о возможности или невозможности указания local (не надо мои слова перекручивать), а во вторых вот вам пример того, что вы неправы:
funct1: function [][var1: "asd" print var1]
funct1

Ну и попробуйте достучитесь тут до var1 из глобального контекста.
9214
11:22> Мне не влом сделать это по мере моих сил и знаний

... требующих правок и уточнений (пардон за каламбур), которые я и внес, иначе они не очень то помогают, и всё что остается от таких объяснений это конфуз и непонимание у новичков. Не нравится быть неправым — отведи время на изучение матчасти.

> /local сам по себе ничего ни к чему не привязывает

/local само по себе это значение типа refinement!, но внутри спецификации функции (о которой собственно и был изначальный вопрос) оно несет именно тот смысл который я описал. В каком месте ты увидел "докапывание до слов" для меня остается мистикой.

> по поводу "нонсенса"

Попробуй понять свои ошибки, прежде чем кидаться в ответку. "для function все слова, объявленные внутри нее, по умолчанию будут локальными" это нонсенс — если все слова локальные, то функция более-менее бесполезна. Возьмем твой пример:

>> function [][var1: "asd" print var1]
== func [/local var1][var1: "asd" print var1]


Заметь что print остался нетронутым, т.к. function собирает только set-word!ы (var1:) и слова из foreach и repeat, что я и сказал выше. Если бы она вела себя в соответствии с твоей теорией, то на выходе ты бы получил:

>> function [][var1: "asd" print var1]
== func [/local var1 print][var1: "asd" print var1]


Т.е. print отвязался бы от своего старого значения (функция печати) и привязался к новому, которое по умолчанию none. /local сам по себе вполне может быть актуальным и для function, к примеру, если ты хочешь локализовать конкретное слово:

>> function [][set 'var1 "asd" print var1]
== func [][set 'var1 "asd" print var1]
>> function [/local var1][set 'var1 "asd" print var1]
== func [/local var1][set 'var1 "asd" print var1]


По своей логике это идентично твоей изначальной функции.

> а во вторых вот вам пример того, что вы неправы

Пока что твой пример не особо работает и только подтверждает мною сказанное.

> Ну и попробуйте достучитесь тут до var1 из глобального контекста.

Все загруженные слова автоматом попадают в глобальный контекст, но не имеют внутри него "осмысленного" значения, т.е. они указывают на unset. Что тут пробовать?

>> type? var1
== unset!
>> system/words = context? 'var1
== true


С другой стороны, контекст var1 внутри тела функции — это сама функция:

>> funct1: function [][var1: "asd" print var1]
== func [/local var1][var1: "asd" print var1]
>> first body-of :funct1
== var1:
>> context? first body-of :funct1
== func [/local var1][var1: "asd" print var1]


Поэтому достучаться до его значения ты в принципе не можешь — потому что этого самого значения нет на стеке, который контекст функции использует:

>> get first body-of :funct1
*** Script Error: context for var1: is not available
*** Where: get
*** Stack:


Т.е. у контекста недостает второй половинки — блока из значений (т.е. стека, который автоматом заполняется при вызове функции). Ну и напоследок:

>> foo: function [/extern bar][bar: "baz" print bar]
== func [][bar: "baz" print bar]
>> foo
baz
>> bar
== "baz"
DVL333
12:40Владимир, вы конечно сделали много важных уточнений и дали массу примеров, которые действительно стоит изучить для углубленного понимания работы Red. Это все, безусловно, полезно, спасибо.
Но все таки хотел бы заметить, что моя изначальная фраза "объявлять слово" была использована в смысле "декларировать" использование этого слова, в который я и вкладывал тот же смысл, что и вы. Я то вас понял, но новичку такое лучше не писать. )
9214
13:20@DVL333 в Red нет таких понятий как "декларация/объявление", "переменная" или "область видимости", в том смысле в котором их используют С-подобные языки. Слово это просто кусок данных загруженный внутри памяти, такой же как все остальное, символьное значение которое ты можешь использовать как *модель* переменной в привычном её понимании, или ключ в словаре, или как элемент диалекта с определенной семантикой. "/local декларирует слово как локальное" новичок прочитает как "/local делает переменную локальной к области видимости функции", после чего все катится по наклонной из-за неправильной концепции работы языка, отсюда и мои упор на основы: слово, контекст, связка — я то как раз это все понимаю, провел тут достаточно времени отучивая и переучивая новичков от "ой массив растет ой переменная не инициализируется".

В случае с @bubnenkoff'ым я бы вообще начал с затравки — Red это, прежде всего, формат данных, эдакий JSON на спидах, твои "код" (блок значений , данные!) это древовидная структура которая загружается (load) в память, и по которой разные трансляторы (do, parse, view, ...) могут "ходить", интерпретируя/компилируя значения в ней как им заблагорассудится, типо s-выражений в Лиспе, только без cons-ячеек и списковых структур. Такие данные, имеющие определенную семантику и транслятор для неё, называются *диалектами*. Спецификация функций это один из таких диалектов.

bubnenkoff
10:17Всем спасибо, я примерно понял. Что это указание к привязке на локальный контекст. Правда все равно в голове каша от того как он в памяти представлено
10:22Так, а вот что происходит когда мы пишем:
f: func[w] [d: copy [] append d w]


Мне в английском чате объясняли долго, но я так и не понял какую роль тут copy играет. Ведь как по мне если мы напишем: d: [] то при каждом вызове функции мы будем обнулять значение d
10:28И не могли бы пояснить как слово контекст следует понимать?
13:48Про копирование. Я правильно понимаю, что если слово определено внутри функции, то оно всегда хренит лишь ссылку на данные. Просто вот какую цитату нашел: ""It's the same in Smalltalk. Compiled method contains reference to a concrete instance of sequence.""
13:49Я достаточно много прочитал по этой теме, но все равно картинка в голове не очень ясная сформировалась. Просто мне упорно кажется что при каждом вызове: d: [] должно происходить затирание значений слова
9214
15:28@bubnenkoff слова и копирование серий никак не связаны между собой. Под контекстом понимай "таблицу" с двумя колонками: символ и его значение. Слова имеют внутри себя символ ("написание" слова) и ссылку на контект ("смысл" слова) в котором, зная символ, можно найти значение. Ссылка на контекст называется связкой. С сериями все чуть более интересно чем ты себе возможно представляешь, надо будет в живом формате тебе это всё разжевать, на пальцах и с картинками.
15:44> "It's the same in Smalltalk. Compiled method contains reference to a concrete instance of sequence."

Брр. Ни компиляции, ни методов, ни объектов тут нету. Фраза к Red вообще никакого отношения не имеет, не знаю откуда ты её выцепил.
DVL333
19:45@bubnenkoff По поводу контекста Владимир вам исчерпывающе ответил. Теперь по поводу копирования.
В вашем примере осуществляется работа с блоком [], который относится к числу indirect типов. Это означает, что в слоте памяти, соответствующем слову d из вашего примера, хранится лишь ссылка на данный блок (неважно, внутри это функции происходит или нет - всегда ссылка). При повторном вызове функции у вас слово d как указывало на блок, так и продолжит на него указывать, в том числе и с уже добавленными в него значениями. Чтобы создать новый пустой (или непустой - какой сами пожелаете) блок и используется функция copy.
Для того, чтобы понять разницу, просто сравните работу вашей функции с copy:
f: func[w] [d: copy [] append d w]
f "hi"
f "hi"
probe d
== ["hi"]

и без copy:
f: func[w] [d: [] append d w]
f "hi"
f "hi"
probe d
== ["hi" "hi"]
9214
20:47@DVL333 d: интерпретатор читает как "пройди по привязке вот этого вот конкретного слова, найди ячейку на которую слово указывает по его символу (d) и засунь в эту ячейку значение которое тебе даст выражение справа от d:".

В случае с d: [...] в ячейку засунется блок, который ссылается на буфер, и получится что и [...] внутри тела функции и [...] на которое теперь ссылается d "расшарили" этот самый буфер. Следующий дальше append d w в этот буфер засовывает какое-то значение -- а поскольку, повторяюсь [...] перед append ссылается на этот буффер, то то что в этот буфер засунулось там и останется, и будет отображаться как содержимое блока.

Более простой пример:

>> block: []
== []
>> append block 'thing
== [thing]
>> append block 'thing
== [thing thing]
>> append block 'thing
== [thing thing thing]
>> word: block
== [thing thing thing]
>> append word 'THING
== [thing thing thing THING]
>> block
== [thing thing thing THING]


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

bubnenkoff
06:40> @bubnenkoff слова и копирование серий никак не связаны между собой. Под контекстом понимай "таблицу" с двумя колонками: символ и его значение. Слова имеют внутри себя символ ("написание" слова) и ссылку на контект ("смысл" слова) в котором, зная символ, можно найти значение. Ссылка на контекст называется связкой. С сериями все чуть более интересно чем ты себе возможно представляешь, надо будет в живом формате тебе это всё разжевать, на пальцах и с картинками.

Я правильно понимаю, что контекстом может являться функция, строка или что либо то другое стоящее справа от двоеточия?
07:06> @bubnenkoff По поводу контекста Владимир вам исчерпывающе ответил. Теперь по поводу копирования.
> В вашем примере осуществляется работа с блоком [], который относится к числу indirect типов. Это означает, что в слоте памяти, соответствующем слову d из вашего примера, хранится лишь ссылка на данный блок (неважно, внутри это функции происходит или нет - всегда ссылка). При повторном вызове функции у вас слово d как указывало на блок, так и продолжит на него указывать, в том числе и с уже добавленными в него значениями. Чтобы создать новый пустой (или непустой - какой сами пожелаете) блок и используется функция copy.

А где про тип indirect можно почитать? И правильно ли я понимаю, что series к нему не относится т.к. в случае с series идет присвоение нового значение d: "abc"
9214
08:11@bubnenkoff нет и нет.
bubnenkoff
08:17@9214 тогда я еще больше запутался... На сколько я понимаю все структуры данных в Red это словари формата ключ-значение. Значением может быть любая последовательность симоволов или любое другое слово
9214
08:32> все структуры данных в Red это словари формата ключ-значение

Нет! Каждая "структура данных" это слот с типом данным и хранимым значением.

> Значением может быть любая последовательность симоволов или любое другое слово

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

>> ";%!?
*** Syntax Error: invalid value at {";%!?}
*** Where: do
*** Stack: load
bubnenkoff
08:35А где про это можно почитать? Я доки Ребол перечитывал несколько раз, но видимо опыт с другими языками мешает. Может есть иллюстрации какие чтобы наглядно было? Документация по Forth может помочь?
9214
08:46@bubnenkoff вот [черновик](https://gist.github.com/9214/7d17d484d71980239d679787eea226aa), если силы и время будут то закончу его на этой неделе.

Документация по Форту... и да и нет. Red не использует интерпретатор с шитым кодом как классические Форты, но общие идеи и философии языков перекликаются. Если ты понимаешь суть и механику Форта (включая такие штуки как create и does>), то с Red у тебя проблем возникнуть не должно (как и с любым другим языком в общем-то). Тем не менее, с точки зрения архитектуры это очень разные языки. С точки зрения концепций и подхода к программированию (использование предметно-ориентированных языков, метапрограммирование, упор на простоту и синергию, отказ от сложности и раздутости решений) -- может помочь. Конкретно к нашему случаю Форт никакого практического отношения не имеет.
bubnenkoff
08:46Спасибо, сейчас приступлю к чтению!
08:47Я вообще из мира Си-подобных языков. Увы ничего другого не знаю. Так что тот же Forth тоже с нуля учить
08:51
parse "aabbcc" [s: to "bb"]


Почему тут index? s будет равняться единице? В начале будет оценено первое значение символа и только потом сработает to. Верно?
9214
08:53@bubnenkoff если ты не планируешь углубляться в создание интерпретаторов с компиляторами и работу с языками, я бы не сказал что учить его обязательно. Интерпретатор (и компилятор) Форта это такое же чудо света как интерпретатор Лиспа -- срывает башню и мешает беззаботно работать, потому что Матрица перед глазами мельтешит. Короче, на свой страх и риск.

> Почему тут index? s будет равняться единице? В начале будет оценено первое значение символа и только потом сработает to. Верно?

Не-не-не, ничего оцененно не будет. [s: to "bb"] это блок данных, окей? Просто блок данных, не несущий **никакой** смысловой нагрузки. Как этот блок данных интерпретируется зависит от того какой интерпретатор ты используешь -- parse или, к примеру, do.
bubnenkoff
08:54Лучше для простоты parse а то запутаюсь
9214
08:59@bubnenkoff вот тебе блок с тремя значениями:
>> block: [to string! 'abc]
== [to string! 'abc]
>> length? block
== 3
>> forall block [probe type? block/1]
word!
word!
lit-word!
== lit-word!


Если ты его скормишь стандартному инетпретатору, он его прочитает как "сконвертируй вот это вот в строку":

>> do block
== "abc"


Если ты скормишь его как грамматику Parse, то parse прочитает его как "сопоставь всё до значения со строковым типом данных, затем сопоставь слово abc":

>> parse ["string" abc] block
== false


Почему false должно быть понятно если ты читал документацию по Parse, но это не суть. Суть в том что один и тот же блок данных разные интерпретаторы (parse и do) могут читать по разному.
09:06Собственно, если ты хочешь понять как работает стандартный интерпретатор Red (другими словами, понять стандартную семантику языка, а не изучить какой-то конкретный диалект вроде Parse, VID, Draw или даже Red/System), то parse тебе не нужен. С другой стороны, для понимания диалектов необходимо понять работу стандартного интерпретатора и загрузчика.
bubnenkoff
10:31@9214 у вас в статье есть фраза "ссылка (косвенный указатель, не прямой)". Имеется ввиду что ссылки бывают прямые и не прямые?
10:35"косвенные типы данных содержат в начинке ссылку на данные, хранимые в отдельной области памяти"
А эта область памяти тоже как слот организована? Или просто кусок памяти? Спрашиваю просто на всякий случае. Вдруг какие-то особенности есть
10:41Можно примеры прямых типов данных? Если в прямой тип данных что-то не влезает он автоматом в косвенный преобразуется? К примеру число это прямой? А если число очень большое?
9214
10:57@bubnenkoff

> Имеется ввиду что ссылки бывают прямые и не прямые?

Имеется в виду что "ссылка" это указатель, но указатель не на сами данные, а на другой указатель, называющийся узлом (это сделано чисто из соображений эффективности, для понимания не обязательно). o --> o --> данные. Ссылок в начинке может быть несколько, от 1 до 3, смотря сколько нужно и сколько влезет. Основной момент, который ты должен уяснить, это то что несколько слотов могут ссылаться на одни и те же данные. слот --> данные <-- слот.

> А эта область памяти тоже как слот организована?

Зависит от типа данных. Иногда это один слот, иногда буфер из слотов (о буферах напишу чуть позже), а иногда буфер из байт.

> Можно примеры прямых типов данных?

Введи immediate! в консоль.

> Если в прямой тип данных что-то не влезает он автоматом в косвенный преобразуется?

Пока что нет, потому что прямые и косвенные данные ведут себя очень по разному и требуют разные подходы к их управлению и оптимизации. Если целое число очень большое, то оно скастуется во float!.

>> 2 ** 30
== 1073741824
>> 2 ** 31
== 2147483648.0

11:38Хотя, это зависит от операции над числами. В любом случае преобразований из прямых типов данных в косвенные нету, исходя из практических соображений. Из косвенных в прямые -- кое где есть, но это особенность системы типов и конкретных типов данных. К примеру, binary! это косвенный тип, а integer! прямой:
>> to integer! #{7FFFFFFF}
== 2147483647


Но это частный случай. Нельзя впихнуть невпихуемое.

>> complement 1 << 31
== 2147483647
>> 1 + complement 1 << 31
*** Math Error: math or number overflow
*** Where: +
*** Stack:
12:22C immediate! я слишком широко взял, all-word! включены в них, но таки содержат внутри себя ссылки. Смотри [здесь](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds) для лучшего понимания -- все структуры с полями типа node! (тот самый узел упомянутый ранее) я обозначил как косвенные.

bubnenkoff
06:42А что посоветуете почитать для начинающих про подобные парадигмы? Как понимаю тут все радикально от Си-подобных языков отличается
9214
09:57Тут упражняться надо, а не читать.
bubnenkoff
10:38А какие упражнения лучше поделать? И как вообще посмотреть как в памяти все располагается? ок я могу дампить слова, но вот как заглянуть поглубже и понять структуры данных и как они устроены?
9214
11:43Читай исходники и ковыряйся с рантаймом, я правда не совсем понимаю зачем тебе эти низкоуровневые детали нужны. Из упражнений поищи что-нибудь на RosettaCode, например, или реши какую-то насущную задачу.
11:59[Обновил](https://gist.github.com/9214/7d17d484d71980239d679787eea226aa) свою писанину.
bubnenkoff
12:41Да просто чтобы понимать как оно работает. Я пока изучаю parse и есть один архитектурный вопрос по нему.

У меня программа разбита на несколько функций. В итоге они мне разбирают документ как надо, но по итогу parse возвращает false т.к. где-то видимо какая-то конструкция ему не нравится. Но документ то сам корректный на выходе.

Но проблема вот в чем. Документов у меня много и у них структура немного может отличаться. Я правильно понимаю, что по логике parse должен возвращать true для всех документов которые он смог разобрать и false для которых не смог.

12:44Тогда вопрос как лучше писать функции. Как только функция заработает нужно добиваться, чтобы она не просто данные собирала но и true возвращала?
9214
15:03Не обязательно. Ты можешь к концу приписать to end если очень хочется true увидеть, логика от этого не поменяется.

bubnenkoff
06:36Так давайте я скажу как понял про то как copy работает, а вы меня поправите если я не прав.

1. Есть два типа: ссылочный и знаковый. Ссылочный хранит себе ссылку, знаковый значение в самой ячейке.

2. Блок [] относится к ссылочному типу. Поэтому когда мы пишем: d: [] мы значение d храним в блоке который где-то в другом месте располагается.

3. Если d: [] находится внутри функции, то при повторном вызове он не пересоздается, а используется уже имещаяся ссылка.

4. Чтобы предотвратить использование имеющейся ссылки мы копируем пустой блок т.е. пишем d: copy []

Верно?
9214
09:341. Да, условно все типы можно на два этих класса разделить.
1. И d: и [] сами по себе являются значениями хранящимеся в блоке (тело функции). При вызове функции [] "положится" в слот на который d "указывает". Получится что d "указывает" (взято в кавчыки потому что это не совсем так) на слот который _сам по себе_ так же указывает на какой-то буфер. Так что когда ты к d аппендишь — ты аппендишь в этот самый буфер.
1. [] точно так же "ложится" в слот на который d "указывает", но поскольку [] по прежнему содержит ссылку на тот же самый буфер, то от этого ничегошеньки не меняется.
1. Всё так, copy [] идет по ссылке в слоте, копирует буфер в новое место, создает новый слот такого же типа что и [] (т.е. блок) и засовывает в этот слот ссылку на свеже-скопированный буфер. Дальше логика такая же что и в 2 c 3.
09:40Более простой пример — открытки и адреса. Допустим у тебя есть открытка с адресом ул. Строителей д. 5 к. 12. Теперь ты этот адрес переписываешь на новую открытку. После этого у тебя есть две разные открытки с одним и тем же адресом.

А теперь замени "открытка" на "слот" и "адрес" на "ссылку".
bubnenkoff
12:11Так, я видимо не понимаю как работает any и any [thru ].
Пример:
parse "aabbccdd" [any thru "bb"]


Я правильно понимаю что parse работает посимвольно? И он будет проверять aa потом ab потом bb? Судя по тому что пишут в англоязычном чате я не прав
9214
12:521. any — сопоставь следом идущее правило как можно больше раз, 0 раз достаточно.
2. thru — сопоставь всё включительно до следующего правила.

В итоге "продолжай сопоставлять включительно до "bb" столько сколько можешь", но в данном случае "столько сколько можешь = 1", соответсвенно any thru "bb" = thru "bb". Позиция встанет на "bbcd", а сам parse вернет false потому что ты достиг конца правила, но не конца строки.
13:14any thru "bb" полезно если у тебя строка с кучей "bb" и тебе надо пропустить все включительно до последнего "bb".
bubnenkoff
13:48
parse "aabbccdd" [s: any "cc" | skip  ]

А вот ту почему s не ставится в другую позицию? Вроде бы мы должны двигатсья до того как cc не встретим
9214
14:03Эм, в данном случае правило не применяется рекурсивно, т.е. s: ставится только один раз в самом начале строки, после чего ты пытаешься сопоставить с any "cc", которое ничего не сопоставляет потому что там "aa", но any пофигу потому что 0 раз достаточно, после чего ты ударяешься о границу правила |, на этом всё. Конец правила достигнут, а конец строки — нет, поэтому false.
14:05Т.е. any "cc" повторяет сопоставление только "cc" впереди себя, игнорируя s:; это два независимых правила.

bubnenkoff
13:30А не могли бы посмотреть англоязычный чат. Я упорно не могу понять, почему мне там говорят, что у меня все из-за thru тормозит
14:12Я не могу понять, откуда там взялось "almost 2450000000000 instead of 700000"
9214
14:44@bubnenkoff на что конкретно посмотреть? Комнат много, а я один.
bubnenkoff
15:13https://gitter.im/red/parse
15:13Я не могу понять почему thru и skip нельзя одновременно и почему оно зависает -- типа куча лишних итераций получается. Я уже на это потратил два дня -- тщетно. Картинка в голове не проясняется
15:14Там мы очень долго обсуждали с моими примерами. Началось все с того что на реальном файле зависло (я его там выкладывал)
15:15Я видимо что-то не понимаю. Поэтому если есть возможность разжуйте как дураку т.к. сам я уже отчаялся это понять
15:15thru идет до нужного символа. skip пропускает
15:16Но почему вместе они приводят к лишним итерациям и как следствие к зависанию понять я не в силах
9214
15:21> thru идет до нужного символа. skip пропускает

Верно, только "символ" а "правило", и не "до" а "через".

> Но почему вместе они приводят к лишним итерациям и как следствие к зависанию понять я не в силах

thru прочёсывает **всю** серию, либо пока правило полностью не сопоставится, либо пока он не уткнется в конец. Если правило не совпало и thru достиг конца, то это считается за несовпадение, и Parse пойдет искать альтернативное правило следующее за |. Как я понял, в твоем случае альтернативное правило это skip. Т.е. условно говоря получается что после первого удачного thru ... ты сначала ищешь до конца файла, а потом пропускаешь один символ, и так продолжается пока улиточными пропусками одного символа ты не доползешь до конца.

bubnenkoff
07:16А можно это как-то на очень простом примере проверить? Чтобы было наглядно. Просто у меня не получилось это визуализировать
07:43Я правильно понимаю что оно как-то так работает? У меня в голове визуальная картинка не возникает. Я себе работу представляю вот так:
parse "aabbaaddaabb" [thru "aa" | skip]

"aa bbaaddaabb" ; thru "aa" (2 steps because two symbols)
 --↑
 
"aab baaddaabb" ; skip
  --↑
"aabb aaddaabb" ; skip
   --↑
   
"aabbaa ddaabb" ; thru "aa" ; thru "aa" (2 steps because two symbols)
     --↑   
   
"aabbaad daabb" ; skip
      --↑  
    
"aabbaadd aabb" ; skip
       --↑    
     
"aabbaaddaa bb" ; thru "aa" (2 steps because two symbols)
         --↑

"aabbaaddaab b" ; skip
          --↑        
      
"aabbaaddaabb " ; skip
           --↑
9214
09:43@bubnenkoff откуда у тебя всё после первого thru "aa" взялось?
bubnenkoff
10:08@9214 ну я в начале думал, что оно так работает. Теперь как понимаю сработает:
"aab baaddaabb" ; skip
  --↑

И потом снова будет выполнен thru
9214
10:09Вот тебе интерактивный симулятор:

callback: func [
	event  [word!]
	match? [logic!]
	rule   [block!]
	input  [series!]
	stack  [block!]
][
	if match? [
		print [
			"event:"  tab event newline
			"rule:"   tab mold rule newline
			"input:"  tab head input newline
			"^-^-"    pad/left/with "↑" index? input space
		]
		
		escape <> first ask ""
	]
]


Запихивай в parse/trace, открываю документацию и играйся. ESC для выхода, всё остальное для продолжения. Для начала сравни разницу между

parse/trace "aabbaaddaabb" [thru "aa" | skip] :callback


и

parse/trace "aabbaaddaabb" [any [thru "aa" | skip]] :callback
bubnenkoff
10:10Вау! Круто! Крктой симулятор! Спасибо!
9214
10:11> Теперь как понимаю сработает

Ничего не сработает. Первый thru "aa" сопоставил, после него никакого другого правила нету, т.е. ты уткнулся в конец правила, обозначенный |. На этом всё — конец правила достигнут, а конец ввода нет, поэтому ты получаешь false.
bubnenkoff
10:13Так а skip же должен будет сработать если thru "aa" false выдал
9214
10:19Брр, давай по шагам:
1. Я Parse и я всегда начинаю с блока который мне дали, в данном случае [thru "aa" | skip].
1. Я беру этот блок и ищу в нем первое попавшееся правило, ищу и нахожу thru "aa".
1. Я беру и пытаюсь сопоставить это правило, начинаю матчить всё пока не пройду сквозь "aa".
1. Мне это удается, я ставлю индекс на "bbaaddaabb". Так как thru "aa" сопоставилось, я ищу правило идущее за ним.
1. Но за ним только |, что говорит мне о том что я достиг конца правила.
1. Я могу вернуть true только если добежал до конца правила и до конца ввода. Но ввод у меня по прежнему на "bbaaddaabb", а правил больше нету.
10:20За "барьер" | Parse может перепрыгнуть только если у тебя сопоставления не было, т.е. если thru "aa" не прошел через "aa".
bubnenkoff
10:21А any как раз пзволяет выполнить вторую проверку если предыдущая провалилась
9214
10:22any будет повторять данный тобой блок до тех пор пока он сопоставляется. А сопоставление будет всегда, потому что у тебя либо thru "aa" находит "aa", либо не находит и перепрыгивает через | к skip, который безоговорочно пропускает 1 элемент, и так до самого конца.

bubnenkoff
10:32@9214 подскажи пожалуйста. Почему следующее правило у меня возвращает fail.

file: {<root>
<id>19160099</id>
<purchaseNumber>0373200101018000262</purchaseNumber>
<lot>
<maxPrice>8186313.66</maxPrice>
<purchaseObjects>
    <purchaseObject>
        <OKPD2>
            <code>11.131.11</code>
            <name>Foo111</name>
        </OKPD2>
        <currency>
        <code>666</code>
        </currency>
        <price>111</price>
    </purchaseObject>
    <purchaseObject>
        <OKPD2>
            <code>22.12.55</code>
            <name>Bar222</name>
        </OKPD2>
        <price>222</price>
    </purchaseObject>
    <purchaseObject>
        <OKPD2>
            <code>33.322.41</code>
            <name>Baz333</name>
        </OKPD2>
        <price>333</price>
    </purchaseObject>        
</purchaseObjects>
</lot>
</root>}


parse-lot: [
    (purchaseObjects: copy [])
   some [
       thru "<purchaseObjects>"  to  "</purchaseObjects>" "</purchaseObjects>" to end pos:
      ]    
]

parse file [
    (lots: copy [])

    some 
    [
      thru "<lot>" parse-lot "</lot>" to end
    ]
    
]


вроде бы все правильно делаю. И есть какие-то фундаментальные проблемы в нем. К примеру не будет ли той самой проблемы с лишними итерациями о которой мы выше говорили
10:38Мне тут подсказывают, что скорее всего "" to end прыгает к концу файла, но как быть если мне нужно только к концу секции котрая парсится прыгнуть
9214
14:14Правильно подсказывают. Твой "конец секции" как я понимаю это , а не end. Если у тебя файлы не коцаные (т.е. везде одинаковый формат и все теги закрыты) и если тебе нужно данные между тегами вытянуть, то твой подход слишком сложный.
DVL333
14:56@bubnenkoff Весь вопрос в том, что вы именно хотите сделать. Насколько я понял, вы хотите сохранять позиции перед тегом "</lot>", которых может быть несколько. Ну тогда так и напишите:
parse file [
    some 
    [
        to "</lot>" pos: "</lot>"
    ]
    to end
]

А вообще говоря, вы читали документацию по parse?

bubnenkoff
07:11А вот куда тут s1 будет указывать?
parse-lot: [
    (purchaseObjects: copy [])
   some [
       thru "<purchaseObjects>"  to  "</purchaseObjects>" 
      ] s: to end s1:
      
  
]

parse file [
    (lots: copy [])

    some 
    [
      thru "<lot>" parse-lot "</lot>" 
    ] to end
    
]

Вот выдача:
>> index? s1
== 749
>> 
>> s1/748
== none

DVL333
08:14@bubnenkoff Вам уже исчерпывающе ответили, куда указывает end. Зачем спрашивать повторно? Вы думаете, что ответ за выходные изменился?
9214
10:40@bubnenkoff

>> series: [very very very long series]
== [very very very long series]
>> parse series [some [thru 'very] start: to end end:]
== true

>> end
== []
>> tail? end
== true
>> head end
== [very very very long series]

>> start
== [long series]
>> tail start
== []
>> head start
== [very very very long series]
>> equal? tail start end
== true
10:43@bubnenkoff индексация всегда относительна текущего индекса, а не абсолютна. Т.е. s1/748 тебе даст 748-ой элемент справа от s1, которого в твоем случае не существует, т.к. ты выскочил за границу буфера.
10:44Возвращаясь к примеру выше, ты можешь индексировать и налево
>> start
== [long series]
>> head start
== [very very very long series]

>> start/1
== long
>> start/2
== series

>> start/-1
== very
>> start/-2
== very
>> start/-3
== very

bubnenkoff
14:21А чем связывание : принципиально отличается от присваивания?
Тем что память выделяется где-то в другом месте и если надо мы можем всегда повесить на слово новое значение?
9214
14:37: это не оператор связывания или присваивания, а лексическая часть значения (word: или :word). Связывание это bind.
bubnenkoff
14:46А как тогда прочитать на русском следующий синтаксис a: "abc" ?
9214
14:51"слову a в том контексте к которому оно привязано ставится/задается значение "abc"".
bubnenkoff
14:56А что такое контекст? Как я понимаю это тоже фундаментальное понятие
9214
14:59@bubnenkoff [на этот вопрос тебе уже отвечали](https://gitter.im/red/Russian?at=5e2718876ced65043b59bfe8).
15:01![](https://files.gitter.im/red/help/19V0/unnamed0.png)
15:09
text
>> cutlery: [spoon spoon spoon spoon]
== [spoon spoon spoon spoon]
>> phrase: split "there is no spoon" space
== ["there" "is" "no" "spoon"]

>> forall cutlery [bind cutlery context [spoon: take phrase]]
== [spoon]

>> cutlery
== [spoon spoon spoon spoon]
>> print cutlery
there is no spoon

>> value? 'spoon
== false
>> unset? :spoon
== true

>> forall cutlery [probe context? cutlery/1]
make object! [
    spoon: "there"
]
make object! [
    spoon: "is"
]
make object! [
    spoon: "no"
]
make object! [
    spoon: "spoon"
]
== make object! [
    spoon: "spoon"
]

bubnenkoff
10:28> : это не оператор связывания или присваивания, а лексическая часть значения (word: или :word). Связывание это bind.

Я не совсем понял. Просто выше ты писал:
>Ссылка на контекст называется связкой.

Так все же слово связывается путем установки двоеточия? И тогда чем bind отличается?
9214
11:23@bubnenkoff на пальцах:

1. Слово содержит в себе символ и ссылку на "таблицу" с одной или несколькими строками и двумя столбцами — "символ" и "значение".
1. bind меняет ссылку (связку) на таблицу.
1. set берет из слова символ, берет ссылку, идет по ссылке, ищет строку по символу и засовывает в "значение" то что ты ему передал.
1. word: идентичен set 'word .
bubnenkoff
13:13Спасибо, а как отрицание записть? Я пробую как:
d: [not any ["<a>" | "<b>"]]

но
parse "<f>" [d]


Возвращает false
9214
13:20Документацию читай :wink:
bubnenkoff
13:20да читал, вроде бы все правильно делаю
9214
13:20Если читал, то "вроде бы" быть не должно.
bubnenkoff
13:21ну хоть намекни что не так. not же инвертиует правило
9214
13:22Инвертирует и остается на месте.
13:23
text
>> parse <a> [not "b" not "c" not "even d" not "or e or g or whatnot" "a"]
== true
13:24Можешь после not ... воткнуть mark: (probe mark) и посмотреть меняется ли позиция, если совсем непонятно.
bubnenkoff
14:51Но по идее же:
>> parse "a" [any [not "b"]]
== false

any проверет следующее правило которое было инвертировано not. Почему тогда результат false?
15:04Я реально не пойму как тогда его использовать
9214
15:39Потому что ты конца серии не достиг.

bubnenkoff
07:44Я правильно понимаю, что корректное правило выполняет продвижение по строке?
>> parse "a" ["a"]
== true


А отрицание просто инвертирует правило, но по строке не двигается?
9214
09:07@bubnenkoff [1](https://doc.red-lang.org/en/parse.html#_core_principles), [2](https://doc.red-lang.org/en/parse.html#__code_not_code).
10:12> Я реально не пойму как тогда его использовать

Его используют чтобы исключить конкретные случаи из общего правила. К примеру, ты хочешь матчить все слова какие вообще могут быть __кроме__ каких-то двух (предположим this и that):
[not ['this | 'that] word!]

bubnenkoff
10:02Спасибо! Понял!
11:56А в каких случаях используется context? Из значения слова объект сделать?
9214
11:57
text
>> :context
== func ["Makes a new object from an evaluated spec" 
    spec [block!]
][
    make object! spec
]
bubnenkoff
14:53А в каких случаях это полезно? Просто я пока не вижу кейсов
9214
14:58[Тут](https://github.com/red/red/wiki/%5BDOC%5D-Comparison-of-aggregate-values-(block!-vector!-object!-hash!-map!%29#object) в общих чертах расписано.

bubnenkoff
08:27А можно ли говорить о контексте как о смысле слова?
08:28Если да, то что является смыслом? данные или функция назначены на слово?
10:19Как face лучше перевести?
Пример фразы: "Creating a new face is achieved by cloning the "
9214
11:34@bubnenkoff если смыслом слова является его значение, то контекст это некое "семантическое поле" которое этот смысл содержит. К примеру "крутой" это слово с одним написанием, но разными значениями — "крутой поворот" в контексте дорожной езды, "крутое яйцо" в контексте кулинарии, "крутой чувак" в социальном контексте. В Red логика примерно такая же — контексты содержат разные значения и придают одному и тому же по написанию слову разные смыслы.

Face — фасад или лицевая сторона, facet — фацет или грань. face! представляет собой графический объект с определенной геометрией ("многогранник"), поэтому такой перевод имеет смысл.
11:51Или может "торец" и "ребро", если думать о создании интерфейсов как о мощении кладкой из разных кирпичей / деревянных брусков.
bubnenkoff
12:43А можно пример того, как одно и тоже в Red в разных контекстах по разному интерпритируется?
Контекст же задает диалект? do\parse\... ?
9214
13:22@bubnenkoff [вот же](https://gitter.im/red/Russian?at=5e42c39ed4daaa26c1983f52). do и parse "задают контекст" в том смысле что они имеют разную семантику и интерпретируют данные по разному.

bubnenkoff
09:37Я не совсем понял, внутренний цикл создается блоком []? Или оператором thru? https://github.com/red/red/wiki/%5BDOC%5D-Parse
Вот в этом коде:
parse "aabbccdd" [ thru [p: (probe p) "cc" ]]
9214
10:31thru и to так работают.
10:35
text
>> parse x: [a b c d e f][remove to 'd] x
== [d e f]
bubnenkoff
11:18Я просто не совсем понимаю как меняет ход выполнения замена some thru "bb" на some [thru "bb"]
9214
11:21Никак не меняет, за исключением того что Parse не всегда запись в первой форме адекватно воспринимает и может багануть.
bubnenkoff
11:21в начале будет выполнено thru "bb"?
11:23Я и изучаю генерацию правил. Не пойму почему мне советуют правило не как правило, а как код генерировать https://gitter.im/red/parse?at=5e4fcd1fdafa3029f64490ca там несколькими сообщениями ниже
9214
11:29По-моему всё что я тебе объяснял о принципах работы языка ты мимо ушей пропустил. "Правила" которые Parse использует это всегда блок данных (который тебе и советуют генерировать), ты же используешь строки (которые тебе потом всё равно надо будет загрузить в блок).
bubnenkoff
11:51О все, теперь понял, спасибо

bubnenkoff
14:24Вопрос, а вот как следующий код работает?
view/flags [b: button "Ok" [b/text: "cancel"]] [resize]


по идее же слеш указывает на путь до элемента с именем flags но как при этом первый блок выполняется? Или какая тут логика применяется?
9214
14:25Логика функций (view) и их "уточнений" (/flags, refinement).
bubnenkoff
14:35а эти уточнения работают как пути? т.е. где-то под капотом и первый блок обрабатывается (тело) и уточнения срабатывают?
9214
14:37Это опции (иногда с параметрами, как в твоем случае) которые ты можешь указывать, при чем тут пути?
bubnenkoff
14:42Ну просто / же означает путь к блоку
14:47И еще вопрос. Почему в Red логика такая, что большинство переменных которые создаются в том же red parse глобальные? В других языках же наоборот стараются по максимум все локальным сделать. А тут если внутри блока что-то объявили, то оно тоже глобальным становится
9214
15:10Переменные, объявление... как об стенку горох.
bubnenkoff
18:29Ну я слова переменными по инерции назвал. Сложно переключиться так сразу
9214
19:15Любое слово должно содержать ссылку на уже существующий контекст (привязку). Единственный контекст который 100% существует при выполнении скрипта это как раз таки глобальный контекст, который определяет среду выполнения языка (т.е. содержит в себе весь доступный функционал). Соответственно, все загружаемые слова по-умолчанию привязываются к нему.

Если в глобальном контексте слова нету, то он расширяется (опять же, это едитсвенный контекст которые может это делать, все остальные имеют фиксированный размер) и слову в нем ставится значение unset, которое условно обозначает "это слово не имеет смысла".

Если же слово уже было в глобальном контексте, то оно получает заранее определенный ему смысл: 1 + 1 (а точнее do load "1 + 1") равняется 2 потому что + привязано к операции сложения.

Другие языки (за исключением пары-тройки Лиспов) подобного функционала не имеют и используют области видимости и переменные.

bubnenkoff
09:52А вообще как понять какой правильный порядок слов должен быть? Какой тут подод используется? Просто я могу писать:
view [panel red [size 300x200] panel on-down [print "hi"] blue [size 200x150] ]

А могу:
view [panel red [size 300x200] panel blue [size 200x150] on-down [print "hi"]  ]

И оно будет одинаково работать. Слова вообще как компануются? Смотрится значение слова и потом то что справа от него в зависимости от значения может стать аргументом?
9214
10:16> Какой тут подод используется?

Подход чтения [документации](https://doc.red-lang.org/en/vid.html#_faces_definition).

> All options can be specified in **arbitrary order**, following the face or style name. A new face name or a layout keyword marks the end of the options list for a given face.

bubnenkoff
11:35> ![](https://files.gitter.im/red/help/19V0/unnamed0.png)

Да я картинку эту видел. Я не понимаю сути. Это подход отличается от мира Си? Типа более высокоуровневый и позволяет имя переменной не затирать? Делая ее словом
9214
11:44Нарисуй мне, по шагам, что происходит с x = 123 в C.
bubnenkoff
11:50Проверяется тип объявленной переменной. Если это int, то для int происходит выделение блока памяти (для хранения 32 битного значения). Затем по этому участку записывается значение 123. В итоге мы имеем адрес в памяти где записано это значение
11:50Но в динамически типизируемых языках типа JS по идее мы можем и имя переменной хранить и переназначать его
9214
12:00Окей, теперь смотри что происходит с x: 123:

* x: 123 загружается из введенной тобой строки как пассивный кусок данных, не имеющий сам по себе абсолютно никакого "внутреннего", заранее определенного смысла.
>> load "x: 123"
== [x: 123]

* этот кусок данных скармливается стандартному интерпретатору do.
>> do [x: 123]
== 123

* do берет этот кусок данных и идет по нему, видит значение типа set-word!; это значение вгутри себя содержит привязку (смотри картинку выше, вникай в суть!), ниточку за которую интерпретатор дёргает чтобы поднянуть то к чему эта нитка на другом конце привязана;
* do подтягивает нитку и хватает контекст к которому слово было привязано; контекст, повторяю в сотый раз, это тупо пространство имен, таблица.
* помимо привязки, x: так же содержит символ, "произношение", в данном случае это x; do берет этот символ и начинает искать его в контексте, ведя пальцем по левой колонке.
* do находит нужную строку в таблице; теперь он сдивгает палец вправо, во вторую колонку, и запихивает туда значение 123, ставя x значение 123 в том контексте к которому x было привязано (в данном случае глобальном).
* 123 возвращается как результать выполнения выражения. Отныне x в глобальном контексте значит 123.
bubnenkoff
12:02Спасибо большое за развернутое объяснение. Не мог бы это добавить в ту статью которую ты писал? Просто я думаю не толькоу меня вопрос возникнет этот
9214
12:03Я работаю над этим. Но толку от моих развернутых объяснений если ты фишку не просекаешь? Играйся в консоли и рисуй коробки со стрелочками, перестань бояться bind и context.
bubnenkoff
12:06Ну я пока доки перечитываю еще раз. Просто очень сложно мыслить начать по другому. Просто как оказывается аналогии из других языков не првильно тут работают. И да буду признателен если порекомендуешь что-то почитать что правильное понимание темы бы сформировало? Просто я совершенно не знаком с Lisp и Forth. Как понимаю много тут из них взято
9214
13:28> Просто очень сложно мыслить начать по другому

"По другому" ты мыслишь с тех пор как выучил русский язык. Слова и контексты в Red по своей логике идентичны словам и контекстам в натуральном языке. Когда я говорю "машина" в контексте дорожной езды, я имею ввиду "автомобиль", когда я говорю "машина" в контексте компьютерных наух, я имею ввиду "компьютер". Lisp и Forth тут не причем, не усложняй себе жизнь.
bubnenkoff
14:22Пеечитываю твою статью. Не понятент помент:
>> load "123"               ; загрузка из строки
== 123                      ; вывод на экран
>> type? load "123"         ; тип данных загруженного слота:
== integer!                 ; целое число


Почему на последнем шаге целое число, а не строка? Или это особенность работы load, что он содержимое строки интерпритирует?
14:25В статье есть уточнение. "Обратите особое, пристальное внимание: при загрузке, тип данных определяется исходя из лексической формы токена, а это значит" мне не совсем понятно что понимать под лексической формой? Когда строка это строка?
9214
14:26Не интерпретирует, загружает. Ты ему даешь строку из символов, он тебе выплевывает блок из значений (или просто одно значение) или выдает ошибку если в строке мусор.
14:27> что понимать под лексической формой? Когда строка это строка?

Сам как думаешь? Что-то является строкой когда оно загружается как значение с типом "строка".
>> type? probe load {"abc"}
"abc"
== string!
>> type? probe load {{def}}
"def"
== string!

14:28То же самое можно сказать и о любом другом значении.
14:30123 которое ты видишь на экране это набор символов (синтаксис). load берет этот набор символов и создает число 123 которое ты можешь умножить на что-то или прибавить к чему-то, т.д. (семантика).
14:31"Париж" это не город, это слово из 5-ти букв. *Париж* — это город.
bubnenkoff
14:50{}- показывает что загружаемые данные имеют строковый тип, верно?
А если сделать load значение-в-кавычках то каким образом тип будет определен?
9214
14:54Он будет определен исходя из лексической формы...
>> type? probe load "{123}"
"123"
== string!

Если это выглядит как строка, то это строка, если это выглядит как целочисленное число, то это целочисленное число, т.д.
14:55{...} это один из форматов строки, я его использовал чтобы кавычки внутри не экранировать.

bubnenkoff
09:44Так, я в очередной раз перечитал всю переписку. Хочу еще раз уточнить.
1. значение слова - это просто данные. Семантика данных определяет их контекст т.е. что посредством них пытаются сделать.
2. do, parse, vid - задают контекст т.е. занимаются интерпритацией данных

Верно теперь все понимаю?
9214
11:44(1) каждый тип данных предоставляет определенный набор действий которые ты над ним можешь выполнять (сложение, сортировка, конвертация, т.д.); какие из них тебе нужны и как с ними обращаться -- это уже твое дело (2) это интерпретаторы, да.
bubnenkoff
11:50А по первому пункту если выражаться умными словами то лексика определяет семантическое значение, так?
11:57Интерпритатор определяет контекст -- как именно интерпритировать те или иные данные. Данные должны быть синтаксически и лексически корректны и иметь определенную семантику в рамках диалекта т.е. интерпритатор должен проверить их корректность написания и уже в рамках их семантики понять как их обработать.

Сам по себе контекст без интерпритации лишен смысла т.е.
x: "1 + 1"
ничего не значит, пока это не будет проинтерпритировано.

Теперь верно мыслю? Или есть какие-то ошибки?
9214
12:09Мыслишь верно, только интерпретатор "корректность написания" не проверяет, это забота загрузчика. Если под "написанием" ты имеешь ввиду расположение уже загруженных значений относительно друг друга то да, это играет роль, но только при интерпретации.
bubnenkoff
12:10О ну все спасибо большое! Наконец то хотя бы грубых ошибок не делаю
12:11я еще не совсем уловил про : и bind. Ты выше писал, что : это лексическая часть слова (кажется так). Но в чем у них разница. Вроде бы эта лексическая часть как раз за связывание так же как bind и отвечает
9214
12:55"Устанавливать значение" и "привязывать к контексту" это две разные операции.
bubnenkoff
13:28блин поясни, я не понимаю разницу
9214
13:30Я кучу раз уже это объяснял, даже с картинками.
13:36Представь что у тебя в руках полая трубка. На твоем конце ты можешь туда засовывать шары, на другом конце они будут выкатываться и падать в коробку.

"Устанавливать значение" — брать трубку и засовывать в нее шары чтобы они выкатились в коробку на другом конце. "Привязывать к контексту" — брать дальний конец трубки и запихивать его в другую коробку.
bubnenkoff
15:45А в случае с кодом я не совсем понимаю в каких случаях нужна привязка контекста. Можно какой-то очень простой пример?
9214
18:20Посмотри как collect устроен, например.

bubnenkoff
10:32> помимо привязки, x: так же содержит символ, "произношение", в данном случае это x; do берет этот символ и начинает искать его в контексте, ведя пальцем по левой колонке

Продолжаю все перечитывать. В данном случае привязка совпадает с произношением символа? А может быть так, что они отличаются?
Двоеточие после слова это лексическое обозначение привязки. Верно же?
11:07> Слово содержит в себе символ и ссылку на "таблицу" с одной или несколькими строками и двумя столбцами — "символ" и "значение".

Почему слово не может сразу казывать на значение?
9214
12:08> В данном случае привязка совпадает с произношением символа?

Привязка и произношение это две разных компоненты слова.

> Двоеточие после слова это лексическое обозначение привязки. Верно же?

Нет.

> Почему слово не может сразу казывать на значение?

Это значение в любом случае должно где-то храниться и как-то адресовываться. Контекст как раз это и делает.
bubnenkoff
12:35тоесть если я пишу: x: 123 то слово x кладется в контекст do который является контекстом по-умолчанию?
9214
12:39Условно говоря да.
bubnenkoff
12:41в каждом контексте есть свой набор слов ("слово":"контекст_слова")? Верно?
9214
12:50("слово":"значение").
bubnenkoff
12:53А и bind - изменение привязки поменяет просто контекст? Если так то общую суть наконец понял
9214
12:56Поменяет или не поменяет зависит от того куда ты слово привязываешь. Если это тот же самый контекст то ничего не поменяется, если в контексте этого слова нету то тоже ничего не изменится.
bubnenkoff
13:49А можно ли говорить о контексте как об объекте с определенными методами (которые и будут интерпритировать контекст)?
9214
13:59Эм, нет. По-моему ты в угадайку играешь.
bubnenkoff
14:00Просто вот тут они разве не про это пишут? https://stackoverflow.com/questions/41416193/what-is-the-difference-between-context-and-object
9214
14:45Это вопрос о разнице между функциями context и object, и разницы между ними нет абсолютно никакой.
>> :context =? :object
== true

bubnenkoff
16:32У меня вопрос. В документации сказано "a pointer to a context, an index in a symbol table which contains the symbol, **and an index in the context which facilitates retrieving the value the word refers to**"

Если контекст это словарь, то зачем выделенная часть? Или там все как-то более хитро устроено и это не словарь по своей структуре?
16:34Просто по логике чтобы найти значение контекста нужно слово найти в ключе словаря контекста. И значение ключа и будет контекстом т.е. никакие дополнительные индексы не нужны
9214
16:54Если у тебя есть индекс то поиск занимает O(1) вместо O(n).
bubnenkoff
17:00А когда я просто значение к консоли ввожу, оно куда-нибудь попадает?
9214
17:01Что ты понимаешь под "попадает"?
bubnenkoff
17:02Ну его интерпритатор контекста пытается сразу выполнить(оценить? или как правильно сказать)?
9214
17:05Пассивные типы данных (числа, блоки, строки, т.д.) падают на стек данных, активные (слова, пути, скобки, фунции) выполняют какое-нибудь действие.
bubnenkoff
17:05Просто я почитал как в Forth все происходит. Если введеное значение совпадает со словом которое есть в контексте то выполняется контекст. Если значение оказывается числом, то оно выводится.

Если его нет в контексте и не число, то ошибка
17:06А тут один стек? Или для данных свой, а для функций свой?
9214
17:07Ты путаешь "контекст" и "значение слова". Контекст это место где значение слова хранится, значение само по себе может быть чем угодно. Контекст в Red и словарь в Forth это разные вещи, то же самое со "словами" — в Форте это любая последовательность символов разделенная пробелами. Забудь о Форте вообще, у него модель интерпретатора/компилятора совсем другая.
17:08Стеков два, для аргументов и для стековых фреймов.
bubnenkoff
17:49Если мы пишем:
x: 1
то получается в контекст по-умолчанию напротив столбца x мы записываем единичку. Верно?
17:53Есть способ полностью вывести на экран контекст полностью без троеточий?
>> context? 'x
== make object! [
    datatype!: datatype!
    unset!: unset!
    none!: none!
    logic!: logic!
    block!: block!
    paren...
18:16>
text
> >> cutlery: [spoon spoon spoon spoon]
> == [spoon spoon spoon spoon]
> >> phrase: split "there is no spoon" space
> == ["there" "is" "no" "spoon"]
> 
> >> forall cutlery [bind cutlery context [spoon: take phrase]]
> == [spoon]
> 
> >> cutlery
> == [spoon spoon spoon spoon]
> >> print cutlery
> there is no spoon
> 
> >> value? 'spoon
> == false
> >> unset? :spoon
> == true
> 
> >> forall cutlery [probe context? cutlery/1]
> make object! [
>     spoon: "there"
> ]
> make object! [
>     spoon: "is"
> ]
> make object! [
>     spoon: "no"
> ]
> make object! [
>     spoon: "spoon"
> ]
> == make object! [
>     spoon: "spoon"
> ]
>


После наверно тридцатого прочтения до меня дошел смысл данного кода. Вопрос - а не приводит ли возможность одного и того же слова иметь разный контекс к путанице при написании программ?
9214
18:22probe context? 'x.
bubnenkoff
18:29ой... там что-то огромное напечаталось на экран. Это и есть весь контекст?
9214
18:40Это глобальный контекст, system/words.

bubnenkoff
13:39А не мог бы еще ответить про: "а не приводит ли возможность одного и того же слова иметь разный контекс к путанице при написании программ? "
9214
14:27Только если ты насильно обфусцируешь код.
bubnenkoff
14:30Я с твоего позволения в англоязычной группе спрошу. Просто интересно. Может есть какие-то применения. Просто это же одна из главных возможностей (или сайд-эффект?).
9214
14:34Применение чего, bind?
14:34Я тебе уже советовал посмотреть как collect устроен, наглядный и практичный пример.
bubnenkoff
14:36Я правильно понимаю, что под посмотреть ты имеешь виду сделать:
probe :collect
9214
14:37Да, или source collect.
bubnenkoff
14:37Я просто не всегда понимаю на что обращать внимание. Пример с ложками у меня укладывался в голове недели три. Сейчас смотрю и кажется что он предельно логичный. До этого было похоже на набор слов.
9214
14:42Обрати внимание на то как функции работают. Первый шаг это посмотреть вот на этот пример и понять почему reduce foo тебе выплюнет ошибку, и как сделать так чтобы reduce foo тебе вернул [1] или [2] не меняя x в глобальном контексте.
>> x: 1
== 1
>> foo: has [x][x: 2 [x]]
== func [/local x][x: 2 [x]]
>> foo
== [x]
>> reduce foo
*** Script Error: context for x is not available
*** Where: reduce
*** Stack:  

>> bar: does [x: 2 [x]]
== func [][x: 2 [x]]
>> bar
== [x]
>> reduce bar
== [2]
>> x
== 2
14:49Или представь что у тебя есть некая библиотека обернутая в объект. Вместо того чтобы писать library/foo library/bar ... ты можешь написать do bind [foo bar ...] library. Можно эту идею расширить и сделать некое подобие RPC — серваку прилетает блок данных, он его привязывает к своему локальному контексту (или даже к нескольким контекстами) и выполняет заданную функцию; Rebol/Services вроде бы так работали.
bubnenkoff
19:16Я вот еще не совсем понял как у нас на вот тут (пометил на следующей картинке) у pi значение стало 3.14 хотя выше мы pi присвоили "pie"
19:17[![изображение.png](https://files.gitter.im/red/Russian/qfLy/thumb/izobrazhenie.png)](https://files.gitter.im/red/Russian/qfLy/izobrazhenie.png)
9214
19:47Сниппеты из разных сессий.
bubnenkoff
19:49ай... а то я уже всю голову сломал))) все переделал 10 раз по шагам)))

bubnenkoff
12:03Я тут продолжаю примеры разбирать. Не могу понять почему тут bind идет со словом 'a

http://www.rebol.com/docs/words/wbind.html
12:08просто "bind will modify the block it is given" получается что связка слова a должна быть изменена
9214
12:24Это сокращение для bind ... context? 'a.

bubnenkoff
06:28Подскажи, а в чем я там туплю. "BIND will modify the block it is given"
words: [a b c]
    fun: func [a b c][print bind words 'a]
    fun 1 2 3
    fun "hi" "there" "fred"


Просто я реально ожидал, что words получит при первом вызове 1 2 3
9214
10:55Дак а в чем проблема то? Это и происходит.
10:57
text
>> words: [a b c]
== [a b c]
>> foo: func [a b c][print bind words 'a]
== func [a b c][print bind words 'a]

>> foo 1 2 3
1 2 3
>> foo "hi" "there" "fred"
hi there fred
10:58Или по другому:
>> bind words: [a b c] foo: func [a b c][print words]
== [a b c]

>> foo 1 2 3
1 2 3
>> foo "hi" "there" "fred"
hi there fred
11:01bind не "модифицирует" блок, он привязывает все слова найденные в данном тобою контексте к этому контексту, и эта привязка остается перманентной потому что слова из блока никуда не исчезают.
bubnenkoff
11:14От меня усользает смысл вот этой записи:
words: [a b c]
fun: func [a b c][print bind words 'a]

мы создали слово которое принимает три значения a b c.

теперь внутри контекста функции привязали к words первый переданный в функцию аргумент. А что с другими двумя?

При выходе из функции контекст words станет получается оригинальным
11:16> bind не "модифицирует" блок, он привязывает все слова найденные в данном тобою контексте к этому контексту, и эта привязка остается перманентной потому что слова из блока никуда не исчезают.

Тоесть мы создаем локальное слово которое совпадает по написанию со словом в другом контексте, но имеет другое значение. Верно?
11:22"bind привязывает все слова найденные в данном тобою контексте к этому контексту"
Просто тогда получается, что 'a это не первый аргумент, а все переданные в функцию слова
9214
11:23> мы создали слово которое принимает три значения a b c.

Мы создали _функцию_ с тремя аргументами.

> теперь внутри контекста функции привязали к words первый переданный в функцию аргумент. А что с другими двумя?

Ты слова внутри words привязываешь к контексту функции. Каждая строка в примере ниже по смыслу идентична с другими строками.
bind words 'a
bind words context? 'a
bind [a b c] context? 'a
bind [a b c] :fun
bind [a b c] func [a b c][print bind words 'a]


> При выходе из функции контекст words станет получается оригинальным

Нет, перечитай что я выше говорил. Привязка перманентная.

> Тоесть мы создаем локальное слово которое совпадает по написанию со словом в другом контексте, но имеет другое значение. Верно?

Ничего нигде не создается. bind проходит по блоку и для каждого значения any-word! спрашивает находится ли оно в данном контексте. Если да, то это слово привязывается к контексту, иначе пропускается.
11:24> Просто тогда получается, что 'a это не первый аргумент, а все переданные в функцию слова

Повторяю третий раз, bind ... 'a это сокращение от bind ... context? 'a.
bubnenkoff
12:00> Привязка перманентная.

Она перманентная только внутри функции же? Потому что у words есть свой глобальный контекст. Он то у нас не поменяется если сделать просто: fun: func[a b c] [print bind words 'a]

>bind [a b c] func [a b c][print bind words 'a]

Это правила вызова такие что мы указываем просто один из элементов блока, а привязывается всё? Мы же могли написать и bind words 'b и bind words 'c
9214
12:03Напиши print words и context? words/1 после всех своих манипуляций, тогда поймешь что значит "перманентная".
12:05> Это правила вызова такие что мы указываем просто один из элементов блока, а привязывается всё?

У тебя очередная путаница в голове. Содержимое блока тут никакой роли не играет, a внутри него и a внутри функции это два разных значения. И, повторяю уже четвертый раз, bind words 'a это bind words context? 'a. Если ты и этого не понимаешь, то сделай probe context? 'a и probe context? 'b, затем сравни разницу.
bubnenkoff
13:33context? words/1 этот кусок очень помог. Как только я увидел его результат до меня дошло что происходит.

> bind words 'a это bind words context? 'a

Вот честно для меня не проще понять.

> bind [a b c] func [a b c][print bind words 'a]

Слово 'a в данном случае является локальным и указывает на тело функции и bind для всех слов в words задает локальный контекст? Получается в данном случае 'a это аналог this\self? Или почему именно 'a а не любое другое слово
9214
13:37Я устал одно и то же повторять.
>> foo: func [a b c][print bind words probe context? probe random/only [a b c]]
== func [a b c][print bind words probe context? probe random/only [a b c]]

>> foo 1 2 3
b
func [a b c][print bind words probe context? probe random/only [a b c]]
1 2 3

>> foo 1 2 3
a
func [a b c][print bind words probe context? probe random/only [a b c]]
1 2 3
bubnenkoff
15:42Так. Кажется начало в голове укладываться. А если мы пишем подобным образом:
bind [a b c] :fun т.е. не создавая слово (word:[a b c]), а передавая блок со словами, то как нам потом до этих слов дотянуться? Ведь как понимаю они просто в стеке разместятся?
9214
15:51Если ты этот блок нигде не сохранил, то никак. Он прилетает на стек и улетает со стека.
bubnenkoff
16:40
bind words 'a
bind words context? 'a
bind [a b c] context? 'a
bind [a b c] :fun
bind [a b c] func [a b c][print bind words 'a]


А можно ли писать вот так:
bind words :fun

?

9214
16:42Попробуй и узнаешь.
bubnenkoff
16:44Я попробовал, оказалось что нет, и не совсем понятно почему...
9214
17:27Без понятия как ты так пробовал.
>> words: [a b c]
== [a b c]
>> foo: func [a b c][print words]
== func [a b c][print words]
>> bind words :foo
== [a b c]

>> foo 1 2 3
1 2 3
>> foo 'a 'b 'c
a b c
bubnenkoff
18:25Я делал так:
>> f: func [][print "Hello"]
== func [][print "Hello"]
>> 
>> words: [a b c]
== [a b c]
>> 
>> bind words :f
== [a b c]
>>  context? w/1
== make object! [
    datatype!: datatype!
    unset!: unset!
    none!: none!
    logic!: logic!
    block!: blo...
>>

Очевидно дело в том, что в моем случае я аргументы в функцию не передаю. Получается переданный аргумент и создает контекст?
18:36Получается у функции без аргументов контекст пустой блок?
18:38
>> f: func[a] []
== func [a][]
>> 
>> w: [a b c]
== [a b c]
>> 
>> bind w :f
== [a b c]
>> context? w/1
== func [a][]

Этот код догадку подтверждает
9214
19:45Контекст это _вообще_ не блок.

bubnenkoff
08:40Продолжаю перечитывать все что ты написал. Ты в англоязычной группе сделал уточнение. Что функция\объект создает контекст, но не является контекстом. Я правильно же написанное понял?
08:44> provides a context to bind to, but is not a context itself.

т.е. когда мы создаем функцию или объект, то их содержимое является контекстом к которому можно привязку сделать. Но сами по себе тело их не контекст. Верно?
9214
10:43Непонятно что ты понимаешь под "содержимым".
bubnenkoff
10:50То что внутри функции или объекта
9214
10:56Это составные типы данных, "внутри" мне ни о чем не говорит. [Функции](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds#L244) и [объекты](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds#L181) хранят ссылку на [контекст](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds#L172) внутри себя.
10:57Ты можешь по спецификации функции определить какие слова будут находиться в её контексте, то же самое с телом объекта.
11:01Если
foo: func [a /b c][if b [a + c]]


Тогда
foo/b 1 2


Это то же самое что
do bind [if b [a + c]] context [a: 1 b: true c: 2]


А
foo 3

Это
do bind [if b [a + c]] context [a: 3 b: false c: none]


С тремя оговорками:
* Время жизни контекста (у объектов они живут на куче до тех пор пока сборщик мусора до них не доберется, у функций они приходят и уходят со стека);
* Типизация (аргументы функции могут быть типизированы, значения внутри объекта — нет);
* Метаданные и прочие прелести жизни (документация в виде строк, возможность закавычивать аргументы).
bubnenkoff
11:42Я твой пример с ложками продолжаю разбирать. Я попробовал его на foreach переписать. Или я опять где-то туплю или bind в цикле можно только через forall сделать. В данном примере связывание не происходит:
ww: [a a a a]
foreach w ww [bind w context [a: take [ "My" "name" "is" "Dima" ] ] ]

9214
11:53Оно происходит, только ты всё ещё не понимаешь разницу между связкой слова на стеке и связкой слова на куче (в блоке). В первом случае ты его привязываешь и оно улетает, потому что ты его нигде не сохранил. Во втором случае оно привязывается и остается лежать на своем месте внутри блока.
11:54Вот что делает forall:
>> forall ww [print get bind ww/1 context [a: take ["My" "name" "is" "Dima"]]]
My
name
is
Dima

>> forall ww [print head bind ww context [a: take ["My" "name" "is" "Dima"]]]
My My My My
My name name name
My name is is
My name is Dima
11:57Вот что делает foreach:
>> foreach w ww [print get bind w context [a: take ["My" "name" "is" "Dima"]]]
My
name
is
Dima

>> foreach w ww [print bind ww context [a: take ["My" "name" "is" "Dima"]]]
My My My My
name name name name
is is is is
Dima Dima Dima Dima
12:03Если ты хочешь это с foreach сделать:
>> foreach w ww [ww: next bind ww context [a: take ["My" "name" "is" "Dima"]] print head ww]
My My My My
My name name name
My name is is
My name is Dima
bubnenkoff
13:45Я проделал пример со стеком. Мне он предельно ясен. Однако все же что-то не так делаю т.к. не получается выполнить привязку.
Вот я создаю слово со значением в глобальном контексте:
x: 666
Вот я создаю контекст на стеке:
context [x: 123]
Вот я связываю контекст со словом:
y: context [x: 123]

Теперь я хочу изменить связку чтобы x ссылался на контекст связанные с y.
По идее я должен написать что-то типа:
bind x 'y
или же:
bind x context [x: 123]

И тогда по идее x стало бы привязано к значению 123. В чем я косячу?
9214
13:49Сообщения об ошибках можно почитать, например. У тебя их тут как минимум две должно быть.
bubnenkoff
13:52Но логика происходящего которую я изложил правильная? Ругается на: bind does not allow integer! for its word argument. Но я не пойму в чем причина. Я же слову меняю привязку
13:52
>> 
>> x: 666
== 666
>> bind x context [x: 123]
*** Script Error: bind does not allow integer! for its word argument
*** Where: bind
*** Stack:  

>>

9214
13:55... ты пытаешься целочисленное значение привязать к контексту, о чем тебе и говорят. Слово это активный тип данных, x тебе дает значение на которое оно указывает, 666.
13:55И bind 'x 'y это не то же самое что bind 'x y.
13:56Первое это bind 'x system/words, второе это bind 'x context [x: 123].
bubnenkoff
14:09А... да. Это логично.
bind 'x context [x: 123]

А вот что тут не так:
>> context? 'x
== make object! [
    datatype!: datatype!
    unset!: unset!
    none!: none!
    logic!: logic!
    block!: blo...
>>

Или все так и контекстом будет блок?
9214
14:11> Я проделал пример со стеком. Мне он предельно ясен.

Что-то слабо верится. Ты только что повторил абсолютно ту же самую ошибку что и в прошлый раз.
bubnenkoff
14:19В стек в начале был засунут новый контекст, а потом слово находящееся в контексте system/words у которого не установлено значение. Верно?
14:21
bind 'x context [x: 123]

тут по идее я слово из system/words c написанием x связываю со значением из другого контекста
9214
14:24
text
вот это вот
      ↓
bind 'x context [x: 123]
context? 'x      ↑
          ↑     и даже вот это вот
и вот это вот

ЭТО РАЗНЫЕ СЛОВА С ОДИНАКОВЫМ НАПИСАНИЕМ
bubnenkoff
14:29
bind 'x
context? 'x

Почему это разные слова? Это же слово x которое находится в контексте system/words
Значение которого в начале было:
>> x: 666
== 666
9214
14:32Если ты у одного их этих слов привязку поменяешь, у других она поменяется?
bubnenkoff
14:33Ну вот я меняю привязку:
bind 'x context [x: 123]

значит x контекст слова x указывает на значение из блока
9214
14:33
text
>> a: ["x" <global>]
== ["x" <global>]
>> b: ["x" <global>]
== ["x" <global>]
>> a = b
== true

>> a/2: <context [x: 1 2 3]> ; меняешь привязку у одного
== <context [x: 1 2 3]>
>> a
== ["x" <context [x: 1 2 3]>]
>> b
== ["x" <global>] ; у другого она не меняется
>> a = b
== false
14:35Но ты почему-то делаешь глаза по 5 рублей и ожидаешь что после одного bind 'x ... _все последующие x_ будут магическим образом привязаны к ....
bubnenkoff
14:37Сейчас буду читать пример.
Я ожидал, что все последующие 'x будут тем же самым 'x из глобального контекста.
9214
14:38Они и будут по дефолту "теми же самыми из глобального контекста", только ты самый первый привязал от глобального к какому-то другому.
14:40
text
>> get bind 'x context [x: 123]
== 123
>> value? 'x
== false

>> block: []
== []
>> append block bind 'x context [x: 123]
== [x]
>> append block quote :x
== [x :x]
>> reduce block
== [123 unset]

>> x: 456
== 456
>> reduce block
== [123 456]

>> set in context? block/1 'x 666
== 666
>> reduce block
== [666 456]
>> set bind block/1 block/1 777
== 777
>> reduce block
== [777 456]

>> set 'x 0
== 0
>> reduce block
== [777 0]
>> set block/2 666
== 666
>> reduce block
== [777 666]

>> set bind block/2 system/words 777
== 777
>> reduce block
== [777 777]

>> set bind block/2 block/1 'foo
== foo
>> reduce block
== [foo 777]
>> set bind block/1 block/2 'bar
== bar
>> reduce block
== [foo bar]

bubnenkoff
15:27[![изображение.png](https://files.gitter.im/red/Russian/Nr7d/thumb/izobrazhenie.png)](https://files.gitter.im/red/Russian/Nr7d/izobrazhenie.png)
15:27Правильно ли я же теперь все понимаю?
9214
15:34В принципе да, можно и проще.

В великой и могучей стране есть много людей с именем Дмитрий. Если один из Дмитриев достигнет понимания bind — достигнут ли его другие Дмитрии? Очевидно что нет (если только мы не имеем дело с разумом роя).

В великом и могучем скрипте есть куча слов с написанием x. Если одно из слов привязывается с помощью bind к какому-то контексту — привяжуются ли к нему другие слова с написанием x? Ответ уже известен.
bubnenkoff
15:42Спасибо что разжевывал мне все это. Ей богу в голову укладывалось до ужаса тяжело. В какой-то момент я даже уже бросить хотел т.к. начало казаться, что я это так и не смогу понять. Сейчас надо будет еще посидеть позакреплять, чтобы уж точно все отложилось.

Есть еще ряд вопросов:
1. Почему если object и context это одно и тоже часто используют именно context?
2. Почему всего два типа данных пораждают контекст? Как я понимаю это функция и object?
3. Правильно ли я понимаю что контекстом функции считается все что идет после слова на которое она вешается? x: и дальше уже идет контекст func[] [...]
9214
15:491. Передает намерение лучше. object это объект, что-то что будет манипулировано, context это скорее окружение внутри которого будут проводить манипуляции.
1. Потому что по своему смыслу они это и делают — создают пространство имен которое связывает символы со значениями. Ты можешь другие сопоставимые типы данных (map! или block! например) в них сконвертировать, если хочешь.
1. Контекст это всегда таблица (или что-то что её моделирует), но "отображается" он как значение к которому оно принадлежит, объект или функция. Есть понятие [reification](https://en.wikipedia.org/wiki/Reification_%28computer_science%29), не знаю как его на русский правильнее перевести.
bubnenkoff
15:52>Ты можешь другие сопоставимые типы данных (map! или block! например) в них сконвертировать, если хочешь

Ты имеешь ввиду, что данные в блоке могут быть сконвертированы в объект если записаны как пары? Типа: [a 1 b 2 c 3]?

15:54> Контекст это всегда таблица (или что-то что её моделирует)

И эти контексты могут иметь связки между собой? Один ссылаться на другой? Все они в куче хранятся?
9214
15:55
text
>> block: [a: 1 b: 2]
== [a: 1 b: 2]
>> object block
== make object! [
    a: 1
    b: 2
]
15:55> И эти контексты могут иметь связки между собой? Один ссылаться на другой?

Нет, они друг от друга не зависят, в этом и есть основная идея. Если бы они друг на друга ссылались, это были бы области видимости.
bubnenkoff
15:56То есть в одном контексте не может использоваться слово указазывающее на связку в другом?
9214
15:58Может конечно, если ты под этим понимаешь "ссылку".
>> foo: context [bar: 'baz]
== make object! [
    bar: 'baz
]
>> bar: context [bar: in foo 'bar]
== make object! [
    bar: 'bar
]
>> bar/bar
== bar
>> get bar/bar
== baz
>> context? bar/bar
== make object! [
    bar: 'baz
]

bubnenkoff
09:07Хотел уточнить, а вот когда мы пишем:
t: text-list data []

То там под копотом что происходит? Просто я в начале ожидал, что на text-list автоматом при создании повесится блок [ ] но оказалось, что этого не происходит и надо явно все писать.
Получается где-то внутри присходит связывание t c [ ]?
9214
09:51Перечитай документацию по View и VID.
bubnenkoff
11:56Проще на русском пояснить, что я там пытаюсь сделать и в чем у меня проблема.
Если я пишу:
result: parse f-data/text ["aa" ]
то парсер у меня корректно все проверяет т.е. значение данных для него существует.
Проблема с самим правилом. Как только я вместо текста в кавычках записываю значение которое получаю из поля то все перестает работать.
Вариант с mold тоже не работает. обращение к /data вместо /text тоже ничего не дает:
result: parse f-data/text [form f-rule/text ]

Ты там написал, что правило не может быть literal string. И я вот так и не понял как из lit-string взять данные
9214
11:59Покажи мне место в документации по Parse где сказано что то что ты делаешь имеет хоть какой-то смысл.
bubnenkoff
12:06А тут проблема в разных контекстах? Я просто понимаю, что наверно что-то не то, но затрудняюсь полностью понять проблему
9214
12:06> Как только я вместо текста в кавычках записываю значение которое получаю из поля то все перестает работать.

То что ты засовываешь в блок это не "значение из поля".
12:07При чем тут контексты, господи помилуй...
bubnenkoff
12:08Ну вот есть объект field. У объекта есть поля, одно из которых /textразве не так?
9214
12:08Так.
bubnenkoff
12:09и при этом я не могу parse это значение передать?
9214
12:09Можешь.
bubnenkoff
12:10Но вот тут я делаю не так:
result: parse f-data/text [ f-rule/text ] ?
9214
12:10Упрости задачу.
>> field: [text "blah blah"]
== [text "blah blah"]

Теперь напиши [field/text] и помедитируй на результат.
bubnenkoff
12:10ок сейчас
9214
12:13Как закончишь, помедитируй на type? first [field/text] и посмотри есть ли такой тип данных в [списке](https://doc.red-lang.org/en/parse.html#_parse_rules) тех что Parse поддерживает.
12:14Ещё очень помогает читать и вникать в сообщения об ошибках.
>> parse [][foo/bar]
*** Script Error: PARSE - invalid rule or usage of rule: foo/bar
*** Where: parse
*** Stack:
bubnenkoff
12:16получается что [ f-rule/text ] распознается как блок, а не как содержимое правило внутри блока?
9214
12:20Содержимое то у него какое?
bubnenkoff
12:21блок содержит path!, а не string!

Получается мне надо сделать:
result: parse f-data/text [ mold f-rule/text ]
но тоже что-то не сработало
9214
12:23Окей, ты написал [mold f-rule/text]. Что теперь по твоему будет внутри этого блока, и как Parse это проинтерпретирует?
12:23Подсказка: эта та же самая проблема что и до этого, только теперь с двумя значениями.
12:28То ли ты ожидаешь что Parse пойдет по f-rule/text и найдет строку (он мог бы на самом деле, только это пока не поддерживается), то ли ты ожидаешь что [mold f-rule/text] магическим образом обернется в строку как если бы его интерпретатор вычислил (но тогда зачем тебе mold если f-rule/text и так указывает на строку?).
bubnenkoff
12:32> Окей, ты написал [mold f-rule/text]. Что теперь по твоему будет внутри этого блока, и как Parse это проинтерпретирует?

reduce наверно нужно для оценки содержимого блока, но я попробовал и тоже не совсем то
>> reduce [mold f-rule/text]
== [{"a"}]
9214
12:36Ну хоть с этим разобрались.
>> "abc"
== "abc"
>> mold "abc"
== {"abc"}
12:37Тебе то что нужно? Экстра слой кавычек?
bubnenkoff
12:37Эврика!
result: parse f-data/text reduce [  f-rule/text ]

щас проверю
14:10Я там не совсем понял твой вопрос в англоязычной группе. Не мог бы его пояснить?
14:16Теперь я решил попробовать вставлять данные в БД.
Синтаксим вставки такой:
SQLite/do [
exec {INSERT INTO "Cars" VALUES(3,'Skoda',9000);}
]


Мне соотвественно нужно просто свое значение вклеить. Я попроборобовал сделать через rejoin
SQLite/do [
 exec rejoin [{INSERT INTO "Cars" VALUES(11,'} reduce f-data/text {', 262666);}]
]

Однако оно начало ругаться:
*** Script Error: data not in correct format: [to-string rejoin [{INSERT INTO "Cars" VALUES(11,'} reduce f-data/text "', 262666);"] /1]


хотя по идее rejoin строку как раз возвращает
9214
14:36Sqlite/do на вход принимает диалект с определенным синтаксисом.
https://github.com/red/code/blob/master/Library/SQLite/SQLite3.red#L301
bubnenkoff
14:46Каждый диалект имеет свой отдельный контекст? Или какие правила?
9214
14:47Никаких правил нету. Тебе дают блок данных и ты делаешь с ним что хочешь.
14:48В данном случае весь функционал просто обернули в объект, "библиотеку".
bubnenkoff
14:48А можешь пояснить чем по сути является диалект. Я правильно понимаю, что это правило интерритации слов?
9214
14:49[Встраиваемый предметно-ориентированный язык](https://ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%B4%D0%BC%D0%B5%D1%82%D0%BD%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D1%8F%D0%B7%D1%8B%D0%BA#%D0%92%D1%81%D1%82%D1%80%D0%B0%D0%B8%D0%B2%D0%B0%D0%B5%D0%BC%D1%8B%D0%B5_%D1%8F%D0%B7%D1%8B%D0%BA%D0%B8).
14:50Но в общем случае это блок + правила интерпретации его содержимого.
14:51В случае с этой библиотекой принимается только определенный набор ключевых слов с определенными параметрами.
bubnenkoff
14:51Так и как быть в моем случае если мне нужно туда свое значение подставить? А то глядя на код мне совершенно не очевидно...
9214
14:51В случае со стандартным интерпретатором принимается в принципе всё что угодно, и семантика у каждого типа данных своя. В случае с Parse принимаются только "грамматические правила".
14:51compose попробуй.
14:52Только описание почитать не забудь перед тем как вопросы задавать, ? compose.
bubnenkoff
14:54Хорошо, сейчас. А диалекты как-то наследуются? Как понимаю compose это часть диалекта red\system?
9214
14:54Или можешь свою обертку придумать, которая за тебя все выражения будет подставлять.
bubnenkoff
14:56Ну до своей обертки я пока не дорос. Документацию по compose посмотрел. Он выражение в скобках оценивает. Но у меня вроде бы другой случай...
9214
14:56> А диалекты как-то наследуются? Как понимаю compose это часть диалекта red\system?

Эм, нет, compose это часть Red, но написан он на Red/System. Один диалект может использовать другие диалекты в своей реализации, VID например иногда использует Parse.
14:56Parse в свою очередь написан на Red/System.
14:56> Но у меня вроде бы другой случай...

Ну ты выражение в скобки то засунь.
14:57compose [... (rejoin [...])].
bubnenkoff
14:57Так, а как ты понимаешь какая функция в каком диалекте доступна? Написание то может быть одинаковое, а смысл разный? Или диалект указывается явно?
14:58> compose [... (rejoin [...])].

А во спасибо, до такого бы не додумался
9214
14:59Может явно, может неявно (к примеру один дилект может позволять смешивать несколько диалектов внутри себя). Обычно это описывается либо в документации, либо в примерах.
15:01К примеру в Draw есть суб-диалект Shape, в VID ты можешь в некоторых местах писать на Draw или RTD (Rich-Text Dialect).
bubnenkoff
15:02А есть какие-то примеры минимальных диалектов? Просто чтобы основную идею понять
9214
15:03Вообще в твоем случае можно попробовать SQLite/query rejoin ....
bubnenkoff
15:04Сейчас попробую. То ли я скобки не так расставил, толи вариант с compose не заработал
exec compose [ (rejoin [{INSERT INTO "Cars" VALUES(11,'}  f-data/text {', 262666);}])]
9214
15:05> А есть какие-то примеры минимальных диалектов?

Можешь на math посмотреть, я не так давно его альтернативную версию [написал](https://github.com/red/red/pull/4332#issuecomment-600152125). Более просто пример это спецификации функций. Или тот же collect, я правда не уверен в том что его можно диалектом назвать.
15:05@bubnenkoff потому что ты compose не туда засунул.
15:06
text
SQLite/do compose [exec (rejoin ...)]
bubnenkoff
15:10Попробовал сделать так:
SQLite/query compose [
       exec  (rejoin [{INSERT INTO "Cars" VALUES(11,'} reduce f-data/text {', 262666);}])
 ]


Script Error: query does not allow block! for its sql argument
9214
15:13Ты описания функций читай хотя бы. ? sqlite/query.
bubnenkoff
15:14ой сори!
9214
15:14Он от тебя ожидает БД запрос в виде строки (например "INSERT INTO ..."), ты ему даешь блок.
bubnenkoff
16:56Да вот такой вариант работает отлично:
SQLite/do compose [
        exec  (rejoin [{INSERT INTO "Cars" VALUES(random(),'} reduce f-data/text {', 262666);}])
        ]

Спасибо еще раз!
9214
18:18
text
sqlite/query rejoin [{INSERT INTO "Cars" VALUES(random(),'} f-data/text {', 262666);}]
bubnenkoff
19:00Скажи, а где можно про философию языка почитать? Пусть даже не Red а чего-то похожего. Просто мне до сих пор не очевидны его сильные и слабые стороны. С одной стороны некоторые вещи делаются в сотню раз проще чем на любом другом языке, с другой я бы без твоей помощи банально в БД значение вставить не смог бы
9214
19:20Можешь старые блоги Карла полистать, или блог Red. Оригинальный [анонс](https://www.youtube.com/watch?v=-KqNO_sDqm4) Red посмотри. Вообще это понимание с опытом приходит (в любом языке), только у каждого наработка этого опыта занимает разное время. Откусывай столько сколько можешь прожевать.

Из книг: Mindstorms Папперта, Thinking Forth Броди, обе есть в свободном доступе (про русский перевод сказать ничего не могу) и по своему посылу в чем-то похожи на основные идеи в Red и Rebol.
19:32Основные идеи дизайна корнями уходят в денотационную семантику и символьные выражения, а исторически всё началось с AmigaOS (Карл Сассенрат автор этой операционки, в те лохматые времена Rebol ещё назывался Magma) и X-Internet с P2P сетями (в современной интерпретации это всё попадает под общий термин distributed computing).
bubnenkoff
19:41Хорошо, спасибо почитаю. Я никак в толк не могу взять. Как получилось все все на столько компактное? Просто тут весь тулчейн весит 1MB а тот же компилятор Си без всего и с кучей проблем в десятки раз больше и там нельзя и половины что можно тут

bubnenkoff
17:08@9214 я перечитал документацию и не понимаю про размер row...
По идее. extract 2 выбирает каждый второй элемент блока.
x: [
    1 "4171" {22657730.xml} "20200101"
    2 "4172" {22643157.xml} "20200101"
    3 "4173" {22643116.xml} "20200101"
    4 "4174" {22643084.xml} "20200101"
    5 "4175" {22647833.xml} "20200101"
]
extract x 2

Тогда тут длжны быть выбраны элементы "4171" "20200101" "4172" "20200101"
9214
17:10extract/index x 4 3.
bubnenkoff
17:16Спасибо, работает!
Но по идее extract x 2 вытащит же выбирает каждый второй элемент, но результат работы не совпадает с ожидаемым
9214
17:21Твоя идея с реальностью не совпадает значит. Второй аргумент указывает размер интервала который пропускается, а значение всегда берется с начала интервала.
bubnenkoff
17:30ой сори
17:31я тупанул, я там index забыл

bubnenkoff
14:02А не мог бы еще раз сказать что на твой взгляд у меня в коде не так. Вот полный кусок.
https://gist.github.com/bubnenkoff/12a6074c4d3393000cc61a08e62f6dc6

Происходит следующее. По нажатии на кнопку генерится sql запрос который передается в make-db-query в которой и просхходит заполнение виджета cells (его в примере на gist нет).

Вроде бы все правильно делаю?
9214
14:06А что с ним не так? На твоем месте я бы не заморачивался, работает и ладно. Потом подрастешь и поправишь.
bubnenkoff
14:14А хотя бы на что внимание то обратить? Просто мне не очевидно...
9214
14:21Разница между func и function например, [форматирование кода](https://doc.red-lang.org/en/style-guide.html).
bubnenkoff
16:27А подскажи как быть в следующей ситуации. Предположим я хочу сгенеририровать три кнопки и передавать в функцию какая именно кнопка нажата. Следующий код работает ожидалось и как видно по результату не корректно. А идей как его иначе переписать нет.
a: collect [repeat i 3 [keep compose [ (to set-word! rejoin ['b- i]) button [f i] ]]]
f: func[i] [print ["button number:" i]]
view a

button number: 3
button number: 3
button number: 3
9214
16:38
text
view collect [repeat i 3 [keep compose [button extra (i) [print face/extra]]]]

bubnenkoff
12:26@9214 подскажи плиз, а как быть с интерфейсом. У меня в нем много кнопок получается. И в какой-то момент оказывается, что имена начинают пересекаться. Какие тут правила? Я стал просто более длинные и осмысленные имена давать вида: generate-sql-button: button
Есть еще какие-то подходы?
12:26Просто как понимаю все компоненты VID видимы друг для друга.
9214
12:39Зачем тебе их именовать вообще?
bubnenkoff
12:41ну вот у меня есть много fields и в них нужно данные какие-то выводить
9214
19:07Ну окей, а имена то им давать зачем? Ты можешь ссылаться на них к примеру по индексу в панели, или сохранив ссылки на их face'ы в отдельный блок. Или можешь на каждый повесить свой обработчик событий который будет делать что тебе надо. Не совсем понятно какую проблемы ты пытаешься решить.

bubnenkoff
07:421. Индекс в панеле -- а не усложнит ли это читабельность? И не приведет ли к куче ошибок когда добавил один элемент и все индексы сдвинулись.
2. "или сохранив ссылки на их face'ы в отдельный блок" -- я это не совсем понял...

Вот я к примеру делаю интерфейс. Обратиться к face я могу только для текущего элемента т.е. чтобы из кнопки достучаться до drop-down мне нужно дать ему имя. Если дать слишком короткое, то дальше в коде или в другом виджете (фасете) я могу дать похожее имя и потом очень долго искать ошибку.
batch-operations:
[
    status-text: text "Set Processing status to NULL" set-to-null-process-status: drop-down data ["Hour" "Day"] 
    button "UPDATE" [
        either all [set-to-null-process-status/text (length? set-to-null-process-status/text) > 0] 
        [
            print [set-to-null-process-status/text]
        ]
        [
            
        ]
    ]
]


Просто если вместо set-to-null-process-status я дам название set-status то потом где-то что-то могу перепизаписать.

Какой подход лучше всего?

bubnenkoff
11:42@9214 слушай, а не мог бы мне про lit-word объяснить, я думал, что это просто символьное представление слова без его оценки, но тут мне стали объяснять обратное:
https://gitter.im/red/help?at=5ecd061b2c49c45f5aa1d02f
https://gitter.im/red/help?at=5ece1eaeb101510b201d40a0

bubnenkoff
09:22@9214 спасибо тебе большое за развернутый ответ на SO! Я до такого пути даже додуматься не мог! Да я там решил понять как обертки делаются над Сишными библиотеками

gavr123456789_gitlab
05:31Где есть гайд с нуля?
05:31Тот что на главной, выглядит так будто я уже знаю rebol или типа того https://github.com/red/docs/blob/master/en/SUMMARY.adoc

9214
16:19@bubnenkoff всегда пожалуйста.
@gavr123456789_gitlab это справочная документация которая предполагает что ты имеешь базовые знания языка. Начни с [FAQ для новичков](https://github.com/red/red/wiki/Beginner%27s-FAQ), там есть ссылки на нужные ресурсы.
gavr123456789_gitlab
20:42@9214 не, ниче из этого не похоже на гайд с нуля, я понял только про 50 базовых типов, но это я уже знал, by example не гайд
20:44Я имею ввиду что-то вроде этого https://wiki.gnome.org/Projects/Vala/Tutorial/ru
9214
20:49Учебника и пользовательской документации конкретно по Red пока нету, можешь [Rebol/Core user guide](http://www.rebol.com/docs/core23/rebolcore.html) почитать.
gavr123456789_gitlab
20:49О, вот чтото более менее помойму нашлось http://helpin.red/Usingwords.html

bubnenkoff
16:48@9214 кстати, спасибо огромное за тот пример парсера, мне пока не хватает знаний его осмыслить, но буду стараться

bubnenkoff
19:16@9214 я тут доки читаю help in red написано: "function makes its variables local" но как мы с тобой выяснили в Red нет переменных. Эта фраза корректна? Или она дана для упрощения понимания?
9214
19:22@bubnenkoff это тот случай медвежьей услуги когда человек учит других при этом сам будучи новичком, не понимая о чем говорит.
bubnenkoff
19:24Скажи, а сколько лет ты уже пишешь на Red\Rebol?
9214
19:26Судя по [статам](http://red.qyz.cz/stats/) я в чате первый раз показался в конце 2016-го. С тех пор думаю и повелось.
bubnenkoff
19:28А какие задачи на нем наиболее часто решаешь? И используешь ли на работе?
9214
19:41Когда время свободное было ковырялся со своими проектами, сейчас над самим языком работаю. В бытность использовал для всяких лабораторных задач (в магистратуре), вроде написания обёртки над легаси библиотекой для одного медицинского аппарата, парсинга файлов, мелкой утилитки для интерфейса мозг-компьютер, прототипа для хакатона. На курсе по программированию препода из себя выводил: "молодой человек, ну не может быть так что вы всё уже решили, мы всё ещё тянем 14 гигов вижуал студио по вайфаю!". Обработку больших данных пытался, но Red слишком сырой для этого пока.
bubnenkoff
19:46Я все же в толк не могу взять. Как так получилось что в Red в 1MB влезает то, что другие в 10GB впихнуть не могут?
9214
19:56Отказ от сторонних библиотек и использование только API операционки, переиспользование кода, создание маленького но мощного функционала, встроенные микро-языки.
bubnenkoff
20:03а вот по твоему опыту, на сколько переиспользование тут эффективно нежели в других языках?
20:04вроде бы везде пытаются код переиспользовать. ООП тот же..))
9214
20:06Ну ты сам сказал что у других 10 гигов а у нас 1 мег, вот и смотри эффективно или нет.
bubnenkoff
20:08А как можно объяснить подобное? Какие подходы языка позволяют повысить переиспользование кода?
9214
20:13Полиморфизм, например. В Red штук 15 типов данных которые условно называются "серии", внутри они переиспользуют один и тот же код, который написан так чтобы работать с любой серией в не зависимости от размера и типа её элемента. В самом Red функции имеют высокую степень полиморфизма, те же арифметические операции например работают над всеми скалярными типами.

bubnenkoff
13:41спасибо большое за примеры. Я их изучу. Сейчас только вот с этим пытаютсь разобраться. Никак не могу понять почему тут все числа захватываются. В правиле же вроде:
ahead ws ""
a: {
<apps>
<app>1</app>
<app>2</app>
<app>3</app>
</apps>
<app>4</app>
}

parse a [
	any [
		thru "<app>" copy _ to "</" (print _) not [ahead ws "</apps>"]
	] 
]
13:42Просто по логике тройку оно не должно было захватить
9214
15:06@bubnenkoff как copy _ to " может знать о том что впереди у тебя идетnot [ahead ws ""]? Никак. Вот оно и матчит 3, ещё до того как ты успеваешь проверить что за ней идет.
bubnenkoff
17:27по логике тогда not [ahead ws ""] должно работать как предикат?
parse a [
	any [
		not [ahead ws "</apps>"] thru "<app>" copy _ to "</" (print _) 
	] 
]

Но почему то не работает
9214
17:49Ты по-моему не совсем понимаешь что ты делаешь :)
bubnenkoff
17:51not [ahead ws ""] проверяет не равна ли следующая строка "</apps>"? Верно же? Если равна, то правило не идет дальше и возвращается false
9214
17:55Но у тебя же идет после , а не до .
17:56
text
>> parse trim/all a [any [<app> copy match to </app> [</app> </apps>] (print match) | skip]]
3
== true
bubnenkoff
17:59Спасибо, сейчас буду разбираться дальше.
Я правильно понимаю, что ahead смотрит вперед но курсор не сдвигает?
9214
18:00Да, так же как и not, только not инвертирует.
bubnenkoff
18:01А в блоке круглых скобок я могу любой код выполнять? Или есть ограничения?
9214
18:05Вот ещё пример:
>> parse [a b <- c d e <-][collect any [ahead [word! '<-] keep word! skip | skip]]
== [b e]
>> parse [a b <- c d e <-][collect any [ahead [[not '<- skip] '<-] keep [not '<- skip] skip | skip]]
== [b e]
18:05@bubnenkoff можешь что угодно там делать, это способ "убежать" из Parse в обычный Red.
bubnenkoff
18:11> Но у тебя же идет после , а не до .

Я еще раз вдумчиво перечитал. В примере последний app как раз после "</apps>"
a: {
<apps>
<app>1</app>
<app>2</app>
<app>3</app>
</apps>
<app>4</app>
}


Поэтому тройку он не должен захватывать:
parse a [
	any [
		not [ahead ws "</apps>"] thru "<app>" copy _ to "</" (print _) 
	] 
]
18:13А хотя погоди, дай еще раз перечитаю все что ты написал
9214
18:13Дак тебе тройку или четверку надо выудить? В группе по /parse я тебе два варианта решения задачи уже показал, в зависимости от формулировки.
bubnenkoff
18:20У меня получилось так. Я писал код чтобы вытащить 4-ку. Потом прочитал написанное и понял, что код должен вытягивать все кроме тройки. Задача сейчас просто с синтаксисом разобраться т.е. понять, почему оно работает не так как ожидалось.
18:20За примеры огромное спасибо, я сегодня весь день сидел читал твои посты на питхабе, чтобы лучше понять суть правил
9214
18:22Да там не столько посты сколько срач на пустом месте, за себя даже стыдно. Суть в том что break, failи reject работают, на работают абы как и местами вообще забагованные. И тебе они в этой задаче в принципе не нужны.
bubnenkoff
18:23Ну вот я долго вчитывался т.к. некоторые моменты очень не очевидны и легко нарваться на ситуацию когда ошибку фиг найдешь
9214
18:32Всё кроме тройки:
a: {
	<apps>
	<app>1</app>
	<app>2</app>
	<app>3</app>
	</apps>
	<app>4</app>
}

parse trim/all a [
	collect any [
		<app> ahead [thru </app> not </apps>]
		keep copy match to </app> </app>
		| skip
	]
]
bubnenkoff
18:37спасибо! буду дальше изучать!

bubnenkoff
10:22да,я наконец-то нашел в чем у меня была ошибка. У меня каждый раз курсор сдвигался на начало <app> и там </apps> не могло быть.

Правильно ли я понимаю, что следующий код выполнит просмотр вперед:
ahead thru "" ws not ""
есть ли за пределами "</app>" "</apps>" или нет? При этом курсор сидвинут не будет?
9214
12:10
text
ahead [thru "</app>" ws not "</apps>"]
bubnenkoff
12:33Все, у меня наконец получилось написать код который работает как у тебя. Правда сам я не додумался, что нужно вначале в "<app>" зайти и уже внутри него проверку сделать
9214
12:40Не совсем понятно что ты подразумеваешь под "зайти" и "внутри".
bubnenkoff
13:37Я долго и упорно писал:
ahead [thru "</app>" ws not "</apps>"] | skip

т.е. мы проверяем нет ли после app apps или выполняем один шаг через skip. Но было не понятно как тогда содержимое app собирать. В итоге оказалось, что можно\нужно вот так:
"<app>" ahead [thru "</app>" ws not "</apps>"] copy _ to "</app>" (print _) | skip

Это не совсем как у тебя, но по крайне мере я до этого сам дошел
13:59Я еще в толк не могу взять. Квадратные скобки же показывают, что написанное внутри них это единое выражение. Верно?
Но иногда я вижу что одиночные правила иногда засовываются в квадратные скобки и их поведение меняется к примеру reject и [reject] и я не совсем понимаю это бага или фича
9214
14:17В документации же всё описанно.
bubnenkoff
14:59Вот в этой https://github.com/red/docs/blob/master/en/parse.adoc ?
9214
15:05reject:
> Forces _enclosing block! rule_ to instantly fail.
15:06Т.е. в какой блок ты reject засунешь тот он и зафейлит.

bubnenkoff
07:22Скажи, а арность это количество аргументов которые принимает функция (слово?)?
09:52Никак не могу твой пример разобрать.
apps: [<apps> some [app | junk] </apps>]
app:  [<app> keep copy match to "<" </app>]
junk: ["<" copy name to #">" thru ["</" name ">"]]

parse trim/all {
    <apps>
    <some>
    <app>1</app>
    <app>2</app>
    </some>
    <app>3</app>
    </apps>
    <foo>
    <app>4</app>
    </foo>
}[
    collect apps
]

Не ясно как он забирает 3

Не мог бы пояснить что происходит в этой строке?
junk: ["<" copy name to #">" thru [""]] ?
10:05Получается, что мы собираем то что внутри app и если попадается другой тег, то пропускаем его он начала до конца?
9214
11:24Да.
bubnenkoff
11:31А как бы ты решил следующую проблему. Мне нужно убелиться, что определенная структура присутствует в документе. Своего рода сделать аналог xpath.
Вот к примеру тут мне нужно знать, что существует info/price, а не просто price.
a: {
<apps>
<app>1</app>
<app>2</app>
<price>15</price>
<app>3</app>
</apps>
<app>4</app>
<info>
<price>17</price>
<code>RUB</code>
</info>
}


При этом мне нужно сделать максимально адаптивно т.к. будет нужно проверять foo/bar/baz т.к. совпадение вида bar/baz даст мне не правильные данные.

Я так думаю, что нужно очередь создать типа: list: [info/price]и по шагам проверять. Типа нашли info выставили флаг, нашли за ним price выставили. Если не найдено. Сбрасываем оба флага и идем дальше. Пометили элемент очереди как найденный. Но тогда строковое описание должно быть преобразовано в объект получается.

Проблема в том, что я не могу придумать формат для подобной очереди т.к. нужно что-то читаемое т.к. мне нужно будет очень много разных комбинаций проверить. Видимо нужно из этой очереди объекты создавать или я не знаю даже что. Ведь у каждого еще флаг должен быть. Найден он или нет
9214
12:18> А как бы ты решил следующую проблему... Своего рода сделать аналог xpath.

Я бы сделал аналог XPath :smile_cat:
bubnenkoff
12:19Я правильно рассуждаю, в части с флагами и очередью?
9214
12:21Стек нужен. Я бы начал с того чтобы a сконвертировать в что-то вроде [apps [app 1 app 2 price 15 app 3] app 4 info [price 17 code RUB]].
12:21И дальше ты уже можешь на этом сделать data/info/price.
bubnenkoff
12:23т.е. огород не городить, а просто превратить все в Red представление и проверять есть все как путь?
12:24На сколько эффективен данный подход? Просто у меня некоторые документы по 10МБ...
9214
12:25Не узнаешь пока не попробуешь.
13:11Черновой вариант.
test: {
	<apps>
	<app>1</app>
	<app>2</app>
	<price>15</price>
	<app>3</app>
	</apps>
	<app>4</app>
	<info>
	<price>17</price>
	<code>RUB</code>
	</info>
}

tokens: parse to binary! trim/all test [
	collect any [
		copy match [tag! | to "<"]
		keep (any [attempt [load match] to string! match])
	]
]

data:  [[set name tag!] [copy match some value] tag!]
value: [not tag! skip]

emit: does [
	reduce [
		to get pick [word! set-word!] data? to string! name
		either data? [match/1][match]
	]
]

process: [some [change data (emit) | skip]]

parse tokens [(data?: yes) process [fail] | (data?: no) process]

>> tokens
== [apps: [app 1 app 2 price 15 app 3] app 4 info: [price 17 code RUB]]
>> tokens/info/price
== 17
bubnenkoff
13:40спасибо, а зачем to binary!?
13:46Что-то на твоем примере ошибка случается:
>> tokens: parse to binary! trim/all test [
[        collect any [
[            copy match [tag! | to "<"]
[            keep (any [attempt [load match] to string! match])
[        ]
[    ]
*** Script Error: PARSE - matching by datatype not supported for any-string! input
*** Where: parse
*** Stack:
9214
15:00Обновись.
bubnenkoff
15:14А да, я только сейчас прочитал, что был апдейт. Я правильно понимаю, что парсер напрямую завязан на лексер и теперь парсер будет работать до 200 раз быстрее?
15:15Я там выше вопрос писал. Он потерялся видимо. Продублирую его: арность это количество аргументов которые принимает функция (слово?)?
9214
15:16Эм, нет. Откуда такой вывод? Арность — да, но в Parse "функций" как таковых нету.
bubnenkoff
15:17"есть данные которые могут быть выполнены как функция" -- так?
9214
bubnenkoff
15:18Я просто не совсем понимаю какую роль лексер играет
9214
15:19Вообще или конкретно в моем примере?
bubnenkoff
15:20Просто в примере который ты давал в группе была строка взятая в блок. И ссылка на баг, в баге было написано что-то типа: "блок нужен т.к. парсер не знает арность аргументов"
9214
15:23А, ты об этом. В Parse каждое ключевое слово принимает опредленное количество параметров, например другое правило. Это правило можно обернуть в блок (тогда это считается за 1 параметр) а можно записать линейно. Иногда Parse линейную запись не понимает.
bubnenkoff
15:23т.е. как я понял он не знает сколько аргументов у to условно говоря запись вида:
to "<" "foo" можно прочитать как дойти до "<" или же что foo является тоже аргументом и нужно дойти до "<foo"
15:25А по поводу лексера не мог бы объяснить что он делает?
9214
15:26Про лексер [тут](https://www.red-lang.org/2020/08/a-new-fast-and-flexible-lexer.html) всё расписанно.
15:28> to "<" "foo" можно прочитать как дойти до "<" или же что foo является тоже аргументом и нужно дойти до "<foo"

Нет, тут как раз таки всё однозначно. Но например в
>> parse "aab" [2 3 thru "a"]
== true

2 3 косячит.
bubnenkoff
15:30Вот не совсем понятно: "converting textual code representation into a structured memory representation".
Я думал интерпритатор просто ходит по JSON-подобной структуре в памяти и исполняет ее на ходу. Что кроется за: "structured memory representation"?
9214
15:31Та самая "JSON-подобная структура" по которой интепретаторы ходят.
bubnenkoff
15:33Лексер = интерпритатор?
Просто в моем понимании загрузчик - загружает в память, интерпритатор интерпритирует.

Или фроентэнд интерпритатора называется лексер и там еще какие-то операции производятся?
9214
15:34> Лексер = интерпритатор?

Это вообще какой-то прыжок веры у тебя получается.
15:35Лексер это и есть загрузчик, из текста в структуру.
bubnenkoff
15:40т.е. лексер просто трансформирует в какое-то представление по которому уже интерпритатор умеет ходить и все?
15:40А перед лексером есть еще какие-то фазы?
9214
15:43Да. Других фаз нету, ты скармливаешь текст и тебе выплёвывают синтаксическое дерево. По этому дереву потом интерпретаторы/компиляторы лазят как обезьяны.
bubnenkoff
17:27А чем принципиально это от JIT отличается? Там же тоже AST по идее
9214
17:31JIT и AST это вообще принципиально разные вещи. И Red работает с CST, а не AST.
bubnenkoff
17:34CST получается сами значения узлов еще сохраняет?
17:35Просто я не совсем понимаю в чем отличие интерпритаторов в других языках. Они же ходят тоже по промежуточному представлению. Или вся разница в том, что тут CST, а у других языков AST?
9214
17:43Не все интерпретаторы AST используют.
bubnenkoff
17:44А что еще кроме AST пригодно для подобных целей? Шитый код это в эту степь?
17:45Есть еще языки где CST используется?
9214
17:51Книжки по компиляторам и парсерам читай :)
bubnenkoff
17:52Ты про книгу дракона? Мне просто она сложной показалась очень. Есть что-то для гуманитариев?)
9214
18:29"Parsing Techniques, Dick Grune" первую главу полистай. Результат парсинга это и есть CST. AST подразумевает уже некоторый анализ и пост-процессинг CST. К примеру CST это [1 + 2 * 3], которое само по себе смысла не имеет. AST к этому добавит что "вот здесь инфиксное выражение с арифметическими операциями над целыми числами и * имеет приоритет над +" и придаст этому некий смысл, необходимый для компиляции/интерпретации.
bubnenkoff
18:32"которое само по себе смысла не имеет" а в случае с Red как тогда оно обрабатывается?
9214
18:35Я это уже сотню раз объяснял.
bubnenkoff
18:35контекст получается смысл задает?

bubnenkoff
10:41open: ["<" copy opening to ">" if (find tags opening) ">"]
Никак не могу понять смысл if (find tags opening). Оно нужно, чтобы передвинуться к закрывающему тегу: ">"?

bubnenkoff
09:18@9214 я тут читаю про copy/deep https://github.com/red/red/issues/2167
Я правильно понимаю, что даже он не обеспечивает глубинное копирование всего? И какая причина такого поведения?

9214
17:44@bubnenkoff в квитке вроде всё расписано, хотя он четырехлетней давности и может не соответствовать действительности.

bubnenkoff
08:36@9214 скажи, а ты в какой стране живешь? Просто я у тебя в письменном английском вижу обороты не характерные даже для европейцев
9214
08:38Большую часть жизни провел на среднем Урале.
bubnenkoff
08:56А еще знаешь русско-язычных программистов на Red?
9214
11:15Лично нет. Из здесь присутствующих @maximvl был активен пару-тройку лет назад когда я только начинал, потом пропал с радара. @uralbash вроде работает в УрФУ, так же пару лет назад склепал примеры с Red для курса по сетевому программированию, состряпал пакет для NixOS и пропал.
bubnenkoff
11:16А ты где работаешь? Работа как-то связана с Red или это хобби?
9214
11:27Как-то связана :)