FAQ
Hi,

I came to this

12:51 <@moritz_> rakudo: my $x = 3; say $x, ' ', ++$x;
12:51 < p6eval> rakudo 7b81c0: OUTPUT«4 4␤»
12:51 <@moritz_> rakudo: my $x = 3; say $x, ' ', $x++;
12:51 < p6eval> rakudo 7b81c0: OUTPUT«4 3␤»

This looks very counter intuitive, because it looks like the arguments
are evaluated right-to-left, not left-to-right. (It just looks like it,
it doesn't actually happen this way; using say(~$x, ....) shows that).

Then again it might be correct, because the first positional parameter
of say() (which is slurpy, but doesn't matter here) is bound to $x, and
$x changes before say() is actually called.

Is it right that the parameter binds to the variable ($x), not to the
number (3) (which would be immutable)? I'm sure that in the presence of
"is rw" the bahviour cited above would be correct, but for 'is copy' or
the default I don't see a reason for that.

Cheers,
Moritz

Search Discussions

  • TSa at Jul 23, 2009 at 3:56 pm
    HaloO,

    Moritz Lenz wrote:
    I came to this

    12:51 <@moritz_> rakudo: my $x = 3; say $x, ' ', ++$x;
    12:51 < p6eval> rakudo 7b81c0: OUTPUT«4 4␤»
    12:51 <@moritz_> rakudo: my $x = 3; say $x, ' ', $x++;
    12:51 < p6eval> rakudo 7b81c0: OUTPUT«4 3␤»
    I would expect that to say '3 4' and '3 3' respectively.

    This looks very counter intuitive, because it looks like the arguments
    are evaluated right-to-left, not left-to-right. (It just looks like it,
    it doesn't actually happen this way; using say(~$x, ....) shows that).

    Then again it might be correct, because the first positional parameter
    of say() (which is slurpy, but doesn't matter here) is bound to $x, and
    $x changes before say() is actually called.
    I would opt for a strict left to right evaluation of expressions
    irrespective of precedence and associativity of operators. E.g.
    my $x = 2; $x++ ** $x; should evaluate to 8 not 4. And $x ** $x++
    should be 4 not 9. Also expressions like $a + $b * $c should evaluate
    $a first then $b and then $c.

    Is it right that the parameter binds to the variable ($x), not to the
    number (3) (which would be immutable)? I'm sure that in the presence of
    "is rw" the bahviour cited above would be correct, but for 'is copy' or
    the default I don't see a reason for that.
    Hmm, it seems to be the case that the binding is defined to be a
    readonly binding to the variable. I consider this a bad thing.
    We should have my $x = 1; foo($x++,$x,$x++); to call foo(1,2,2)
    and not foo(1,3,2) or even foo(2,3,1). The capture creation for
    the foo call should be strictly left to right and capturing the
    value at that moment.


    Regards, TSa.
    --
    "The unavoidable price of reliability is simplicity" -- C.A.R. Hoare
    "Simplicity does not precede complexity, but follows it." -- A.J. Perlis
    1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
  • Patrick R. Michaud at Jul 26, 2009 at 1:17 am

    On Thu, Jul 23, 2009 at 05:56:31PM +0200, TSa wrote:
    Hmm, it seems to be the case that the binding is defined to be a
    readonly binding to the variable. I consider this a bad thing.
    We should have my $x = 1; foo($x++,$x,$x++); to call foo(1,2,2)
    and not foo(1,3,2) or even foo(2,3,1). The capture creation for
    the foo call should be strictly left to right and capturing the
    value at that moment.
    ...except that captures don't capture values -- they form references.

    Pm
  • Yary at Jul 26, 2009 at 1:50 am

    On Sat, Jul 25, 2009 at 2:04 PM, Patrick R. Michaudwrote:
    On Thu, Jul 23, 2009 at 05:56:31PM +0200, TSa wrote:
    Hmm, it seems to be the case that the binding is defined to be a
    readonly binding to the variable. I consider this a bad thing.
    We should have my $x = 1; foo($x++,$x,$x++); to call foo(1,2,2)
    and not foo(1,3,2) or even foo(2,3,1). The capture creation for
    the foo call should be strictly left to right and capturing the
    value at that moment.
    ...except that captures don't capture values -- they form references.
    So we get a call to foo with three identical references to $x, which
    has the value "3", or "1"? That would be interesting. Or is capture
    meant to be lazy, and any postincrement is only called the first time
    foo dereferences that parameter? That would be very interesting! Which
    I would fully support in a language whose code I never had to
    maintain, but would not have to want to explain to anyone with a
    straight face.

    /me thinks he should hang out on #perl6 but knows he won't any time soon.
  • Larry Wall at Jul 27, 2009 at 9:10 pm

    On Sat, Jul 25, 2009 at 06:50:12PM -0700, yary wrote: : On Sat, Jul 25, 2009 at 2:04 PM, Patrick R. Michaudwrote:
    : > On Thu, Jul 23, 2009 at 05:56:31PM +0200, TSa wrote:
    : >> Hmm, it seems to be the case that the binding is defined to be a
    : >> readonly binding to the variable. I consider this a bad thing.
    : >> We should have my $x = 1; foo($x++,$x,$x++); to call foo(1,2,2)
    : >> and not foo(1,3,2) or even foo(2,3,1). The capture creation for
    : >> the foo call should be strictly left to right and capturing the
    : >> value at that moment.
    : >
    : > ...except that captures don't capture values -- they form references.
    :
    : So we get a call to foo with three identical references to $x, which
    : has the value "3", or "1"? That would be interesting. Or is capture
    : meant to be lazy, and any postincrement is only called the first time
    : foo dereferences that parameter? That would be very interesting! Which
    : I would fully support in a language whose code I never had to
    : maintain, but would not have to want to explain to anyone with a
    : straight face.

    Yes, I think think you're probably right that the correctest answer
    to this will be to make the operation of binding $x++ trigger
    the autoincrement lazily. But I don't think you'd have to explain
    anything for ordinary calls, since there is a one-to-one correspondence
    between capture formation and binding, and the binding happens almost
    immediately after capture composition (perhaps only notionally, since
    capture composition an obvious optimizer target). The only time it
    would be difficult to explain is if you say something like:

    my $capture := \($x++);
    foo(|$capture); # increments $x
    bar(|$capture); # increments $x again

    But perhaps \($x++) can be explained by analogy to { $x++ }. It's
    basically just a thunk, and the eventual binding and/or evaluation is
    what prevents it from degrading into the morass of call-by-name-ness.
    So it's very much like the thunks in

    $maybe ?? $x++ !! $y++

    where you don't know which will be incremented until the implementation
    of ??!! decides to run one thunk or the other.

    It's also a strange way to name a monadic sort of relationship:

    my $capture := \($x++);
    $x = 0;
    $capture xx * # 0,1,2,3,4
    Lately I've been thinking of lazy lists as Perl 6's cheap knockoff
    of the idea of monads, modulo the appropriate amount of handwaving
    (not to mention handwringing) over side effects. Naming a lazy list
    basically gives a name to the relationship between the consecutive
    elements (where in the case of infix:<...> the new elements are
    specifically defined in terms of the prior ones). Yes, I'm ignoring
    a bunch of cool type theory when I say that. I'm hoping this will
    make Perl 6 usable by non-geniuses without getting them into trouble
    too terribly often. :)

    But certainly a lot of the get-into-trouble examples involve $x++,
    so we'll need to be careful with that particular monad^Wside effect.

    Larry
  • TSa at Jul 29, 2009 at 4:21 pm
    HaloO,

    Larry Wall wrote:
    Yes, I think think you're probably right that the correctest answer
    to this will be to make the operation of binding $x++ trigger
    the autoincrement lazily.
    I consider this answer far from correct. Postincrement is an operator
    like any other code object and it returns a value. E.g. the standard
    postincrement does not return an lvalue, that is $x++ = 3 is an error.
    Overloaded definitions should adhere to this behavior.

    my $capture := \($x++);
    foo(|$capture); # increments $x
    bar(|$capture); # increments $x again
    Since postfix:<++> is like any other code object we would also
    have

    my $capture := \($x.blahh)
    foo(|$capture); # calls .blahh
    bar(|$capture); # calls .blahh again

    This should not be the case. The capture should call the code
    object once and capture the return value. The other way can
    be written as \({$x.blahh}) if that is what the programmer wants.

    But perhaps \($x++) can be explained by analogy to { $x++ }. It's
    basically just a thunk, and the eventual binding and/or evaluation is
    what prevents it from degrading into the morass of call-by-name-ness.
    So it's very much like the thunks in

    $maybe ?? $x++ !! $y++

    where you don't know which will be incremented until the implementation
    of ??!! decides to run one thunk or the other.
    But ??!! is specced to take three thunks as parameters. The capture
    generator \ should not have thunks as parameters. This means that
    \(some_condition() ?? $x !! $y) captures either $x or $y and sticks
    to that. It should not thunk the whole expression and evaluate
    some_condition whenever the capture is accessed.

    It's also a strange way to name a monadic sort of relationship:

    my $capture := \($x++);
    $x = 0;
    $capture xx * # 0,1,2,3,4
    \($x++) should not capture $x because this was the argument of
    the sub call. Or do we want \($x + $y) to capture $x and $y
    along with the fact that when the capture is accessed their
    values at that time need to be dispatched to infix:<+>?

    But certainly a lot of the get-into-trouble examples involve $x++,
    so we'll need to be careful with that particular monad^Wside effect.
    Actually not. Every code object invocation is a get-into-trouble
    example unless it is purely functional code.


    Regards, TSa.
    --
    "The unavoidable price of reliability is simplicity" -- C.A.R. Hoare
    "Simplicity does not precede complexity, but follows it." -- A.J. Perlis
    1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan
  • TSa at Jul 29, 2009 at 4:14 pm
    HaloO,

    Patrick R. Michaud wrote:
    ...except that captures don't capture values -- they form references.
    I know. The semantics I have in mind is available as \($x is copy)
    which unfortunately is not the default. I'm actually unsure if
    this is valid syntax because that implies a mixture of signature
    and statement syntax inside \(). E.g. the question is if
    \($x + $y is copy) is valid.


    Regards, TSa.
    --
    "The unavoidable price of reliability is simplicity" -- C.A.R. Hoare
    "Simplicity does not precede complexity, but follows it." -- A.J. Perlis
    1 + 2 + 3 + 4 + ... = -1/12 -- Srinivasa Ramanujan

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupperl6-language @
categoriesperl
postedJul 22, '09 at 11:03a
activeJul 29, '09 at 4:21p
posts7
users5
websiteperl6.org

People

Translate

site design / logo © 2021 Grokbase