Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

explanation: on embedding, root/package values, closedness, multiple declarations, etc #64

Open
myitcv opened this issue Feb 23, 2024 · 0 comments
Labels
concept guide For content that in the "explanation" diataxis quadrant content idea Idea for a new piece of content

Comments

@myitcv
Copy link
Member

myitcv commented Feb 23, 2024

(the title is terrible which tells me this idea needs a bit of finessing).

On Slack we had a really good exchange regarding embedding, root/package values, closedness, multiple declarations, etc. This issue captures a concept guide (most likely) that covers some of these points.

Slack thread
Erik Mogensen
  [5 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708684891394629)
I have a question as to how definitions are different when applied to the root, [rather than being applied to a specific label](https://cuelang.org/play/?id=FtB75SB8CRQ#cue@export@cue)
#API: api: [_]: value: int
api: #API.api
api: example: othervalue: _
Here, othervalue is not legal, because api is constrained.
#API: api: [_]: value: int
#API
api: example: othervalue: _
This is "logically" the same, #API 's api label is added to the root but it [does not constrain it](https://cuelang.org/play/?id=fKQastuo9-n#cue@export@cue). The output is:
api: {
        example: {
                othervalue: _
                value:      int
        }
}
What is the difference between these two?
48 replies
Erik Mogensen
  [5 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708685257535229?thread_ts=1708684891.394629&cid=C012UU8B72M)
I have a hunch that it has something to do with the invisible root scope, which is a struct...
Jonathan Matthews
  [5 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708685542723579?thread_ts=1708684891.394629&cid=C012UU8B72M)
I believe it's because you're "embedding" #API in the root struct, and embedding negates relaxes the closeness of the embedded value: https://alpha.cuelang.org/docs/reference/spec/#embedding (edited) 
Jonathan Matthews
  [5 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708685698897319?thread_ts=1708684891.394629&cid=C012UU8B72M)
Your underlying problem is to do with it being at the root, which you can't close via unification with a definition, as you can't /refer/ to the root in the same way as in your first example.
Jonathan Matthews
  [5 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708685753736819?thread_ts=1708684891.394629&cid=C012UU8B72M)
But if you embedded #API in the same way inside any other, non-root, struct, I believe you'd see the same behaviour.
Erik Mogensen
  [5 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708686473939829?thread_ts=1708684891.394629&cid=C012UU8B72M)
Thanks, this was my hunch.  We've misused the root scope too much in our early endeavours, importing stuff left, right and centre to the root.
myitcv
  [4 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708689087060689?thread_ts=1708684891.394629&cid=C012UU8B72M)
[@Erik Mogensen](https://cuelang.slack.com/team/U06DA87KVNY)
 I wouldn't say you've misused anything here :slightly_smiling_face:
myitcv
  [4 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708689126668169?thread_ts=1708684891.394629&cid=C012UU8B72M)
[@Jonathan Matthews](https://cuelang.slack.com/team/U03E1LP31AA)
 is right to say that embedding #API relaxes the closedness constraint
myitcv
  [4 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708689171929499?thread_ts=1708684891.394629&cid=C012UU8B72M)
For example
myitcv
  [4 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708689172495659?thread_ts=1708684891.394629&cid=C012UU8B72M)
https://alpha.cuelang.org/play/?id=Hr-29on_xoU#w=function&i=cue&f=eval&o=cue
myitcv
  [4 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708689180512399?thread_ts=1708684891.394629&cid=C012UU8B72M)
#Person: {
    name?: string
}

#Person
name: "paul"
age: 99
myitcv
  [4 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708689193323709?thread_ts=1708684891.394629&cid=C012UU8B72M)
It would seem intuitive that the "root" value is constrained by #Person.
myitcv
  [4 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708689223866169?thread_ts=1708684891.394629&cid=C012UU8B72M)
It is, but the usual constraint with definitions of not allowing additional fields does work/apply here because the embedding of the definition relaxes that closedness constraint
myitcv
  [4 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708689243645919?thread_ts=1708684891.394629&cid=C012UU8B72M)
So what to do in the case of constraint the root value to not have additional fields?
myitcv
  [4 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708689265295739?thread_ts=1708684891.394629&cid=C012UU8B72M)
This is where in https://github.com/cue-lang/cue/issues/943 we envisage something like must()
myitcv
  [4 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708689284355099?thread_ts=1708684891.394629&cid=C012UU8B72M)
So my example would become:
myitcv
  [4 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708689289997619?thread_ts=1708684891.394629&cid=C012UU8B72M)
#Person: {
    name?: string
}

must(#Person)
name: "paul"
age: 99  // error: cannot define age here
(edited)
myitcv
  [4 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708689354442859?thread_ts=1708684891.394629&cid=C012UU8B72M)
We also have other ideas for how to make this more usable by configuring/otherwise that package values must satisfy certain schemas (without needing to embed must() as above)
eonpatapon
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708693768678949?thread_ts=1708684891.394629&cid=C012UU8B72M)
Not sure to understand why the root value is relaxed in this case
eonpatapon
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708693780990689?thread_ts=1708684891.394629&cid=C012UU8B72M)
If i do it in a field, it's not relaxed: https://alpha.cuelang.org/play/?id=a-zFsYdl1UL#w=function&i=cue&f=eval&o=cue
Jonathan Matthews
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708693948906369?thread_ts=1708684891.394629&cid=C012UU8B72M)
That's a nuance (that I can't put precise words around) related to the fact that you have 2 separate definitions of what's inside c. If you merge them, the behaviour is as the root struct behaviour earlier in this thread: https://alpha.cuelang.org/play/?id=yV-Q1vWkAeg#w=function&i=cue&f=eval&o=cue
eonpatapon
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694078398569?thread_ts=1708684891.394629&cid=C012UU8B72M)
Oh right I think I got it
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694443162419?thread_ts=1708684891.394629&cid=C012UU8B72M)
I should have been more careful with my words above: closedness is relaxed to allow the embedding
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694445525329?thread_ts=1708684891.394629&cid=C012UU8B72M)
https://alpha.cuelang.org/docs/reference/spec/#embedding
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694453068229?thread_ts=1708684891.394629&cid=C012UU8B72M)
A struct may contain an embedded value, an operand used as a declaration. An embedded value of type struct is unified with the struct in which it is embedded, but disregarding the restrictions imposed by closed structs. So if an embedding resolves to a closed struct, the corresponding enclosing struct will also be closed, but may have fields that are not allowed if normal rules for closed structs were observed.
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694459867639?thread_ts=1708684891.394629&cid=C012UU8B72M)
The wording here is very tricky :slightly_smiling_face:
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694539495509?thread_ts=1708684891.394629&cid=C012UU8B72M)
Perhaps best demonstrated by https://alpha.cuelang.org/play/?id=cQUOq8AzscS#w=function&i=cue&f=eval&o=cue
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694558689739?thread_ts=1708684891.394629&cid=C012UU8B72M)
So the embedding of the definition at the root does result in the root value being closed if anything were to refer to it
eonpatapon
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694559806249?thread_ts=1708684891.394629&cid=C012UU8B72M)
This root embedding bit me several times... but it makes more sense now why its not closed
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694597855809?thread_ts=1708684891.394629&cid=C012UU8B72M)
The root value can be referenced, for example when an imported package value is used
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694634342969?thread_ts=1708684891.394629&cid=C012UU8B72M)
(although noting that in that case we have had thoughts about automatically closing an imported package value because it seems "most logical")
Jonathan Matthews
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694661575179?thread_ts=1708684891.394629&cid=C012UU8B72M)
[@myitcv](https://cuelang.slack.com/team/UNVGZ9A2K)
 
[@eonpatapon](https://cuelang.slack.com/team/UT0MNFL1X)
's example seems /5%/ different from this (https://alpha.cuelang.org/play/?id=AN8ZiEkJLBD#w=function&i=cue&f=eval&o=cue), where a Definition is open at the time of definition, but closed at the time of reference.
I don't 100% grok why https://cuelang.slack.com/archives/C012UU8B72M/p1708693780990689?thread_ts=1708684891.394629&cid=C012UU8B72M doesn't allow c to be added to, given that it's being added to the same way that #A is added to in my example. (edited) 




eonpatapon
If i do it in a field, it's not relaxed: https://alpha.cuelang.org/play/?id=a-zFsYdl1UL#w=function&i=cue&f=eval&o=cue
[From a thread in help](https://cuelang.slack.com/archives/C012UU8B72M/p1708693780990689?thread_ts=1708684891.394629&cid=C012UU8B72M) | [Today at 13:09](https://cuelang.slack.com/archives/C012UU8B72M/p1708693780990689?thread_ts=1708684891.394629&cid=C012UU8B72M) | [View reply](https://cuelang.slack.com/archives/C012UU8B72M/p1708693780990689?thread_ts=1708684891.394629&cid=C012UU8B72M)
eonpatapon
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694666422959?thread_ts=1708684891.394629&cid=C012UU8B72M)
When you want to use cue vet main.cue some.yaml , my intuition was to embed a definition at the root an call it day. But that doesn't work. So I need to do: cue vet -d '#MyDef' main.cue some.yaml (edited) 
:+1:
1

myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694875327199?thread_ts=1708684891.394629&cid=C012UU8B72M)
[@eonpatapon](https://cuelang.slack.com/team/UT0MNFL1X)
 that's precisely the "workaround" required for now
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708694893649779?thread_ts=1708684891.394629&cid=C012UU8B72M)
Noting that must() (at least as we hold it in our head currently) would obviate the need for that.
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695145577609?thread_ts=1708684891.394629&cid=C012UU8B72M)
Inlining the code to make referring to it easier
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695149537469?thread_ts=1708684891.394629&cid=C012UU8B72M)
#A: {
   a: int
}

c: {
    #A
}

c: b: "foo" // error
 (edited) 
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695180399129?thread_ts=1708684891.394629&cid=C012UU8B72M)
This is an interesting example, and one that I think we "solve" by better documentation
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695189424379?thread_ts=1708684891.394629&cid=C012UU8B72M)
Because it's akin to writing
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695232036939?thread_ts=1708684891.394629&cid=C012UU8B72M)
#A: {
   a: int
}

c: { 
    #A 
} & {
    b: "foo"
}
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695267309789?thread_ts=1708684891.394629&cid=C012UU8B72M)
Given that { A } is A for any A (including definitions) then this can equivalently be rewritten as:
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695283493039?thread_ts=1708684891.394629&cid=C012UU8B72M)
#A: {
   a: int
}

c: #A & {
    b: "foo"
}
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695289076219?thread_ts=1708684891.394629&cid=C012UU8B72M)
Which makes the error more "obvious"
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695303776279?thread_ts=1708684891.394629&cid=C012UU8B72M)
Noting that:
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695315293029?thread_ts=1708684891.394629&cid=C012UU8B72M)
#A: {
   a: int
}

c: {
    #A
    b: "foo"
}
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695316539769?thread_ts=1708684891.394629&cid=C012UU8B72M)
is fine
myitcv
  [3 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695346914519?thread_ts=1708684891.394629&cid=C012UU8B72M)
[@Jonathan Matthews](https://cuelang.slack.com/team/U03E1LP31AA)
 - quite possibly the topic of a good concept guide?
New
Jonathan Matthews
  [2 hours ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708695395392419?thread_ts=1708684891.394629&cid=C012UU8B72M)
100%. But I definitely need to do a bit of spec reading to grok the above nuanced differences better!
Erik Mogensen
  [19 minutes ago](https://cuelang.slack.com/archives/C012UU8B72M/p1708703245082179?thread_ts=1708684891.394629&cid=C012UU8B72M)
Thanks for this interesting thread, everyone! :sparkles:
@myitcv myitcv added content idea Idea for a new piece of content concept guide For content that in the "explanation" diataxis quadrant labels Feb 23, 2024
@cue-lang cue-lang deleted a comment from jpluscplusm Feb 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
concept guide For content that in the "explanation" diataxis quadrant content idea Idea for a new piece of content
Projects
Status: Backlog
Development

No branches or pull requests

1 participant