Получение ссылки на включающий список / блок в Rebol

Учитывая подсписок, есть ли способ получить ссылку на его родительский / включающий список / блок? Например:

fs: [
 usr [
  local [
   bin []
  ]
  share []
 ]
 bin []
]

l: fs/usr/local ;grab a sublist
p: none ;now grab l's parent (which is fs/usr) without hardcoding the path

Спасибо за любую помощь!


person rebnoob    schedule 12.03.2013    source источник


Ответы (1)


Для блока нет "родительской" ссылки! series, поскольку на нее можно ссылаться из нескольких других блоков! серии, поэтому понятие «родитель» в таких случаях не имеет смысла.

Тем не менее, вы можете вручную добавить обратную ссылку в свой блок, когда вам это нужно (просто обратите внимание, когда ПРОБИРОВАНИЕ или ФОРМОВАНИЕ «дочернего» блока приведет к разыменованию указанных блоков, что приведет к гораздо более подробному результату. чем хочешь).

Совет: я иногда добавляю обратные ссылки для значений блоков, используя «скрытый» заголовок (просто перемещая смещение блока, передаются значения, которые вы хотите скрыть). Он устойчив к ПРОБЕ и удобен, но не может быть сериализован (например, на диске) без необходимости написания вашей собственной специальной процедуры сериализации для надлежащей обработки этих обратных ссылок (обычно означает замену их несерийным значением: целым числом, словом, проблема, тег ... все, что позволяет вам восстановить эту ссылку после загрузки обратно).

Например:

>> x: [1 2 3]
== [1 2 3]
>> y: [a b c]
== [a b c]
>> insert/only x y            ; insert a reference to y in x
== [1 2 3]
>> x
== [[a b c] 1 2 3]            ; y reference is at first position
>> x: next x                  ; let's hide it now
== [1 2 3]
>> x
== [1 2 3]
>> x/-1                       ; here is how to retrieve our "hidden" header
== [a b c]

Обратите внимание, что ярлык / -1 в настоящее время не работает в R3, как в R2.

Итак, для вашего собственного примера кода, приведенного выше, вам нужно создать функцию, которая будет погружаться в вашу исходную структуру блока и вставлять эти скрытые обратные ссылки, чтобы вы могли легко получить к ним доступ при необходимости. Вот пример кода для обработки вашей структуры:

insert-back-ref: func [blk [block!] parent [block! none!]][
    if parent [                     ;-- no processing if root call
        insert/only blk next head parent ;-- insert the back-reference in child
        parent/1: blk: next blk     ;-- reset the parent reference to child to
    ]                               ;-- point after the back-ref (and hide it)
    forall blk [
        if block? blk/1 [              ;-- if a child block is found
            insert-back-ref blk/1 blk  ;-- process its content recursively              
        ]
    ]
]

insert-back-ref fs none            ;-- pass none as root parent

?? fs
l: fs/usr/local
?? l
p: l/-1
?? p
p: p/-1
?? p

Это выведет:

fs: [
    usr [
        local [
            bin []
        ]
        share []
    ]
    bin []
]
l: [
    bin []
]
p: [
    local [
        bin []
    ]
    share []
]
p: [[
        local [
            bin []
        ]
        share []
    ]
    bin []
]

Фактически, мы создали структуру графа с использованием вложенных ссылок на блоки, по которым можно очень просто перемещаться, используя встроенные последовательные действия и пути.

person DocKimbel    schedule 12.03.2013
comment
Я прочитал ваше первое редактирование и начал кодировать, но должен признать, что ваш код намного круче моего! Большое спасибо за объяснение и код Док! - person rebnoob; 13.03.2013
comment
Рад, что смог помочь. :) Когда вы привыкнете к ссылкам на серии и смещениям серий, вы сможете быстро придумывать такой добрый код самостоятельно, просто продолжайте практиковаться. - person DocKimbel; 13.03.2013
comment
Я, конечно, собираюсь! Спасибо еще раз! - person rebnoob; 14.03.2013