<commit_before><?php

namespace Complex\CollectionStream;

use Complex\CollectionStream\Exception\InvalidParameterException;
use Complex\CollectionStream\Exception\InvalidElementTypeException;
use Complex\CollectionStream\Exception\StreamConsumedException;
use Complex\CollectionStream\Operation\Filter;
use Complex\CollectionStream\Operation\Iterator;
use Complex\CollectionStream\Operation\Limit;
use Complex\CollectionStream\Operation\Map;
use Complex\CollectionStream\Operation\Operation;
use Complex\CollectionStream\Stream\ArrayStream;
use Iterator as StlIterator;

class OperationPipe
{
    /** @var Operation */
    private $lastOperation = null;
    private $isConsumed = false;

    public function __construct($iterable)
    {
        $collection = null;

        if ($iterable instanceof StlIterator) {
            $collection = $iterable;

        } elseif (is_array($iterable)) {
            $collection = new ArrayStream($iterable);

        } else {

            throw new InvalidParameterException(
                "Invalid constructor argument. Must be an array or implement the Iterator interface"
            );
        }

        $this->lastOperation = new Iterator($collection);
    }

    /**
     * @param Operation $operation
     */
    public function add(Operation $operation)
    {
        if ($this->lastOperation !== null) {
            $prevOperation = $this->lastOperation;
            $operation->setPrev($prevOperation);
            $prevOperation->setNext($operation);
        }

        $this->lastOperation = $operation;
    }

    private function next()
    {
        return $this->lastOperation->advance();
    }

    private function consumeStream()
    {
        if($this->isConsumed)
            throw new StreamConsumedException();

        $this->isConsumed = true;
    }

    /*
     * Operations
     */

    public function limit($limit)
    {
        $this->add(new Limit($limit));

        return $this;
    }

    public function filter($function)
    {
        $this->add(new Filter($function));

        return $this;
    }

    public function map($function)
    {
        $this->add(new Map($function));

        return $this;
    }

    /*
     * Terminators
     */

    public function each($function)
    {
        $this->consumeStream();

        $current = null;

        while (($current = $this->next()) !== null) {
            call_user_func_array($function, array($current));
        }
    }

    public function toArray()
    {
        $streamValueArray = [];

        $this->each(function($element) use (&$streamValueArray) { $streamValueArray[] = $element; });

        return $streamValueArray;
    }

    public function first()
    {
        $this->consumeStream();

        $result = $this->next();

        return Optional::ofNullable($result);
    }

    public function min()
    {
        $min = null;

        $this->each(function($element) use (&$min) {
            $this->enforceNumericElement($element);
            if ($min === null || $element < $min) {
                $min = $element;
            }
        });

        return $min;
    }

    public function max()
    {
        $max = null;

        $this->each(function($element) use (&$max) {
            $this->enforceNumericElement($element);
            if ($max === null || $element > $max) {
                $max = $element;
            }
        });

        return $max;
    }

    public function sum()
    {
        $sum = 0;

        $this->each(function ($element) use (&$sum) {
            $this->enforceNumericElement($element);
            $sum += $element;
        });

        return $sum;
    }

    public function count()
    {
        $count = 0;

        $this->each(function($element) use (&$count) { $count++; });

        return $count;
    }

    public function average()
    {
        $total = 0;
        $count = 0;

        $this->each(function($element) use (&$total, &$count) {
            $this->enforceNumericElement($element);
            $count++;
            $total += $element;
        });

        return $total / $count;
    }

    /*
     * Helpers
     */

    private function enforceNumericElement($element)
    {
        if (!is_numeric($element)) {
            throw new \InvalidArgumentException(sprintf('{0} is not numeric', gettype($element)));
        }
    }

} <commit_msg>Style adjustments<commit_after><?php

namespace Complex\CollectionStream;

use Complex\CollectionStream\Exception\InvalidParameterException;
use Complex\CollectionStream\Exception\StreamConsumedException;
use Complex\CollectionStream\Operation\Filter;
use Complex\CollectionStream\Operation\Iterator;
use Complex\CollectionStream\Operation\Limit;
use Complex\CollectionStream\Operation\Map;
use Complex\CollectionStream\Operation\Operation;
use Complex\CollectionStream\Stream\ArrayStream;
use InvalidArgumentException;
use Iterator as StlIterator;

class OperationPipe
{
    /** @var Operation */
    private $lastOperation = null;
    private $isConsumed = false;

    public function __construct($iterable)
    {
        $collection = null;

        if ($iterable instanceof StlIterator) {
            $collection = $iterable;

        } elseif (is_array($iterable)) {
            $collection = new ArrayStream($iterable);

        } else {

            throw new InvalidParameterException(
                "Invalid constructor argument. Must be an array or implement the Iterator interface"
            );
        }

        $this->lastOperation = new Iterator($collection);
    }

    /**
     * @param Operation $operation
     */
    public function add(Operation $operation)
    {
        if ($this->lastOperation !== null) {
            $prevOperation = $this->lastOperation;
            $operation->setPrev($prevOperation);
            $prevOperation->setNext($operation);
        }

        $this->lastOperation = $operation;
    }

    private function next()
    {
        return $this->lastOperation->advance();
    }

    private function consumeStream()
    {
        if ($this->isConsumed) {
            throw new StreamConsumedException();
        }

        $this->isConsumed = true;
    }

    /*
     * Operations
     */

    public function limit($limit)
    {
        $this->add(new Limit($limit));

        return $this;
    }

    public function filter($function)
    {
        $this->add(new Filter($function));

        return $this;
    }

    public function map($function)
    {
        $this->add(new Map($function));

        return $this;
    }

    /*
     * Terminators
     */

    public function each($function)
    {
        $this->consumeStream();

        $current = null;

        while (($current = $this->next()) !== null) {
            call_user_func_array($function, array($current));
        }
    }

    public function toArray()
    {
        $streamValueArray = [];

        $this->each(function ($element) use (&$streamValueArray) {
                $streamValueArray[] = $element;
            });

        return $streamValueArray;
    }

    public function first()
    {
        $this->consumeStream();

        $result = $this->next();

        return Optional::ofNullable($result);
    }

    public function min()
    {
        $min = null;

        $this->each(function ($element) use (&$min) {
                $this->enforceNumericElement($element);
                if ($min === null || $element < $min) {
                    $min = $element;
                }
            });

        return $min;
    }

    public function max()
    {
        $max = null;

        $this->each(function ($element) use (&$max) {
                $this->enforceNumericElement($element);
                if ($max === null || $element > $max) {
                    $max = $element;
                }
            });

        return $max;
    }

    public function sum()
    {
        $sum = 0;

        $this->each(function ($element) use (&$sum) {
                $this->enforceNumericElement($element);
                $sum += $element;
            });

        return $sum;
    }

    public function count()
    {
        $count = 0;

        $this->each(function ($element) use (&$count) {
                $count++;
            });

        return $count;
    }

    public function average()
    {
        $total = 0;
        $count = 0;

        $this->each(function ($element) use (&$total, &$count) {
                $this->enforceNumericElement($element);
                $count++;
                $total += $element;
            });

        return $total / $count;
    }

    /*
     * Helpers
     */

    private function enforceNumericElement($element)
    {
        if (!is_numeric($element)) {
            throw new InvalidArgumentException(sprintf('{0} is not numeric', gettype($element)));
        }
    }

} 
{'fraction_non_alphanumeric': 0.12974074493377108, 'fraction_numerical': 0.0011321181931393638, 'mean_word_length': 1.9387890884896872, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2642687', 'n_tokens_mistral': 2450, 'n_tokens_neox': 2328, 'n_words': 499}