You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I think that there is a simple and fully backwards-compatible way to enable the scenario where one would want to create a "base" version of a resource, and then functionally update it with a CE to create new "derived" resources.
In other words, myResourceBase.With {...} is a CE builder: it can be used exactly like myResource {...} and it will just use myResourceBase as the default instead.
Here is how it works:
/// Defined as usual.typeMyResourceConfig={ setting1:string; setting2:string }interface IBuilder with// .../// Note: instead of defining the initial value inside Yield,/// we add an extra constructor that takes the initial value as argument.typeMyResourceBuilder(initial: MyResourceConfig)=new()= MyResourceBuilder({ setting1 ="default1"; setting2 ="default2"})member_.Yield _ = initial
/// Defined as usual.[<CustomOperation "setting1">]member_.Setting1(config,value)={ config with setting1 = value }// same for setting2.../// Defined as usual.letmyResource= MyResourceBuilder()/// We add the extension property `Then`, which just creates a builder with `this` as the initial value.typeMyResourceConfigwithmemberthis.With= MyResourceBuilder(this)
Advantages:
It's a pretty small addition (albeit to every builder);
It's fully backwards-compatible (we just add a ctor to the builder and an extension property to the config record);
It provides an alternative to writing a function to create several slightly differing resources;
It provides a way to conditionally set a value with the CE but without needing to support if/match inside the CE (which I think is just not possible with custom CE keywords). For example Conditional values in Farmer builders, or composing builders? #731 would be solved with:
letdeploymentBase= arm {
location Location.UKSouth
// more resources here
add_resource myVm
}letdeployment=match myVm.PublicIpId with| None -> deploymentBase
| Some ip -> deploymentBase.With { output "vmIP" ip.ArmExpression }
Inconvenients:
It might not be compatible with some builders that have a Run method (since we are now building CEs with an initial state that has already been Run). But the Run methods I've looked at were idempotent, so they should be fine.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
I think that there is a simple and fully backwards-compatible way to enable the scenario where one would want to create a "base" version of a resource, and then functionally update it with a CE to create new "derived" resources.
The use case would look like this:
In other words,
myResourceBase.With {...}
is a CE builder: it can be used exactly likemyResource {...}
and it will just usemyResourceBase
as the default instead.Here is how it works:
Advantages:
It's a pretty small addition (albeit to every builder);
It's fully backwards-compatible (we just add a ctor to the builder and an extension property to the config record);
It provides an alternative to writing a function to create several slightly differing resources;
It provides a way to conditionally set a value with the CE but without needing to support
if
/match
inside the CE (which I think is just not possible with custom CE keywords). For example Conditional values in Farmer builders, or composing builders? #731 would be solved with:Inconvenients:
Run
method (since we are now building CEs with an initial state that has already beenRun
). But theRun
methods I've looked at were idempotent, so they should be fine.Beta Was this translation helpful? Give feedback.
All reactions