Reputation: 1513
Given a sublist is there a way to get a reference to it's parent/enclosing list/block? For example:
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
Thanks for any help!
Upvotes: 0
Views: 91
Reputation: 3199
There is no "parent" reference for a block! series, as it can be referenced from multiple other block! series, so the concept of "parent" is meaningless in such cases.
However, you can manually add a back-reference in your block when you need it (just watch out when PROBE-ing or MOLD-ing the "child" block then, it will result in dereferencing pointed blocks leading to a much more verbose result than you want).
Tip: I sometimes do add back-references for block values using an "hidden" header (just moving the block offset passed the values you want to hide). It's PROBE-resistant and handy, but can't be serialized (e.g. on disk) without having to write your own specific serialization routine to handle those back-references appropriately (means usually replacing them with a non-series value: integer, word, issue, tag...whatever allows you to rebuild that link once loaded back).
For example:
>> 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]
Please note that /-1 shortcut is currently not working in R3 as in R2.
So, for your own code example above, you need to make a function that will dive into your initial block structure and insert those hidden back-references, so you can access them easily when needed. Here is an example code for processing your structure:
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
This will output:
fs: [
usr [
local [
bin []
]
share []
]
bin []
]
l: [
bin []
]
p: [
local [
bin []
]
share []
]
p: [[
local [
bin []
]
share []
]
bin []
]
Actually, we have created a graph structure using nested block references that can be navigated very simply using built-in series actions and paths.
Upvotes: 4