cue icon indicating copy to clipboard operation
cue copied to clipboard

Evaluate(opts ...Option), similar to Validate and Syntax

Open verdverm opened this issue 4 years ago • 7 comments

Is your feature request related to a problem? Please describe.

I'd like to be able to process a Value with Options like Validate & Syntax, but get a Value back.

Describe the solution you'd like

Value.Evaluate(opts ...Option) Value which has the same interface as Validate & Syntax

Describe alternatives you've considered

  • Using Syntax and then processing that with cue.Context.BuildExpr.
  • Custom walk with Fields(opts), this seems like what Evaluate would be close too

verdverm avatar Oct 25 '21 23:10 verdverm

It is always good to have a concrete example to which one can ground such requests.

mpvl avatar Oct 26 '21 11:10 mpvl

Something like the last set of bullet points in the questions here: https://github.com/cue-lang/cue/discussions/1329

But that I may want to progressively fill and resolve references for a subset of the fields. This could be useful in something like Dagger or where a CUE Value is used by a program that interacts with the outside world.

Maybe having something like the UnifyAccept second parameter that acts like a mask for which fields to consider? (If I am understanding that param correctly)

verdverm avatar Oct 26 '21 21:10 verdverm

Arriving here via https://github.com/cue-lang/cue/discussions/1329#discussioncomment-1556815, per @mpvl in https://github.com/cue-lang/cue/issues/1327#issuecomment-951831172 I think we need a more comprehensive use case to help drive the design here. Pseudo code in particular helps to visualise the solution.

myitcv avatar Oct 29 '21 05:10 myitcv

I'll work on some examples, I'm assuming there is no rush on this.

I'd argue that users may find intriguing use cases if such a function did exist.

... and currently there isn't a Value function which can return a new Value after running the evaluator with a given set of Option. We have Syntax() ast.Node and Validate() err, so Evaluate() Value would fit nicely. I think one could ctx.BuildExpr(val.Syntax(myOpts...)) today to get the effect of a Value.Evaluate(myOpts...)?

verdverm avatar Oct 29 '21 16:10 verdverm

I'm assuming there is no rush on this.

Correct.

myitcv avatar Oct 29 '21 16:10 myitcv

@myitcv we should probably consolidate the Evaluate(...Option) discussion here (so it doesn't keep spilling over into #1326 )

package main

import (
	"fmt"

	"cuelang.org/go/cue"
	"cuelang.org/go/cue/cuecontext"
)

const input = `
a: {
	i: int
	j: int | *i
}
`

func main() {
	c := cuecontext.New()
	val := c.CompileString(input)

	fmt.Println("\noriginal\n===============")
	val.Walk(func(v cue.Value) bool {
		fmt.Printf("\n%# v\n", v)
		return true
	}, nil)

	val = val.FillPath(cue.ParsePath("a.i"), 42)

	fmt.Println("\nfilled\n===============")
	val.Walk(func(v cue.Value) bool {
		fmt.Printf("\n%# v\n", v)
		return true
	}, nil)

	//
	//  This would be equivalent to the lines after
	//
	// val.Evaluate(cue.Final(), cue.Concrete(true))

	a := val.Syntax(cue.Final(), cue.Concrete(true))
	val = c.BuildExpr(a.(ast.Expr))


	fmt.Println("\nfinal\n===============")
	val.Walk(func(v cue.Value) bool {
		fmt.Printf("\n%# v\n", v)
		return true
	}, nil)

}

Gives

original
===============

a: {
        i: int
        j: int | *i
}

i: int
j: int | *i

int

int | *i

filled
===============

a: {
        i: 42
        j: int | *i
}

i: 42
j: int | *i

42

int | *i

final
===============

a: {
        i: 42
        j: 42
}

i: 42
j: 42

42

42

verdverm avatar Oct 29 '21 17:10 verdverm

Tony Worm suggested that I include my use case here.

I'm dynamically combining several sources of configuration and wanted a way to be able to display the effective configuration to users. To accomplish this, I'm currently using value.Syntax(cue.Final()) which is fine as the very next thing I do is format.Node. However, my unified configurations are fairly large, and so users may reasonably wish to print only a particular path (and indeed some convenience commands in my CLI offer this). With an AST, I have two choices: 1) use LookupPath etc first, then call .Syntax or 2) Call .Syntax first, then round-trip to a Value or JSON and query that. I'm now doing (1) and it is fine, but it wasn't what I was initially expecting. It's a little bit annoying because there isn't a single codepath where I extract paths. As a result, each codepath that extracts a value path must call .Syntax(Final()) itself. My initial expectation was that I would have been able to do: final := value.Eval(Final()) or similar up front in a central place.

brandonbloom avatar Feb 16 '22 18:02 brandonbloom