def iterable_func(self):
        """
        An internal function which has generator semantics. Defined using the
        `yield` syntax.
        Used to grab the first element during class initialization, and
        subsequently on calls to `next()` to get the remaining elements.
        We rely on the implicit StopIteration built into this type of function
        to propagate through the final `next()` call.
        """
        # BFS is not done until the queue is empty
        while self.queue:
            logger.debug(
                (
                    "recursive_operation_ls BFS queue not empty, "
                    "getting next path now."
                )
            )

            # rate limit based on number of ls calls we have made
            self.ls_count += 1
            if self.ls_count % SLEEP_FREQUENCY == 0:
                logger.debug(
                    (
                        "recursive_operation_ls sleeping {} seconds to "
                        "rate limit itself.".format(SLEEP_LEN)
                    )
                )
                time.sleep(SLEEP_LEN)

            # get path and current depth from the queue
            abs_path, rel_path, depth = self.queue.pop()

            # set the target path to the popped absolute path if it exists
            if abs_path:
                self.ls_params["path"] = abs_path

            # if filter_after_first is False, stop filtering after the first
            # ls call has been made
            if not self.filter_after_first:
                if self.filtering:
                    self.filtering = False
                else:
                    try:
                        self.ls_params.pop("filter")
                    except KeyError:
                        pass

            # do the operation_ls with the updated params
            res = self.client.operation_ls(self.endpoint_id, **self.ls_params)
            res_data = res["DATA"]

            # if we aren't at the depth limit, add dir entries to the queue.
            # including the dir's name in the absolute and relative paths
            # and increase the depth by one.
            # data is reversed to maintain any "orderby" ordering
            if depth < self.max_depth:
                self.queue.extend(
                    [
                        (
                            res["path"] + item["name"],
                            (rel_path + "/" if rel_path else "") + item["name"],
                            depth + 1,
                        )
                        for item in reversed(res_data)
                        if item["type"] == "dir"
                    ]
                )

            # for each item in the response data update the item's name with
            # the relative path popped from the queue, and yield the item
            for item in res_data:
                item["name"] = (rel_path + "/" if rel_path else "") + item["name"]
                yield GlobusResponse(item)