Repository: scikit-hep/awkward

Issue:
List of Empty Objects is not supported
### Version of Awkward Array

1.8.0

### Description and code to reproduce

```python
>>>  import awkward as ak
>>> ak.to_arrow([{},{},{}])
ValueError                                Traceback (most recent call last)
Input In [12], in <cell line: 1>()
----> 1 ak.to_arrow([{},{},{}])

File ~/miniconda/envs/mongo-arrow_env/lib/python3.9/site-packages/awkward/operations/convert.py:2507, in to_arrow(array, list_to32, string_to32, bytestring_to32, allow_tensor)
   2501     else:
   2502         raise TypeError(
   2503             f"unrecognized array type: {layout!r}"
   2504             + ak._util.exception_suffix(__file__)
   2505         )
-> 2507 return recurse(layout, None, False)

File ~/miniconda/envs/mongo-arrow_env/lib/python3.9/site-packages/awkward/operations/convert.py:2247, in to_arrow.<locals>.recurse(layout, mask, is_option)
   2242 elif isinstance(layout, ak.layout.RecordArray):
   2243     values = [
   2244         recurse(x[: len(layout)], mask, is_option) for x in layout.contents
   2245     ]
-> 2247     min_list_len = min(map(len, values))
   2249     types = pyarrow.struct(
   2250         [
   2251             pyarrow.field(layout.key(i), values[i].type).with_nullable(
   (...)
   2255         ]
   2256     )
   2258     if mask is not None:

ValueError: min() arg is an empty sequence
```

It works properly with `pyarrow`:

```python
>>> import pyarrow as pa
>>> pa.array([{},{},{}]).tolist()
[{}, {}, {}]
```


Discussion:

Resolving patch:
diff --git a/src/awkward/operations/convert.py b/src/awkward/operations/convert.py
--- a/src/awkward/operations/convert.py
+++ b/src/awkward/operations/convert.py
@@ -2258,7 +2258,7 @@ def recurse(layout, mask, is_option):
                 recurse(x[: len(layout)], mask, is_option) for x in layout.contents
             ]
 
-            min_list_len = min(map(len, values))
+            min_list_len = min(map(len, values), default=len(layout))
 
             types = pyarrow.struct(
                 [


Test patch:
diff --git a/tests/test_1578-to_arrow-empty-recordarray.py b/tests/test_1578-to_arrow-empty-recordarray.py
new file mode 100644
--- /dev/null
+++ b/tests/test_1578-to_arrow-empty-recordarray.py
@@ -0,0 +1,14 @@
+# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import pytest  # noqa: F401
+import numpy as np  # noqa: F401
+import awkward as ak  # noqa: F401
+
+pytest.importorskip("pyarrow")
+
+
+def test():
+    layout = ak.layout.RecordArray([], keys=[], length=3)
+    struct = ak.to_arrow(layout)
+    assert len(struct) == len(layout) == 3
+    assert struct.tolist() == [{}, {}, {}]
diff --git a/tests/v2/test_1578-to_arrow-empty-recordarray.py b/tests/v2/test_1578-to_arrow-empty-recordarray.py
new file mode 100644
--- /dev/null
+++ b/tests/v2/test_1578-to_arrow-empty-recordarray.py
@@ -0,0 +1,14 @@
+# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import pytest  # noqa: F401
+import numpy as np  # noqa: F401
+import awkward as ak  # noqa: F401
+
+pytest.importorskip("pyarrow")
+
+
+def test():
+    layout = ak._v2.contents.RecordArray([], fields=[], length=3)
+    struct = ak._v2.to_arrow(layout)
+    assert len(struct) == len(layout) == 3
+    assert struct.tolist() == [{}, {}, {}]