I came across this line of code in Kotlin:
private val creators: ArrayMap<Class<*>,() ->ViewModel> = ArrayMap()
What does the comma mean? Is this a bug? According to this post, commas are not allowed:
Define multiple variables at once in Kotlin (e.g Java : String x,y,z;)
The comma separates the generic parameters of ArrayMap. The first parameter is Class<*>, while the second parameter is () -> ViewModel
Related
How can I escape a function name so that it can span multiple lines? For example
#Test
fun `This is a really long description of what should happen to this function when the IDs do not match up.`() {
// test
}
What I would want is something like
#Test
fun `This is a really long description of what should happen to this \
function when the IDs do not match up.`() { // test }
Is this possible?
It is not possible, function names convention allows spaces in test methods but not multiple lines : https://kotlinlang.org/docs/coding-conventions.html#names-for-test-methods
In tests (and only in tests), you can use method names with spaces enclosed in backticks.
A method with multiple lines in its name would not be callable even through reflection. (see https://stackoverflow.com/a/45750788/7346454)
I would like to make plus mean something else, than addition. For example, creation of lazy expressions for computational graph. Unfortunately, class extensions cant override member functions. The following code will print 3:
operator fun Int.plus(other: Int) = listOf(this, other)
fun main() {
println( 1 + 2 )
}
Is is possible to force overriding?
No it is not possible. 1 + 2 is lowered into 1.plus(2), and there is a well defined order in how the compiler finds an appropriate plus method. Specification:
If a call is correct, for a callable f with an explicit receiver e
of type T the following sets are analyzed (in the given order):
Non-extension member callables named f of type T;
Extension callables named f, whose receiver type U conforms to type T, in the current scope and its upwards-linked scopes, ordered
by the size of the scope (smallest first), excluding the package
scope;
[...]
[...]
When analyzing these sets, the first set which contains any
applicable callable is picked for c-level partition, which gives us
the resulting overload candidate set.
So the plus method that is declared in Int is always found first, and the search stops there. Any extension you define will be ignored.
Hypothetically, if the built-in Int.plus is an implicitly imported extension function, then your code would have worked! Implicitly imported extensions are #6 on that list :)
My workaround for this situation is to use the "declare functions with almost any name by adding backticks" feature:
infix fun Int.`+`(other: Int) = listOf(this, other)
fun main() {
println( 1 `+` 2 )
}
This wouldn't work for some names that have reserved characters like square brackets, angle brackets, slashes, and dot (not an exhaustive list).
New to Kotlin, I have seen this code:
val myModule : Module = module {
viewModel { MyViewModel(get()) }
single { MyRepository() }
}
Looking at the Kotlin docs, it isn't clear to me what the braces mean after "module". Is module a function and the braces are used to initialize the function? If this is true, can you point me to the part in the Kotlin documentation that indicates this? I can't find anything in the docs that shows an example of this. Here is the link:
https://kotlinlang.org/docs/reference/properties.html
Note that your example seems like Koin code.
In a more general sense:
In kotlin when the last parameter of a function is another function ( see Higher order functions) you can put it outside the parenthesis, and if it is the only (non optional) parameter you can omit the parenthesis enterily.
In your example module viewModel and single are functions that take another function as their only parameter, this way you can pass the lambda defining this paramter directly without any parenthesis.
The braces mean that the module function receives a lambda as a parameter. http://kotlinlang.org/docs/reference/lambdas.html#passing-a-lambda-to-the-last-parameter
How do I replace multiple characters in a String?
Like Java's replaceAll(regex:replacement:) function.
str.replaceAll("[$,.]", "") //java code
This answer is very close but I want to change more than one character at the same time.
[$,.] is regex, which is the expected input for Java's replaceAll() method. Kotlin, however, has a class called Regex, and string.replace() is overloaded to take either a String or a Regex argument.
So you have to call .toRegex() explicitly, otherwise it thinks you want to replace the String literal [$,.]. It's also worth mentioning that $ in Kotlin is used with String templates, meaning in regular strings you have to escape it using a backslash. Kotlin supports raw Strings (marked by three " instead of one) which don't need to have these escaped, meaning you can do this:
str = str.replace("""[$,.]""".toRegex(), "")
In general, you need a Regex object. Aside using toRegex() (which may or may not be syntactical sugar), you can also create a Regex object by using the constructor for the class:
str = str.replace(Regex("""[$,.]"""), "")
Both these signal that your string is regex, and makes sure the right replace() is used.
If you're happy to work with regular expressions, then refer to the accepted answer here. If you're curious as to how you can achieve this without regular expressions, continue reading.
You can use the String.filterNot(predicate:) and Set.contains(element:) functions to define a String.removeAll extension function as follows:
/**
* #param charactersToRemove The characters to remove from the receiving String.
* #return A copy of the receiving String with the characters in `charactersToRemove` removed.
*/
fun String.removeAll(charactersToRemove: Set<Char>): String {
return filterNot { charactersToRemove.contains(it) }
}
You would call on this function as follows: myString.removeAll(setOf('$', '.'))
I am trying to use one of my defined functions that accepts a string yet the software won't compile.
fun passes(address: String) = Collections.frequency(addresses, address) <= CONNECTIONS_PER_IP
fun passes(remoteAddress: InetSocketAddress) = passes(remoteAddress.hostName)
I can't even call the string function using a custom string, for example passes("127.0.0.1").
None of the following functions can eb called with the arguments supplied.
passes(String) defined in abendigo.Firewall
passes(InetSocketAddress) defined in abendigo.Firewall
I presume you're using java.lang.String instead of kotlin.String in the Kotlin source code. Please use only kotlin.String instead, this is the type that string literals in Kotlin have (but in the bytecode it's still transformed to java.lang.String).
The issue was an import of java.lang.String. For some reason IntelliJ imported it.