Entry of which key is same with an element index #124

Open
opened 2025-12-30 01:21:12 +01:00 by adam · 6 comments
Owner

Originally created by @taichi-ishitani on GitHub (Mar 25, 2024).

Hi,

As shown example below, entries of which key matches with an element index will be deleted.

foo { [0] = 2; 3 }
bar = foo[0]
$ ./pkl eval foo.pkl
foo {
  3
}
bar = 3

On the other hand, entries of which key does not match with an element index will not be deleted.

foo { [1] = 2; 3 }
bar = foo[0]
$ ./pkl eval foo.pkl
foo {
  [1] = 2
  3
}
bar = 3

Which behavior is wrong?

Originally created by @taichi-ishitani on GitHub (Mar 25, 2024). Hi, As shown example below, entries of which key matches with an element index will be deleted. ```pkl foo { [0] = 2; 3 } bar = foo[0] ``` ```console $ ./pkl eval foo.pkl foo { 3 } bar = 3 ``` On the other hand, entries of which key does not match with an element index will not be deleted. ```pkl foo { [1] = 2; 3 } bar = foo[0] ``` ```console $ ./pkl eval foo.pkl foo { [1] = 2 3 } bar = 3 ``` Which behavior is wrong?
Author
Owner

@bioball commented on GitHub (Mar 25, 2024):

Currently, there is a bug when mixing entries whose keys are integers with elements. So, the first snippet is incorrect, and is a bug.

This happens because Pkl mistakenly interprets [0] = 2 as "assign to element with index 0", instead of "declare an entry with key 0".

@bioball commented on GitHub (Mar 25, 2024): Currently, there is a bug when mixing entries whose keys are integers with elements. So, the first snippet is incorrect, and is a bug. This happens because Pkl mistakenly interprets `[0] = 2` as "assign to element with index 0", instead of "declare an entry with key 0".
Author
Owner

@taichi-ishitani commented on GitHub (Mar 26, 2024):

Thank you and I understood.
For the first example, what is the expected value of foo[0]? Should it return the element with index 0?

@taichi-ishitani commented on GitHub (Mar 26, 2024): Thank you and I understood. For the first example, what is the expected value of `foo[0]`? Should it return the element with index 0?
Author
Owner

@odenix commented on GitHub (Mar 26, 2024):

Currently, there is a bug when mixing entries whose keys are integers with elements. So, the first snippet is incorrect, and is a bug.

What does [n] = x mean for Dynamic? Does it mean the same as for Listing, the same as for Mapping, or something else?

@odenix commented on GitHub (Mar 26, 2024): > Currently, there is a bug when mixing entries whose keys are integers with elements. So, the first snippet is incorrect, and is a bug. What does `[n] = x` mean for `Dynamic`? Does it mean the same as for `Listing`, the same as for `Mapping`, or something else?
Author
Owner

@bioball commented on GitHub (Mar 27, 2024):

Currently, the behavior is: if there is an element at index n, [n] = x means: overwrite element at that index. And foo[0] means either "get element with index 0`, or "get entry with key 0", depending on which exists. In our current model, it is not possible to for entries with number keys to coexist with elements at the same number index.

With our current behavior, I think this should throw with a duplicate member definition error. It doesn't make sense for this to be accepted as one element declaration:

foo { [0] = 2; 3 }

I think there's some room for improvement here. This is surprising:

bar {
  1
}

foo = (bar) {
  [0] = 0
  [1] = 1
  [2] = 2
}

This produces:

bar {
  1
}
foo {
  0
  [1] = 1
  [2] = 2
}

Possibly, we can change the grammar for "assign to element index N", which might help here. For example, here's some made up syntax:

foo {
  amend [0] = 0
}
@bioball commented on GitHub (Mar 27, 2024): Currently, the behavior is: if there is an element at index `n`, `[n] = x` means: overwrite element at that index. And `foo[0]` means either "get element with index 0`, or "get entry with key 0", depending on which exists. In our current model, it is not possible to for entries with number keys to coexist with elements at the same number index. With our _current_ behavior, I think this should throw with a duplicate member definition error. It doesn't make sense for this to be accepted as one element declaration: ``` foo { [0] = 2; 3 } ``` I think there's some room for improvement here. This is surprising: ``` bar { 1 } foo = (bar) { [0] = 0 [1] = 1 [2] = 2 } ``` This produces: ``` bar { 1 } foo { 0 [1] = 1 [2] = 2 } ``` Possibly, we can change the grammar for "assign to element index N", which might help here. For example, here's some made up syntax: ``` foo { amend [0] = 0 } ```
Author
Owner

@taichi-ishitani commented on GitHub (Mar 28, 2024):

I think this should throw with a duplicate member definition error.

Is it expected behavior that Pkl raise an error if an entry and an element have the same idnex?
I'm developing a Pkl parser written in Ruby so I post this issue.

@taichi-ishitani commented on GitHub (Mar 28, 2024): > I think this should throw with a duplicate member definition error. Is it expected behavior that Pkl raise an error if an entry and an element have the same idnex? I'm developing a Pkl parser written in Ruby so I post this issue.
Author
Owner

@odenix commented on GitHub (Nov 5, 2024):

Pkl's behavior for dynamic objects that contain both elements and integer-keyed entries is confusing. I think it cannot even be reasoned about because a key with index x and entry with key x will cause a collision in VmObject.cachedValues.

I can think of several solutions, but one stands out for being simple to understand and implement:

  • A dynamic object cannot have both elements and entries.

This would also solve the following oddities:

  • Dynamic can have both elements and entries, but can't have separate defaults for them
  • Listing and Mapping have a length property, but Dynamic doesn't

Are there legitimate use cases for supporting dynamic objects that contain both elements and entries?

@odenix commented on GitHub (Nov 5, 2024): Pkl's behavior for dynamic objects that contain both elements and integer-keyed entries is confusing. I think it cannot even be reasoned about because a key with index `x` and entry with key `x` will cause a collision in `VmObject.cachedValues`. I can think of several solutions, but one stands out for being simple to understand and implement: * A dynamic object cannot have both elements and entries. This would also solve the following oddities: * Dynamic can have both elements and entries, but can't have separate `default`s for them * `Listing` and `Mapping` have a `length` property, but `Dynamic` doesn't Are there legitimate use cases for supporting dynamic objects that contain both elements and entries?
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/pkl#124