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).
Related
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(" ")
I'm new to kotlin. Ive always used the map transform with curly braces. Then -
Why does this work ->
val x = someList.map(::SomeConstructor)
and this doesn't?
val x = someList.map{ ::SomeConstructor }
I didn't find usage of map with circular brackets anywhere on the online tutorials.
Please try to explain in detail, or provide suitable reference article.
What you ask is explained in this official documentation.
If and only if the last argument of a function is a lambda, you can extract it from the call paranthesis, to put it inline on the right of the function. It allows a nicer DSL syntax.
EDIT: Let's make an example :
One of the good use-case is context programming. Imagine you've got a closeable object. You want to delimit its usage to ensure it's properly closed once not needed anymore. In Java, you've got the try-with-resources:
try (final AutoCloseable myResource = aquireStuff()) {
// use your resource here.
}
Kotlin provide the use function. Now, you can do either :
acquireStuff().use( { doStuff1(it) ; doStuff2(it) } )
or write :
acquireStuff().use {
doStuff1(it)
doStuff2(it)
}
It looks like a Java try-w-resource, but is extensible to any of your API. Allowing you to design libraries giving advanced constructs to end-users.
Sorry for the terrible title, but I can't seem to find an allowable way to ask this question, because I don't know how to refer to the code constructs I am looking at.
Looking at this file: https://github.com/Hexworks/caves-of-zircon-tutorial/blob/master/src/main/kotlin/org/hexworks/cavesofzircon/systems/InputReceiver.kt
I don't understand what is going on here:
override fun update(entity: GameEntity<out EntityType>, context: GameContext): Boolean {
val (_, _, uiEvent, player) = context
I can understand some things.
We are overriding the update function, which is defined in the Behavior class, which is a superclass of this class.
The update function accepts two parameters. A GameEntity named entity, and a GameContext called context.
The function returns a Boolean result.
However, I do not understand the next line at all. Just open and close parentheses, two underscores as the first two parameters, and then an assignment to the context argument. What is it we are assigning the value of context to?
Based on IDE behavior, apparently the open-close parentheses are related to the constructor for GameContext. But I would not know that otherwise. I also don't understand what the meaning is of the underscores in the argument list.
And finally, I have read about the declaration-site variance keyword "out", but I don't really understand what it means here. We have GameEntity<out EntityType>. So as I understand it, that means this method produces EntityType, but does not consume it. How is that demonstrated in this code?
val (_, _, uiEvent, player) = context
You are extracting the 3rd and 4th value from the context and ignoring the first two.
Compare https://kotlinlang.org/docs/reference/multi-declarations.html .
About out: i don't see it being used in the code snippet you're showing. You might want to show the full method.
Also, maybe it is there only for the purpose of overriding the method, to match the signature of the function.
To cover the little bit that Incubbus's otherwise-great answer missed:
In the declaration
override fun update(entity: GameEntity<out EntityType>, // …
the out means that you could call the function and pass a GameEntity<SubclassOfEntityType> (or even a SubclassOfGameEntity<SubclassOfEntityType>).
With no out, you'd have to pass a GameEntity<EntityType> (or a SubclassOfGameEntity<EntityType>).
I guess that's inherited from the superclass method that you're overriding. After all, if the superclass method could be called with a GameEntity<SubclassOfEntityType>, then your override will need to handle that too. (The Liskov substitution principle in action!)
I can document a function like this:
f: func [
"a description"
arg1 [string!] "a description of an argument 1"
][
arg1
]
I can use ?/help in order to retrieve informations about the the function (a description, a usage, the argument list, a description of each argument and it's type)
? f
USAGE:
F arg1
DESCRIPTION:
a description
F is a function value.
ARGUMENTS:
arg1 -- a description of an argument 1 (Type: string)
I cannot document dialects like this. Is there an automatic way to document dialects (like func does)? Do I have to do this manually?
There's nothing for it currently, but it's a good idea. So good that someone has suggested it before. :-)
Do I have to do this manually?
You can manually write a new generator which defines your "dialect spec" format. Then either do something like give it a HELP command, or extend HELP to recognize it.
Very short example to demonstrate a group of techniques which may come in handy in doing something like this (not all expected to be obvious, rather to hint at the flexibility):
make-dialect: function [spec [block!] body [block!]] [
return function ['arg [block! word!]] compose/deep/only [
case [
arg = 'HELP [
foreach keyword (spec/keywords) [
print [keyword "-" {your help here}]
]
]
block? arg [
do func [arg] (body) arg
]
'default [
print "Unrecognized command. Try HELP."
]
]
]
]
So there's your function that takes a dialect spec and makes a function. Once you've got your generator, using it can be less manual:
mumble: make-dialect [keywords: [foo baz bar]] [
print ["arg is" mold arg]
]
>> mumble help
foo - your help here
baz - your help here
bar - your help here
>> mumble [<some> [dialect] {stuff}]
arg is [<some> [dialect] {stuff}]
The techniques used here are:
Soft Quoting - Usually you would have to say mumble 'help to "quote" the help as a lit-word! to get it to pass the word! to mumble (as opposed to running the default HELP command). But because arg was declared in the generated function as 'arg it was "soft quoted"...this means that words and paths will not be evaluated. (Parens, get-words, and get-paths still will be.) It's a tradeoff because it means that if someone has a variable they want to pass you they have to say :var or (var) as the argument instead of just var (imagine if the block to pass the dialect is in a variable) so you don't necessarily want to use it...but I thought it an interesting demo to make mumble help work without the lit-word!
Deep Composition - The spec and the body variables which are passed to make-dialect only exist as long as make-dialect is running. Once it's over, they'll be gone. So you can't leave those words in the body of the function you are generating. This uses COMPOSE/DEEP to evaluate parens in the body before the function generator runs to make the result, effectively extracting the data for the blocks and stitching them into the function's body structure.
Reusing Function's Binding Work - The generated function has a spec with a parameter arg that didn't exist at the call site of make-dialect. So arg has to be rebound to something, but what? It's possible to do it manually, but one easy way is to let FUNC do the work for you.
Those are some of the techniques that would be used in the proposed solution, which seeks to not only document dialects but provide an easy method by which their keywords might be remapped (e.g. if one's Rebol system has been configured for another spoken language).
Let us say I have a situation like this:
;; Capture whatever the print word pointed to into a variable
outer-print: :print
foo: context [
;; within foo, override print and implement in terms of outer-print
print: func [value] [
outer-print "About to print"
outer-print value
outer-print "Done printing"
]
]
I can do this, or if I have more than one thing I want from the outer context I could capture it explicitly:
;; Capture current context into something called outer
outer: self
foo: context [
;; within foo, override print and implement in terms of outer/print
print: func [value] [
outer/print "About to print"
outer/print value
outer/print "Done printing"
]
]
Is this the right idiom, or is there a better way of doing it? Are there circumstances where this might not give me what I expect?
this is good style, especially the second, which is more flexible as it allows you to mass-effect all uses of the outer print, without any ambiguity. when using direct binding, it may occur that the word outer-print is redefined or the context changes between two calls to make foo [] and in the end, points to two different bindings.
static symbol resolving
For the sake of completeness there is a third alternative which doesn't require any extra words to be setup. I don't have a proper naming for it, feel free to suggest a better title.
This method defies any binding issues down the line because you use the function value directly:
foo: context compose/deep [
;; within foo, override print and implement using native print directly
print: func [value] [
(:print) "About to print"
(:print) value
(:print) "Done printing"
]
]
Now the interesting part is if you SOURCE the inner print function:
>> p: get in foo 'print
>> SOURCE P
== p: func [value][native "About to print" native value native "Done printing"]
see how the native value of print is used directly in the body, instead of a word referring to it.
This is, in fact, probably the closest we can get to some form of compilation in pure REBOL. instead of constantly using symbols to fetch and evaluate, we can simply statically resolve them manually, using reduce or compose as in the above.
pros:
It can never be hi-jacked by some advanced and malicious binding code, i.e. even if there are no direct word bounds to PRINT in ANY and ALL contexts, you still have a direct reference to the original function in your body.
cons:
Its a very static way to code, and isn't very "Rebolish".
The
;; Capture current context into something called outer
comment suggests that you think there is some "current context" in Rebol. That is false. Every word has got its own context. Thus, there are cases when your
outer: self
code doesn't work as you expect. For example, let's suppose that you want to access two variables, 'print and 'set. It is possible for the words to have different "outer" contexts. In that case the trick will be certain to not work for at least one of the words, but it may, in fact, not work for both.