Skip to content

[Bug]: Inconsistent initial=None Parameter Handling in asyncstdlib.accumulate #176

@Atry

Description

@Atry

What happened?

Issue Description

asyncstdlib.accumulate handles the initial=None parameter inconsistently compared to itertools.accumulate. When initial=None is explicitly passed, the two libraries produce different results.

Expected Behavior (itertools.accumulate)

When initial=None is explicitly provided, itertools.accumulate treats it as if no initial value was specified and starts accumulation from the first element of the iterable.

Actual Behavior (asyncstdlib.accumulate)

When initial=None is explicitly provided, asyncstdlib.accumulate treats None as a literal initial value and includes it in the accumulation sequence.

Minimal Reproducible Example

import asyncstdlib
import itertools

async def async_gen():
    """Async generator: yields 1, 2, 3"""
    for i in [1, 2, 3]:
        yield i

def sync_gen():
    """Sync generator: yields 1, 2, 3"""
    for i in [1, 2, 3]:
        yield i

def safe_accumulator(x, y):
    """Accumulator that can handle None values"""
    if x is None:
        return y
    return x + y

# Test itertools.accumulate with initial=None (expected behavior)
print("=== itertools.accumulate with initial=None ===")
result_itertools = list(itertools.accumulate(sync_gen(), safe_accumulator, initial=None))
print(f"Result: {result_itertools}")

print("\n=== asyncstdlib.accumulate with initial=None ===")
async def test_asyncstdlib():
    result = []
    async for item in asyncstdlib.accumulate(async_gen(), safe_accumulator, initial=None):
        result.append(item)
    return result

result_asyncstdlib = await test_asyncstdlib()
print(f"Result: {result_asyncstdlib}")

print(f"\nResults match: {result_itertools == result_asyncstdlib}")
print(f"itertools result: {result_itertools}")
print(f"asyncstdlib result: {result_asyncstdlib}")

# Show the difference clearly
if result_itertools != result_asyncstdlib:
    print("\n🔴 INCONSISTENCY DETECTED:")
    print(f"  itertools treats initial=None as 'no initial value': {result_itertools}")
    print(f"  asyncstdlib treats initial=None as literal None value: {result_asyncstdlib}")
else:
    print("\n✅ Results are consistent")

Output:

=== itertools.accumulate with initial=None ===
Result: [1, 3, 6]

=== asyncstdlib.accumulate with initial=None ===
Result: [None, 1, 3, 6]

Results match: False
itertools result: [1, 3, 6]
asyncstdlib result: [None, 1, 3, 6]

🔴 INCONSISTENCY DETECTED:
  itertools treats initial=None as 'no initial value': [1, 3, 6]
  asyncstdlib treats initial=None as literal None value: [None, 1, 3, 6]

Request Assignment [Optional]

  • I already understand the cause and want to submit a bugfix.

Metadata

Metadata

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions