How does this extension property to capitalize the first letter of every word in a string work? - kotlin

I'm recently trying to get into kotlin (coming from java) and did some beginner coding challenges.
The task is to write a function that capitalizes the first letter of every word in a string
I could solve the task in my own way, but I still don't understand this sample solution:
fun capitalizeSentence(str: String) {
println(str.split(" ").joinToString(" ") { it.capitalize() })
}
Can someone explain to me, why this lambda expressions manages to capitalize the first letter of every word, even when using the joinToString method right after the split method?

joinToString() accepts an optional transform function which it applies to each item before joining. It might be confusing to you, because this code performs operations in a different order than the code flow itself. This code is effectively an equivalent of this one:
str.split(" ")
.map { it.capitalize() }
.joinToString(" ")

Related

How to use lambdas like in Kotlin-JS?

I'm writing library on Kotlin, that builds file from each function that returned string. I get stuck on writing lambda(or something like this) that have inside many fun : String. Need to realize this like in Kotlin-JS,
div {
+ "div content"
}
or similar. vararg functions : String is bad option for me, because user of library have to use the loop inside(or similar).
How to realize this? Thanks.

Using Kotlin Symbol Processing API to compile String expression

I have a requirement where I need to make operation on Strings. This operation is expensive at runtime, and need to be made only on static expression. Therefore I want to do it at compile time.
Since the operation need to be made a lot of time, in many different modules, having to copy paste, doing manually the conversion, to past the result in the source code is long and slow.
I would like to add an annotation on the Strings which is required to convert, and have a file generated with all the results.
An example could be
val original = #Convert "Hello world"
functionRequiringTheConvertedStringValue(DATA.get(original))
original being equal to "Hello world" and the Data.get function giving the result.
With the DATA class being a static file containing all the string converted and able to fetch them.
Therefore I want to use an annotation processing, but when reading the examples, and the examples, I can't find a way to achieve the logic I want to implement.
I created a SymbolProcessor, but I am not able to get any expression, I can only get functions (KSFunctionDeclarationImpl) and classes (KSClassDeclarationImpl).
...
override fun process(resolver: Resolver): List<KSAnnotated> {
val symbols = resolver.getSymbolsWithAnnotation("com.example.annotation.Convert")
symbols.forEach {
logger.warn("class: ${it.javaClass.name}")
}
val ret = symbols.filter { !it.validate() }.toList()
return ret
}
When I use the annotation on an expression, I do not get it using the getSymbolsWithAnnotation.
My question being, how to get the expression and their value which are annotated by the annotation I created.
Edit:
Seems to be an open issued : https://github.com/google/ksp/issues/1194

How to find specific keyword in a string?

I have following code:
val contains = jobAd.toString().lowercase()
.contains(keyword.lowercase())
Problem is its getting hit even the string have "javascript". But i only want it to behit when it's actually the word java.
What am i doing wrong?
If you want to match only an entire word, you can use word boundaries in a regular expression like this:
fun String.findWord(word: String) = "\\b$word\\b".toRegex().containsMatchIn(this)
Then you can write for instance:
"I like Java!".findWord("Java") // true
"I like JavaScript".findWord("Java") // false
Note that this is case sensitive and not very robust, because for instance, it is possible to inject a regular expression. This is just to give you the general idea.

Purpose of repeat function

Using kotlin I can repeat an action in at least two ways:
val times = 5
// First option
for (i in 0 until times) {
print("Action $i")
}
// Second option
repeat(times) {
print("Action $it")
}
I'd like to know the purpose of repeat.
Should the traditional for loop be replaced with repeat function if possible?
Or are there special cases for this function?
Are there any advantages in repeat function?
EDIT
I've made some research about this question. As long as kotlin is open source project, I could download the sources and check git history.
I found that
1) repeat function is a replace for times function extension.
public inline fun Int.times(body : () -> Unit)
2) KT-7074. times function has become deprecated. But why?
It's just a matter of convenience (shortens the code). There are even more ways for example using an IntRange and forEach
(0..4).forEach {
println(it)
}
0 1 2 3 4
They all serve the same purpose, so the choice is yours.
You don't need to worry about performance either, since repeat and forEach are inline functions, which means the lambda code is copied over to the call site at compile time.
Next lines are all just my opinion:
there are no special cases when you should or shouldn't use repeat
function.
it has more concise syntax.
In places where you don't need to manipulate the loop counter or need to repeat only some simple action I would use that function.
It's all up to you to decide when and how to use it.
From Standard.kt:
/**
* Executes the given function [action] specified number of [times].
*
* A zero-based index of current iteration is passed as a parameter to [action].
*
* #sample samples.misc.ControlFlow.repeat
*/
#kotlin.internal.InlineOnly
public inline fun repeat(times: Int, action: (Int) -> Unit) {
contract { callsInPlace(action) }
for (index in 0 until times) {
action(index)
}
}
As you can see repeat(times) is actually for (index in 0 until times).
There is also a zero-based loop counter and it is: it.
Should the traditional for loop be replaced with repeat function if
possible?
I can't find any reason for that
Or are there special cases for this function?
None I can think of.
Are there any advantages in repeat function?
None I can think of, or maybe(?) just 1:
for educational purposes, I suppose it's easier to teach
that repeat(n) { } performs n iterations of the block of statements inside the curly brackets.

Position of `#` label in Kotlin when denoting receiver with `this`

I am a newbie in Kotlin. I am curious about the difference of labeled this in Kotlin with prefix # or postfix #.
I have just seen a code which writes SignInActivity#this, which seems to work exactly same as this#SignInActivity.
Are these two exactly the same thing? If not, what is the difference between the two?
I was trying to do some research on *#this form, but I couldn't find any reference on it. All I could find was this official doc which demonstrates this#*. It will be nice if anybody could share me with the correct reference I should go to.
SignInActivity# this is just another expression for this, with the functionality of defining an unnecessary label called SignInActivity(which has nothing to do with actual class name) for this.
According to Kotlin grammar documentation:
labelReference (used by atomicExpression, jump)
: "#" ++ LabelName
;
labelDefinition (used by prefixUnaryOperation, annotatedLambda)
: LabelName ++ "#"
;
hello# is just a label with the name "hello" (for Returns and Jumps) ,
whereas #hello is a reference for the labeled loop or block.
These expressions combined can be used as below:
loop# for (i in 1..100) {
for (j in 1..100) {
if (...) break#loop //jump to loop#
}
}
SignInActivity#this means SignInActivity.this (Java)
this#SignInActivity means - using the SignInActivity context instead a local context (usually is in closures).