pkl icon indicating copy to clipboard operation
pkl copied to clipboard

Improve interaction between `-x` and `-f` eval flags

Open cakemanny opened this issue 1 year ago • 7 comments

When using eval's -x option, the --format option appears to be ignored.

Evaluating the following

pkl eval --format=json -x y - <<EOF            
x { 1; 2; 3 }
y { "a"; "b"; "c" }
EOF

gives

new Dynamic { "a"; "b"; "c" }

I had expected it to give

[
  "a",
  "b",
  "c"
]

Checked with Pkl 0.26.3 (macOS 14.4.1, native) and a build from main, Pkl 0.27.0-dev+9692504 (macOS 14.6.1, native).

If only always wanting a fixed format, a workaround for now is to configure both wishes in the output property.

Details

x { 1; 2; 3 }
y { "a"; "b"; "c" }

output {
  renderer = new JsonRenderer {}
  value = y
}

cakemanny avatar Nov 02 '24 13:11 cakemanny

This a dupe of #742

HT154 avatar Nov 02 '24 15:11 HT154

Ahh, ok. So what I have to understand is that the default for -x is actually output.text and that --format changes the renderer that is used to construct that value.

I guess the part about -x and output.text is implied in the online docs about pkl eval. Though not apparent when only reading the CLI --help output.

Perhaps it's possible to improve the docs for the --format option, make it clearer that it's changing the modules' renderers rather than ensuring a specific output format.

I think Pkl stands out here as, with Pkl, rendering happens inside the language behind this hidden output property. Anyone coming to Pkl from another configuration language might expect that the language stops once the contents of the module file have been computed and then the tool is rendering to the supported formats.

Rereading the introduction's concepts, the paragraph on evaluation seems to misrepresent Pkl in this regard:

Evaluating a module produces an in-memory data model that is roughly comparable to a JSON data model. If evaluation completes successfully, the Pkl evaluator converts the data model to an external representation

To me it implies that Pkl works like how I understand Dhall, CUE and KCL to work. (Which I now believe not to be the case).

Sorry for this wall of text. I really just wanted to try to explore where my misconceptions came from and see if I could help find a way to avoid someone else falling into this trap.

Also, in case it's helpful, the use case that I had was: given a large amount of configuration in a single module, can Pkl select and output only part of it. That's what I was after when I spotted the -x option. In case that's useful input to future ergonomics.

cakemanny avatar Nov 02 '24 18:11 cakemanny

Is there a reason why -x isn't defined as "set output.value"?

odenix avatar Nov 02 '24 20:11 odenix

Is there a reason why -x isn't defined as "set output.value"?

Modules can set output.text directly so output.value may be ignored entirely.

HT154 avatar Nov 02 '24 22:11 HT154

Modules can set output.text directly so output.value may be ignored entirely.

Right, but I think this problem already exists for -f .

The following would at least be consistent and easy to explain:

  • -x overrides output.value and resets output.text
  • -f overrides output.renderer and resets output.text

odenix avatar Nov 03 '24 00:11 odenix

Rereading the introduction's concepts, the paragraph on evaluation seems to misrepresent Pkl in this regard:

Evaluating a module produces an in-memory data model that is roughly comparable to a JSON data model. If evaluation completes successfully, the Pkl evaluator converts the data model to an external representation

I think that sentence is a little misleading, but it's actually correct in the strict sense. The conversion can be: Pkl string -> string bytes (in the case of the CLI), or can also be: Pkl object to class/struct/primitive in a host language (in the case of using Pkl as a library).

To your point, the discrepancy between Pkl and Cue/KCL/Dhall is that rendering happens in-language, and you can affect how rendering happens when you author Pkl code.

Is there a reason why -x isn't defined as "set output.value"?

One of the use-cases for the -x flag is for scripting use-cases, for example, pkl eval -x 'package.version'.

If it was defined as set output.value, you'd get something like:

$ pkl eval -x 'package.version' PklProject
"1.0.0"

Instead of:

$ pkl eval -x 'package.version' PklProject
1.0.0

But, I'm more and more thinking that we should provide some way to improve the interaction between -x and -f. Or, introduce a new flag to address this pain point.

bioball avatar Nov 03 '24 01:11 bioball

Posting here so it's more visible, but the workaround was given in #752: -x 'module.output.renderer.renderValue(<expr>).

FWIW I hit this while evaluating Pkl and it seems like unfortunate behavior to me. If module.output.render is set correctly, why is it ignored? (I get that -x sets it too, it's rhetorical) I think changing it so -x sets module.renderer instead would make it more intuitive.

ThinkChaos avatar Jan 16 '25 23:01 ThinkChaos