[GH-ISSUE #30] Support for deep object merging #12

Open
opened 2026-05-22 22:05:09 +01:00 by JakeStanger · 8 comments
Owner

Originally created by @JakeStanger on GitHub (Nov 6, 2023).
Original GitHub issue: https://github.com/corn-config/corn/issues/30

Currently object merging only takes the immediate children into account.

There may be utility in changing this, or adding additional syntax, to perform a 'deep merge', running the merge against every child object.

Issue originates from the below discussion, which compares the feature to Nix's 'attrset merge':

Discussed in https://github.com/orgs/corn-config/discussions/29

Originally posted by fbewivpjsbsby November 6, 2023

  1. What version of corn are you using?
    corn-cli 0.9.2
  2. What is your operating system?
    Windows 10

Description

It is like nixos module, config will merge when you imports config, use // operators or use mkMerge.
Corn is override attrsets now.

Steps to reproduce

  1. Write this in corn file:
let {
  $preferences_user_enable = {
    Value = true
    Status = "user"
  }

  // telemetry
  $policies_disable_telemetry = {
    DisableTelemetry = true
    DisableFirefoxStudies = true
  }
  // #TODO 'raw data' need git version corn
  // theme
  $policies_theme = {
    Preferences = {
      'toolkit.legacyUserProfileCustomizations.stylesheets' = $preferences_user_enable
      'layout.css.backdrop-filter.enabled' = $preferences_user_enable
      'widget.non-native-theme.use-theme-accent' = $preferences_user_enable
    }
  }

  $policies_ech = {
    // ech need enable DNS over HTTPS
    DNSOverHTTPS = {
      Enabled =  true
      ProviderURL = "https://1.1.1.1/dns-query"
      Locked = false
      ExcludedDomains = [""]
    }
    Preferences = {
      'network.dns.echconfig.enabled' = $preferences_user_enable
      'network.dns.http3_echconfig.enabled' = $preferences_user_enable
    }
  }
} in
{
  policies = {
    // telemetry
    ..$policies_disable_telemetry
    // ech
    ..$policies_ech
    // theme
    ..$policies_theme
  }
}
  1. run corn [your corn file name].corn -t json It is override by $policies_theme:
{
  "policies": {
    "DisableTelemetry": true,
    "DisableFirefoxStudies": true,
    "DNSOverHTTPS": {
      "Enabled": true,
      "ProviderURL": "https://1.1.1.1/dns-query",
      "Locked": false,
      "ExcludedDomains": [
        ""
      ]
    },
    "Preferences": {
      "toolkit.legacyUserProfileCustomizations.stylesheets": {
        "Value": true,
        "Status": "user"
      },
      "layout.css.backdrop-filter.enabled": {
        "Value": true,
        "Status": "user"
      },
      "widget.non-native-theme.use-theme-accent": {
        "Value": true,
        "Status": "user"
      }
    }
  }
}
Originally created by @JakeStanger on GitHub (Nov 6, 2023). Original GitHub issue: https://github.com/corn-config/corn/issues/30 Currently object merging only takes the immediate children into account. There may be utility in changing this, or adding additional syntax, to perform a 'deep merge', running the merge against every child object. Issue originates from the below discussion, which compares the feature to Nix's 'attrset merge': ### Discussed in https://github.com/orgs/corn-config/discussions/29 <div type='discussions-op-text'> <sup>Originally posted by **fbewivpjsbsby** November 6, 2023</sup> 1. What version of corn are you using? corn-cli 0.9.2 2. What is your operating system? Windows 10 ### Description It is like nixos module, config will merge when you imports config, [use ```//``` operators](https://ryantm.github.io/nixpkgs/functions/library/attrsets/#function-library-lib.attrsets.mergeAttrsList) or [use mkMerge](https://nixos.org/manual/nixos/stable/#sec-option-definitions-merging). Corn is override attrsets now. ### Steps to reproduce 1. Write this in corn file: ```corn let { $preferences_user_enable = { Value = true Status = "user" } // telemetry $policies_disable_telemetry = { DisableTelemetry = true DisableFirefoxStudies = true } // #TODO 'raw data' need git version corn // theme $policies_theme = { Preferences = { 'toolkit.legacyUserProfileCustomizations.stylesheets' = $preferences_user_enable 'layout.css.backdrop-filter.enabled' = $preferences_user_enable 'widget.non-native-theme.use-theme-accent' = $preferences_user_enable } } $policies_ech = { // ech need enable DNS over HTTPS DNSOverHTTPS = { Enabled = true ProviderURL = "https://1.1.1.1/dns-query" Locked = false ExcludedDomains = [""] } Preferences = { 'network.dns.echconfig.enabled' = $preferences_user_enable 'network.dns.http3_echconfig.enabled' = $preferences_user_enable } } } in { policies = { // telemetry ..$policies_disable_telemetry // ech ..$policies_ech // theme ..$policies_theme } } ``` 2. run ```corn [your corn file name].corn -t json``` It is override by $policies_theme: ```json { "policies": { "DisableTelemetry": true, "DisableFirefoxStudies": true, "DNSOverHTTPS": { "Enabled": true, "ProviderURL": "https://1.1.1.1/dns-query", "Locked": false, "ExcludedDomains": [ "" ] }, "Preferences": { "toolkit.legacyUserProfileCustomizations.stylesheets": { "Value": true, "Status": "user" }, "layout.css.backdrop-filter.enabled": { "Value": true, "Status": "user" }, "widget.non-native-theme.use-theme-accent": { "Value": true, "Status": "user" } } } } ``` </div>
Author
Owner

@jficz commented on GitHub (Apr 16, 2025):

I'd suggest ... operator for deep merge and keep .. with current shallow merge behavior. Both have utility.

<!-- gh-comment-id:2809470932 --> @jficz commented on GitHub (Apr 16, 2025): I'd suggest `...` operator for deep merge and keep `..` with current shallow merge behavior. Both have utility.
Author
Owner

@JakeStanger commented on GitHub (Jun 22, 2025):

I'm not a fan of ... because it's too similar to ... It'd be easy to miss, and it's not obvious what the difference is.

<!-- gh-comment-id:2994261098 --> @JakeStanger commented on GitHub (Jun 22, 2025): I'm not a fan of `...` because it's too similar to `..`. It'd be easy to miss, and it's not obvious what the difference is.
Author
Owner

@jficz commented on GitHub (Jun 26, 2025):

fail point. I couldn't find any existing prior art for deep merge operator (didn't dig too much) but I got a few more ideas in no particular order:

>.
>>
.>
+>
>+
*.
**
.*

I don't like any of those very much, most of them have an established meaning in other languages, except perhaps +>, .> and >.

<!-- gh-comment-id:3007952340 --> @jficz commented on GitHub (Jun 26, 2025): fail point. I couldn't find any existing prior art for deep merge operator (didn't dig too much) but I got a few more ideas in no particular order: ``` >. >> .> +> >+ *. ** .* ``` I don't like any of those very much, most of them have an established meaning in other languages, except perhaps `+>`, `.>` and `>.`
Author
Owner

@JakeStanger commented on GitHub (Jun 26, 2025):

Perhaps it could be considered a "union merge" and copy the Typescript & union operator (or &&).

A nix-style // is also an option, but only if it's not confusing.

<!-- gh-comment-id:3007994504 --> @JakeStanger commented on GitHub (Jun 26, 2025): Perhaps it could be considered a "union merge" and copy the Typescript `&` union operator (or `&&`). A nix-style `//` is also an option, but only if it's not confusing.
Author
Owner

@jficz commented on GitHub (Jun 26, 2025):

ha, I forgot about nix's //. Shame on me :)
Since corn is inspired by Nix in many ways (at least that's what it looks like to me), I think // is a good idea. I think any operator will be confusing to some and keeping some level of consistency with "close relatives" is imho the best compromise

<!-- gh-comment-id:3008003820 --> @jficz commented on GitHub (Jun 26, 2025): ha, I forgot about nix's `//`. Shame on me :) Since corn is inspired by Nix in many ways (at least that's what it looks like to me), I think `//` is a good idea. I think any operator will be confusing to some and keeping some level of consistency with "close relatives" is imho the best compromise
Author
Owner

@jficz commented on GitHub (Aug 28, 2025):

yeah, except // is used for comments in cornlang

<!-- gh-comment-id:3232969805 --> @jficz commented on GitHub (Aug 28, 2025): yeah, except `//` is used for comments in cornlang
Author
Owner

@JakeStanger commented on GitHub (Aug 28, 2025):

Very good point, forgot about that. My preference would probably still be for a &

<!-- gh-comment-id:3233062716 --> @JakeStanger commented on GitHub (Aug 28, 2025): Very good point, forgot about that. My preference would probably still be for a `&`
Author
Owner

@jficz commented on GitHub (Aug 31, 2025):

In this case I'd agree with & as opposed to && which is imho better typographically but at the same time more confusing logically. Happy to do the testing but code-wise not sure I can help much, rust isn't exactly a language I understand (at this point) :(

<!-- gh-comment-id:3240375595 --> @jficz commented on GitHub (Aug 31, 2025): In this case I'd agree with `&` as opposed to `&&` which is imho better typographically but at the same time more confusing logically. Happy to do the testing but code-wise not sure I can help much, rust isn't exactly a language I understand (at this point) :(
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
corn-config/corn#12
No description provided.