src/Primitive/Support/Traits/SliceableTrait.php
protected function getSlice($start, $stop, $step)
    {
        $length = $this->length();
        $step = (isset($step)) ? $step : 1;

        if ($step === 0)
        {
            throw new InvalidArgumentException('Slice step cannot be 0');
        }

        if (isset($start))
        {
            $start = $this->adjustBoundary($length, $start, $step);
        }
        else
        {
            $start = ($step > 0) ? 0 : $length - 1;
        }

        if (isset($stop))
        {
            $stop = $this->adjustBoundary($length, $stop, $step);
        }
        else
        {
            $stop = ($step > 0) ? $length : -1;
        }

        // Return an empty string if the set of indices would be empty
        if (($step > 0 && $start >= $stop) || ($step < 0 && $start <= $stop))
        {
            return new static('');
        }

        // Return the substring if step is 1
        if ($step === 1)
        {
            return $this->cut($start, $stop - $start);
        }

        // Otherwise iterate over the slice indices
        $str = '';
        foreach ($this->getIndices($start, $stop, $step) as $index)
        {
            $str .= (isset($this[$index])) ? $this[$index] : '';
        }

        return new static($str);
    }
protected function getSlice($start, $stop, $step)
    {
        $length = $this->length();
        $step = (isset($step)) ? $step : 1;

        if ($step === 0)
        {
            throw new InvalidArgumentException('Slice step cannot be 0');
        }

        if (isset($start))
        {
            $start = $this->adjustBoundary($length, $start, $step);
        }
        else
        {
            $start = ($step > 0) ? 0 : $length - 1;
        }

        if (isset($stop))
        {
            $stop = $this->adjustBoundary($length, $stop, $step);
        }
        else
        {
            $stop = ($step > 0) ? $length : -1;
        }

        // Return an empty string if the set of indices would be empty
        if (($step > 0 && $start >= $stop) || ($step < 0 && $start <= $stop))
        {
            return new static('');
        }

        // Return the substring if step is 1
        if ($step === 1)
        {
            return $this->cut($start, $stop - $start);
        }

        // Otherwise iterate over the slice indices
        $str = '';
        foreach ($this->getIndices($start, $stop, $step) as $index)
        {
            $str .= (isset($this[$index])) ? $this[$index] : '';
        }

        return new static($str);
    }
Returns a new SliceableStringy instance given start, stop and step
arguments for the desired slice. Start, which indicates the starting
index of the slice, defaults to the first character in the string if
step is positive, and the last character if negative. Stop, which
indicates the exclusive boundary of the range, defaults to the length
of the string if step is positive, and before the first character
if negative. Step allows the user to include only every nth character
in the result, with its sign determining the direction in which indices
are sampled. Throws an exception if step is equal to 0.

@param int|null $start Optional start index of the slice
@param int|null $stop  Optional boundary for the slice
@param int|null $step  Optional rate at which to include characters

@return static                   A new instance containing the slice
@throws InvalidArgumentException If step is equal to 0