doc
doc copied to clipboard
Replace incorrect use of "currying" with "priming"
The documentation currently uses the term "currying" to refer to what is more broadly known as "partial function application" (but frequently incorrectly called "currying"). However, Raku generally doesn't use the phrase "partial function application", probably because it's a real mouthful and could be off-putting to people not familiar with functional programming jargon. Instead, Raku prefers the term "priming", see S06.
Accordingly, this PR changes (nearly) all uses of "currying" or related words to the "priming" equivalent; it also adds a "priming" entry to the glossary.
The only two (intentional) uses of "currying" left are in a TODO section of the Haskell-to-Raku guide and in the documentation for the (Rakudo-specific, unspecified) type CurriedRoleHOW
.
See related discussion with @raiph in the comments to this StackOverflow answer.
I think the aim is noble but do you think this is enough? I mean, we have been using the term "whatever-currying" somewhat regularly for years now. How many involved people know that we are practically breaking away from that terminology?
I don't think this applies to whatever-currying, but more to what .assuming
does?
I support changing the documentation from "currying" to "priming". The change makes the documentation more correct, and just because some people were accustomed to using words in the wrong way before, that doesn't mean they need to keep doing so going forward. Using more standard terms will also make it easier for the wider world to come to Raku. And a key thing is that it isn't changing actual language keywords so it isn't going to break code.
I will also say I'm surprised this wasn't already done almost a decade ago, as I distinctly recall being in a discussion about this very matter then. I have my own other language heavily influenced by Raku, and I used the term "currying" originally to refer to the partial function application, following Raku's example, and then the discussion convinced me to refer to it as "priming" instead. I had thought Raku was making the same change at that time.
@lizmat wrote:
I don't think this applies to whatever-currying, but more to what
.assuming
does?
But the point is that whatever-priming/currying does exactly the same thing as .assuming
. Here are functionally equivalent lines of code:
my &add1-v1 = 1 + *;
my &add1-v2 = &[+].assuming(1);
my &find-primes-v1 = *.grep(&is-prime);
my &find-primes-v2 = List.^lookup('grep').assuming(*, &is-prime);
And since using *
achieves the same result as using .assuming
, it makes sense to call them both "priming".
I didn't see this until now, but S06 makes this point explicitly:
Perl 6 has several ways of performing partial function application. Since this is an unwieldy term, we've settled on calling it priming. (Many folks call this "currying", but that's not really a correct technical usage of the term.) Most generally, priming is performed on a Callable object by calling its .assuming method, described elsewhere. This section is about a convenient syntactic sugar for that.
For any unary or binary operator (specifically, any prefix, postfix, and infix operator), if the operator has not specifically requested (via signature matching) to handle * itself, the compiler is required to translate directly to an appropriately primed closure at compile time. We call this autopriming.
Maybe ^^^^ is what @duncand is remembering being settled, and the docs just never got updated?
Here are functionally equivalent lines of code: my &add1-v1 = 1 + *; my &add1-v2 = &[+].assuming(1);
Except that the first creates a Callable
out of thin air, and the second one creates a Callable
by wrapping an existing Callable
. I can see the second one be called "priming". But calling the first one "priming" as well, feels wrong to me.
For instance, what would be the "assuming" version of *.frobnicate
?
Except that the first creates a
Callable
out of thin air
No it doesn't. Both create a Callable
by wrapping &infix:<+>
, just with different spelling.
For instance, what would be the "assuming" version of *.frobnicate ?
That's just my second example but without assuming any args. So it'd be:
my &frobnicate = WhateverTypeHasFrobnicateMethod.^lookup('frobnicate');
# or, if you prefer to _explicitly_ assume nothing:
my &frobnicate2 = WhateverTypeHasFrobnicateMethod.^lookup('frobnicate').assuming();
(But all that does is let you call frobnicate
with subroutine syntax, so you might as well have just used frobnicate $arg:;
)
Except that method calls are late bound, so that won't fly.
In any case, to me there is a difference between creating a Callable
out of thin air (which I think the syntax *.frobnicate
is doing), and calling .assuming
on an existing Callable
.
Except that method calls are late bound, so that won't fly.
I see what you mean; Str.^lookup('tc').assuming()
always calls the Str
method, whereas *.tc
will call the first tc
method in the mro
of whatever it's called on.
So here's how I'd describe that difference: &assuming
is a function that takes a function and 0 or more arguments; it returns a function that calls the original function with the both the arguments passed to &assuming
and the arguments passed to the inner function.
Or, in code a simplified version (e.g., no named args) of &assuming
would be:
sub assuming(&code, *@args) {
-> *@rest { code(|@args, |@rest) }
}
Whereas *
, when used before a method call, is a function (er, syntax that is equivalent to a function) that takes a method-name and zero or more arguments. It returns a function that takes 1 or more arguments; this inner function calls the method named in the outer function with the arguments passed to *
and the arguments passed to the inner function.
Or in code (again, simplified and this time also ignoring *
when used as an operand).:
multi whatever(Str $method-name, *@args) {
-> $invocant, *@rest { $invocant."$method-name"(|@args, |@rest)}
}
So, I now agree with @lizmat that these are two (subtly) different things. And that &assuming
meets the strict definition of "partial function application" whereas *
does not – even though *
does perform partial application, it does something more.
But even if what *
does isn't quite partial application, it's certainly not currying. And I agree with S06 that it makes sense to call what *
does "priming" – which, after all, doesn't have to be 100% the same as a strict definition of partial function application. For example, when we have the expression *.grep(&so)
it makes sense to say that we've primed the grep
method with &so
. More generally, I'd say that – though your point about late-binding is important – what &assuming
and *
do is similar enough that we ought to use the same terminology when discussing them.
@codesections wrote:
I didn't see this until now, but S06 makes this point explicitly:
Perl 6 has several ways of performing partial function application. Since this is an unwieldy term, we've settled on calling it priming. (Many folks call this "currying", but that's not really a correct technical usage of the term.) Most generally, priming is performed on a Callable object by calling its .assuming method, described elsewhere. This section is about a convenient syntactic sugar for that. For any unary or binary operator (specifically, any prefix, postfix, and infix operator), if the operator has not specifically requested (via signature matching) to handle * itself, the compiler is required to translate directly to an appropriately primed closure at compile time. We call this autopriming.
Maybe ^^^^ is what @duncand is remembering being settled, and the docs just never got updated?
Yes, thank you!
I should also clarify that I don't necessarily support the actual changes of this specific pull request, but rather the principle of using "priming" rather than "currying" where it is the more clearly correct meaning. Before it seemed like this was recognized but not completely followed through on years ago, like you found some vestigial uses of the wrong term. But now I recognize it is possible that what you found is some cases where "currying" is referring to something else. But I don't know enough to judge so I'm neutral on the current PR itself.
On a different subject matter I noticed it seems GitHub allows me to edit other people's comments, which is odd, I would have thought only the author of a comment would be allowed to edit it.
Just a heads up that in RakuAST there is CurryThunk
. This could be changed to PrimeThunk
without any issue.
At first I was against this change but the more I think about it the more I think that "priming" something is a lot more evocative to me than "currying" something is, even though the latter still feels more familiar.
My point is specifically that it might cause confusion if this change happens without people really knowing about it, and that in general it almost feels more important to inform people about it than what the doc says. If the doc just "contradicts" what people say and nothing reflects on that, I think that's almost automatically bad PR ("they are indecisive", "look how many of them use plain wrong terminology" etc.). Just think of the "path to Raku" topic; it would be great to do better than that, regarding clear communication and expressing some sort of expectations to people who want to help anyway.
@2colours wrote:
My point is specifically that it might cause confusion if this change happens without people really knowing about it, and that in general it almost feels more important to inform people about it than what the doc says. If the doc just "contradicts" what people say and nothing reflects on that,
Those all seem like fair points. Do you have a suggestion for what we could/should do to inform people/reflect on the change? The only thing that's coming to mind for me is one of us writing a personal blog post, but I'm not sure if that would address your concerns or not?
(The "you" ^^^ can be singular or plural; I'd of course welcome ideas from anyone about how to communicate re: doc terminology. AFAIK, we don't currently have a process for that but I can see how it'd be useful.)
I think as far as the existing patterns go, writing, if only a short article about the rationale, and "circulating" it in the weekly/mastodon/reddit/IRC is mostly good. I can't immediately think of a better way now.
See ticket #3796
I am in general in favor of this change; can we address existing comments and can someone summarize what's left to decide?
@codesections, @lizmat - is there anything left to address in this PR or can I apply it?
@coke,
I'm with codesections (and Larry) that the word "Currying" is a poor choice (because what it refers to is not currying), and the word "Priming" is a good choice (because it's a good choice of English word that describes what it's doing), and thus the "Currying" heading @silentTeee spotted above should be changed to "Priming".
Did silentTree's as a separate followup commit. Thanks everyone.