We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Bug in recursive attach of MetricsLambda
As a result of #385, the recursive attach of MetricsLambda is not working as intended. 

The code below throws this error: `NotComputableError: Accuracy must have at least one example before it can be computed.`

```python
import torch

from ignite.metrics import Accuracy, Precision, Recall, MetricsLambda
from ignite.engine import Engine

accuracy_1 = Accuracy()
accuracy_2 = Accuracy()
mean_accuracy = (accuracy_1 + accuracy_2) / 2


metrics = {
#     "a1": accuracy_1,
#     "a2": accuracy_2,    
    "mean accuracy": mean_accuracy,
}


y_pred = torch.randint(0, 2, size=(15, 10, 4)).float()
y = torch.randint(0, 2, size=(15, 10, 4)).long()

def update_fn(engine, batch):
    y_pred, y = batch
    return y_pred, y

validator = Engine(update_fn)

for name, metric in metrics.items():
    metric.attach(validator, name)

def data(y_pred, y):
    for i in range(y_pred.shape[0]):
        yield (y_pred[i], y[i])

d = data(y_pred, y)
state = validator.run(d, max_epochs=1)

print(state.metrics)
```

cc @vfdev-5 @amitibo 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ignite/metrics/metrics_lambda.py`
Content:
```
1 from ignite.metrics.metric import Metric
2 from ignite.engine import Events
3 
4 
5 class MetricsLambda(Metric):
6     """
7     Apply a function to other metrics to obtain a new metric.
8     The result of the new metric is defined to be the result
9     of applying the function to the result of argument metrics.
10 
11     When update, this metric does not recursively update the metrics
12     it depends on. When reset, all its dependency metrics would be
13     resetted. When attach, all its dependencies would be automatically
14     attached.
15 
16     Args:
17         f (callable): the function that defines the computation
18         args (sequence): Sequence of other metrics or something
19             else that will be fed to ``f`` as arguments.
20 
21     Example:
22 
23     .. code-block:: python
24 
25         precision = Precision(average=False)
26         recall = Recall(average=False)
27 
28         def Fbeta(r, p, beta):
29             return torch.mean((1 + beta ** 2) * p * r / (beta ** 2 * p + r + 1e-20)).item()
30 
31         F1 = MetricsLambda(Fbeta, recall, precision, 1)
32         F2 = MetricsLambda(Fbeta, recall, precision, 2)
33         F3 = MetricsLambda(Fbeta, recall, precision, 3)
34         F4 = MetricsLambda(Fbeta, recall, precision, 4)
35     """
36     def __init__(self, f, *args):
37         self.function = f
38         self.args = args
39         super(MetricsLambda, self).__init__()
40 
41     def reset(self):
42         for i in self.args:
43             if isinstance(i, Metric):
44                 i.reset()
45 
46     def update(self, output):
47         # NB: this method does not recursively update dependency metrics,
48         # which might cause duplicate update issue. To update this metric,
49         # users should manually update its dependencies.
50         pass
51 
52     def compute(self):
53         materialized = [i.compute() if isinstance(i, Metric) else i for i in self.args]
54         return self.function(*materialized)
55 
56     def attach(self, engine, name):
57         # recursively attach all its dependencies
58         for index, metric in enumerate(self.args):
59             if isinstance(metric, Metric):
60                 if not engine.has_event_handler(metric.started, Events.EPOCH_STARTED):
61                     engine.add_event_handler(Events.EPOCH_STARTED, metric.started)
62                 if not engine.has_event_handler(metric.iteration_completed, Events.ITERATION_COMPLETED):
63                     engine.add_event_handler(Events.ITERATION_COMPLETED, metric.iteration_completed)
64         super(MetricsLambda, self).attach(engine, name)
65
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ignite/metrics/metrics_lambda.py b/ignite/metrics/metrics_lambda.py
--- a/ignite/metrics/metrics_lambda.py
+++ b/ignite/metrics/metrics_lambda.py
@@ -53,12 +53,18 @@
         materialized = [i.compute() if isinstance(i, Metric) else i for i in self.args]
         return self.function(*materialized)
 
-    def attach(self, engine, name):
-        # recursively attach all its dependencies
+    def _internal_attach(self, engine):
         for index, metric in enumerate(self.args):
-            if isinstance(metric, Metric):
+            if isinstance(metric, MetricsLambda):
+                metric._internal_attach(engine)
+            elif isinstance(metric, Metric):
                 if not engine.has_event_handler(metric.started, Events.EPOCH_STARTED):
                     engine.add_event_handler(Events.EPOCH_STARTED, metric.started)
                 if not engine.has_event_handler(metric.iteration_completed, Events.ITERATION_COMPLETED):
                     engine.add_event_handler(Events.ITERATION_COMPLETED, metric.iteration_completed)
-        super(MetricsLambda, self).attach(engine, name)
+
+    def attach(self, engine, name):
+        # recursively attach all its dependencies
+        self._internal_attach(engine)
+        # attach only handler on EPOCH_COMPLETED
+        engine.add_event_handler(Events.EPOCH_COMPLETED, self.completed, name)

{"golden_diff": "diff --git a/ignite/metrics/metrics_lambda.py b/ignite/metrics/metrics_lambda.py\n--- a/ignite/metrics/metrics_lambda.py\n+++ b/ignite/metrics/metrics_lambda.py\n@@ -53,12 +53,18 @@\n         materialized = [i.compute() if isinstance(i, Metric) else i for i in self.args]\n         return self.function(*materialized)\n \n-    def attach(self, engine, name):\n-        # recursively attach all its dependencies\n+    def _internal_attach(self, engine):\n         for index, metric in enumerate(self.args):\n-            if isinstance(metric, Metric):\n+            if isinstance(metric, MetricsLambda):\n+                metric._internal_attach(engine)\n+            elif isinstance(metric, Metric):\n                 if not engine.has_event_handler(metric.started, Events.EPOCH_STARTED):\n                     engine.add_event_handler(Events.EPOCH_STARTED, metric.started)\n                 if not engine.has_event_handler(metric.iteration_completed, Events.ITERATION_COMPLETED):\n                     engine.add_event_handler(Events.ITERATION_COMPLETED, metric.iteration_completed)\n-        super(MetricsLambda, self).attach(engine, name)\n+\n+    def attach(self, engine, name):\n+        # recursively attach all its dependencies\n+        self._internal_attach(engine)\n+        # attach only handler on EPOCH_COMPLETED\n+        engine.add_event_handler(Events.EPOCH_COMPLETED, self.completed, name)\n", "issue": "Bug in recursive attach of MetricsLambda\nAs a result of #385, the recursive attach of MetricsLambda is not working as intended. \r\n\r\nThe code below throws this error: `NotComputableError: Accuracy must have at least one example before it can be computed.`\r\n\r\n```python\r\nimport torch\r\n\r\nfrom ignite.metrics import Accuracy, Precision, Recall, MetricsLambda\r\nfrom ignite.engine import Engine\r\n\r\naccuracy_1 = Accuracy()\r\naccuracy_2 = Accuracy()\r\nmean_accuracy = (accuracy_1 + accuracy_2) / 2\r\n\r\n\r\nmetrics = {\r\n#     \"a1\": accuracy_1,\r\n#     \"a2\": accuracy_2,    \r\n    \"mean accuracy\": mean_accuracy,\r\n}\r\n\r\n\r\ny_pred = torch.randint(0, 2, size=(15, 10, 4)).float()\r\ny = torch.randint(0, 2, size=(15, 10, 4)).long()\r\n\r\ndef update_fn(engine, batch):\r\n    y_pred, y = batch\r\n    return y_pred, y\r\n\r\nvalidator = Engine(update_fn)\r\n\r\nfor name, metric in metrics.items():\r\n    metric.attach(validator, name)\r\n\r\ndef data(y_pred, y):\r\n    for i in range(y_pred.shape[0]):\r\n        yield (y_pred[i], y[i])\r\n\r\nd = data(y_pred, y)\r\nstate = validator.run(d, max_epochs=1)\r\n\r\nprint(state.metrics)\r\n```\r\n\r\ncc @vfdev-5 @amitibo \n", "before_files": [{"content": "from ignite.metrics.metric import Metric\nfrom ignite.engine import Events\n\n\nclass MetricsLambda(Metric):\n    \"\"\"\n    Apply a function to other metrics to obtain a new metric.\n    The result of the new metric is defined to be the result\n    of applying the function to the result of argument metrics.\n\n    When update, this metric does not recursively update the metrics\n    it depends on. When reset, all its dependency metrics would be\n    resetted. When attach, all its dependencies would be automatically\n    attached.\n\n    Args:\n        f (callable): the function that defines the computation\n        args (sequence): Sequence of other metrics or something\n            else that will be fed to ``f`` as arguments.\n\n    Example:\n\n    .. code-block:: python\n\n        precision = Precision(average=False)\n        recall = Recall(average=False)\n\n        def Fbeta(r, p, beta):\n            return torch.mean((1 + beta ** 2) * p * r / (beta ** 2 * p + r + 1e-20)).item()\n\n        F1 = MetricsLambda(Fbeta, recall, precision, 1)\n        F2 = MetricsLambda(Fbeta, recall, precision, 2)\n        F3 = MetricsLambda(Fbeta, recall, precision, 3)\n        F4 = MetricsLambda(Fbeta, recall, precision, 4)\n    \"\"\"\n    def __init__(self, f, *args):\n        self.function = f\n        self.args = args\n        super(MetricsLambda, self).__init__()\n\n    def reset(self):\n        for i in self.args:\n            if isinstance(i, Metric):\n                i.reset()\n\n    def update(self, output):\n        # NB: this method does not recursively update dependency metrics,\n        # which might cause duplicate update issue. To update this metric,\n        # users should manually update its dependencies.\n        pass\n\n    def compute(self):\n        materialized = [i.compute() if isinstance(i, Metric) else i for i in self.args]\n        return self.function(*materialized)\n\n    def attach(self, engine, name):\n        # recursively attach all its dependencies\n        for index, metric in enumerate(self.args):\n            if isinstance(metric, Metric):\n                if not engine.has_event_handler(metric.started, Events.EPOCH_STARTED):\n                    engine.add_event_handler(Events.EPOCH_STARTED, metric.started)\n                if not engine.has_event_handler(metric.iteration_completed, Events.ITERATION_COMPLETED):\n                    engine.add_event_handler(Events.ITERATION_COMPLETED, metric.iteration_completed)\n        super(MetricsLambda, self).attach(engine, name)\n", "path": "ignite/metrics/metrics_lambda.py"}], "after_files": [{"content": "from ignite.metrics.metric import Metric\nfrom ignite.engine import Events\n\n\nclass MetricsLambda(Metric):\n    \"\"\"\n    Apply a function to other metrics to obtain a new metric.\n    The result of the new metric is defined to be the result\n    of applying the function to the result of argument metrics.\n\n    When update, this metric does not recursively update the metrics\n    it depends on. When reset, all its dependency metrics would be\n    resetted. When attach, all its dependencies would be automatically\n    attached.\n\n    Args:\n        f (callable): the function that defines the computation\n        args (sequence): Sequence of other metrics or something\n            else that will be fed to ``f`` as arguments.\n\n    Example:\n\n    .. code-block:: python\n\n        precision = Precision(average=False)\n        recall = Recall(average=False)\n\n        def Fbeta(r, p, beta):\n            return torch.mean((1 + beta ** 2) * p * r / (beta ** 2 * p + r + 1e-20)).item()\n\n        F1 = MetricsLambda(Fbeta, recall, precision, 1)\n        F2 = MetricsLambda(Fbeta, recall, precision, 2)\n        F3 = MetricsLambda(Fbeta, recall, precision, 3)\n        F4 = MetricsLambda(Fbeta, recall, precision, 4)\n    \"\"\"\n    def __init__(self, f, *args):\n        self.function = f\n        self.args = args\n        super(MetricsLambda, self).__init__()\n\n    def reset(self):\n        for i in self.args:\n            if isinstance(i, Metric):\n                i.reset()\n\n    def update(self, output):\n        # NB: this method does not recursively update dependency metrics,\n        # which might cause duplicate update issue. To update this metric,\n        # users should manually update its dependencies.\n        pass\n\n    def compute(self):\n        materialized = [i.compute() if isinstance(i, Metric) else i for i in self.args]\n        return self.function(*materialized)\n\n    def _internal_attach(self, engine):\n        for index, metric in enumerate(self.args):\n            if isinstance(metric, MetricsLambda):\n                metric._internal_attach(engine)\n            elif isinstance(metric, Metric):\n                if not engine.has_event_handler(metric.started, Events.EPOCH_STARTED):\n                    engine.add_event_handler(Events.EPOCH_STARTED, metric.started)\n                if not engine.has_event_handler(metric.iteration_completed, Events.ITERATION_COMPLETED):\n                    engine.add_event_handler(Events.ITERATION_COMPLETED, metric.iteration_completed)\n\n    def attach(self, engine, name):\n        # recursively attach all its dependencies\n        self._internal_attach(engine)\n        # attach only handler on EPOCH_COMPLETED\n        engine.add_event_handler(Events.EPOCH_COMPLETED, self.completed, name)\n", "path": "ignite/metrics/metrics_lambda.py"}]}