Skip to content

Conversation

aquaresima
Copy link

@aquaresima aquaresima commented Sep 13, 2025

Hello,

This file introduces a macro for updating named tuples and a deep merge function to handle nested updates. It also includes a pretty print function for displaying named tuples.

I wrote this macro for my personal use, but because I use DrWatson in all my scientific projects, and I believe that this is a valuable tool for anyone working with nested tuples, I think it would be nice to have it here! I added tests and a an example case (in the test file) that you can add in the doc.

The idea is to use it to update experiment configurations within loops:

base = (a=5, b=(d=6, f=7), c=(to="be", or="not to be"))

for a in 1:3
    @update! base_config begin
        a = a 
    end
    @assert base.a == a 
end

It works like this:

## Example usage:
base = (a=5, b=(d=6, f=7), c=(to="be", or="not to be"))

# It can also be used to instantiate tuples
my_tuple = @update NamedTuple() begin
    a = 5 # Adding a new nested field
    b.d = 6
    b.f = 7
    c.to = "be"
    c.or = "not to be"
end

my_tuple == base || error("Tuples are not equal")

new_config = @update base begin
    b.e = (new="field", m=66) # Adding a new nested field
    b.g.nested = (;new ="field") # Adding a deeper nested field
    b.a = "This is changed" # Changing 
    c = "to be changed" # Changing an existing field
end

println("Base configuration:")
pretty_nt_print(base)

println("\nUpdated configuration:")
pretty_nt_print(new_config)
Base configuration:

{
    a := 5
    b := {
      d := 6
      f := 7
     }
    c := {
      to := be
      or := not to be
     }
   }


Updated configuration:

{
    a := 5
    b := {
      d := 6
      f := 7
      e := {
        new := field
        m := 66
       }
      g := {
        nested := {
          new := field
         }
       }
      a := This is changed
     }
    c := to be changed
   }

There is also an in-place @update! version

@update! base begin
    b.e = (l=65, m=66) # Adding a new nested field
    b.g.first = "Nested" # Adding a deeper nested field
    b.a = "This is changed" # Changing 
    c = "to be changed" # Changing an existing field
end

# @assert base == new_config

base = @update base a = "inline" 
@update! base b = "inline with !" 

This file introduces a macro for updating named tuples and a deep merge function to handle nested updates. It also includes a pretty print function for displaying named tuples.
@aquaresima
Copy link
Author

aquaresima commented Sep 13, 2025

Before merging, if you are interested anyway, one should decide whether to maintain or not the warning for the creation/deletion of fields.

Currently, creating a nested field that was not previously there or replacing a field with a value using a named tuple generates a warning. In the context of the example I get:

┌ Warning: Field b in b.e is not a NamedTuple. Overwriting b with a new NamedTuple.

┌ Warning: Field g in b.g.first does not exist, assign it to an empty NamedTuple

However, I am uncertain about the practicality of this feature within the library's broader context.

Because the user is modifying the named tuples "in batch", this framework is as useful as prone to errors. Thus, the warnings are convenient to avoid making the most common mistake:

  • You think that the field you want to update is a.b.c while it is a.c

Tho, this can be done on purpose, and in that case, having the warning at run-time can be pretty annoying.

@Datseris
Copy link
Member

Hi there, thanks for the contribution! I agree that this is generally useful functionality, however it is probably a better fit for https://github.com/JeffreySarnoff/NamedTupleTools.jl . There is some functionality overlap there as well. Can you try to add it as a contribution there?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants