Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@adamgfraser
Copy link
Contributor

Resolves #7759.

@adamgfraser adamgfraser requested a review from jdegoes January 29, 2023 20:20
test("unnested") {
val configProvider1 = ConfigProvider.fromMap(Map("key" -> "value"))
val config1 = Config.string("key")
val configProvider2 = ConfigProvider.fromMap(Map("key" -> "value")).unnested("nested")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't exactly what I imagined unnested doing.

Rather, I would expect that, if you do:

val configProvider2 = ConfigProvider.fromMap(Map("nested.key" -> "nested.value")).unnested("nested")

Then you can successfully load Config.string("key") from such a ConfigProvider.

In other words, the unnested operator lets you take a ConfigProvider that is overly nested, and unnest it, such that it can be used with "flatter" configs.

The ConfigProvider#nested operator "pretends" the config data is nested, and can be used when the Config expects data that is actually more nested than it actually is; the ConfigProvider#unnested operator "pretends" the config data is not nested, and can be used when the Config expects data that is less nested than it actually is.

Maybe there are issues with this approach or maybe I just don't see how this test demonstrates such a relationship?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you may be confusing nested with unnested.

nested takes each Config and nests it under the specified name. So the way you would do what you want would be nested:

val configProvider = ConfigProvider.fromMap(Map("nested.key" -> "value")).nested("nested")
configProvider.load(Config.string("key")) // "value"

It gives you a ConfigProvider that automatically nests each Config under the specified property name.

unnested is the inverse of this so whereas nested automatically adds the specified layer of nesting to every Config that is fed to it, unnested removes a layer of nesting.

val configProvider = ConfigProvider.fromMap(Map("key" -> "value")).unnested("nested")
configProvider.load(Config.string("key").nested("nested") // "value"

I think these two operators need to have this relationship with each other, though their names could potentially be flipped. I think the overall issue is that ConfigProvider is contravariant with respect to the path whereas we intuitively expect it to be covariant. In other words, it is something that when fed a path gives you some values whereas intuitively we think of it as something that just has basically a map from paths to values.

So when we have the current nested we could either describe it as "nesting" each of the Config values loaded, which is accurate, or allowing us to "unnest" an overly nested config provider by allowing us to treat it as if it did not have that layer of nesting.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, 👍

result <- configProvider.load(config)
} yield assertTrue(result == "value1" -> "value2")
} +
test("within with multiple layers of nesting") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Lets you make targeted changes to a region of configuration data, effectively massaging the structure of data as it is, into the structure of data as a Config wants it to be.

@jdegoes jdegoes merged commit f08ec43 into zio:series/2.x Jan 30, 2023
@adamgfraser adamgfraser deleted the 7759 branch January 30, 2023 14:49
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.

Enhance ConfigProvider structural operators

2 participants