Well. If python is a dynamically scoped language, what they do is correct. If they are lexically scoped (which python is described as) the variable defined in the if should never have different visibility in the same scope.
In a lexically scoped language you don't define variables conditionally. What ruby does is also icky, but obviously the developers of both python and ruby wanted to save the developer an extra declaration. The ruby version is at least more correct from a lexical standpoint (it is set to nil if left "nondefined").
The example in the article shows a need for cartesian product of (bucket name) and (lifetime policy), with a fixed location. Nothing stops you from defining a separate category for the exceptions, and just append them to the resulting list. Or you may want to assign each bucket its own location, then you define it along side the bucket name.
Don't want to sound too harsh, but to me HCL is even worse than plain YAML.
By expressiveness, HCL is somewhat similar to Ansible-flavoured YAML - in both you need to use magic keywords to create any kind of abstraction (e.g. a loop).
HCL is worse than regular YAML because there's only one "true" parser for it, that is official Hashicorp's HCL parser. So if you are locked into Golang ecosystem, then sure it can work for you, otherwise you are out of luck.
There are a couple of tools that convert HCL into JSON, I tried both, they somewhat work, but in the end of the day it's a big hack. At that point I just gave up on using HCL and started using something else that generates JSON.
Hope you find some configuration layer that fits your users more than HCL or YAML.
Luckily, the main point of the article is that syntax doesn't matter, but abstractions do. In other words, you can use your favorite DSL, that being Python or TCL or something else.
Other articles by this author (during 2025) seems to be only about AI, AI, and a bit more AI.