There was a number of reasons, among which is the ability to create functions that look like custom language constructs, this way we have synchronized
as a function, and not a built-in keyword:
synchronized(lock) {
// do something
}
or with
:
with(foo) {
print(propOfFoo)
funOfFoo()
}
It also enables type-safe builders
You can write it like this:
jdbcClient.update(sql) { queryResult ->
if(queryResult.failed()) {
}
}
In Kotlin, there is a convention that if the last parameter of a function accepts a function, a lambda expression that is passed as the corresponding argument can be placed outside the parentheses.
If the lambda is the only argument to that call, the parentheses can be omitted entirely.
Do you mean like if a variable starts with _ it's automatically made private? Honestly I'd just stick with the Kotlin style guide which is pretty sane.
Personal coding styles are going away with the advent of gofmt, prettier, black, etc. It's really quite freeing and a big help on teams. Not as big of an issue for a single coder.
Yes, as others have said, you do get primitives in Kotlin, but it's perhaps a little more opaque than you're used to. It's worth looking at the Kotlin docs on the matter, but the tldr is
> "On the Java platform, numbers are physically stored as JVM primitive types, unless we need a nullable number reference (e.g. Int?) or generics are involved. In the latter cases numbers are boxed."
So it's mostly left to the compiler to do the right thing, but admittedly it can be a little challenging to ensure you don't accidentally force boxing unless you're fairly diligent.
They're othogonal concerns.
Coroutines are used for more than just "lightweight threads". Ever use <code>buildSequence</code> (now just <code>sequence</code>)?
A coroutine is a chunk of code than can voluntarily suspend itself. That's great for sequence generation because it resolves the impedance mismatch between pull-based sequences and push-based generation code. It's also good for async code, since every async operation entails that the current "computation" be suspended.
Coroutines are useful in places where threads would cause problems - typically when you would have so many threads that they would put undue pressure (memory, scheduling, etc.) on the JVM. Async is one example, as are actors.
I have a Kotlin application that had been using threads, though not very many threads and most of them are sleeping most of the time. I had tried porting it over to the experimental coroutines, and specifically to kotlinx.coroutines. It worked. But (at least in IntelliJ 2018.2.4 and the 1.2.71 version of the plugin), things weren't as nice as with explicit threads. Stack traces were less intelligible, and breakpoints didn't work quite right. In the end, I realized that we weren't really gaining anything from using coroutines, so I switched back.
One thing that I might keep, and even try to polish up a bit more, was some code that I had written that used coroutines to automatically perform "tail calls" even in non-tail positions (there are some API challenges, but I think I can resolve them, especially now that Kotlin supports callable references to suspend fun
s). But again, that doesn't really have anything to do with threading.
let
here is a function, not a language keyword.
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/let.html
You can just use regular if statement and Kotlin compiler will automatically know that inside the if(doge != null)
block, doge is not null, and that in the else block, it's null.
var doge: String? = null;
if (doge != null) { // you can safely dereference doge here; the compiler knows it's not null println("wow"); println("such doge"); println(doge) } else { println("not wow"); println("no doge"); }
He's asking specifically about Kotlin Native, which has nothing to do with the JVM.
You can introduce a type parameter with some generic constraints, like this:
fun <T> a(val b: T): Unit where T : UpperLevelStandardClass, T : myInterface { .... }
It's documented at the bottom of this page: https://kotlinlang.org/docs/reference/generics.html
I like Uncle Bob's videos, but he is way off-base with both of his criticisms of Kotlin here.
The rationale behind final-by-default, which comes straight from the very respected "Effective Java", is that a class intended to be subclasses is often much harder to write properly than a class that isn't. Having to type an additional 4 characters is a small price to pay to remind the programmer of this. It makes perfect sense to default to the safer option.
And his criticism of Kotlin's null-safety is even more bizarre, this is one of Kotlin's best features! The whole point of statically typed languages is to catch errors at compile-time rather than catching them at runtime. Why would anyone not want to use a language that would do that for them?
His argument against it, which is "you shouldn't need it because your tests should catch that" could be used against all of static typing.
The right part of the when
branch needs to be a single expression. The compiler thinks the println
is part of the next branch (that's where the incompatible type comes from - it's expecting a boolean for the branch).
The solution is to use blocks, i.e. wrap the two lines in curly braces, as described in the docs.
Those guides are most likely for pre-1.3.0 coroutines, where that was allowed. The coroutines available in 1.3.0 make a push towards structured concurrency, where every coroutine has a scope and when that scope ends it can be cancelled. To launch a coroutine like you would pre-1.3.0, use <code>GlobalScope.launch {}</code> instead.
This is documented here:
https://kotlinlang.org/docs/reference/null-safety.html
> An uninitialised this available in a constructor is passed and used somewhere ("leaking this");
There would be 2 solutions to this:
this
to other functions in contructors to avoid leaking the uninitialised this
objectThe first solution would be pretty restrictive and cause a lot more trouble than is solved. The second solution would probably be pretty hard to implement (and impossible in the general case), lead to longer compilation times and to strange compilation errors after small changes because the compiler isn't able to prove the safety of the calls anymore. Some perfectly safe code would probably not be compilable because the compiler wouldn't be smart enough.
Plus there might be interoperability issues with java. Having limited null safety in the constructor is a pragmatic solution, and causes little problems in the real world.
> the proposed Kotlin solution reads much better but is not as performant because it swaps a single O(1) method indirection for an O(n) search across types for each visit.
At least in Scala, that hasn't been the case for 10 years now:
> Martin Odersky: Much earlier, Scala used to compile pattern matches to switches, using a compiler-generated $tag
method. This was removed because our measurements showed that it was actually slower than a sequence of instanceof tests. See the paper "Matching Objects with Patterns", ECOOP 2007, for more details.
Apparently, reasonably modern JVMs are really good at recognizing and optimizing patterns such as these.
Ah, I'm not 100% sure but this may be a case of smart casting. You may have found a weird edge case. (If Kotlin knows for sure your value is, say, a String, then it auto casts for you, for example)
You want xor (exclusive or).
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-boolean/xor.html
Edit: for the second request you already have syntactic sugar if you're willing to incure an allocation
if (thingOne in listOf(thing2, thing3))
I don't know the specific reason they went with arrayOf(…)
instead of supporting a native syntax using […]
(same for mapOf( key to value)
), but I do know that one of the reasons is those aren't special language constructs—they are just top-level functions.
A lot of Kotlin seems to follow this mindset, that it's better to use top level functions and the built-in type checker, rather than adding language extensions.
One awesome side effect of this is you can, effectively, create your own extensions that act exactly as the "native" functions. in the mapOf
example above, the <code>to</code> itself is just an infix function.
public infix fun <A, B> A.to(that: B): Pair<A, B> = Pair(this, that)
It's literally that simple, and now you have something that works very much like a language-level construct, but is actually just a method call.
For some tutorials please take a look at https://kotlinlang.org/docs/tutorials/native/basic-kotlin-native-app.html and others. Regarding Android+iOS development take a look at https://github.com/JetBrains/kotlin-mpp-example
Yes, the Kotlin/Native compiler is a frontend for LLVM https://en.m.wikipedia.org/wiki/LLVM
The targets can be specified through the Kotlin/Native gradle plugin konan for example https://kotlinlang.org/docs/tutorials/native/gradle-for-kotlin-native.html
Inferring from your question that you actually want a substring until the first line feed or the whole string otherwise, you can take a look at this function:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/substring-before.html
val sub = someString.substringBefore('\n')
There's a fairly lengthy discussion in the docs about when Kotlin doesn't perform implicit casts. Due the reasons outlined there, I doubt you'll find a way to implicitly convert primitives, because it can lead to unexpected errors.
While Kotlin is designed to reduce boilerplate, it's primary goal is safer code. Forcing the developer to be aware of type conversions like this is a good example of where safety was chosen over being terse.
Hopefully someone with more experience can help further. You may get more help if you included specific types for the original example. It's hard to infer what you are converting from with the examples there, and which libraries you are using.
The documentation addresses this directly.
> In Kotlin, if is an expression, i.e. it returns a value. Therefore there is no ternary operator (condition ? then : else), because ordinary if works fine in this role.
Note: This page is the first result when you search of "kotlin ternary".
In Kotlin, bitwise operators are implemented as functions. For &=, the function is called and. Go here and ctrl-f for "bitwise and", you will see a list of all the bitwise operators in Kotlin. Hope that helps.
I would interpret it as a "redundant" construct which should be avoided.
> In general, if a certain syntactic construction in Kotlin is optional and highlighted by the IDE as redundant, you should omit it in your code. Do not leave unnecessary syntactic elements in code just "for clarity".
https://kotlinlang.org/docs/reference/coding-conventions.html#avoiding-redundant-constructs
Methods coming from Java code (JavaFX for example) are treated in a special way because there is no way to deduce the nullability of its arguments and return values.
I can't test this right now but it sounds like a problem with line endings. Odds are you're on windows, so by default a newline isn't just "\n"
, it's "\r\n"
. "\r"
moves the "cursor" back to the beginning of the line being written to.
When you split on "\n"
, it leaves behind the "\r"
character. All of the odd behaviors you're seeing can be explained by this stray "\r"
. The reason "Ice Cream"
is the only one that works consistently is because you likely don't have a newline at the end of your file.
To remedy this, either change your line endings, or trim each string in foodList
.
You can achieve this by usng when
and also introducing the <code>is</code> keyword and smart casts.
when(person) {
...
is Student && person.studentName == "Richard" => "Still here Ricky?"
is Student && person.studentName == "Foo" => "Hey, ${person.studentName}."
...
Effective Java absolutely influenced Kotlin. There is no question. You see it cited in the documentation for Kotlin.
https://kotlinlang.org/docs/reference/operator-overloading.html#assignments
lays it out fairly plainly that they do it completely intentionally. The confusing part is why this doesn't happen with just a mutableList, ie
val test3 = mutableListOf<String>("one") test3 += "two"
is not subject to that rule.
The large problem is probably that your statement can validly go to two different forms, and there is not a precedence for index operations. x[1] += 1 is confusing because it can be
x.set(1, x.get(1) + 1)
or
x.get(1).plusAssign(1)
You have two options in Kotlin.
You probably want to learn the general kotlin constructs first and apply them to android app development afterwards. Kotlin koans is a great guided way to start.
Try to be less sensitive to Reddit voting, people are rarely rewarded for complaining about downvotes. Even with a vote of 0 plenty of people will still see your work.
Also you got 22 votes when you posted this library just 5 days ago, so people may have felt that this post was repetitive.
Is there any way you can use tailrec to make your function more efficient?
In my app BeatScratch, I transport data between Dart UI code and Kotlin + Swift backend code using common models all implemented with Protobuf. This article explains exactly how to do it. It pretty much "just works" and is about as efficient as you're going to get if you have data models with any degree of complexity and want access to the same models in both Dart and Kotlin (and other platform code).
I'm not sure if this would completely solve your problem of writing queries, but SQLDelight will generate type safe apis to use from your kotlin code and provides some code completion when writing the queries. Otherwise if you're not tied to SQL, can always check out an orm like realm
In that particular case, widening an Int to a Float is a lossy widening. At the upper end of the range, there are Ints that can't be perfectly represented by Floats. When promoting such an Int, you would get a meaningfully different Float.
In the general case, I don't know. Some promotions are safe. I guess they are going for consistency.
> why not add something like the custom add operation methods, but for converting
I don't know what you mean. Things like +
work by essentially having a bunch of overloads. You could do the same thing. If you want your function to also accepts Ints, create an overload. You'll quickly run into combinatorial explosion (what happens if they pass an Int and a Float, or pass a Float and an Int?).
In that case, the OP should follow this book and start with Assembly.
I've worked with C programmers, and believe me, some can be really stubborn. I had one class partner who wrote all her code in Java using C conventions.
I would rewrite and reformat her code. She would rewrite and reformat my code. Some people are just incapable of letting go of prior knowledge they mastered once upon a time.
It would be absolutely backwards for it to return false. You seem very intent on having your way though, so there's no chance of convincing you. But, let's use the kotlin documentation for this:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/is-digit.html
val chars = listOf('a', '+', '1') val (digits, notDigits) = chars.partition { it.isDigit() } println(digits) // [1] println(notDigits) // [a, +]
so let's remove the 1
val chars = listOf('a', '+') val (digits, notDigits) = chars.partition { it.isDigit() } println(digits) // [] println(notDigits) // [a, +]
Huh, that's funny. it partitioned an empty list for the things that are digits, isDigit
.
Therefore an empty list of nothing is a list of digits. per the definition of .isDigit()
. Therefore an empty string (you would split it into its constituent chars), is an exact list of digits. You can literally test this with the above code.
I know it's not a tutorial, but Kotlin in Action sounds like it would fit the bill as well. I bought it intending to learn Kotlin without knowing java, but it actually assumes a background in java. It also has hints about how to interop with Java if needed.
Hi! We send stickers to people who do Kotlin talks. You can find more info here https://kotlinlang.org/community/talks.html
Sometimes you can also get stickers at Kotlin-related events, however, all we know that events haven't been an option for the last year...
Hard to say what is an issue here without seeing the relevant code. All this tells me is that you have a ByteArray property that is either non-nullable or was autocast to non-nullable that you used the !! operator on.
Refer to this page of the kotlin docs if you are struggling with null safety in kotlin.
https://kotlinlang.org/docs/reference/null-safety.html
In the future please post a code snippet so it is easier for others to help!
Reposting my response from the ticket:
I don't think either of these changes are necessary. For the first one, you're proably looking for the xor infix function.
The second one is also very easy to implement as an extension function:
fun <T> T.equalsAny(vararg others: T): Boolean {
for (other in others) {
if (this == other) return true
}
return false
}
Which can be used like so:
val exampleOne = 1
val exampleTwo = 2
val exampleThree = 1
if (exampleOne.equalsAny(exampleTwo, exampleThree)) {
//code
}
See example on the Kotlin playground: https://pl.kotl.in/AH2ej02OQ
You can use the find call, it'll return the first matching value and since you mention you have unique values that should work. The below code will check each HashMap in the list for a matching id value, and on the first match add the name value to selectedItems list.
datalist.find { it["id"] == id }.let { selectedItems.add(it["name"])) }
Lambdas are pretty much just functions without a name. Where you could use a function, you can just type {inputs -> <code-which-manipulates-the-inputs>}
instead, constructing a lambda expression without having to define a specific function with all the usual bells and whistles.
I replied to your original question. Then you asked me why I was not using Django Rest? What? Why should I? Then I told you politely that I'm using Kotlin.
You have asked us for personal opinions. I gave you mine. What did you except? "Oh, I used to use Python but now I'm using Kotlin because it's worse..."
If you're familiar with Python have a look at https://kotlinlang.org/docs/reference/ and you'll soon see that Kotlin is as elegant and concise as Python but much more powerful. Static typing, threading, coroutines, extension functions, null safety, the collections and stream API, runtime performance ... Or have a look at the Spring docs and compare the features to Django or Flask.
Nobody here will write an essay.
> I'm assuming kotlins coroutines are balanced over threads automatically like in go.
Coroutines by themselves don't have any inherent dispatch strategy. It's up to code outside the Kotlin standard library to actually start or resume a coroutine on a specific thread.
kotlinx.coroutines, however, does have specific dispatch strategies. For example, you can have coroutines always resume on a single thread, or have them scheduled to the thread pool, or something even more exotic.
I'm not familiar with Go, but I'm assuming that it doesn't allow you to interact with threads directly. If that's true, then Kotlin gives you more control, which is necessary for Java interop reasons.
I don't believe you're using assertTrue correctly. It should look like one of the following:
assertTrue(false, "This is wrong")
assertTrue("This is wrong") { false }
In addition to the different use cases alreadt mentioned in other comments, named parameters with default are not really interop friendly. According to the @JvmOverload docs:
> If a method has N parameters and M of which have default values, M overloads are generated: the first one takes N-1 parameters (all but the last one that takes a default value), the second takes N-2 parameters, and so on.
So, you wouldn't have all the configurable with proper default values for every property. For that, it would require a 2ˆM methods.
Edit: Properly read the docs.
Not sure if you know already, but have you seen the <code>expect</code> and <code>actual</code> constructs? It is one of the ways they are planning on leveraging platform-specific implementations (such as for dates) on shared code.
The learning curve should not be a problem, if you do the Koans.
https://kotlinlang.org/docs/tutorials/koans.html
They are done quickly, for sure in a few hours, if you know the relevant programming paradigms. And syntax is not really a problem, if you use an IDE or any editor with syntax checks.
You should solve the Kotlin Koans. After that, if you are trying to solve a problem, google for the solution in Java and translate and optimize it, if you want to write something yourself, else just adopt it (Kotlin has very good Java interoparability).
Kotlin Koans: https://kotlinlang.org/docs/tutorials/koans.html
That's not how lazy is done in Kotlin.
val cached by lazy { expensive(); }
https://kotlinlang.org/docs/reference/delegated-properties.html#lazy
The other way will throw an error unless expensive()
returns a Delegate, because what follows by
must be a Delegate.
Also, check this regarding builders: https://kotlinlang.org/docs/reference/type-safe-builders.html
EDIT: Also, the conclusion at the end that "Lombok offers some more features than Kotlin" is pointless. You haven't done the legwork to show that in this article, and it's not worth provoking people to say it.
It's fine to do a comparison of languages and I think all in all a lot of work was put into this article and it shows, but there are huge gaps in your coverage of Kotlin features, like saying Delegates don't exist (while also using the by
keyword???), not really addressing null safety operators, equating first-class functions and @Helper
, etc.
Really? I think it defaults to public.
>The default visibility, used if there is no explicit modifier, is public.
https://kotlinlang.org/docs/reference/visibility-modifiers.html#visibility-modifiers
And as a stylistic (and functional) addition you can drop the empty body braces '{}' and prepend 'data' before class to get a lot of additional functionality for free with this type of class.
See: data classes
It only works for inline functions, which have the restriction that lambdas can only be called from that function, or passed to other inline functions. So once all the inlining is done, there should be no stack frames other than the one in which the lambda was defined. https://kotlinlang.org/docs/reference/inline-functions.html
An example of such feature would be value types (structured stack-allocated objects) which would make perfect sense in Kotlin and especially Kotlin/Native. We're looking forward to the Project Valhalla that aims to add support for value types on JVM.
https://www.udacity.com/course/developing-android-apps-with-kotlin--ud9012 is free, and it's pretty good.
It doesn't cover the bluetooth aspect, but it'll get you familiar with the Jetpack UI/app framework, as well as familiar with Kotlin.
One reason might be suspend functions. Suspending functions as supertypes was only introduced as experimental in 1.5.30 and it requires you to set language version as 1.6 for it to work: Docs link
I believe that you can have suspending version of the invoke operator function though.
It took me weeks to understand how to work and integrate with multiple multiplatform libs mostly because i was reading the wrong documentation KMM documentation
Fortunately i found the documentation i was looking for by accident.
This is a suggestion, since most mobile devs will try to create a shared lib and add it to their existing apps, maybe include a link on "How to create and publish a multiplatform lib" in the KMM docs.
There are quite a few optimisations I can think of:
If ever the first number, it[i] is greater than zero you can return result immediately, because there is no way you can find any more triples.
Similarly, if ever the sum of the first and second number are greater than zero, you can also return result immediately, because the third number cannot be negative, so there are no more triples.
And if third number is ever less than zero, then you can also return result immediately, since there can, of course, be no more triple.
One final, minor, point is that just as Kotlin has a Pair, it also has a Triple: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-triple/
So when a coroutine is suspended via <code>suspendCoroutine</code>, it gives you an instance of Continuation
. This object represents everything that will be done when you resume the coroutine - it's the "bookmark" if you will.
One-shot continuations can only be resumed once. So it has a sort of pause/resume semantic.
But the continuation object is an object, and I could try to resume it multiple times. If I did that, Kotlin would throw an exception because Kotlin continuations are not full continuations.
Full continuations let you resume them multiple times. Each time they're resumed, they'll pick up from the suspension point. All the local variables will again have the values they had when the continuation was suspended.
Full continuations are more powerful than one-shot continuations, but they come with a cost. There's more state to keep around when dealing with full continuations. And one-shot continuations are "good enough" for most purposes.
I think there was some talk about allowing Kotlin continuations to be serialized, and that might open up a path to support opt-in full continuations. But AFAIK that hasn't yet happened.
Most people will never deal with this layer. Most people use kotlinx.coroutines
, and that's what the linked article is talking about. kotlinx.coroutines
is built on top of the standard library <code>kotlin.coroutines</code>.
Also web dev here and also starting to learn Kotlin more. But I do come from a more traditional language background (Java, C++)
​
Sorry things are frustrating :( I certainly understand the feeling. For example I started learning Clojure awhile back and I had(and to some extent still have) some frustrations in wrapping my head around functional programming and the Clojure syntax.
​
If Javascript is the only thing you've known, there's quite a bit that's going to take some adjusting to when it comes to a more substantial language like Kotlin. I think your example though is more indicative of how Android is structured vs the language itself. It has been some time since I've done Android work I'll admit so I could be totally wrong here; but that looks roughly what you'd have to write even in Java; I wouldn't get discouraged about things just yet in regards to Kotlin itself!
​
I know it's tempting to try diving into things with an actual project but it sounds like it might make sense to take a step back and take the time to learn about the language a bit more - Kotlin is pretty much interoperable with Java; I might start with some simple Java tutorials or if you're more visually minded, I started learning Java through Processing , used Kotlin and Processing to pull down some images from Mapbox for a personal project a couple months ago.
Actually there is a Ceylon plugin for IntelliJ!. I think they switched focus from Eclipse to IntelliJ after Google switched for Android development. It's pretty good, but probably not as good as Kotlin's support for obvious reasons.
I agree that Ceylon isn't as popular as Kotlin but I haven't given up hope yet! It's a really nice language. Even if it never takes off, I'm really happy to see that its ideas are spreading to other languages like TypeScript and Kotlin.
Anyway, I didn't mean to offend. I just thought it sounded like a good alternative given your constraints. I hope you enjoy using Kotlin!
com/jodge/movies/data/persistence package:
Movie.kt
https://kotlinlang.org/docs/reference/coding-conventions.html#class-header-formatting
MovieDataSource.kt
override fun findAll(): List<Movie> = movieDao.findAll()
The process of creating libraries for kotlin is rather frustrating, and its often not clear how to install 3rd party libraries.
Even then, if can be hard to know what flavor of kotlin (eg. native) a library runs in.
Are there any plans / what can we see in the future on this?
Use a constructor property:
class Test(private val map: HashMap<String, String>) : Map<String, String> by map { override fun get(key: String) : String? { return map[key]?.capitalize() // want to access original HashMap method } }
Example usage:
fun main(args: Array<String>) { val originalMap = HashMap<String, String>() val test = Test(originalMap) originalMap["key"] = "value" println(test["key"]) }
Prints:
Value
If you really care about every instance of Test
having it's own map instance, make the main constructor private and define fun newInstance(): Test
in a companion object
. Example:
class Test private constructor(private val map: HashMap<String, String>) : Map<String, String> by map { companion object { fun newInstance(): Test = Test(HashMap()) } }
For future questions:
In the case of primitives, just set a default value:
var id: Int = 0
For non-primitive types, you probably want the <code>lateinit</code> modifier.
Also, I noticed that you used Integer
instead of Int
. If you are coming from Java land, and this was an intentional choice to allow nullable integers, use Int?
instead. You'll still have to initialize it, but you can initialize it to null
if that's the intention. Otherwise, Int
is equivalent to int
in Java.
You need to use a older version of the storage library.
As stated here:
https://firebase.google.com/support/release-notes/android#latest_sdk_versions
"Cloud Storage version 16.0.1" >Removed the deprecated StorageMetadata.getDownloadUrl() and UploadTask.TaskSnapshot.getDownloadUrl() methods. To get a current download URL, use StorageReference.getDownloadUr().
Neil Smyth published last month a good book about android development
The section about the Kotlin language is rather brief, so I would suggested using other Resources to learn the Kotlin language, like Head First Kotlin.
Really love it, thanks for sharing the video. I learned some more language feature straight from his talk.
Here is some of language features with couple of notices I got from what he mentioned in the talk (allow me to add here in case someone else might want to look at)
Edit: format text
The stdlib's measureTimeMillis captures the outside context rather than trying to expose an inner context, and only returns the elapsed time and mutates the scope's variables it was called in. Maybe use that/replicate the behaviour?
Kotlin has recently introduced a roadmap for upcoming releases, you can find a deadline as well as a comprehensive (although not exhaustive) list of all features the next release will target.
Nice write up!
Nit -> you can definitely use ThreadLocals from coroutines (with some limitations like you won't be able to propagate the updated value to the caller)
This is already doable in kotlin: see "Intermediate flow operators" here: https://kotlinlang.org/docs/reference/coroutines/flow.html
suspend fun performRequest(request: Int): String { delay(1000) // imitate long-running asynchronous work return "response $request" }
fun main() = runBlocking<Unit> { (1..3).asFlow() // a flow of requests .map { request -> performRequest(request) } .collect { response -> println(response) } }
Have you got an example of what you would want this function to do? The Number
class is just an abstract class that forces the concrete types to implement the methods for converting between numeric types.
You can declare a generic type to be of a certain upper bound type but it doesn't really give much advantage (that I'm aware of) over just using the Number
class itself other than the return type can be specific. You'll still need to cast internally to use specific functions of Int
, Float
, etc.
fun <T : Number> someFunction(x: T): T {
...
}
Not true actually. Ceylon is a JVM language with Union Types..
https://ceylon-lang.org/documentation/1.3/tour/types/
I've not used it but the concept I think would be extremely useful. As an example, I was working with a chart library where data could be either Int or Double. Was trying to write a wrapper so that the dev didn't need to know the sequence of calls needed to make the chart, they just implemented a function to return the data.
Now clearly I could have an interface IntegerChart and a DoubleChart but it would have been nice to say 'you have to write a function which returns either a list of Int or a list of Double.
Right now, I could do AbstractChart<T> but can't enforce the type of T easily whereas a union type would allow it
I hate ranges of numbers and for
's dependency on it. For example take a look at this small exercise based on this code golf
You'll notice there's so many different ways to iterate over a range of ints incrementing, decrementing, inclusive of end and exclusive of end. And don't even try iterating over a range of int decrementing exclusive of end. I'd rather just write c-style for
loops
You said you're trying to avoid dupe classes but maybe try Sealed classes?
https://kotlinlang.org/docs/reference/sealed-classes.html
sealed class DataRecord(val date: Date? = null) {
data class V1(val date: Date? = null) : DataRecord(date)
data class V1(val date: Date? = null) : DataRecord(date)
.... More versions
}
Then you can easily use a when statement to check the versions
I don't believe that is possible. (see https://kotlinlang.org/docs/reference/delegated-properties.html ) You would need to declare the delegated property inside of the class, like
class SomethingChangedEvent(foos: Collection<Any>) { val foos by ReadByCopyProperty(foos) }
If thats how your delegated property class is set up
Correct. I've seen a few possibilities that I'll summarize for you. The first option you're already using: intent.putExtra("phone", person?.phone)
which will use the value passed to it, or pass null with no meaningful way to deal with the problem.
​
intent.putExtra("phone", person?.phone ?: "default value")
will allow you to set a default value if a null is passed.
​
intent.putExtra("phone", person?.phone.orEmpty())
The orEmpty() extension function will set the value to an empty string ""
if a null value is passed, according to https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/or-empty.html
So, for multiple words, the official coding convention is to use "CamelHumps" not whitespace.
For example, a package name might be myPackageName
, a class MyMultiWordClass
.
Now, for project names you need to also account for revision control conventions and URLs, because usually eventually someone may want to version your project in a git repository, and host it in GitLab, yada yada yada. These tools will turn My Project
into my%20project
or my+project
, but not consistently. Even a MyProject
camel case will be turned into myproject
. Ergo, it's usually best to completely avoid multiple words in project names.
And I say this from having made similar mistakes in the past. It's just not worth it. :)
The groupBy could do the job.
​
​
before.groupBy {
if (it % 5 == 0) {
it / 5 - 1
} else {
it / 5
}
}
You don’t need two generics, you should be able to just do:
operator fun <A : Any> A?.invoke(block: A.() -> Unit) { this?.block() }
But then, at least on JVM, you’ll have a signature clash between the nullable and non-nullable overloads, which you can resolve adding different Jvm names to them:
@JvmName("invokeNonNull") operator fun <T : Any> T.invoke(block: T.() -> Unit) { block() } @JvmName("invokeNullable") operator fun <T : Any> T?.invoke(block: T.() -> Unit) { this?.block() }
But it might be better to avoid this overload and just export the nullable version as the public API:
private fun <T: Any> T.invokeNonNull(block: T.() -> Unit) { block() } operator fun <T: Any> T?.invoke(block: T.() -> Unit) { this?.invokeNonNull(block) }
How about Sequence and generateSequence?
I think I have this figured out.
​
Based on this page runBlocking
uses the current thread as its run context, and any launch
invocations within that context will inherit that context. Because the dispatcher is single-threaded, coroutines will run sequentially because you're creating a new coroutine, switching to that coroutine on the thread, then going back to the loop.
When you use GlobalScope.launch()
it uses Dispatchers.Default
which throws coroutines into a thread pool. This thread pool will send coroutines to different threads for executions as they are launched. In addition, the launch()
function in this context will also throw new coroutines into the thread pool.
So the behavior you experienced is expected. When you launch a bunch of coroutines in a single thread they will be executed kinda sequentially unless they suspend at some point, giving control to another coroutine. When you spawn coroutines in a thread pool, they will run concurrently on different threads.
Just read this:
https://mashable.com/2018/03/30/google-vs-oracle-explainer/#mL_Ptr0DJPqm
Kotlin is a completely different case as JetBrains started developing it as OSS back in 2010: https://kotlinlang.org/docs/reference/faq.html
Here is a comparison of Kotlin and Java. You can search for Kotlin vs Java to find more comparisons.
Some great tips here! I wasn't aware of @TestInstance(Lifecycle.PER_CLASS)
, and have always wished that's the way JUint tests were run.
I do find it kind of funny that the author repeatedly defends using AssertJ saying they don't mind "the dots and parenthesis". When I see Kotlin with a lot of user-defined operators, foo bar baz quux
, I'm left wondering what's a function and what's an argument. So I not only don't mind the dots and parenthesis, but actually find that they make the code easier to read.
That said, one thing I do prefer about kotlintest (or even kotlin.test -- yes, two different things) over AssertJ is the exception testing:
AssertJ, even from Kotlin, is more verbose:
// AssertJ assertThatThrownBy { // ... }.isInstanceOf(FooException::class.java)
// kotlin.test assertFailsWith<FooException> { // ... }
// kotlintest shouldThrow<FooException> { // ... }
The assertThatThrownBy
error message isn't as helpful in the case where no exception is thrown:
Expecting code to raise a throwable.
versus (this is from assertFailsWith
):
Expected an exception of class com.example.FooException to be thrown, but was completed successfully.
assertFailsWith
and shouldThrow
just return the exception, so it can be tested like any other object, while AssertJ's assertThatThrownBy
returns an AbstractThrowableAssert
, which has its own API for testing common exception properties. More to learn/remember, and less flexible. If I've got a custom exception with a "foo" property, how do I test it in AssertJ? It's immediately obvious with the other libraries that just give me the exception.I extended the example from the official documentation (https://kotlinlang.org/docs/reference/sealed-classes.html). Worked in my case, couldn't compile this :)
sealed class Expr { class Const(val number: Double) : Expr() class Sum(val e1: Expr, val e2: Expr) : Expr() class Bla() : Expr() // as soon as you comment this out, it works object NotANumber : Expr()
fun eval(expr: Expr): Double = when(expr) { is Const -> expr.number is Sum -> eval(expr.e1) + eval(expr.e2) NotANumber -> Double.NaN } }
Right, but your annotation is inside the constructor on the field rather than on the constructor itself. You can't use a constructor annotation in Kotlin without the constructor
keyword (see: https://kotlinlang.org/docs/reference/annotations.html#usage)
An object
is basically static (not really but I think of it like that).
This means that there is no this
in the context of the inner object.
Either: make the outside class an object
and make it basically static or make the inner object
an inner class
to get access to the outer this
reference.
Also read this: https://kotlinlang.org/docs/reference/nested-classes.html
The possible ways:
class Test {
var test = "test"
inner class InnerTest { var inner = // can be replaced by "test" } }
object Test1 { var test = "test"
object InnerTest { var inner = Test1.test // could be "test" as well } }
Yeah, this is doing the same thing as the implicit groovy map constructor, a syntactically nicer way of doing it in Kotlin is:
class Person @JvmOverloads constructor(var name: String? = null, var age: Int? = null)
Note that you need to add the constructor keyword before the ctor arguments so that you can annotate it with @JvmOverloads.
You could also add the data annotation to the class if you wanted hashcode, equals and toString. Then you can instantiate it in numerous ways (including with no args for spring data):
>>> Person() Person(name=null, age=null) >>> Person("dave",12) Person(name=dave, age=12) >>> Person(age=12) Person(name=null, age=12) >>> Person(name="dave") Person(name=dave, age=null) >>> Person("dave") Person(name=dave, age=null) >>> Person(name="dave", age=12) Person(name=dave, age=12)
Seems like you could do something similar via property delegates rather than needing to completely create your own binding framework.
You might want to take a look at using the withIndex()
function with for loops, to clean up the while loops in your circle
class. See the bottom of this section of the kotlin docs.
Please refer to these documentation topics: https://kotlinlang.org/docs/reference/inline-functions.html#non-local-returns
https://kotlinlang.org/docs/reference/lambdas.html#anonymous-functions
Simply put, 'return' without a label returns from the nearest enclosing function that is declared using the 'fun' keyword. If you have a case when you often need to return from a lambda and not from the enclosing function, the best option is to use the anonymous function syntax instead.
It's only a problem when using existing JavaScript libraries.
I guess it could be dealt with by writing wrapper libraries in Kotlin, instead of just type definitions, that would expose a more Kotlin-friendly interface to the JS library underneath. But that's a lot of work and I don't think people are going to do it - except for maybe the most popular libraries.
You can try it out yourself with the ts2kt tool, and see how it converts some existing TypeScript declarations.
There are things in TypeScript such as union types, intersection types, mapped types, string literal types and more, that accurately represent the working of JavaScript libraries, plus the whole structural typing thing.
I personally just use TypeScript for frontend code, even though I miss some of Kotlin's features.
I imagine the Kotlin JS target could be useful if you have a library that you want to use both on the frontend and the backend (and mobile), so it will allow you to share this code between platforms. I wouldn't use Kotlin for the entire frontend though.
This isn't AndroidDev, but I would strongly suggest to repackage large projects in small modules to seriously optimize Droid development. I see people going to the whole build->deploy process multiple times a day for minimal changes. Use an emulator, work with local files and tests instead of playing on the device.
I'd love an annotation driven approach like Lombok, but until that happens you can check out kassava, the library I wrote for this exact problem.
Example usage:
import au.com.console.kassava.kotlinToString
class Person(val firstName: String, val lastName: String){ override fun toString() = kotlinToString(properties = arrayOf(Person::firstName, Person::lastName) }
Example output:
Person(firstName=Rick, lastName=Sanchez)
FYI this question has been asked on StackOverflow
fixed. Also, came across a weird scenario which took a while to figure out. Posted a SO question here. Thanks for your patience. https://stackoverflow.com/questions/44276695/is-jsname-annotation-required-for-every-method
Remember, the fact that its kotlin vs jsx doesn't really matter. You should figure out the html & css you'll need then use the kotlin react dsl to create it. There are tons of resources to do things like what you want for jsx and you can rewrite those in kotlin. The kotlin react dsl and jsx do the same thing, which compile down to some javascript that creates react elements. Checkout this page to see what jsx actually is. https://reactjs.org/docs/react-without-jsx.html