hofstadter-io / cuetorials.com

Learn you some CUE for a great good!
https://cuetorials.com
BSD 3-Clause "New" or "Revised" License
116 stars 34 forks source link

AnyOf Pattern doesn't work when fields are optional and array #72

Open kak-bo-che opened 1 year ago

kak-bo-che commented 1 year ago
import "list"

#test: this={
    a?:        [...string]
    b?:        string
    c?:        string
    #AnyOfABC: true & list.MinItems([ for label, val in this if list.Contains(["a", "b", "c"], label) {label}], 1)
}
{
    "a": ["bar"],
    "b": "foo"
}
cue eval -c ./test.cue ./testany.json -d "#test"
#test.#AnyOfABC: conflicting values false and true:
    ./test.cue:7:13
    ./test.cue:7:20

changing from array a to string works or changing the array field from optional to default works as well. This is slightly outside of the content of the page, bug a simple derivative.

verdverm commented 1 year ago

yeah, I never tested that. There are better solutions on the horizon in https://cuetorials.com/cueology/futurology/builtin-helpers/

kak-bo-che commented 1 year ago

Changing the list to non-optional only works because the empty list will have a label and the constraint will pass as the label is always available. The underlying issue seems to be that the simplified example as given in the tutorial doesn't seem to work when providing data to validate instead of embedding it in the definition:

test.cue

import "list"

#test: this={
    a?:        string
    b?:        string
    c?:        string
    #AnyOfABC: true & list.MinItems([ for label, _ in this if list.Contains(["a", "b", "c"], label) {label}], 1)
}

test.json

{
    "b": "foo"
}
cue eval -c ./test.cue ./testany.json -d "#test"
#test.#AnyOfABC: conflicting values false and true:
    ./test.cue:7:13
    ./test.cue:7:20
verdverm commented 1 year ago

I think this is because this in the definition is local to the definition, thus the data is not part of it. In other words, there is only one this, not per data value to which it is applied. Also note, that the way cue handles json/yaml is slightly different from how it handles CUE values.

So I suspect there are some scoping complexities at play here.

The optional list works with the example from the page: https://cuelang.org/play/?id=yDm35mVv9iR#cue@export@cue