You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I was wondering about this phenomenon with CUE conjunctions related to an embedded label referring to a field defined at the same level. If the value of this field is a struct embedding a subfield with containing the same label, the reference must be resolved multiple times.
Note that it seems to have consistent behaviors whether we use embedding, the & operator and/or using a selection path . on an ancestor for the reference.
Here is a minimal example :
x
x: x: a: 1
resulting in
x: {
x: a: 1
a: 1
}
a: 1
ie the reference x is resolved twice. During evaluation:
the subfield x: a: 1 is first copied and unified with the top-level x: x: a: 1, adding a: 1 to x:,
then x is resolved again adding a: 1 at the root level.
This makes sense to me since references within conjunctions are related to a form continuation, so all step of evaluation must be consistent with each other. A better argument is that: If this weren't the case, iex would be copied only once, then unifying the input with the output would give a different output.
In theory, I could imagine some patterns where one would like to embed a substructure within the structure itself. But I cannot wrap my head on some real-life example. Even without the recursion on x embedded multiple times. If someone have already encountered this, I would be happy to know.
In any case, this brings great complexity I believe. For example, trying to reproduce the example with lists, given that lists are represented as structs with integer keys. E.g. [ [ { a: 7 }, ], ] would be represented as { 1: 1: a: 7 }, the example above would be
For which eval doesn't resolve r[0], but export fails, which is good. It reports
r: cannot add field 0: was already used:
./tmp.cue:2:7
Now when inlining by hand the reference
root: {
[ [ {a:1} ] ]
[ {a:1} ]
}
we see the error reported from somewhere else in the evaluator:
s.0: conflicting values [{a:1}] and {a:1} (mismatched types list and struct):
./tmp.cue:7:5
./tmp.cue:8:3
./tmp.cue:8:5
I played a little bit with self-referential structures a few months back, the evaluator seems to do a good job (with exceptions I think #2526 and #2536). It seems to me this pattern can be somewhat thought of as "negative cycles". The result of this is that the definition of what is a value in CUE is a fix point. Indeed "references are generative". But since the concept of a value is important regarding operational semantics, the formalization with standard formalizations such as big step or small step seems compromised.
I wonder if there was any thoughts on this during the design choice about preventing structural cycles (referring to ancestor nodes, e.g. x: y: x), or during implementation, and if there was concrete use cases in mind.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I was wondering about this phenomenon with CUE conjunctions related to an embedded label referring to a field defined at the same level. If the value of this field is a struct embedding a subfield with containing the same label, the reference must be resolved multiple times.
Note that it seems to have consistent behaviors whether we use embedding, the
&
operator and/or using a selection path.
on an ancestor for the reference.Here is a minimal example :
resulting in
ie the reference
x
is resolved twice. During evaluation:x: a: 1
is first copied and unified with the top-levelx: x: a: 1
, addinga: 1
tox:
,x
is resolved again addinga: 1
at the root level.This makes sense to me since references within conjunctions are related to a form continuation, so all step of evaluation must be consistent with each other. A better argument is that: If this weren't the case, ie
x
would be copied only once, then unifying the input with the output would give a different output.In theory, I could imagine some patterns where one would like to embed a substructure within the structure itself. But I cannot wrap my head on some real-life example. Even without the recursion on
x
embedded multiple times. If someone have already encountered this, I would be happy to know.In any case, this brings great complexity I believe. For example, trying to reproduce the example with lists, given that lists are represented as structs with integer keys. E.g.
[ [ { a: 7 }, ], ]
would be represented as{ 1: 1: a: 7 }
, the example above would beFor which
eval
doesn't resolver[0]
, but export fails, which is good. It reportsNow when inlining by hand the reference
we see the error reported from somewhere else in the evaluator:
I played a little bit with self-referential structures a few months back, the evaluator seems to do a good job (with exceptions I think #2526 and #2536). It seems to me this pattern can be somewhat thought of as "negative cycles". The result of this is that the definition of what is a value in CUE is a fix point. Indeed "references are generative". But since the concept of a value is important regarding operational semantics, the formalization with standard formalizations such as big step or small step seems compromised.
I wonder if there was any thoughts on this during the design choice about preventing structural cycles (referring to ancestor nodes, e.g.
x: y: x
), or during implementation, and if there was concrete use cases in mind.Cheers
@4ad @rogpeppe @mpvl
/edit1: typos & precisions
Beta Was this translation helpful? Give feedback.
All reactions