jsonnet icon indicating copy to clipboard operation
jsonnet copied to clipboard

Limited access to `super` in conditional field name

Open tavin opened this issue 3 years ago • 3 comments
trafficstars

This may just be a request for clarification, or else a bug/enhancement depending on the wisdom of jsonnet devs.

Currently it's not allowed to do this:

{} + {
  [if 'spec' in super then 'spec']+: {
    // overrides here
  }
}

I think I understand why access to self and object locals is forbidden in field expressions like the above, but it seems to me that checking for existence in super would not cause any problems.

I have seen some discussions about similar code using self or about attempting to iterate super in a comprehension; what I'm looking for is a clear yes or no about whether it should be possible to do exactly what is written above.

The goal here is to write smart mixins that can alter the object on the left side of + without adding fields that should not be present. The workarounds are (imo) messy. Thanks for your consideration!

tavin avatar Nov 02 '22 10:11 tavin

I have seen some discussions about similar code using self or about attempting to iterate super in a comprehension; what I'm looking for is a clear yes or no about whether it should be possible to do exactly what is written above.

No.

but it seems to me that checking for existence in super would not cause any problems.

The problem is what would be the fields of this object on its own:

std.objectFields({
  [if 'spec' in super then 'spec']+: {
    // overrides here
  }
})

The goal here is to write smart mixins that can alter the object on the left side of + without adding fields that should not be present.

So the goal is to modify a field, but only if it exists?

My first thought would be something like:

local override_spec(obj) = if spec in obj then { spec +: { /* overrides here */  }  }

sbarzowski avatar Nov 06 '22 21:11 sbarzowski

The problem is what would be the fields of this object on its own:

std.objectFields({
  [if 'spec' in super then 'spec']+: {
    // overrides here
  }
})

Does it matter? I mean, I don't mind if objectFields() returns spec in the list or not. Or it could be treated as a hidden field.

It sounds like you're hinting at implementation obstacles? I don't know the ins and outs of course, but surely there is already some magic going on with super in order to support the +: operator? Just spitballing here, I realize I might be asking for the moon :)

My first thought would be something like:

local override_spec(obj) = if spec in obj then { spec +: { /* overrides here */  }  }

Yes that's what I had to do, but if your design pattern was to chain a series of imports with + after a variable base object, now each mixin requires a wrapper function.

tavin avatar Nov 30 '22 17:11 tavin

Well anyway, I will conclude by putting this forth as a feature request. I suggest the field be treated as hidden until it's merged with a super in which the field exists and is not hidden.

One can imagine a syntax like this, if it would aid implementation:

{} + {
  spec?+: {
    // overrides here
  }
}

tavin avatar Feb 06 '23 19:02 tavin