protected function grep($expression, $limit = null)
    {
        // initialize our return map and book-keeping values
        $map = new static;
        $bnd = empty($limit) ? null : abs($limit);
        $cnt = 0;

        // define a helper to add matching values to our new map, stopping when
        // any designated limit is reached
        $helper = function ($value, $key) use ($expression, $map, $bnd, &$cnt) {
            if ($this->passes($this->call($expression, $value, $key))) {
                $map->set($key, $value);
                if (null !== $bnd && $bnd <= ++$cnt) {
                    return false;
                }
            }
        };

        // walk the array in the right direction
        if (0 <= $limit) {
            $this->walk($helper);

        } else {
            $this->walk_backward($helper);
        }

        return $map;
    }