Raku / doc

🦋 Raku documentation
https://docs.raku.org/
Artistic License 2.0
287 stars 291 forks source link

False statement in language/operators about Raku's evaluation model #4058

Open florian-pe opened 2 years ago

florian-pe commented 2 years ago

The issue concers this page : https://docs.raku.org/language/operators

Here is pretty much the first sentence

The precedence and associativity of Raku operators determine the order of evaluation of operands in expressions.

Which is false, as demonstrated by this example :

$ raku -e 'print(1) ** print(2) ** print(3); say ""'
WARNINGS for -e:
Useless use of "**" in expression "print(1) ** print(2) **" in sink context (line 1)
123

I made a github issure very recently about it, as I confounded operators precedence and associativity VS order of evaluation of operands. If there are no side effects, then it doesn't change anything and you wouldn't even know that the order is different, as a language user, but if there are side effects, then it becomes apparent that there is a distinction.

https://stackoverflow.com/questions/71941798/why-does-print-isnt-affected-by-operator-precedence/71942002

coke commented 2 years ago

The linked stackoverflow question is for perl, not raku.

florian-pe commented 2 years ago

@coke Yes, the stackoverflow question is about Perl. But what's your point ? My raku example clearly shows that what the documentation is wrong. The stackoverflow question is about the EXACT SAME subject.

florian-pe commented 2 years ago

And I should add the problem is not that the documentation is wrong abour a random issue. The problem is that it is wrong about the evaluation model of Raku. It is wrong about something so ridiculously fundamental that it's almost annoying to read when we know it is wrong.

Altai-man commented 2 years ago

B-but it should be (evaluating as stated in the docs), shouldn't it? I believe we want to ask why it works this way someone who knows the guts better to explain.

florian-pe commented 2 years ago

@Altai-man You're absolutely right, someone who knows the internals and/or the specifications should weight in to explain to us the rationale behind this.

I'm guessing that the raku implementation should behave as stated in the specification (at first RFCs + Apolcalypse, Exegesis, Synopsis, but now the "spec test" I believe). The docs aren't meant to be a specification I think, which is kind of a shame.

The Docs are really more a tutorial than a reference. And a lot of times the features are not described exhaustively.

I really think this is one of think that is unfriendly to beginners. Because if you need ed specifics about the semantics of a given feature, where else are you supposed to get your answer if it is not in the Docs ?

The Docs probably started with good intentions. They are meant for beginners, but not for intermediate/advanced users.

The Regex and Grammars sections are really incomplete for example. A lot of what is exposed in the Apocalypses/Synopsis/Exegesis are simply left out. Sometimes the specification changed, sometime features aren't yet implemented, sometimes features are implemented but not documented. We just don't know.

It's also kind of a shame considering that regexes are Perl's 🧬.

lizmat commented 1 year ago
    my Mu $methodcall       := nqp::hash('prec', 'y=');
    my Mu $autoincrement    := nqp::hash('prec', 'x=');
    my Mu $exponentiation   := nqp::hash('prec', 'w=', 'assoc', 'right');
...
trait_mod:<is>(&infix:<**>, :prec($exponentiation));

That makes exponentiation the tightest infix operator, right associative.

It may be late, but I think Raku is doing the right thing in this respect. Am I missing something?

thundergnat commented 1 year ago

Raku is doing the right thing. (In this case at least.) The return value of a successful print statement is 1, (well... True, but 1 in numeric context,) so it is evaluating 1 ** 1 ** 1, then not doing anything with it; hence the warning.

Consider what happens if we override the print routine with something that returns its parameter (and if we use numbers that will generate a value other than 1):

sub print { &CORE::print($^a); $^a }          # override print to return its supplied parameter
print(2) ** print(3) ** print(4);             # warns "useless use"
say '';                                       # add a line feed since print doesn't
say "\n", print(2) ** print(3) ** print(4);   # as expected
say 2 ** 3 ** 4;                              # for comparison

output:

Useless use of "**" in expression "print(2) ** print(3) **" in sink context (line 2)
234
234
2417851639229258349412352
2417851639229258349412352

Looks to me like it is doing the right thing. I suspect the OP may be confused about what print() returns.

Edit: I suppose the order that the value generating routines are processed is not the same as the order the expression is evaluated is what the point of this was. And I missed that. :eyeroll:

However, I still think that the important bit is the order of evaluation of the final expression rather than the order-of-operation of any side-effect generating expression. Perhaps it is worth mentioning that evaluation order of any interim values is not guaranteed, only the final evaluation.

2colours commented 1 year ago

Oh yes... I can recall a similar case with the hyper operator.