google / jsonnet

Jsonnet - The data templating language
http://jsonnet.org
Apache License 2.0
6.98k stars 440 forks source link

ERROR: Dynamic field with Comprehension does not recornize variables #1168

Closed youngbo89 closed 2 months ago

youngbo89 commented 2 months ago

Description

Expect Dynamic field with Comprehension does works, but not:

// test.jsonnet 
{
  local myList = [
    {
      name: 'A',
    },
    {
      name: 'B',
    },
  ],

  [item.name]: item for item in myList
}
$ jsonnet test.jsonnet 
test.jsonnet:11:33-39 Unknown variable: myList

  [item.name]: item for item in myList

But this case, it works

// test2.jsonnet 
local myList = [
  {
    name: 'A',
  },
  {
    name: 'B',
  },
];

{
  [item.name]: item
  for item in myList
}
$  jsonnet test2.jsonnet            
{
   "A": {
      "name": "A"
   },
   "B": {
      "name": "B"
   }
}

version

$  jsonnet --version
Jsonnet commandline interpreter (Go implementation) v0.20.0
CertainLach commented 2 months ago

This is not a bug, locals defined inside of comprehensions may only be used by defined fields, and may use locals defined by comprehension, but can't be used by comprehension itself. I.e

{
  local valueX2 = item.value * 2,
  [item.key]: valueX2,
  for item in {a: 1, b: 2}
} == {a: 2, b: 4}
youngbo89 commented 2 months ago

This is not a bug, locals defined inside of comprehensions may only be used by defined fields, and may use locals defined by comprehension, but can't be used by comprehension itself. I.e

{
  local valueX2 = item.value * 2,
  [item.key]: valueX2,
  for item in {a: 1, b: 2}
} == {a: 2, b: 4}

It does not work for "Top-level object" case. For example:

// child.libsonnet
{
  [obj.name]: {
  }
  for obj in $.myObjects
}

// parent.libsonnet
(import const.libsonnet) +
(import child.libsonnet) +
...

and I got this result:

jsonnet child.libsonnet:87:13-14 No top-level object found.

Is it also expected result, too?

CertainLach commented 2 months ago

Is it also expected result, too?

Yes.

Object comprehension is evaluated eagerly, before object extension is done, so $, self, super don't work in that context. We can't get fields of object, whose fields we may not yet know.

youngbo89 commented 2 months ago

Thank you for kind explanations!