Bindings
Here we will look at some more real world examples of writing code in niva. https://github.com/gavr123456789/bazar/tree/main/Bindings
Simple example
To bind some external types and methods we use internal Bind package:content:
method.
Let's imagine we need to bind a type Person from Java.
First we will add just type itself, since all fields are private, we will add it without them:
Then lets bind getters and setters. For that we have additional fields:
arg:
Now let's add methods.
To bind void changeAge(int newAge)
we will use keyword message changeAge::Int -> Unit
With introduceFriend(String friendName, int friendAge)
we have a problem:
we can't just bind it because it contains 2 arguments, so first lets come up with a new name.
It could be introduceFriend: age:
if we are pragmatic, but in Smalltalk methods usually named so it reads like English. person introduceFriend: "Bob" age: 42
is not too good so lets make it longer but more Smalltalk like:
See, much better, even though it is longer now, we write code once and read dozens of times, so readability is much more important, plus the length is unimportant because the methods will be autocompleted by LSP.
Try to come up with a name for the isAdult function.
Full bind would look like:
@rename:
@rename
is useful when signature of niva method doesn't match with target matches: 1 from: 2 to: 3
== 1.fromTo(2, 3)
not: HttpClient send::Request handler::Handlers
!=fun HttpClient.send(x: Request,y: Handlers){}
send:handler:
will be transformed to sendHandler
function, but we need just send
.
@emit:
@emit: "code"
will directly emit some backend lang code, kinda like asm pragma from C.
This can be useful in some corner cases when just renaming with @rename:
is not enough.
Bind a function without receiver
Since everything in niva should have a receiver, here is a common approach on binding functions without receiver:
create fake type
create the constructor
add @emit pragma
There is no such type as Console in Kotlin, but it looks pretty good still.
change args order
Sometimes it can be useful to change the order of arguments, for example to bind a function for the type of the first real argument.
Or just to make a better api with some shortcuts like here.
For example look at this binding:
$0 means the receiver of the method, in this case its ProcessBuilder. $1
$2
etc. is for other arguments by position.
These numbers are checked at compile time. So a single
will generate:
Full file: