Passing StringBuilder::append as argument in Kotlin - kotlin

I'm using BIP39 plugin for Java to create a mnemonic.
So I've converted (well mostly IDEA did) this Java code to a function in Kotlin syntax which looks like this:
fun mnemonicBuilder(): String {
val sb = StringBuilder()
val entropy = ByteArray(Words.TWELVE.byteLength())
SecureRandom().nextBytes(entropy)
MnemonicGenerator(English.INSTANCE)
.createMnemonic(entropy, sb::append)
return sb.toString()
}
IntelliJ IDEA keeps telling me that "None of the following functions can be called with the arguments supplied." for sb::append.
My quess is that .createMnemonic requires the second argument to have no return value (given by Target interface) but all appenders return the StringBuilder as a value.
Please, can somebody help me?

Indeed, argument signatures do not match. You can solve it by using lambda instead of the method reference:
MnemonicGenerator(English.INSTANCE)
.createMnemonic(entropy) { sb.append(it) }

Related

mockkStatic for extension method with generic parameter: "Not enough information to infer type variable T"

FYI: I'm currently using Mockk-1.12.4 and Kotlin-1.6
I've got an extension method that returns an object of type T:
fun <T> Entity.selectReferenceAsSingleObject(referenceName: String): T {
return this.selectReferencesByName(referenceName).single().asObjet() as T
}
This is defined as top level function in an Extentions.kt file (so not a class). I'm wanting to mock this with MockK by using mockkStatic
mockkStatic(Entity::selectReferenceAsOptionalSingleObject)
However I'm getting the error:
Not enough information to infer type variable T
because it cannot work out what type I should be mocking. I've tried adding my type parameter in a bunch of places
mockkStatic<KFunction<MyType>>(Entity::selectReferenceAsSingleObject)
mockkStatic<MyType>(Entity::selectReferenceAsSingleObject)
mockkStatic(Entity<KFunction<MyType>>::selectReferenceAsSingleObject)
mockkStatic(Entity<MyType>::selectReferenceAsSingleObject)
mockkStatic(Entity::<KFunction<MyType>>selectReferenceAsSingleObject)
mockkStatic(Entity::<MyType>selectReferenceAsSingleObject)
mockkStatic(Entity::selectReferenceAsSingleObject<KFunction<MyType>>)
mockkStatic(Entity::selectReferenceAsSingleObject<MyType>)
mockkStatic(Entity::selectReferenceAsSingleObject as KFunction<MyType>)
mockkStatic(Entity::selectReferenceAsSingleObject as MyType)
But nothing works and it either tells me the same error or tells me that type arguments are not allowed there. I'm not sure what I need to do to fix my syntax as IntelliJ isn't giving me any hints so I feel kind of stuck. Any help would be appreciated.
Try this:
mockkStatic("your.package.YourFileExtensionKt")
you can also give the file a nice name:
#file:JvmName("Extension")
would look like this:
mockkStatic("your.package.Extension")
anyway for the test to work you must use a mock in the extended class, in this case Entity, it would look like this:
#Test
fun test() {
val entity : Entity = mockk(relaxed = true)
every { entity.selectReferenceAsSingleObject<Any>(any()) } returns "whatever"
val result = entity.selectReferenceAsSingleObject<Any>("test")
assertEquals("whatever", result)
}

Extension function with different signature is confusing with different extension function in kotlin

class Example
fun main(){
val example: Example = Example()
// what function i am calling is it fun Example.extensionFun() ?
// Or is it Example.extensionFun(string: String) ?
example.extensionFun()
}
// first extension function
fun Example.extensionFun(){
println("Hey i'm first extension function")
}
// second extension function
fun Example.extensionFun(testArgument: String = "test argument "){ // argument just to change the function signature
println("Hey i'm second extension function ")
}
In the above example i have created two extension function with the same name but different signature.
When i try to call ->
example.extensionFun()
then IDE just calls the "fun Example.extensionFun()"
but even if i try to call
fun Example.extensionFun(testArgument: String ="test argument")
by using code completion pop up and selecting second extension function it is again calling
fun Example.extensionFun()
and thus it left me single way to call the second extension function which is by passing the different value for the testArgumet (argument). for eg.
example.extensionFun("different value")
but there is many cases where we don't want to change the default value of the function parameter when we are calling it.
I think i found a bug but kindly please share your opinion
When it's ambiguous, the compiler calls the overload that has fewer arguments. In fact, I don't think it even generates overloads for function signatures that are already explicitly declared. They should probably provide a compiler warning to let you know the default value is pointless, but maybe that was deemed too expensive for compile times.
Your only option is to use a different function name to break the ambiguity.

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.

final or val function parameter or in Kotlin?

Why does Kotlin removed the final or val function parameter which is very useful in Java?
fun say(val msg: String = "Hello World") {
msg = "Hello To Me" // would give an error here since msg is val
//or final
...
...
...
}
Kotlin function parameters are final. There is no val or final keyword because that's the default (and can't be changed).
After Kotlin M5.1 support of mutable parameters removed, In earlier versions that can be achieve using
fun foo(var x: Int) {
x = 5
}
According to Kotlin developers, main reasons of removing this feature are below -
The main reason is that this was confusing: people tend to think that this means passing a parameter by reference, which we do not support (it is costly at runtime).
Another source of confusion is primary constructors: “val” or “var” in a constructor declaration means something different from the same thing if a function declarations (namely, it creates a property).
Also, we all know that mutating parameters is no good style, so writing “val” or “var” infront of a parameter in a function, catch block of for-loop is no longer allowed.
Summary - All parameter values are val now. You have to introduce separate variable for re-initialising. Example -
fun say(val msg: String) {
var tempMsg = msg
if(yourConditionSatisfy) {
tempMsg = "Hello To Me"
}
}
And another reason is that val and var differ by only one letter. This can be very confusing. So for function parameters they removed the option completely. Thus eliminating the confusion in this one small area (yet keeping it everywhere else--go figure).
This decision was made to avoid fragile base class problem. It happens when a small change in base classes (superclasses) makes subclasses malfunction.

How to define a oneline function calling a nullable variable function

If I have something like:
fun showProgressView() = ultraRecyclerView?.showProgressBar()
it says that it returns Unit? and not Unit (edited)
-----EDIT-----
One way can be
fun showProgressView() = ultraRecyclerView?.showProgressBar() ?: Unit
but it looks not right for me.
Another way:
fun showProgressView() { ultraRecyclerView?.showProgressBar() }
But I cant find a way for android studio maintain that format.
If you use the short expression form of a function, the inferred result type of the expression determines the function return type. If that is a platform type from Java, it could be nullable. If it is a Kotlin type then it will know the correct nullability.
But since you use the safe operator ?. you are saying for sure it could be nullable. And if the result is null or Unit then that gives the inferred result type of Unit?
Which is odd, but is exactly what you are saying. Therefore, either use a normal function body with { .. } or give the function an explicit return type if possible.
fun showProgressView(): Unit { ultraRecyclerView?.showProgressBar() }
You can also erase the nullability, by creating an extension function on Unit?:
fun Unit?.void() = Unit
And use it whenever you want to fix the return type:
fun showProgressView() = ultraRecyclerView?.showProgressBar().void()
IntelliJ IDEA / Android Studio do not appear to have a setting to keep the style of a block body function on a single line. Even so, you can use run to get around this:
fun showProgressView() = run<Unit> { ultraRecyclerView?.showProgressBar() }
Normally you do not need to add explicit type arguments to run but in this case providing them gives you the desired method signature (return type of Unit and not Unit?).
Note: This answer is adapted from a comment I gave to why assignments are not statements.