final public function join($parts) : string
    {
        if (is_array($parts)) {
            $parts = new ArrayIterator($parts);
        }
        Preconditions::checkArgument($parts instanceof Traversable, 'parts must be an array or a Traversable');
        $iterator = $this->modifyIterable(FluentIterable::from($parts))
            ->transform(
                function ($element) {
                    return ToStringHelper::valueToString($element);
                }
            )
            ->iterator();
        $res = '';
        while ($iterator->valid()) {
            $res .= $iterator->current();
            $iterator->next();
            if ($iterator->valid()) {
                $res .= $this->separator;
            }
        }
        return $res;
    }
final public function join($parts) : string
    {
        if (is_array($parts)) {
            $parts = new ArrayIterator($parts);
        }
        Preconditions::checkArgument($parts instanceof Traversable, 'parts must be an array or a Traversable');
        $iterator = $this->modifyIterable(FluentIterable::from($parts))
            ->transform(
                function ($element) {
                    return ToStringHelper::valueToString($element);
                }
            )
            ->iterator();
        $res = '';
        while ($iterator->valid()) {
            $res .= $iterator->current();
            $iterator->next();
            if ($iterator->valid()) {
                $res .= $this->separator;
            }
        }
        return $res;
    }
Returns a string containing the string representation of each element of $parts, using the previously
configured separator between each.

@param array|Traversable $parts
@return string
@throws \InvalidArgumentException if $parts is not an array or a Traversable