Hi Guys,

Today I was making a code review and I came across the following snippet:

```
metrics.allocated.put(
    name,
    {strings::join("/", "allocator/allocated", name),
     process::defer(self(), [this, name]() {
       double result = 0;
       foreachvalue (const Slave& slave, this->slaves) {
         Option<Value::Scalar> value =
           slave.allocated.get<Value::Scalar>(name);
         if (value.isSome()) {
           result += value.get().value();
         }
       }
       return result;
    })});
```

I think by the code here is hard to tell what is happening here. If you look at 
the declaration of `metrics.allocated` somewhere else you notice that allocated 
has the following declaration:

```
hashmap<std::string, process::metrics::Gauge> total;
```

And gauge is certainly no container type, nor its constructor takes an 
`std::initializer_list` as a parameter. In fact its signature is:

```
Gauge::Gauge(const std::string& name, const Deferred<Future<double>()>& f)
```

What is happening here is that brace constructors allows you to infer the type 
being constructed, which makes the snippet there be equivalent to:

```
metrics.allocated.put(
    name,
    Gauge(
        strings::join("/", "allocator/allocated", name),
        process::defer(self(), [this, name]() {
          double result = 0;
          foreachvalue (const Slave& slave, this->slaves) {
            Option<Value::Scalar> value =
              slave.allocated.get<Value::Scalar>(name);
            if (value.isSome()) {
              result += value.get().value();
            }
          }
          return result;
       })));
```

What I’m proposing is to only allow this type of construction in a few cases, 
namely for tuples, pairs and initializer lists where it actually improves 
readability.

Do you guys have any opinions on the matter?

Reply via email to