FAQ

Sam S. via RT wrote:
Storing IterationEnd in an array or passing it to a &map, would certainly
qualify as "doing something other than the intended =:= check" to it,
so... just don't do those things.
Don't introspect? Don't metaprogram?
How do you intend for &map and &reduce to do a preliminary check to
make sure that no input element is IterationEnd, without iterating over
the input list?
I imagine that the check would be performed by whatever puts values
into the IterationEnd-delimited context, where they have come from
something else. So normally this would be a check when *outputting*
from an iterator, in its pull-one method. One can always check that the
value being returned by pull-one isn't IterationEnd in the cases where
one doesn't intend to return the sentinel to end the iteration.

For example, a List knows how many elements it has, even if some
of those elements are IterationEnd. The iterator returned by the
List.iterator method transfers values from the counted context to the
IterationEnd-delimited context, internally maintaining an index that it
compares to the element count. (This happens in methods pull-one and
reify-and-pull-one in the anonymous iterator class in List.iterator).
That iterator code could check whether a value that it has retrieved by
index is IterationEnd, and signal an error if it is.

In the case of map, obviously it can't check its input values,
because they're already in an IterationEnd-delimited context, coming
from an iterator. But map can check its output: it can look at what
the user-supplied iteration function returned, and signal an error if
that's IterationEnd.

-zefram

Search Discussions

  • Zefram at May 21, 2016 at 2:49 pm

    Sam S. via RT wrote:
    Can you describe an actual example of something a Perl 6 module author
    might want to do that could cause IteratorEnd to be leaked outside of
    its intended context?
    Introspect on the CORE:: stash. Perhaps in order to parse code that
    refers to objects by their Perl 6 names, and which makes use of the
    public iterator API including the approved "=:= IteratorEnd" check.
    It never reaches the "outside world", as long as implementers follow
    this protocol.
    So, say, putting the object into a public namespace is an unapproved
    use, and has to be unapproved because it would cause such a leak.
    Oops, the core implementation is breaking the protocol. Better remove
    CORE::<IterationEnd>.
    If the documentation does not sufficiently deter people from trying this,
    then maybe this should be a p6doc ticket instead.
    If you want to maintain the situation of IterationEnd being reified as
    a named object, but not able to be processed by the language's general
    mechanisms, then the documentation certainly needs to prohibit more
    than just direct, deliberate references to it. Prohibit name lookups
    from stashes? Prohibit metaprogramming of iterator code? It's not at
    all obvious which things are intended to be unsupported.
    So if you want to litter other parts of Perl 6 with (potentially
    performance-degrading) checks for the sentinel value
    The checks are not free, of course, but they're cheap. As jnthn has
    explained, you're using a sentinel-delimited API specifically because
    that identity comparison is cheap.

    -zefram
  • Zefram at May 21, 2016 at 5:57 pm

    Sam S. via RT wrote:
    is there anything else other than the `CORE::` object that would leak an
    `IterationEnd` value into a Seq/List passed to user code?
    There are some kinds of programming that would be liable to innocently run
    into the actual object even if it doesn't have a regular name. It looks
    like Perl 6 broadly intends to enable the affected kinds of programming,
    but this is where my Perl 6 knowledge runs out: I don't know which
    specifically exist now or how to do them. Still, I think the prospects
    are worrying enough even where Perl 6 doesn't actually do them yet.

    First, there's MOP stuff, where metaclass code might wrap method calls or
    otherwise tweak their implementation. This kind of code would naturally
    need to handle all the kinds of value that can be passed to or returned
    from a method. So it can see the IterationEnd value in the operation
    of valid iterator code, without specifically knowing that it's dealing
    with iterator code.

    In a related vein, think about introspection into the call records of a
    running program. For example, one might want to produce a stack trace
    that shows the arguments to each call, as does Perl 5's Carp::confess().
    Or one might run a program under a Perl 6 debugger, trying to emit trace
    data for each call and return.

    One can also consider introspection into the non-running code reified
    in Sub objects and the like, or plugging extensions into the compiler.
    Where the code has a "=:= IterationEnd" operation, the introspection
    would be liable to see the IterationEnd value, even if it wasn't
    spelled with a regular name. Reformulating "$a =:= IterationEnd" as
    "is_IterationEnd($a)" could avoid this problem for the comparisons,
    but it still arises for code that returns the sentinel.

    -zefram

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupperl6-compiler @
categoriesperl
postedMay 21, '16 at 12:19a
activeMay 21, '16 at 5:57p
posts3
users1
websiteperl6.org

1 user in discussion

Zefram: 3 posts

People

Translate

site design / logo © 2019 Grokbase