Defining new infix operators in Raku - operators

Please tell me how to define a new operator in Raku, for example, how would one implement an arrow operator defined something like this:
operator ▶ {my ($left, $right) = #_; $left->{$right}}

It's fairly simple:
sub infix:<▶> ($left, $right) {
$left."$right"()
}
# Example:
class Foo {
method bar { "hello" }
}
my $a = Foo.new;
say $a ▶ 'bar'
# hello
The sub infix:< > defines new infix operators (other options are prefix, postfix, circumfix, and postcircumfix, the latter two require an opening and closing part, like <( )> for open and close parentheses).
The ($left, $right), as the name suggests, handle the left and right side values.
To call a method based on an string, you use the structure ." "() with the method name in quotation marks and followed by parentheses — even if there are no arguments. In this case, we just insert the variable for basic interpolation, although more complex operations are possible.

Related

Kotlin multiline-string annotation parameters

In Java, now that it supports text blocks, you can do this:
#Schema(description = """
Line one.
Line two.
""")
public void someMethodName() { ... }
In Java, text blocks are compile-time constants and they automatically remove the indents. But in Kotlin, if you do this:
#Schema(description = """
Line one.
Line two.
""")
fun someMethodName() { ... }
you end up with unwanted spaces in front of each line. Unfortunately, you can't use trimMargin() or trimIndent() because they are not compile-time constants. Is there a way to make it look as nice in Kotlin as it does in Java?
Unfortunately for your use case, I don't think so. The point of the triple quote is to provide a way to write "Formatted" text into a string. If Java doesn't behave the same way as Kotlin, then technically it's the odd one out as any other language I've used behaves the same way as Kotlin. Your best alternative would be something like the following:
#Schema(description = "Line one.\n"
+ "Line two.\n"
+ "Line three.")
fun someMethodName() { ... }
The string concatenation will be performed at compile time since it is between literals.

How do I specify an ActionListener in Kotlin?

I want to add an ActionListener to a JButton in Kotlin. In Java, I would just write this:
JPanel makeButtonPanel() {
JPanel panel = new JPanel(new FlowLayout());
JButton dirButton = new JButton("Change directory");
dirButton.addActionListener(e -> chooseDirectory());
panel.add(dirButton)
return panel;
}
But it's not so simple in Kotlin. I first tried this:
private fun makeButtonPanel() : JPanel {
val panel = JPanel(FlowLayout())
val dirButton = JButton("Choose")
dirButton.addActionListener(e -> chooseDirectory()) // error message here
// ...
}
private fun chooseDirectory() { ... }
But I'm getting this error message:
Type Mismatch
Required: ((ActionEvent!) -> Unit)!
Found: KFunction1<ActionEvent, Unit>
I understand that the ! means that this is a java method with uncertain nullability, but that doesn't help me understand how to write it. All I want it to do is call the chooseDirectory() method. There must be a clean, simple way to do this, but I don't see it.
As you've discovered, you need to use braces ({ }).
This is because braces are a necessary part of defining a lambda in Kotlin.  (That differs from languages like Java and Scala, where the necessary part is the -> or => arrow.  That's because in Kotlin the arrow is optional if there are one or no parameters; if one, the it keyword is used.)
Without the braces, the code would call your chooseDirectory() function, and try to pass its result to addActionListener() — which obviously wouldn't work.
Braces are also sufficient: they're taken as defining a lambda unless you're giving the body of a function or method or an if/when branch.  (Again, this differs from most C/Java-like languages.  In Kotlin, if you just want a block scope, you have to use a construct such as run.)
As for the parentheses, they're optional here.  You could include them if you wanted:
dirButton.addActionListener({ chooseDirectory() })
But Kotlin has a convention that if a function's last parameter is a function, you can pass it after the parens:
dirButton.addActionListener(){ chooseDirectory() }
And if that would make the parens empty, then you can omit them entirely:
dirButton.addActionListener{ chooseDirectory() }
That's to allow functions that look like new language syntax.  For example, you may have met the with function:
with(someObject) {
itsProperty = someValue
}
That's just a perfectly ordinary function, defined in the standard library, and taking a function as its last parameter.  Similarly, repeat:
repeat(10) {
// Some code to be run 10 times…
}
There's one further thing worth mentioning here.  In Kotlin, lambdas are one way to define functions, which are first-class types and can be defined, passed around, and used just like other types.  This differs from Java, which has traditionally used interfaces for those purposes — often interfaces with a Single Abstract Method (‘SAM interfaces’) — and in which lambdas are little more than syntactic sugar for defining an anonymous implementation of such an interface.
As a special case, for interoperability, Kotlin allows a lambda to define an implementation of a Java SAM interface (or, since Kotlin 1.4, of a Kotlin fun interface), instead of a function.
ActionListener is a Java SAM interface, which is why you can use a lambda here.
Okay, I figured it out, and it was pretty simple. I just have to dispense with the parentheses and say
dirButton.addActionListener { chooseDirectory() }
I'm still not clear on when I should use braces instead of parentheses.

If regexes are methods, which class they correspond to?

Regexes are actually Methods:
say rx/foo/.^mro # ((Regex) (Method) (Routine) (Block) (Code) (Any) (Mu))
In that case, it means that they can act on self and are part of a class. What would that class be? My hunch is that it's the Match class and that they are actually acting on $/ (which they actually are). Any other way of formulating this?
Ultimately, all regexes expect to receive an invocant of type Match or some subclass of Match. In Perl 6, an invocant is simply the first argument, and is not special in any other way.
Those regexes declared with rule, token or regex within a package will be installed as methods on that package. Most typically, they are declared in a grammar, which is nothing more than a class whose default parent is Grammar rather than Any. Grammar is a sub-type of Match.
grammar G {}.^mro.say # ((G) (Grammar) (Match) (Capture) (Cool) (Any) (Mu))
It's thus quite natural to see these as just methods, but with a body written in a different language. In fact, that's precisely what they are.
It's a little harder to see how the anonymous regexes are methods, in so far as they don't get installed in the method table of any type. However, if we were to write:
class C {
method foo() { 42 }
}
my $m = anon method () { self.foo }
say C.$m()
Then we see that we can resolve symbols on the invocant through self, even though this method is not actually installed on the class C. It's the same with anonymous regexes. The reason this matters is that assertions like <ident>, <.ws>, <?before foo> and friends are actually compiled into method calls.
Thus, anonymous regexes being methods, and thus treating their first argument as an invocant, is what allows the various builtin rules, which are declared on Match, to be resolved.
A method does not have to correspond with any class:
my method bar () { say self, '!' }
bar 'Hello World'; # Hello World!
my regex baz { :ignorecase 'hello world' }
'Hello World' ~~ /<baz>/;
'Hello World' ~~ &baz;
&baz.ACCEPTS('Hello World'); # same as previous line
# baz 'Hello World';
By default methods, and by extension regexes have a has relationship with whatever class they are declared inside of.
class Foo {
method bar () { say self, '!' }
# has method bar () { say self, '!' }
regex baz { :ignorecase 'hello world' }
# has regex baz () { :ignorecase 'hello world' }
}
A regex does need some requirements fulfilled by whatever it's invocant is.
By just running it as a subroutine, it tells you the first one:
my regex baz { :ignorecase 'hello world' }
baz 'Hello World';
No such method '!cursor_start' for invocant of type 'Str'
in regex baz at <unknown file> line 1
in block <unit> at <unknown file> line 1
Usually a regex is declared inside of a class declared with grammar.
grammar Foo {
}
say Foo.^mro;
# ((Foo) (Grammar) (Match) (Capture) (Cool) (Any) (Mu))
So the requirements are likely fulfilled by Grammar, Match, or Capture in this case.
It could also be from a role that gets composed with it.
say Foo.^roles.map(*.^name);
# (NQPMatchRole)
There is even more reason to believe that it is Match or Capture
my regex baz {
^
{ say 'baz was called on: ', self.^name }
}
&baz.ACCEPTS(''); # baz was called on: Match
my regex baz ( $s ) {
:ignorecase
"$s"
}
baz Match.new(orig => 'Hello World'), 'hello';
# 「Hello」
I see no reason someone couldn't do that themselves in a normal class though.
Note that $/ is just a variable. So saying it is passed to a regex is a misunderstanding of the situation.
my regex baz ( $/ ) {
:ignorecase
"$/"
}
'Hello World' ~~ /<baz('hello')>/;
# 「Hello」
# baz => 「Hello」
It would be more accurate to say that when calling a regex from inside of another one, the current $/ is used as the invocant to the method/regex.
(I'm not entirely sure this is actually what happens.)
So the previous example would then be sort-of like this:
'Hello World' ~~ /{ $/.&baz('hello') }/;
This explanation combines what I think Brad++ and Jonathan++ just taught me, with what I thought I already knew, with what I discovered as I dug further.
(My original goal was to directly explain Brad's mysterious No such method '!cursor_start' message. I've failed for now, and have instead just filed a bug report, but here's what else I ended up with.)
Methods
Methods are designed to work naturally in classes. Indeed a method declaration without a scope declarator assumes has -- and a has declaration belongs inside a class:
method bar {} # Useless declaration of a has-scoped method in mainline
But in fact methods also work fine as either:
subs (i.e. not behaving as an object oriented method at all); or
methods for prototype-based programming (i.e. object orientation, but without classes).
What really makes methods methods is that they are routines with an "invocant". An invocant is a special status first parameter that:
Is implicitly inserted into the method's signature if not explicitly declared. If a method is declared inside a class, then the type constraint is that class, otherwise it's Mu:
class foo { my method bar {} .signature .say } # (foo: *%_)
my method bar {} .signature .say # (Mu: *%_)
Is a required positional. Thus:
my method bar {}
bar # Too few positionals passed; expected 1 argument but got 0
Is always aliased to self. Thus:
my method bar { say self }
bar 42 # 42
Is occasionally explicitly declared by specifying it as the first parameter in a signature and following it with a colon (:). Thus:
my method bar (Int \baz:) { say baz }
say &bar.signature; # (Int \baz: *%_)
bar 42; # 42
bar 'string'; # Type check failed in binding to parameter 'baz'
Regexes
Focusing just on the invocant perspective, regexes are methods that take/expect a match object as their invocant.
A regex is typically called in three somewhat different scenarios:
By direct use. For example my regex foo { . }; say 'a' ~~ &foo; # 「a」 (or just say 'a' ~~ / . /; # 「a」, but I'll only cover the essentially identical named example to simplify my explanation). This translates to say &foo.ACCEPTS: 'a'. This in turn is implemented by this code in Rakudo. As you can see, this calls the regex foo with the invocant Match.'!cursor_init'(...) -- which runs this code without :build. The upshot is that foo gets a new Match object as its invocant.
By way of the Grammar class's .parse method. The .parse method creates a new instance of the grammar and then calls the top "rule" (rule/token/regex/method) on that new grammar object. Note that a Grammar is a sub-class of Match; so, just as with the first scenario, the rule/regex is being passed an as-yet-empty match object. If the top rule matches, the new grammar/match object will be returned by the call to .parse. (Otherwise it'll return Nil.)
By way of one of the above. The top rule in a grammar will typically contain calls to lower level rules/tokens/regexes/methods. Likewise, a free standing rule/regex may contain calls to other rules/regexes. Each such call will involve creating another new grammar/match object that becomes the invocant for the nested call. If the nested call matches, and it's a capturing call, then the new grammar/match object is added to the higher level grammar/match object.

What's the advantage of creating a one line function that contains a string, that wouldn't be achievable by just assigning a string to a variable?

In Kotlin, I understand that a string can be assigned to a function directly, such as:
fun foo(): String = "Hello World"
But you can also assign a String to a variable directly as well:
var foobar: String = "Hello Word"
My question is, why would you ever create a function when you could just create a variable? I can't see the point in the existence of this functionality.
The interesting thing about
fun foo(): String = "Hello World"
is that it is using the expression syntax, and is equivalent to:
fun foo(): String {
return "Hello World"
}
While just returning a constant isn't very useful, using the expression syntax, avoiding the {block} and return statements allows much more concise function definitions in the case where the entire function can be expressed in one expression.
For example, if foo() was a method on a class, you could say hello with a property of that class:
class Hello(var what : String = "World") {
fun foo(): String = "Hello, $what!"
}
fun main() {
val hello = Hello()
println(hello.foo())
hello.what = "Universe"
println(hello.foo())
}
This prints:
Hello, World!
Hello, Universe!
This is more about when to prefer a function v/s a property.
Kotlin coding conventions has a section that describes this.
A property should be preferred over a function when-
the underlying algorithm does not throw
value is cheap to calculate (or caсhed on the first run)
returns the same result over invocations if the object state hasn't changed
In terms of an API use-case, in some cases exposing a function instead of a property might be a good idea as that gives you the scope to change the implementation of this API in future. What might be a hardcoded value today, could be replaced by code that computes the value in future.
It's simple, think about what the word coding means. Coding rules. Rules that are complicated get broken down in rules that are exactly one level below in abstraction, so that the program is as intelligible as possible.
Well, the function name is just one level above the expression. This is even more true in a language as expressive as kotlin where one line can easily be equivalent to several lines of Java.
If you are talking about strings or primitives exclusively then, yes, an attribute is a more natural choice than a function.

What do grave accents do/mean in Kotlin?

In as many expressions/definitions as possible please.
I'm writing a test function, where after the call fails, the function returns:
`this `fails with` "the state is propagated"`
(with the grave accents surrounding fails with ^ i don't know how to escape, sorry)
You want to use them when something is a Kotlin keyword (like Java's System.in) but you need to call it. Then you can do
System.`in`
instead to make it work.
You can also use this in variables, functions, classes and any other identifiers. There is a small paragraph on this topic on Kotlin's documentation.
Actually, it is more than that.
You can use any class, function, variable, or identifier whose name contains spaces or symbols with grave accents.
class `Class name with spaces` {
fun `method name with spaces, +, -`(`a parameter`: Int) {
val `variable?!` = `a parameter` + 1
println(`variable?!`.toString())
}
}
fun main(args: Array<String>) {
val instance = `Class name with spaces`()
instance.`method name with spaces, +, -`(100)
}
This is a compilable and working code:
This is often used in testing, in order to make the test method names self-explanatory.
class OperationsUnitTest {
#Test
fun `addition should be commutative`() {
...
}
}