func, а то время как для function все слова, объявленные внутри нее, по умолчанию будут локальными (а еще есть does и has, но с их помощью объявляются функции, не требующие аргументов)./local привязывает слова внутри тела функции к контексту данной функции. Без понимания со стороны @bubnenkoff'а что такое "слово", "привязка" и "контекст" объяснять это ему смысла нет./local может быть указан в спецификации любой функции. function автоматически собирает только set-word!ы и word!ы используйщиеся как аргументы foreach и repeat. has локализует все слова в данном тобой блоке./local сам по себе ничего ни к чему не привязывает - он лишь указывает, что как надо будет привязывать.local (не надо мои слова перекручивать), а во вторых вот вам пример того, что вы неправы:funct1: function [][var1: "asd" print var1] funct1
var1 из глобального контекста./local само по себе это значение типа refinement!, но внутри спецификации функции (о которой собственно и был изначальный вопрос) оно несет именно тот смысл который я описал. В каком месте ты увидел "докапывание до слов" для меня остается мистикой.>> 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]
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"
/local декларирует слово как локальное" новичок прочитает как "/local делает переменную локальной к области видимости функции", после чего все катится по наклонной из-за неправильной концепции работы языка, отсюда и мои упор на основы: слово, контекст, связка — я то как раз это все понимаю, провел тут достаточно времени отучивая и переучивая новичков от "ой массив растет ой переменная не инициализируется".load) в память, и по которой разные трансляторы (do, parse, view, ...) могут "ходить", интерпретируя/компилируя значения в ней как им заблагорассудится, типо s-выражений в Лиспе, только без cons-ячеек и списковых структур. Такие данные, имеющие определенную семантику и транслятор для неё, называются *диалектами*. Спецификация функций это один из таких диалектов.f: func[w] [d: copy [] append d w]
copy играет. Ведь как по мне если мы напишем: d: [] то при каждом вызове функции мы будем обнулять значение dd: [] должно происходить затирание значений слова[], который относится к числу 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"]
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 соответственно берет буфер на который ссылается ячейка и копирует все его элементы в другую область памяти, создавая серию с новым буфером.[], который относится к числу indirect типов. Это означает, что в слоте памяти, соответствующем слову d из вашего примера, хранится лишь ссылка на данный блок (неважно, внутри это функции происходит или нет - всегда ссылка). При повторном вызове функции у вас слово d как указывало на блок, так и продолжит на него указывать, в том числе и с уже добавленными в него значениями. Чтобы создать новый пустой (или непустой - какой сами пожелаете) блок и используется функция copy.series к нему не относится т.к. в случае с series идет присвоение нового значение d: "abc" >> ";%!?
*** Syntax Error: invalid value at {";%!?}
*** Where: do
*** Stack: loadcreate и does>), то с Red у тебя проблем возникнуть не должно (как и с любым другим языком в общем-то). Тем не менее, с точки зрения архитектуры это очень разные языки. С точки зрения концепций и подхода к программированию (использование предметно-ориентированных языков, метапрограммирование, упор на простоту и синергию, отказ от сложности и раздутости решений) -- может помочь. Конкретно к нашему случаю Форт никакого практического отношения не имеет.parse "aabbcc" [s: to "bb"]
index? s будет равняться единице? В начале будет оценено первое значение символа и только потом сработает to. Верно?[s: to "bb"] это блок данных, окей? Просто блок данных, не несущий **никакой** смысловой нагрузки. Как этот блок данных интерпретируется зависит от того какой интерпретатор ты используешь -- parse или, к примеру, do.parse а то запутаюсь>> 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 прочитает его как "сопоставь всё до значения со строковым типом данных, затем сопоставь слово abc":>> parse ["string" abc] block == false
false должно быть понятно если ты читал документацию по Parse, но это не суть. Суть в том что один и тот же блок данных разные интерпретаторы (parse и do) могут читать по разному.parse тебе не нужен. С другой стороны, для понимания диалектов необходимо понять работу стандартного интерпретатора и загрузчика.o --> o --> данные. Ссылок в начинке может быть несколько, от 1 до 3, смотря сколько нужно и сколько влезет. Основной момент, который ты должен уяснить, это то что несколько слотов могут ссылаться на одни и те же данные. слот --> данные <-- слот.immediate! в консоль.float!.>> 2 ** 30 == 1073741824 >> 2 ** 31 == 2147483648.0
binary! это косвенный тип, а integer! прямой:>> to integer! #{7FFFFFFF}
== 2147483647>> complement 1 << 31 == 2147483647 >> 1 + complement 1 << 31 *** Math Error: math or number overflow *** Where: + *** Stack:
immediate! я слишком широко взял, all-word! включены в них, но таки содержат внутри себя ссылки. Смотри [здесь](https://github.com/red/red/blob/master/runtime/datatypes/structures.reds) для лучшего понимания -- все структуры с полями типа node! (тот самый узел упомянутый ранее) я обозначил как косвенные.false т.к. где-то видимо какая-то конструкция ему не нравится. Но документ то сам корректный на выходе.true для всех документов которые он смог разобрать и false для которых не смог.true возвращала? to end если очень хочется true увидеть, логика от этого не поменяется.copy работает, а вы меня поправите если я не прав.[] относится к ссылочному типу. Поэтому когда мы пишем: d: [] мы значение d храним в блоке который где-то в другом месте располагается.d: [] находится внутри функции, то при повторном вызове он не пересоздается, а используется уже имещаяся ссылка.d: copy []d: и [] сами по себе являются значениями хранящимеся в блоке (тело функции). При вызове функции [] "положится" в слот на который d "указывает". Получится что d "указывает" (взято в кавчыки потому что это не совсем так) на слот который _сам по себе_ так же указывает на какой-то буфер. Так что когда ты к d аппендишь — ты аппендишь в этот самый буфер.[] точно так же "ложится" в слот на который d "указывает", но поскольку [] по прежнему содержит ссылку на тот же самый буфер, то от этого ничегошеньки не меняется.copy [] идет по ссылке в слоте, копирует буфер в новое место, создает новый слот такого же типа что и [] (т.е. блок) и засовывает в этот слот ссылку на свеже-скопированный буфер. Дальше логика такая же что и в 2 c 3.any и any [thru ].parse "aabbccdd" [any thru "bb"]
aa потом ab потом bb? Судя по тому что пишут в англоязычном чате я не правany — сопоставь следом идущее правило как можно больше раз, 0 раз достаточно.thru — сопоставь всё включительно до следующего правила."bb" столько сколько можешь", но в данном случае "столько сколько можешь = 1", соответсвенно any thru "bb" = thru "bb". Позиция встанет на "bbcd", а сам parse вернет false потому что ты достиг конца правила, но не конца строки.any thru "bb" полезно если у тебя строка с кучей "bb" и тебе надо пропустить все включительно до последнего "bb".parse "aabbccdd" [s: any "cc" | skip ]
s не ставится в другую позицию? Вроде бы мы должны двигатсья до того как cc не встретимs: ставится только один раз в самом начале строки, после чего ты пытаешься сопоставить с any "cc", которое ничего не сопоставляет потому что там "aa", но any пофигу потому что 0 раз достаточно, после чего ты ударяешься о границу правила |, на этом всё. Конец правила достигнут, а конец строки — нет, поэтому false.any "cc" повторяет сопоставление только "cc" впереди себя, игнорируя s:; это два независимых правила.thru тормозитthru идет до нужного символа. skip пропускаетthru прочёсывает **всю** серию, либо пока правило полностью не сопоставится, либо пока он не уткнется в конец. Если правило не совпало и thru достиг конца, то это считается за несовпадение, и Parse пойдет искать альтернативное правило следующее за |. Как я понял, в твоем случае альтернативное правило это skip. Т.е. условно говоря получается что после первого удачного thru ... ты сначала ищешь до конца файла, а потом пропускаешь один символ, и так продолжается пока улиточными пропусками одного символа ты не доползешь до конца.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
--↑ thru "aa" взялось?"aab baaddaabb" ; skip --↑
thrucallback: 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
thru "aa" сопоставил, после него никакого другого правила нету, т.е. ты уткнулся в конец правила, обозначенный |. На этом всё — конец правила достигнут, а конец ввода нет, поэтому ты получаешь false.[thru "aa" | skip].thru "aa"."aa"."bbaaddaabb". Так как thru "aa" сопоставилось, я ищу правило идущее за ним.|, что говорит мне о том что я достиг конца правила.true только если добежал до конца правила и до конца ввода. Но ввод у меня по прежнему на "bbaaddaabb", а правил больше нету.| Parse может перепрыгнуть только если у тебя сопоставления не было, т.е. если thru "aa" не прошел через "aa".any как раз пзволяет выполнить вторую проверку если предыдущая провалиласьany будет повторять данный тобой блок до тех пор пока он сопоставляется. А сопоставление будет всегда, потому что у тебя либо thru "aa" находит "aa", либо не находит и перепрыгивает через | к skip, который безоговорочно пропускает 1 элемент, и так до самого конца.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
]
]"" to end прыгает к концу файла, но как быть если мне нужно только к концу секции котрая парсится прыгнуть, а не end. Если у тебя файлы не коцаные (т.е. везде одинаковый формат и все теги закрыты) и если тебе нужно данные между тегами вытянуть, то твой подход слишком сложный.parse file [
some
[
to "</lot>" pos: "</lot>"
]
to end
]parse?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
end. Зачем спрашивать повторно? Вы думаете, что ответ за выходные изменился?>> 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
s1/748 тебе даст 748-ой элемент справа от s1, которого в твоем случае не существует, т.к. ты выскочил за границу буфера.>> 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
: принципиально отличается от присваивания?: это не оператор связывания или присваивания, а лексическая часть значения (word: или :word). Связывание это bind.a: "abc" ?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"
]: это не оператор связывания или присваивания, а лексическая часть значения (word: или :word). Связывание это bind.bind отличается?bind меняет ссылку (связку) на таблицу.set берет из слова символ, берет ссылку, идет по ссылке, ищет строку по символу и засовывает в "значение" то что ты ему передал.word: идентичен set 'word .d: [not any ["<a>" | "<b>"]]
parse "<f>" [d]
falsenot же инвертиует правилоnot ... воткнуть mark: (probe mark) и посмотреть меняется ли позиция, если совсем непонятно.>> parse "a" [any [not "b"]] == false
any проверет следующее правило которое было инвертировано not. Почему тогда результат false?>> parse "a" ["a"] == true
this и that):[not ['this | 'that] word!]
context? Из значения слова объект сделать?text
>> :context
== func ["Makes a new object from an evaluated spec"
spec [block!]
][
make object! spec
]face! представляет собой графический объект с определенной геометрией ("многогранник"), поэтому такой перевод имеет смысл.do и parse "задают контекст" в том смысле что они имеют разную семантику и интерпретируют данные по разному.[]? Или оператором thru? https://github.com/red/red/wiki/%5BDOC%5D-Parseparse "aabbccdd" [ thru [p: (probe p) "cc" ]]
thru "bb"? view/flags [b: button "Ok" [b/text: "cancel"]] [resize]
flags но как при этом первый блок выполняется? Или какая тут логика применяется?/ же означает путь к блокуunset, которое условно обозначает "это слово не имеет смысла".1 + 1 (а точнее do load "1 + 1") равняется 2 потому что + привязано к операции сложения.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"] ]
x = 123 в C.123. В итоге мы имеем адрес в памяти где записано это значение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.bind и context.>> load "123" ; загрузка из строки == 123 ; вывод на экран >> type? load "123" ; тип данных загруженного слота: == integer! ; целое число
>> type? probe load {"abc"}
"abc"
== string!
>> type? probe load {{def}}
"def"
== string!123 которое ты видишь на экране это набор символов (синтаксис). load берет этот набор символов и создает число 123 которое ты можешь умножить на что-то или прибавить к чему-то, т.д. (семантика).{}- показывает что загружаемые данные имеют строковый тип, верно?load значение-в-кавычках то каким образом тип будет определен? >> type? probe load "{123}"
"123"
== string!{...} это один из форматов строки, я его использовал чтобы кавычки внутри не экранировать.x: "1 + 1": и bind. Ты выше писал, что : это лексическая часть слова (кажется так). Но в чем у них разница. Вроде бы эта лексическая часть как раз за связывание так же как bind и отвечаетcollect устроен, например.x: так же содержит символ, "произношение", в данном случае это x; do берет этот символ и начинает искать его в контексте, ведя пальцем по левой колонкеx: 123 то слово x кладется в контекст do который является контекстом по-умолчанию?("слово":"контекст_слова")? Верно? ("слово":"значение").bind - изменение привязки поменяет просто контекст? Если так то общую суть наконец понялcontext и object, и разницы между ними нет абсолютно никакой.>> :context =? :object == true
x: 1x мы записываем единичку. Верно?>> context? 'x
== make object! [
datatype!: datatype!
unset!: unset!
none!: none!
logic!: logic!
block!: block!
paren...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" > ] >
probe context? 'x.system/words.bind?collect устроен, наглядный и практичный пример.source collect.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
library/foo library/bar ... ты можешь написать do bind [foo bar ...] library. Можно эту идею расширить и сделать некое подобие RPC — серваку прилетает блок данных, он его привязывает к своему локальному контексту (или даже к нескольким контекстами) и выполняет заданную функцию; Rebol/Services вроде бы так работали.pi присвоили "pie"bind will modify the block it is given" получается что связка слова a должна быть измененаbind ... context? 'a.words: [a b c]
fun: func [a b c][print bind words 'a]
fun 1 2 3
fun "hi" "there" "fred"words получит при первом вызове 1 2 3text >> 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
>> 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
bind не "модифицирует" блок, он привязывает все слова найденные в данном тобою контексте к этому контексту, и эта привязка остается перманентной потому что слова из блока никуда не исчезают.words: [a b c] fun: func [a b c][print bind words 'a]
words первый переданный в функцию аргумент. А что с другими двумя?words станет получается оригинальнымbind не "модифицирует" блок, он привязывает все слова найденные в данном тобою контексте к этому контексту, и эта привязка остается перманентной потому что слова из блока никуда не исчезают.'a это не первый аргумент, а все переданные в функцию слова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]
bind проходит по блоку и для каждого значения any-word! спрашивает находится ли оно в данном контексте. Если да, то это слово привязывается к контексту, иначе пропускается.bind ... 'a это сокращение от bind ... context? 'a.words есть свой глобальный контекст. Он то у нас не поменяется если сделать просто: fun: func[a b c] [print bind words 'a]bind words 'b и bind words 'cprint words и context? words/1 после всех своих манипуляций, тогда поймешь что значит "перманентная".a внутри него и a внутри функции это два разных значения. И, повторяю уже четвертый раз, bind words 'a это bind words context? 'a. Если ты и этого не понимаешь, то сделай probe context? 'a и probe context? 'b, затем сравни разницу.context? 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 а не любое другое слово>> 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
bind [a b c] :fun т.е. не создавая слово (word:[a b c]), а передавая блок со словами, то как нам потом до этих слов дотянуться? Ведь как понимаю они просто в стеке разместятся?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
>> 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
>> 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...
>>>> f: func[a] [] == func [a][] >> >> w: [a b c] == [a b c] >> >> bind w :f == [a b c] >> context? w/1 == func [a][]
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]
forall сделать. В данном примере связывание не происходит:ww: [a a a a] foreach w ww [bind w context [a: take [ "My" "name" "is" "Dima" ] ] ]
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
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
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
x: 666context [x: 123]y: context [x: 123]x ссылался на контекст связанные с y.bind x 'ybind x context [x: 123]x стало бы привязано к значению 123. В чем я косячу?bind does not allow integer! for its word argument. Но я не пойму в чем причина. Я же слову меняю привязку>> >> x: 666 == 666 >> bind x context [x: 123] *** Script Error: bind does not allow integer! for its word argument *** Where: bind *** Stack: >>
x тебе дает значение на которое оно указывает, 666.bind 'x context [x: 123]
>> context? 'x
== make object! [
datatype!: datatype!
unset!: unset!
none!: none!
logic!: logic!
block!: blo...
>>system/words у которого не установлено значение. Верно?bind 'x context [x: 123]
system/words c написанием x связываю со значением из другого контекстаtext
вот это вот
↓
bind 'x context [x: 123]
context? 'x ↑
↑ и даже вот это вот
и вот это вот
ЭТО РАЗНЫЕ СЛОВА С ОДИНАКОВЫМ НАПИСАНИЕМbind 'x context? 'x
x которое находится в контексте system/words>> x: 666 == 666
bind 'x context [x: 123]
x контекст слова x указывает на значение из блока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
bind 'x ... _все последующие x_ будут магическим образом привязаны к ....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]
bind — достигнут ли его другие Дмитрии? Очевидно что нет (если только мы не имеем дело с разумом роя).x. Если одно из слов привязывается с помощью bind к какому-то контексту — привяжуются ли к нему другие слова с написанием x? Ответ уже известен.x: и дальше уже идет контекст func[] [...] object это объект, что-то что будет манипулировано, context это скорее окружение внутри которого будут проводить манипуляции.map! или block! например) в них сконвертировать, если хочешь.map! или block! например) в них сконвертировать, если хочешь[a 1 b 2 c 3]?>> 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
]t: text-list data []
text-list автоматом при создании повесится блок [ ] но оказалось, что этого не происходит и надо явно все писать. t c [ ]?result: parse f-data/text ["aa" ]mold тоже не работает. обращение к /data вместо /text тоже ничего не дает:result: parse f-data/text [form f-rule/text ]/textразве не так?>> field: [text "blah blah"] == [text "blah blah"]
[field/text] и помедитируй на результат.type? first [field/text] и посмотри есть ли такой тип данных в [списке](https://doc.red-lang.org/en/parse.html#_parse_rules) тех что Parse поддерживает.>> parse [][foo/bar] *** Script Error: PARSE - invalid rule or usage of rule: foo/bar *** Where: parse *** Stack:
[ f-rule/text ] распознается как блок, а не как содержимое правило внутри блока? result: parse f-data/text [ mold f-rule/text ][mold f-rule/text]. Что теперь по твоему будет внутри этого блока, и как Parse это проинтерпретирует?f-rule/text и найдет строку (он мог бы на самом деле, только это пока не поддерживается), то ли ты ожидаешь что [mold f-rule/text] магическим образом обернется в строку как если бы его интерпретатор вычислил (но тогда зачем тебе mold если f-rule/text и так указывает на строку?).[mold f-rule/text]. Что теперь по твоему будет внутри этого блока, и как Parse это проинтерпретирует?>> reduce [mold f-rule/text]
== [{"a"}]SQLite/do [
exec {INSERT INTO "Cars" VALUES(3,'Skoda',9000);}
]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]Sqlite/do на вход принимает диалект с определенным синтаксисом.compose попробуй.? compose.compose это часть диалекта red\system? compose посмотрел. Он выражение в скобках оценивает. Но у меня вроде бы другой случай...compose это часть Red, но написан он на Red/System. Один диалект может использовать другие диалекты в своей реализации, VID например иногда использует Parse.compose [... (rejoin [...])].SQLite/query rejoin ....compose не заработалexec compose [ (rejoin [{INSERT INTO "Cars" VALUES(11,'} f-data/text {', 262666);}])]math посмотреть, я не так давно его альтернативную версию [написал](https://github.com/red/red/pull/4332#issuecomment-600152125). Более просто пример это спецификации функций. Или тот же collect, я правда не уверен в том что его можно диалектом назвать.compose не туда засунул.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? sqlite/query."INSERT INTO ..."), ты ему даешь блок.SQLite/do compose [
exec (rejoin [{INSERT INTO "Cars" VALUES(random(),'} reduce f-data/text {', 262666);}])
]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 2extract/index x 4 3.extract x 2 вытащит же выбирает каждый второй элемент, но результат работы не совпадает с ожидаемымmake-db-query в которой и просхходит заполнение виджета cells (его в примере на gist нет).func и function например, [форматирование кода](https://doc.red-lang.org/en/style-guide.html).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
generate-sql-button: buttonface я могу только для текущего элемента т.е. чтобы из кнопки достучаться до 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 то потом где-то что-то могу перепизаписать.lit-word объяснить, я думал, что это просто символьное представление слова без его оценки, но тут мне стали объяснять обратное: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>"]
]
]copy _ to "" может знать о том что впереди у тебя идетnot [ahead ws ""]? Никак. Вот оно и матчит 3, ещё до того как ты успеваешь проверить что за ней идет.not [ahead ws ""] должно работать как предикат?parse a [ any [ not [ahead ws "</apps>"] thru "<app>" copy _ to "</" (print _) ] ]
not [ahead ws ""] проверяет не равна ли следующая строка "</apps>"? Верно же? Если равна, то правило не идет дальше и возвращается falsetext >> parse trim/all a [any [<app> copy match to </app> [</app> </apps>] (print match) | skip]] 3 == true
>> 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]
идет после , а не до .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 _) ] ]
/parse я тебе два варианта решения задачи уже показал, в зависимости от формулировки.break, failи reject работают, на работают абы как и местами вообще забагованные. И тебе они в этой задаче в принципе не нужны.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
]
]ahead thru "" ws not ""ahead [thru "</app>" ws not "</apps>"] | skip
"<app>" ahead [thru "</app>" ws not "</apps>"] copy _ to "</app>" (print _) | skip
reject и [reject] и я не совсем понимаю это бага или фичаreject засунешь тот он и зафейлит.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
]3junk: ["<" copy name to #">" thru ["" name ">"]] ?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 выставили. Если не найдено. Сбрасываем оба флага и идем дальше. Пометили элемент очереди как найденный. Но тогда строковое описание должно быть преобразовано в объект получается.a сконвертировать в что-то вроде [apps [app 1 app 2 price 15 app 3] app 4 info [price 17 code RUB]].data/info/price.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
to binary!?>> 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:
to условно говоря запись вида: to "<" "foo" можно прочитать как дойти до "<" или же что foo является тоже аргументом и нужно дойти до "<foo">> parse "aab" [2 3 thru "a"] == true
2 3 косячит.[1 + 2 * 3], которое само по себе смысла не имеет. AST к этому добавит что "вот здесь инфиксное выражение с арифметическими операциями над целыми числами и * имеет приоритет над +" и придаст этому некий смысл, необходимый для компиляции/интерпретации.open: ["<" copy opening to ">" if (find tags opening) ">"]if (find tags opening). Оно нужно, чтобы передвинуться к закрывающему тегу: ">"?