14

An example on the 'class Signature' page appears as:

sub named(:official($private)) { "Official business!" if $private }; named :official; <----- Note: That's where to example ends ... there is no output described or shown. So I typed in the code and when the method 'named' is executed it always prints "Official business!" no matter the value of $private. That is, if $private=True then invoking 'named' prints "Official business!" as you might expect but with $private=False invoking 'named' still prints 'Official business!' whereas I thought there should be no output generated. I'm missing something aren't I but what?

Keith Hardy
  • 171
  • 4
  • 7
    Welcome to SO. Without an [MRE], Qs can be really hard to answer, and your Q is a case in point. You've described a problem *in English* -- "with `$private=False` invoking 'named' still prints 'Official business!'" -- but not code. I've found a way to get that result (described in yet another answer to your Q) but it required me to use pretzel logic. Bottom line, if none of our answers help, please edit your Q to provide a [MRE]. And, if you aren't aiming to tease readers with riddles, and write any other SOs, please write a [MRE] for them when you first publish them. Again, welcome to SO. :) – raiph Nov 08 '21 at 00:34
  • Apologies if the triple link felt weird. I'm tempted to delete the comment but will for now just explain myself. ❶ Writing `[mre]` (not as code) is automatically converted into a link. (Write it as `a [mre]` not `an [mre]`. Oops.) ❷ I'm prolix but try to complete all my related thoughts in a single comment. My first go deliberately avoided triple mre links, but was too long. Switching to `[mre]` solved that problem. ❸ When I published the comment and realized "Ah, I forgot that", I decided the MRE emphasis was OK, perhaps warranted. I hope you didn't feel bad; that certainly wasn't my intent. – raiph Nov 10 '21 at 17:28

4 Answers4

7

I see how the doc example was confusing. Here's an expanded version of that explanation:

sub named(:official($private)) {
   # Inside the function, the argument the caller passed in
   # is bound to the variable $private.  Nothing is bound to official.
   say $private;
}

# Outside the function, the caller doesn't need to care what term the 
# function uses.  All it needs to know is the name of the parameter – :official
named(:official('foo')); # OUTPUT: «foo»

This is especially handy when the function is in a different module – the owner of the function can refactor the name of the their $private argument without breaking any external callers. And, if they think of a better name for external callers to use, they can even add that without breaking backwards compatibility: sub named(:official(:better-name(:$private))) { … } lets callers use either :official or :better-name as the parameter name, without having any impact on the variable name inside the function.

Does that make more sense?

Oh, and one note regarding this:

if $private=True then invoking 'named' prints "Official business!" as you might expect

If I'm understanding you correctly, you mean writing something like

sub named(:official($private)=True) { "Official business!" if $private }

Is that what you meant? If so, you should know that $private=True in that signature isn't really setting $private to anything – it's just providing a default value for the variable $private. So you can get this output:

sub named(:official($private)=True) {
      say $private;
}

named();               # OUTPUT: «True»
named(:official(42));  # OUTPUT: «42»

In any event, I'll send in a PR to the docs repo and try to clarify the named argument examples a bit. Hope you enjoy Raku!

codesections
  • 8,900
  • 16
  • 50
  • I just tried `sub named(:official($private=True)) { say $private }` in a couple versions of Rakudo and got a compile-time error for both. What version did you use to get that to compile? – raiph Nov 08 '21 at 00:09
  • @raiph, sorry that was a copy-paste error on my part (which I've now fixed); the `)` needs to go before `=True`, not after. Thanks for pointing that out! – codesections Nov 08 '21 at 01:33
  • Huh. I thought I'd tried that. (It's part of the answer I just published. Which I now need to go fix...) – raiph Nov 08 '21 at 01:35
  • @raiph I'm interested to learn that you didn't realize that would compile, despite how knowledgeable you are. I guess it goes to show how differently we can all use Raku, because that's syntax I use pretty regularly – especially when writing CLIs with flags. Something like `sub MAIN(Bool :v(:$verbose)=True) {}` – codesections Nov 08 '21 at 14:07
  • 2
    A riddle inside a riddle. :) ❶ I thought it *would* compile. And ❷ might explain what Keith was trying/seeing. ❸ But when I tried it, it failed at compile time. (With `)` both before and after.) I even included that "fact" in my answer. ❹ I published my answer. ❺ I wrote my first comment on your answer. ❻ You told me it *did* work! ❼ Huh?!? Quick double check. Argh! I'd screwed up! ❽ I edited my answer to remove my false "fact". ❾ (This all happened in less than 5 minutes so there's no record of this in my answer's versions.) ❿ I don't see how it solves Keith's Q/riddle... – raiph Nov 08 '21 at 14:31
  • ⓫ Ahhh. Got it. I'd screwed up again. I could now delete my prior comment, or edit it to say the penny has dropped (ie I now think your answer solves Keith's riddle) because it's less than 5 minutes since I wrote it, or at least it was when I began writing this one, but then that would impoverish the record of my pretzel logic, steeling it from [Dan's time machine](https://en.wikipedia.org/wiki/Pretzel_Logic_(song)), so I won't do that. – raiph Nov 08 '21 at 14:41
  • 2
    "All it needs to know is the name of the parameter – :public". Did you mean `:official` instead of `:public`? – uzluisf Nov 10 '21 at 16:12
7

There are a couple of things going on in this short example:

sub named(:official($private)) { "Official business!" if $private }
           -------- --------
               |        |
               |        > '$private' is the name of this var within the sub
               |
               > 'official' is the (sigilless) name of this var outside
           
           ------------------
                   |
                   > ':official($private)' is the 
                            raku Pair 'official => $private'  

named :official
----- ---------
  |       |
  |       > the raku Pair 'official => True' (so $private ~~ True)
  |
  > the same as 'named( official => True );'

So when you try this in the repl...

> named :official;             #Official business!
> named( official => True )    #Official business! [same thing]
-or-
> named :!official             #()
> named( official => False )   #() [same thing]

At first encounter, in this example, raku is quite quirky. Why?

  • the raku Pair literal syntax makes it easy to handle common function argument cases such as :dothis but :!notthat adverbs
  • the :name(value) formulation is re-used here to map external to internal var names - nothing special needed since the Pair syntax already does it - but super useful for code encapsulation
  • similar situation with argument aliases ... you can think of this as Pairs of Pairs ... again, no special syntax needed since just using the built in Pair literal syntax

So, imho, raku is uniquely cool in that we just have to learn some basic elemental syntax (in this case, the Pair literals) and then they can be applied consistently in many ways to concisely solve quite thorny coding scenarios.

librasteve
  • 6,832
  • 8
  • 30
5

Via pretzel logic I've concluded that:

  • You may have carefully written your Q to trick us, and you will reveal the truth if we correctly solve the riddle.

Or (a tad more likely perhaps... ):

  • Adopting that mindset will help us all -- you, readers, answerers -- have fun as we try to solve the riddle inherent in your sincere Q even if you weren't planning to make this fun...

Either way, please read this answer and let me know if it contributes to solving the riddle. TIA. :)


I'm missing something aren't I but what?

Perhaps this is a key for solving the riddle: we're supposed to ask ourselves "What has Keith deliberately missed out of the Q?".

Of course, if this is so, the first thing you've omitted is that it's a riddle. In which case, major kudos! And if it's not an intentional riddle, well, it's still a riddle, so kudos anyway, and let's try solve it!


@codesection's answer points at perhaps the strongest clue. While you didn't write a minimal reproducible example, you did write the sub definition code, and you did say you'd written $private=False.

So let's presume you literally wrote that sub definition and you literally wrote $private=False.

Furthermore, that:

with $private=False invoking 'named' still prints 'Official business!' whereas I thought there should be no output generated.

means there was some output generated in all cases.

Anyhoo, how can all of these things be true at the same time?


These are compile-time errors:

sub named( :official( $private = True ) )   { "Official business!" if $private }
sub named( :official( $private = False ) )  { "Official business!" if $private }

So is this:

$private = False;

unless there was a prior my $private....

And this:

sub named( :official( $private ) ) {
  $private = True;
  "Official business!" if $private
}
named;

yields Cannot assign to a readonly variable or a value (currently at runtime) because, by default, parameters to routines are readonly.


You also said there was output (ostensibly Official business!, but perhaps sometimes something else, eg ()?).

You didn't mention a say or similar routine for displaying output. How could that be? Let's introduce a say.


So, putting these things together, and applying pretzel logic, I arrived here:

sub named(:official($private)) { "Official business!" if $private }
my $private;
$private = False;
say named :official;         # Official business!
say named :!official;        # ()
say named official => False; # ()
say named :official(False);  # ()
say named;                   # ()

An interpretation of this as solving the riddle:

  • () is not "no output". So it doesn't contradict your Q narrative.

  • We've written $private = False. It has no impact on the code, because of lexical scoping, but we did write it. :)


Am I warm?

raiph
  • 31,607
  • 3
  • 62
  • 111
3

Dear kind and generous raku folk,

Thank you for the replies and discourse. After which I now understand what I didn't understand. And the root of my misunderstanding started here: At the time of writing this, the doc page for class Pair says:

There are many syntaxes for creating Pairs

and goes on to give examples, one of which is this line:

:foo(127) # short for foo => 127

So I thought in the raku interactive environment that these two lines:

> :foo(127)
foo => 127
> :foo.kv
(foo True)

Would answer (foo 127) for the last line. However sadly, no, the answer is (foo True)

But I didn't know that when I went off to read the 'Class Signature' page and got into a pickle with the example:

sub named(:official($private));
named :official

Which now appears to be a truncated example.

And sent me off on a tangent thinking there was lot of magic in what a colon can do.

Anyway, I hope everyone is keeping well ... see you later alligators.

raiph
  • 31,607
  • 3
  • 62
  • 111
Keith Hardy
  • 171
  • 4
  • 2
    1) "Would answer (foo 127) for the last line. " That's because `:foo` is simply a shorthand for `:foo(True)` or `foo => True`. If you want `(foo 127)`, then you've to specify that other value explicitly, i.e., `:foo(127).kv #=> (foo 127)`. I think having pairs like `:foo` default to boolean values make these pairs excellent for boolean flags (e.g., `send-message 'hello!', :verbose, :header`). 2) "... see you later alligators." Rakoons might be a cooler moniker for Rakus folks ;-) (thanks lizmat for coining the term!) – uzluisf Nov 10 '21 at 16:28