cuelang / cue

CUE has moved to https://github.com/cue-lang/cue
https://cuelang.org
Apache License 2.0
3.09k stars 172 forks source link

cue errors out on solvable cycles #622

Closed Ereski closed 3 years ago

Ereski commented 3 years ago

What version of CUE are you using (cue version)?

$ cue version
cue version devel linux/amd64

I am not sure how to get the actual version, but I installed cue today with:

go get -u cuelang.org/go/cmd/cue

Master is at cefe38b12bc4df48f5bc100d0a45fc9ec563e36d

What did you do?

Running cue export on:

a0: X
a1: a0 * 2
Y: a1

b0: Y
b1: b0 / 2
X: b1

X: 5.0

What did you expect to see?

{
    "a0": 5.0,
    "a1": 10.0,
    "Y": 10.0,
    "b0": 10.0,
    "b1": 5.0,
    "X": 5.0
}

What did you see instead?

cycle error:
    ./example.cue:2:5

Comments

If I replace a0: X with a0: 5.0 (the value of X) I get the expected result.

mpvl commented 3 years ago

This cycle may be mathematically solvable, but it is illegal CUE. CUE does not allow self-references other than the value directly. That is, it is illegal to have a cycle as an operand to an expression (like b0 / 2).

In general, CUE does not do any mathematical resolution, even if it is very simple. This is outside the scope of CUE. It could be solved with tooling build on top of CUE, but is it not something that should be part of the main evaluator, as it will have all kinds of undesirable consequences.

Ereski commented 3 years ago

Then the issue is with cue's docs. Opened a new issue: #624

mpvl commented 3 years ago

Ah, yes indeed. I stand corrected. There is an illegal cycle, but the 5.0 in

X: b1
X: 5.0 // this breaks the cycle and should allow CUE to resolve it.

should break it.

Ereski commented 3 years ago

So I think I found a way to make this work. First I made all a* and b* fields definitions since they are just intermediary values:

#a0: X
#a1: #a0 * 2
Y: #a1

#b0: Y
#b1: #b0 / 2
X: #b1

X: 5.0

This still errors out, but inlining #a0 and #b0:

#a1: X * 2
Y: #a1

#b1: Y / 2
X: #b1

X: 5.0

and cue now computes Y correctly:

$ cue export example.cue 
{
    "Y": 10.0,
    "X": 5.0
}

I can even add more intermediary steps:

#a0: X + 1
#a1: #a0 * 2
Y: #a1

#b0: Y / 2
#b1: #b0 - 1
X: #b1

Y: 5.0
$ cue export example.cue 
{
    "Y": 5.0,
    "X": 1.5
}

So there's definitely something funky going on, but at least I can now make it work the way I wanted to.

mpvl commented 3 years ago

Either way, your original example should work as well. We're working on some refactoring that makes fixing this easy(-ish) as well as improve performance (or at least prepare for improving performance).

cueckoo commented 3 years ago

This issue has been migrated to https://github.com/cue-lang/cue/issues/622.

For more details about CUE's migration to a new home, please see https://github.com/cue-lang/cue/issues/1078.