I expect as much. Having going through FedRAMP before, the alternative would be to make their regular commercial infrastructure be up to FedRAMP standards, which is incredibly onerous (things like change tracking, DR, US Citizen access only to production systems, etc.)
The thing about FedRAMP is that it's not one thing, it's a framework. Even if you have a FedRAMP package for a system, you need a fresh ATO to use it at any customer.
Technically, there is no citizenship requirement for FedRAMP.
In reality, at every US Government customer I'm aware of, US Persons (Citizen or PermRes) are the only ones that can deploy code to production. You can have non-USP writing code but it must be reviewed and rolled out by USP.
YOLO is a pretty simple and flexible architecture. Like most of these models, you can label some data and just freeze the intermediate layers and just retrain the final predictor head.
Checkout as well darknet, which runs at really high fps on super cheap hardware
Pensions compete with self-directed retirement in the same way that a salary competes with founding your own business: they take all the risk and all the mental effort and give you something you can (mostly) rely on without any added effort, in exchange for a smaller return than is technically possible if you took the risk and planning effort yourself.
Some people would definitely be better off managing their own retirement, but just due to the way these things work my bet is about half of all people (the left of the bell curve) would be better off with a pension.
Pensions are also risky when you’re young because so much of their value depends on the final salary. Leave a job young without those promotions and 5 years of service can mean almost nothing 30+ years later in retirement.
Where you sit on that bell curve isn’t obvious at age 20, but it’s much clearer at age 40. Benefiting people who have already messed things up and swap.
Thus that single binary choice after college is likely suboptimal.
When my dad started work in the 1970s he only had a pension which he - like most his age - didn't bother participating in. He latter got old enough to realize that he should save (probably when a new job offered a 401k with match) and regretted it so much he looked things up. Turns out that if he joined until that company laid him off he would get $0.75/month from the pension once he turned 65. In short a stupid investment. Those who were older like you say did much better.
there is one big advantage of a pension: you cannot outlive them. If you die at 65 (as my dad did) bad luck, but if you live to 109 you still get that income to live on.
Assuming the entity paying the pension has the cash. Not a problem for the federal government, obviously, but for other governments, and especially non government entities, running out of cash is a possibility.
Another risk is not having it be sufficiently inflation adjusted. An investment in SP500, however, would protect you from declines in the currency’s purchasing power.
Most pensions since the 1970s or prehaps before are government insured in the us. But my family has stories of the relative who worked for a company for decades the company sent bankrupt when he was 60 and the pension was invested in the now worthless company stock.
the above is why I tend to oppose employee owned conpanies. Too much risk for the common man to have so much net worth in their job.
Even insured, they constantly require bailouts by federal Congress because PBGC can’t handle the load, depending on the political influence of the group being bailed out.
Auto manufacturing, teamsters, coal miners, etc. Only question is how much pull your group has in Congress.
The biggest pension (and IRA/401k) bailout, however, is the implicit backstop the US provides the public equity markets. Might as well cut out the middleman and own the inflation protected asset yourself rather than accept a defined benefit in someone else’s control.
I’m skeptical of the value in doing this. There are a mountain of tools like NullAway, ErrorProne, Immutables that make it so much easier to write safe code in Java. New developments in the language like first-class record types improve the DX as well.
I think Kotlin helped push Java in the right direction, but at this point it seems like a weaker choice. Spending years to migrate a massive Java code base like this feels like wasted time.
I, personally, happen to like writing in Kotlin more than Java - with a lot of experience in both (though admittedly, all? the Java I wrote is in the pre-Streams style).
I like:
* data class Foo(val theImplementationAndStyleOfDataClasses: String)
* elvis?.operator?.chaining
* the order of variable declaration (type afterward)
* how function pointers at the end of a method call can be auto-inserted as the next curly bracket
* how you can have fun foo() = returnValue; in one line.
* fun `method names that can have spaces - and dashes - in them`()
The preceding 3, combined, allow for:
@Test
fun `much easier testing`() = commonTestSetupWrapper {
// the code under test
}
* val immutable by default
While I agree that Kotlin has definitely helped push Java in the right direction; and I agree that it's probably not especially necessary to migrate 10MM lines of Java code to Kotlin, especially since they're fully interoperable, I definitely would prefer writing _new_ code in Kotlin over Java for the for-the-lazy devex improvements, if nothing else.
fwiw, my "good at it" programming history follows the lineage in historical order of:
* Java (8?? years of it including competition programming)
* C# (5+ years)
* Python (2016ish to current)
* Ruby (3-ish years, lots of Rails)
* Kotlin (2-3 years, through current - written over 40k lines of Kotlin in the last year, alone)
`method names that can have spaces - and dashes - in them`
Eugh, that is a turnoff. Maybe I have programmer Stockholm’s, but at least with a single connected word, I can always double click to select the token. Maybe, I might have wanted dashes at some point, but spaces seem like a step way too far.
What benefit do they provide in testing scenarios? I've never written Kotlin, but from an outsider's perspective, it seems like a slim benefit, outweighed by the cost of the mere existence of this syntactical oddity in the language's grammar.
When writing tests, you can name the methods more useful things, such as:
class MyTestableClass {
fun `methodName - when input does not parse to valid regex throw exception`() {
}
}
It's pretty clear what is under test in a situation like that. That's basically the only situation I ever see it used in (and would code-smell the heck out of it if I saw it in other circumstances).
People who are familiar with RSpec-style testing are very used to this sort of thing.
describe MyTestableClass do
context 'input parsing issues' do
context 'when not valid regex' do
it 'throws exception' do
...
end
end
end
end
Anecdotally, I've also found that such style naming for tests allows me to write out the desired names for all the tests ahead of time more easily and then implement them. That happens to be my flow.
This study only compared camelCase to snake_case and what the results are mixed, depends on what you call "hard to read". They only seem to have tested finding identifiers from a word cloud, and it did take more time to read camelCase identifiers (although they were also resulted in more accuracy).
It's important to note that the researchers only tested short phrases with 2 and 3 words. "getNextPath" is a different beast compared to "methodName_whenInputDoesNotParseToValidRegexThrowException".
On the other hand, there is a good body of research that generally shows that proper sentences (not just 2-3 words) without spaces are harder to read, at least for English speakers[1]. Early medieval Latin manuscripts did not use space between words[2]. The fact that spaces were seen as an improvement when they were introduced, is probably telling.
[2] Roman-era inscriptions did use an interpunct (a small middle dot) to separate words, but this practice fell out of fashion in Late Antiquity and Early Middle Ages and I'm not sure if it was ever the norm in handwriting.
Sure, but I like writing the other more. It's entirely a style thing and you're not required to do it :) it's also basically only ever seen in tests :)
That doesn’t seem to be the case based on the study. And normal for one thing, such as paragraphs of prose, might not translate to another thing, such as a sequence of words in a line of code.
I like how tests are made in Python - you don't even need classes, just functions, and use a single assert keyword for everything. Also it's easy to parametrize them using decorators.
Also, once you get used to assertj, you'll never want single-assert again. It's fantastically useful to know (for example) not just that two lists aren't equal, but specifically what elements differ.
If the list contains numbers or strings, you can use
assert sorted(x) == sorted(y)
If you want to add map, then you have to write
assert list(sorted(i.getValue() for i in someCollection)) == [3, 4, 5]
If the list contains non-sortable values, but they are hashable and unique, you can use sets:
assert set(x) == set(y)
If the values are not unique, but hashable, you can use a counter (like a set but with count for repeating values):
assert Counter(x) == Counter(y)
(by the way I learned about this trick from a LLM)
And if the values are neither sortable, nor hashable, you'll have to write a helper function.
But still, pytest tests are less wordy and they don't require you to create a class.
This situation is familiar to me, I had to write such helper function when writing tests in PHP, for some reason it is not included in PHPUnit assertions.
Parameterized tests are a huge, huge win, yeah. I am a big fan of them and look for how to do them in every test framework I use. RSpec was the weirdest for me; but NUnit and JUnit have been quite easy, and I'm not surprised at all they're easy in Python too (admittedly, I don't remember if I ever wrote them in that language).
In the RSpec case, those don't have to translate to method names with embedded spaces. It seems that using fun `...` instead of a dsl: test "..." is the mistake.
It's a place to put intetion that isn't so much of a second class citizen that it will likely be ignored and/or not updated if it ceases to be true. You want your test methods fine grained (many methods that each check one variation, instead of one method that checks a whole list of them) and every extra redundancy (method naming vs the variation of data actually passed vs documentation) increases the the chance of those redundancies getting out of sync.
In fact I've occasionally found myself writing reflection code to parse the test method name as input just to avoid that problem altogether (for name and data, not for documentation). And that was in plain Java even, the pattern could be far more useful with that kotlin naming freedom.
It reminds me of Spock tests written in Groovy. I have to help maintain a code base like that now at work where a Groovy zealot (who has moved on) convinced the teams to write tests in Groovy instead of Java.
When a test fails, the method name describes what it was supposed to do written out like a sentence enclosed in double quotes which seems like a win but not much of one.
When you need to add a new test or analyze if an existing test needs to be changed, you have to eyeball all the code in the test class because even with methods named with spaces, it's not always indicative of what it does.
With Java, I can sort a list of method names and have a better idea immediately what needs to be updated or added.
Spock is an exercise in syntax cleverness with regular confusion opportunity and little gain IMO. Way too much implicit syntax that IDEs struggle with.
Refactoring Spock tests sucks due to how the context is different based on the clause you’re in.
Isn't this breaking Jakob's law of the rest of the tooling though? I can se flows borking with something like "x failed at expect" in a majority of reporting tools not specifically meant to deal with this spaces in functions stuff.
Not really—-most CI reporting is based off junit/testng report XML files. I doubt your CI reporting is parsing out test names with regexes out of log files.
> at least with a single connected word, I can always double click to select the token
I'd expect an IDE for Kotlin to detect `stuff like this` and select the entire name. Considering Kotlin came from JetBrains, IDEs are most likely already in the Kotlin community's DNA.
(i never wrote or anything related to Kotlin myself but i do appreciate IDEs helping with stuff like this)
Which are not nearly as capable and will forever be catching up. For a better situation look at Apple’s sourcekit. I’d take kotlin over swift in less than a heartbeat if it was more open source than Swift. Which us a very low order.
The feature isn't just about spaces. It's also how you'd work around interacting with JVM code that uses what would be Kotlin keywords. For instance, Java classes with a method named "is" or "val" can be called through
val isBar = foo.`is`(bar)
rather than needing to use reflection like you would to accomplish the same in Java.
The Kotlin style guide basically says "never use this outside of test names" and some targets, such as old Android, don't even support the feature in test cases.
As others have said, I would not expectany any style guideline to tolerate those names outside of tests. But it's not entirely test-only: When you are dealing with code generation for schema defined in/for other languages, being able to just drop names in backticks and be done with it would be far less hassle than making up your own transformation and deciding between verbosity and safety from collisions.
If you use a good IDE it will select the whole method name.
In general you would not use spaces for method names of anything that’s a shared/common use facility. They are best used to give test methods readable names. E.g. “test parallel writes are thread-safe”. And not “write with timeout.”
While that is avoidable by sticking to a coding style, that horrid and unavoidable 'fun' instead of 'function' (or 'fn') just saps my will to work on such a codebase.
I like Kotlin, but what I hate is that in the meantime I migrated all my programming to Neovim and Helix. All programming? No, not Kotlin, because the LSP isn't there and JetBrains clearly has no interest, they want to sell their IDEs.
Now don't get me wrong, I have an IntelliJ license since 10 years, even back when I was employed and paid it out of my own pocket.
It's not about the price. I would gladly pay for the LSP implementation. But I don't want to use IntelliJ anymore.
So a new project on the JVM where I have a say in the stack? Java or maybe Scala. No more Kotlin.
Not only that. Their official position is sitting with smug face saying “well, duh, you’re free to roll out your own LSP and IDE implementation”, ignoring the fact that nobody outside of Google and JetBrains cares about Kotlin.
And why would they? If the stewards aren’t interested in investing into healthy ecosystem.
When it's "sleeping" code, not as in unused but as in not currently being worked on (no changes in open branches), then it can be quite valuable to have some bulk translation run while the code actually is sleeping, and not at some future time when there'll likely be a whole burst of activity happening in parallel. Repo host products might actually add "transform while sleeping" a possible feature, with their cross-branch knowledge, and perhaps some history mangling for a best effort approach to retaining some of th knowledge available through blame through the conversion.
As for Kotlin in general, I agree with your list. I really enjoy the way Kotlin improves the dev experience not so much with audacious new (or "new to a java-like environment", of course I'm looking at you, Scala) concepts but with small trivialities like being able to assign the outcome of an expression chain to a name without polluting that name's scope with intermediates that really don't have any purpose after the result of that chain is assgned.
And I don't hold it against Java that it does not follow that path (it focuses on more impactful changes), I would consider it almost out of character if it introduces e.g. .let. The only thing I'm a bit torn about when it comes to Kotlin is wether the "this" variants of scope functions were a good idea. They are certainly part of kotlin, and some "DSLy" styles would really not be the same without them, but if I were to pull what I like about kotlin into other languages I'd probably introduce let and apply (and the this-less run) and skip run/with/apply (assuming that the target language even has a this to run/with/apply on)
> * data class Foo(val theImplementationAndStyleOfDataClasses: String)
For the purists there are records now in Java (which can be combined with destructuring / pattern matching - there were significant improvements in this area in the last few JDK releases, and more are coming!). In this regard Java had surpassed Kotlin by some margin.
For the enterprise coders, there is the Immutables project (https://immutables.org) which you can say is Lombok on steroids (but implemented correctly, that is, by generating classes which you can inspect as regular source code, instead of relying on hacking the compiler...).
> * elvis?.operator?.chaining
This will hopefully be finally resolved by one of the subprojects of project Valhalla, as a prerequisite for value class support (which cannot be null, so...).
The others on your list are small and subjective stylistic differences, of course your preference may vary, but should not weigh heavily in any Java vs Kotlin discussion.
Java records do not have a copy method (or with clause or whatever equivalent), and there are no keyword arguments.
This makes Java records extremely painful to use for any data has more than 3 fields or so. You could use them together with an annotation processor like RecordBuilder (or Immutables or Lombok, but I don't think they support records?), but that's just not pure Java. Annotation processors that generate byte code always come with their own complexity.
Kotlin data classes have their own warts (order-based destructuring can be dangerous and the copy() method is a bit hacky) but the overall ergonomics for large value objects are better than Java records at this point.
Lombok supports `@With` on records, which adds wither methods. And there are ongoing JEP discussions on how to support this natively in Java.
Lombok is so ubiquitous today that I effectively consider it part of the language. And even with Lombok, the Java toolchain is so much faster, easier to use, and more stable than Kotlin.
Kotlin is a great language, marginally better than Java, but I'm not sure it's worth enduring the toolchain. And Java keeps improving.
If you think Kotlin is marginally better than Java, you probably have a superficial understanding of Kotlin. Kotlin is vastly better than Java, which isn't surprising because Kotlin was designed 15 years later with the explicit goal of being a better Java and fixing as many of Java's design mistakes as possible. For example, the designers of Kotlin went through the book "Effective Java" and tried to avoid the listed pitfalls by design.
Java will never get close to Kotlin because even though Java can, and thankfully does, still improve, it's too late to revise many of it design decisions, and large language features often need to be considered in a language's design from the start.
On Android, Kotlin is an even bigger win because Android uses an old Java version and has become Kotlin-first.
In my opinion, Java will remain the best choice for libraries that target multiple JVM languages. For everything else, I use Kotlin without thinking twice. Kotlin 2.0 laid the groundwork for toolchain improvements, which have indeed been a long-standing pain point.
Nah: If you think Kotlin is vastly better than Java, then you have a poor grasp of Java. I offer the same evidence you did.
Having worked professionally in both, I find that good programmers can write excellent code in both languages; bad programmers can write terrible code in both languages. The average cultural practice of the Kotlin community is perhaps better than the average cultural practices of the Java community (which huge and defies averaging anyway). But Java code which emphasizes immutability, uses Optional instead of nulls, uses streams, etc is pretty indistinguishable from Kotlin.
I first learned Java in 1997 and have been using it professionally since 2005. If your Kotlin code is pretty indistinguishable from your Java code, you aren't using Kotlin properly. Here is what I wrote on this topic in 2022:
Here are some of my favorite Kotlin improvements over Java that I leverage all the time:
* Much improved type system (nullable types, function types, declaration site variance, type aliases, contracts, better type inference, reified function type arguments)
* Local variables are final by default ("val")
* Type-level distinction between read-only and mutable collections (but compiled to Java collections under the hood, so no conversion required when interacting with Java)
* Much improved collection API
* Much improved lambdas (e.g., no pain points w/ mutating variables and checked exceptions)
* Extension functions (incredibly useful in practice)
* Much better DSL capabilities (great for UIs, generating HTML, etc.)
* Yes, the Kotlin type system is better, no question. And yet it doesn't really matter for 90% of code, Java's type system is "good enough". And in the places where it tends to suffer, IntelliJ ends up covering the ground anyway (validating various annotation values, spring properties, sql, etc).
* The difference between nullable types and Optional<?> types is not material. TBH I quite like Optional<?> and how it meshes with streams.
* "final by default" is indeed nice. But putting `final` everywhere (which we do) is at most a tiny annoyance. This is not material.
* Clear type distinctions between mutable and readonly collections is better, but not material, because we treat all collections as immutable.
* Java streams hit 90% good enough, and StreamEx tends to fill in another 9%.
* We don't have pain points with mutating variables in closures because we don't use mutable variables.
* We don't have problems with checked exceptions because we don't use checked exceptions (and when interfacing with foreign code that throws checked exceptions, we use @SneakyThrows or wrap).
* Coroutines are a major net negative for Kotlin, and Loom is already here. After many years of async programming in JS/TS, Ruby, and (going back far enough) C++, I've concluded that async programming (and function coloring) is absolutely toxic and should be avoided unless it's absolutely required for performance (or the platform, ie GUIs).
* Multiplatform support has great future potential, but it doesn't seem to be ready yet. I just started a greenfield project and _really_ wanted to use KMP. Decided against it in favor of a React frontend. I don't want to live on the bleeding edge, I have work to do. And I've been bitten by deadended technologies enough times in my life to know the risk isn't worth it.
I could go on but I think you get the point - my Java looks like Kotlin, and the parts of Kotlin that would really diverge from my code aren't things I want. You could tell me that I should use coroutines everywhere and I just simply disagree.
> This will hopefully be finally resolved by one of the subprojects of project Valhalla
I think we'll see them come in through https://openjdk.org/jeps/8303099 although I'm not a huge fan of the approach chosen (tri state nullability: explicitly nullable, explicitly non-nullable, legacy code that should just be treated as nullable).
Except for native support for reification, almost all of Kotlin can be reimplemented by Java if you wait long enough and stack enough class annotations. It's all stylistic up to a certain point, but the classic Java style combined with the glacial improvement process is one reason why some people want to use a different language.
I think I'll have an easier time convincing someone to consider Kotlin than I'll have convincing someone to add Immutables+Manifold to the dependency chain. You end up writing Java that's not really Java like, but also not something that there's a good standard style for, and that usually ends up in a mess.
I'm glad with pattern matching, Java is now pushing Kotlin to improve rather than the other way around. I'll hope to use those features one day, when companies finally upgrade from Java 11 to Java 17 in five or ten years.
> pattern matching ... In this regard Java had surpassed Kotlin by some margin.
I did just glance at Java's pattern matching; and yeah, it does look like it is a bit more powerful than Kotlin's pattern matching in that it can, at the same time, look for both type and a conditional. That's relatively neat - not something I've personally needed / wanted; but neat just the same :)
The JVM is a really nice virtual machine in how it lets us use both of these languages fully interchangeably to pick the one we like more.
I'm glad Java has been investing in some of these areas, too. Everyone improves when paradigms and new learnings are distilled.
Honestly, none of those differences you listed seems especially compelling to me, except possibly for the ?. operator.
What would be compelling: Array types that don't hate generics, or generic collection types that don't hate primitive types. Does Kotlin improve on Java at all here? It's such a pain having to remember this bonus complexity when all I want is a consistent way to manage a bunch of things. (I suspect not, as I think the limitations are at the JVM level, but I don't know.)
10+ years in the making, at this year's Devoxx Brian Goetz said that they are almost ready with the design of Project Valhalla and can start JEP-ing it in future JDK releases. No timeline yet, so we probably will not see it until the next-after-next LTS release (29?)... But Java, like Cobol, is not going anywhere, so the wait will be worth it.
Great, though is that perhaps orthogonal to my complaints? My vague understanding is that Valhalla is about transparently allocating local objects on the stack instead of the heap when possible (i.e., when escape analysis confirms that they can't "get out" of the method that declared them), the way primitives are now.
But these are the same problems! I'm not intimately familiar with the current state and internals of project Valhalla, but they were proposing `primitive classes` backed by primitive types, allowing said class to be used as a type in generic code. Moreover, primitives would become ValueObjects, so you would have your int[] which would also be an Object[]. In other words, the difference between primitives and objects would be much smaller in terms of the language.
Bottom line is, you could have your cake and eat it too - have an int[] that looks like a List<Int>, and vice versa, while retaining the performance characteristics of an array.
Thanks, I'd thought that the goal was to reimplement aspects of the compiler+JVM to preserve existing language semantics but be more performant, but from what you've written I take it that the goal is actually to expand the language semantics themselves, in a way that would bring primitive types and objects (and thus generics) closer together.
Kotlin does improve on the primitives/boxed situation. For example in Kotlin there is just "Int", not both "int" and "Integer". The language will use stack-allocated primitives wherever possible and boxed objects when necessary (in Collection generics or when you've explicitly opted into nullability). The distinction is abstracted away from you as a programmer. Sounds like the consistency you want.
Stripping out Maps/Lists with boxed keys and values is the first easy thing to do when perf tuning a piece of code. It's so frequently impactful that it's worth doing immediately without any measurement.
You just swap them out with fastutils or trove and call it a day.
I think you're right, that's probably the best (lowest mental overhead, fewest footguns) way -- always use a List instead of a raw array, and always box primitive types. This also avoids the parallel explosion of Stream types and methods (IntStream, mapToInt(), etc. (and the fact that there's no BooleanStream or ByteStream, etc.)).
That said, I tend to get bitten by the fact that == on 2 boxed numeric values is roughly as misleading as possible -- it does reference comparison, but interns small integer values only, so (Integer)42 == (Integer)42, but (Integer)420 != (Integer)420. (So the small values you probably used in your unit tests will appear to work just fine with your broken, ==-using code.)
ETA: Deleted a misplaced "new". I also don't love that, e.g., ++x does a heap allocation + deallocation if x is boxed (since boxed types are immutable). But usually I care more about the cycles I spend coming up with correct code than cycles the CPU spends executing it.
Indeed. It's C# that makes me like Kotlin so much. I was trained in Java but used C# in a fully-professional setting for longer. C# as a language make a lot of very smart decisions that Kotlin took into itself when being created and out if it comes a non-Microsoft-owned (which matters for some people), comfortable, powerful language.
If I had to switch and use C# as my main work language for a company, I would be perfectly happy to.
The value in the conversion of existing code in this particular case isn't 100% clear to me either, but I think calling Kotlin a weaker choice than Java at this time is naive, particularly when preceding that with "there are a mountain of tools" that you can bolt on to Java to give it features that are built in to Kotlin.
What makes Kotlin such a strong choice for many orgs today is its batteries-included multiplatform capability. We are able to write data models, validation logic, business logic, etc just once and compile to JVM, WASM, and native targets. For orgs with very large codebases and frontend applications (web + iOS + Android) this is an attractive capability because we can have a single codebase for a ton of core functionality, and have each frontend import a library which is native to its own platform.
Of course many technologies with this promise have come and gone over the years, but this is the first one with a strong backing that has allowed us to _natively_ interoperate with each target platform.
I believe these are all driving factors that have been pushing well known companies, that were previously Java shops, toward Kotlin. If you speak to a broad range of people in the industry you'll find many more orgs moving from Java to Kotlin than from Kotlin back to Java. We can simply get more work done with less code and ship to all our frontend platforms, and unless Java can do the same, I don't see the industry moving in that direction.
It’s like marriage. Yes there are tools that can give you most of the same rights and privileges as marriage, or you could just get married and get all of that for the cost of writing one check and signing some papers. No lawyers. Done. Move on with your life.
The question of optional things is always laid out as if the choices of my coworkers do not exist. Are you expecting me to work solo, or to be a bloody tyrant who pushes through all of my own ideas over the objections of an entire team? These are some of the most antisocial people in any debate on software. No I don’t get to just chose to use or ignore a tool in an ecosystem. That’s why picking a system with batteries included is a simpler transaction. I can go to a new company and have expectations, not arguments.
> What makes Kotlin such a strong choice for many orgs today is its batteries-included multiplatform capability. We are able to write data models, validation logic, business logic, etc just once and compile to JVM, WASM, and native targets.
Not familiar with Kotlin but how does that work? Does it come included with a PAL? Because it you want to be platform agnostic, you can't for instance use a Java RegularExpression in your platform agnostic code.
The PAL (Platform Abstraction Layer I assume) is just the stdlib that is provided. The stdlib is not the same for all platforms, as can be seen in the documentation. A regex implementation is provided for all platforms, but is not quite the same on all platforms: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.text/-r...
In shared code you can define interfaces that have to be implemented by any platform you use.
Java did improve over the years. But it still defaults to doing basically everything wrong by default. Parameters are non final, classes are open, things are mutable, etc. It's unsafe by default. And it's hard to fix because it breaks backwards compatibility. Kotlin doesn't have that problem and it has been doing the right thing by default for a long time. It's still getting better.
I think on Android the choices are either to start from scratch or to migrate to Kotlin for Facebook. Sticking with Java on Android just makes everything harder. All the new frameworks are Kotlin centric. Most Android developers they'd be hiring would have been using Kotlin for years. Etc. So, I can see why Facebook is making the effort to keep their code base alive and future proof. Android is more Kotlin focused and has been for years. And that's only going to be more the case now that compose multi platform is a thing.
Btw, most of the stuff you mention is probably more applicable to server side Java and less to Android. IMHO, Spring + Kotlin is a very nice combo on servers. Very well supported by Spring and they bundle a lot of convenient things for Kotlin. And I don't need any of the tools you mention because it does the right thing by default.
> And I don't need any of the tools you mention because it does the right thing by default.
I mostly agree with you, but Spring+Kotlin does require the allopen plugin, so it's kind of hacking Kotlin to do the wrong thing (all classes open) in order to support an arguably bad design choice by Spring.
A whole lot of pie in the sky architects, which seems to be all of Kotlin authors and all of Kotlin-writing cadets, sure love to dream that closed by default is a good design choice and think of times when something open was extended or accessed that wasn’t actually consciously fore-thought of the intended points of extension. But they conveniently ignore the costs of these shackles to their business and agility, and I argue that the costs are far greater than the benefits, especially for non-library code. We just spent a couple of decades fighting the waterfall delusion of big design up front. Yet closed-by-default takes us back to the Stone Age that ignores the reality that there’s no way that the original code authors could’ve thought of all legitimate/sensible uses ahead of time. But good engineers tend to decompose code into smaller classes and functions, which often have a pretty good chance of being extended rather safely in practice.
It is wild but such is the consequence of the culture that punishes explicit failure, and ignores failure to be able to ship fixes for the unpredicted situation and ignores failure to have a productive code base. I cry for the mounds of copy-pasted code that must result from this policy that treats its engineers code like radioactive garbage.
Exception: final parameters. They should never be assignable.
As long as they're already writing new code in Kotlin, translating the existing code makes a ton of sense, if they can do it cost effectively (which is sounds like they did).
One of the huge problems with a language migration is that you're left with old and new and all the parallel tooling, context switching, and impedance mismatches. There's often a claim that the existing code will be migrated eventually, but IME that doesn't actually happen with large code bases. Then if there's ever a third migration, you're left with three languages in play.
It's much better to aim for 100% migration, as close to 100% automated as possible. Then when you're done, you're really done. Maintenance, training, and the next migration will be easier.
There are a lot of nice things I enjoyed when I was still working with Kotlin extensively. Null safety, data class, sealed class, exhaustive when, top level functions, object class, higher order function, extension functions etc. They fundamentally change the way dev think, producing safer, lighter and more maintainable code.
Contrary to the popular notion of dismissing certain syntax differences as sugar, I consider it one of the most important factors simply because we spend more time reading than writing code. To me Java has always been verbose and dreadful to read, there's something fundamental wrong if you need your IDE generate so much then force to train your eyes to skip over most of them while reading.
I find Kotlin to be more elegant and fluent especially with native syntax support of the above features. I can read it at least 25% faster than Java. Perhaps which one is better is personal taste, but I'd maintain syntax is very important, just like natural languages.
Especially because outside Android, Kotlin Virtual Machine will never happen, it will always be a guest language on the Java ecosystem.
Nothing on Kotlin will ever matter on the decisions taken by Oracle, IBM, Amazon, Azul, PTC, Aicas, microEJ, Microsoft, Red-Hat,.... on their JVM/JDK implementations and related tooling.
I would argue that Scala drove Kotlin. And over the last 10 years at least, it's been Kotlin driving Java.
What I saw happen was Kotlin taking over the mantle of "better java" from Scala, and aiming for an 80/20 type language compared to Scala. And for the most part, it's those 80% that are finding their way into Java.
Many of Kotlin's profound improvements will never find their way into Java because it's 25 years too late to do so. Java improves where it still can, which is the right thing to do. Sometimes Java even manages to improve on Kotlin because now it can learn from Kotlin and other languages. Nevertheless, it's impossible for Java to catch up to Kotlin, which was designed 15 years later with the explicit goal of fixing as many of Java's design mistakes as feasible for a JVM language.
Yeah Facebook was (in)famous for autogenerated code in their apps and frameworks. In fact early on they had to do some hack on Android since they had more classes in their FB app than was supported by the operating system lol.
So super inefficient binaries, but I guess more efficient to develop (or I assume that was the idea)?
You are getting the details wrong (I was there). This was the single DEX limit, and Google would just bump it in AOSP every time their own apps hit it (as their apps didn't support older OS versions). FB at the time was supporting back to froyo, which had a much lower limit than "modern" apps needed. See this note for more info: https://www.facebook.com/notes/10158791578712200/
By the Dalvik Virtual Machine (DVM). 65k method limit is what Facebook hit. tbf, DVM was engineered to run on embedded systems with 64MiB RAM (as a replacement for J2ME).
It is probably more that Kotlin's order breaks with the most common ordering, and at the cost of more characters. Not to mention the needless variation that has come along with it (e.g. : vs ->)
Having the identifier first makes it easier to parse unambiguously; the C syntax has been historically criticized for not being context-free because of stuff like "A * B" being impossible to parse correctly without knowing whether A is a type or not. While Java doesn't have the equivalent problem, Kotlin keeps its options open wrt future syntactic extensions for type names.
Identifier-first can also be a lot more readable when gnarly (and thus lengthy) types are involved, since you don't have to scan the line to find it. It makes for neater-looking code with multiple declarations one after another, too.
As far as commonality, both syntaxes are very common, and have been so historically as well (roughly speaking, C vs Pascal syntax families). It should also be noted that most new languages go for identifier-first, so if anything, it's more future-proof in this sense.
There are plenty of old languages using it. Pascal/Delphi, Ada etc. That's where the current crop of languages got that syntax from, it's not like it came out of the blue all of a sudden.
And I already explained the reasoning. No, it's not to avoid the lawsuit, it's because many people genuinely find it more readable for various reasons. Which is why it keeps showing up in all kinds of languages that are otherwise wildly different syntactically.
Yes, there are older languages using Pascal style declaration, but any of C,C++,Java dwarf it in terms of popularity and general exposure (thus my use of the term "common").
And again, in the latter part I'm talking about Kotlin's use of 'fun' and ':'.
My comment had nothing to do with lambdas. The point is that Kotlin uses fun and : instead of fn/func and ->, which is a needless and tedious break with other modern languages using Pascal-style function declaration.
Using val instead of let is similarly off-putting.
Meta operates at such a large scale that the engineering management decision process becomes qualitatively different from smaller organizations. They can justify enormous investments in keeping their code base fresh for small improvements in productivity and quality.
I'm trying to unfuck a C# codebase that was converted from Java by some tool. It did an OK job (nevermind the reasons for all this) but no one went through and resolved the problems that don't cause a build failure. These conversions have a blast radius of unknown proportions.
Java is still horrible. Every time I go back to Java it seems like nothing has changed and I say this from the perspective of using a JVM language that is 9 years older than Kotlin.
The legal issues around Java between Alphabet and Oracle are settled at this point and no longer a risk for third-party software vendors. But it's pretty clear that Android is moving away from Java, so anyone with a strategic commitment to that platform has to plan around that reality.
It's safe to say that Android is definitely moving away from Java in terms of new language features. I mean, if you want to support older Android versions and use modern Java features or newer parts of standard libraries, you'll usually have to rely on desugaring or making sure you're using classes that are supported in Android.
IMO, Android is moving away from modern versions of Java. Java and its underlying standard library will always play a big role in Android development.
The way I see it, Kotlin makes a lot of sense for Android development because Kotlin can introduce new things in its standard library that make older versions of Java look ancient. It's not like you can use new Java features in Android, so using Kotlin makes people not care as much about new features of Java that are only available in modern versions of Java.
Android folks were forced to acknowledge modern Java, otherwise they would lose access to Maven Central ecosystem, as everyone adopts newer Java versions.
Hence ART is updatable via Play Store since Android 12, and is currently on Java 17 LTS.
unless you're not using the jvm (which is owned by oracle, despite being opensource), you won't have any difference between kotlin and java from a legal perspective tbh.
Most important reason for the rebirth of golang (after it's initial dip in early '10s) and wide spread adoption of Kotlin is the ownership of Java by Oracle. It doesn't matter what fine print exists, but everyone knows what kind of a*holes Oracle and Larry Ellison are, they will find a way to squeeze you. Everyone is going to sprint away from Java as soon and as much as possible. For someone like FB, Kotlin being a nicer language is just cherry on the cake.
The nice thing about null-safety in Kotlin is that it is built-in and it requires no extra annotations or added tooling. Not having @ProxySingletonAbstractJunkFactoryFactoryBean sprinkled all over your code does it ever so slightly more readable.
But if built-in null safety and lower verbosity was all that Kotlin had to offer I doubt it would have won. Kotlin offers a lot more features that Java does and most probably will not offer in the next 10 years:
- Extension methods: No more terrible FooUtil or BarHelper classes.
- Context parameters (preview feature)
- Coroutines (they are not just about concurrency - you can use them to write generators as well[1]).
- Keyword arguments: This makes using constructing data classes possible without generating builders, and in general lets you deal with multi-argument methods in a safer and more readable way. It also cuts down the boilerplate of defining 20 different overloads that call each other.
- Interface Implementation by delegation: This feature makes it easy and painless to follow the motto "composition over inheritance". Java makes implementation inheritance 50 orders of magnitude easier than composition with manual delegation, so it's pretty natural that the vast majority of Java code- bases overuse inheritance in very bad ways.
- Properties: This reduces the need to worry about direct field access causing API breakage in the future, and removes the need for the absolutely massive boilerplate associated with getters and setters in Java. It's true that records remove the need for that, but records only work for purely immutable data classes (and right now they are only practically usable with a small number of fields).
- Delegated Properties: Not something I use every day, but it's very useful when I do use it.
- Unsigned integers (specifically bytes): Writing any byte-wrangling code in Java is a downright nightmare.
- Reified Generics: Java may get something equivalent to that with Project Valhalla, but I'm not sure how comprehensive it would be.
- If expression: Java made switch an expression with JEP 361, but if is still a statement. This leads to a lot of bloated and somewhat unsafe code where you have to define a variable before the if and then assign to he variable in each branch.
- Expression Bodies for function: This is a very small feature, but it's pretty nice to cut down boilerplate and make functions more readable when you need it.
DSL Features
------------
Kotlin is perfect for DSLs thanks to features like:
- Closure blocks: Kotlin lets you pass the last closure argument to a function as a block of code inside curly braces that follows the function call. This features lends itself very well to readable DSL. In Java you would need to embed the closure inside the function argument list and add an extra parentheses. This gives you some of (see the next couple of points) the DSL capabilities of Kotlin, but the DSL becomes very hard to read and use when a lot of blocks are involved. There is a good reason why Kotlin DSLs are based on blocks, while Java DSLs are based on the less-flexible fluent interface pattern: block-based DSLs are just too hard to read and write in Java.
- Inline functions: Inline functions allow the compiler to perform some optimizations in advance that may be harder for the JIT to do (namely inlining the provided block closures), but the real kicker is that you can use flow control statements (break, continue and return) that affect the calling scope.
- Multiple "this" in context. You can have multiple values for this inside a nested scope. The compiler manages to find the right reference for the "this" alias based on your usage, but in case of ambiguity (where the deepest "this" wins), you can disambiguate your choice. This feature sounds overly complex and unnecessary at first, but it allows a lot of power for the Kotlin DSL system.
- Closures with this receivers: Using the multiple this values from above, you can have closures that receive their own "this" to introduce DSL methods. Being able to introduce these methods without shadowing the "this" from the parent context is crucial for powerful DSLs.
- Infix functions and operator overloading: Needless to say, these features make DSLs even nicer.
I've probably skipped a couple of features I can't recall right now, but I hope that it shows that Kotlin is a lot more than just "Java with null-safety and data classes" as some people think.
> Interface Implementation by delegation: This feature makes it easy and painless to follow the motto "composition over inheritance". Java makes implementation inheritance 50 orders of magnitude easier than composition with manual delegation, so it's pretty natural that the vast majority of Java code- bases overuse inheritance in very bad ways.
While we're on this subject, I'd like to rant for a bit. Why is this not a standard feature in every OO language today? The adage that composition should be preferred to (implementation) inheritance is itself older than Java, and was already fairly common wisdom 20 years ago - yet PL design has seemingly not reflected this.
So in the case from the README, where you're trying to curate a sample of your data, the only thing that you're reading is the metadata, UNTIL you run `export_files` and that actually copies the binary data to your local machine?
Exactly! DataChain does lazy compute. It will read metadata/json while applying filtering and only download a sample of data files (jpg) based on the filter.
This way, you might end up downloading just 1% of your data, as defined by the metadata filter.
I'm of two minds about this. On the one hand, I think there's a valid argument that traditional media is struggling to hold the attention of modern readers, and trust in news organizations is at all-time lows.
On the other hand, there has always been a solid separation between the editorial page and the newsroom of every major paper, just look at WSJ. WSJ has not endorsed a presidential candidate since 1928, but it's no secret that their editorial board is robustly conservative. The Post is clearly a left of center publication and their editorial board has opinions that they should be free to share. In a world where Musk has turned Twitter into a pay-to-play MAGA playpen, I don't think there is anything wrong with a newspaper *opinion section* providing a clear, well-articulated endorsement of a candidate based on their merits.
Right. If this decision had been made and announced two years ago, no one cares. But according to published reports, the Editorial Board actually wrote up an endorsement and then the owner decided to spike it at the last minute- that's a big huge deal! This whole thing is just really poorly handled on Bezos part.
If the reports are true and 8% of their paid subscribers have canceled since Friday (1), Bezos really screwed up quite badly here. And you have the Editorial Page Editor David Shipley throwing Bezos directly under the bus in that same report (2) so he had to come out and offer this ham-handed justification, but it is just a sign of a dumb decision.
I just can't believe he decided that lying to a bunch of reporters was a good idea.
2: "As recently as last week, according to a person present, Shipley said he sought to talk Bezos out of his decision. Shipley added, 'I failed.'" Ibid.
Mr. Bezos has told others involved with The Post that he is interested in expanding The Post’s audience among conservatives, according to a person familiar with the matter. He has appointed Mr. Lewis — a chief executive who previously worked at the Rupert Murdoch-owned Wall Street Journal — and has informed Mr. Lewis that he wants more conservative writers on the opinion section, the person said. -- https://www.nytimes.com/2024/10/25/business/media/washington-post-presidential-endorsement.html
He is making a serious play to capture an audience from the other half of the country. There is no way to do that without losing a painful share of his current reach.
The false story of the frog in the pot applies here: if you want to make a change like that it has to be slow and steady, at an imperceptible pace. Doing something big and obvious destroys your pivot. You've lost trust with your existing customer base with out actually getting anything from your new, intended customer base.
Again, announce this two years ago and it's a nothing burger and you could be working on that stated process (speaking for myself I don't think it likely to work, but it's at least a plan). Doing it now, in this way- after the editorial was already written- it's a big deal.
> You've lost trust with your existing customer base with out actually getting anything from your new, intended customer base.
You may not be aware of the new profound respect Bezos is getting from Musk and friends on X. Deep testaments to Bezos' character are suddenly flying freely around. Those devotions are invisible to most people who aren't on the right. But they make an impression on the audience that Bezos says he is after.
That may be true for Bezos himself- but do you think that respect and affirmation will trickle down to the Washington Post and net them new subscribers? I'm extremely skeptical. This is not the first time someone has tried this pivot, e.g. the Post's old stablemate Newsweek, and it's not an easy thing to do.
Bezos wants diverse opinions in the Washington Post op-ed section. He wants more than just progressive liberal viewpoints always being there, right at the top of the front page. Which I think is correct.
I usually read the New York Times, but these past few weeks it's become almost unbearable with its preachiness toward why you, idiot reader, need to vote Kamala.
Fine, but at least provide some kind of counterpoint. Newspapers lose their prestige as "reporting the truth" when everything they report on represents one world view.
We don't question the New York Post or Daily Kos because they're supposed to be biased. The problem comes from a supposedly "unbiased" news org becoming more and more biased. This doesn't just show up in the opinion section, it's also what stories newspapers decide to cover.
Are you suggesting that a newspaper making an endorsement is "malicious election interference", or that there was "malicious election interference" involved in them deciding not to publish the endorsement?
You’re saying that Bezos telling the editorial board to not endorse is election interference?
I’m really struggling to see how not doing something could ever qualify as interference.
The whole concept of journalists endorsing a candidate feels a lot closer to interference. Feels a bit sad that the editorial board can’t see that without being told by someone like Bezos.
> I don't think there is anything wrong with a newspaper opinion section providing a clear, well-articulated endorsement of a candidate based on their merits.
Yes and no, but mostly no. The context is the problem. There's not a high enough wall between news and op-ed. When op-ed does what is supposed to be option and that simply reflects the "journalism" on the news side of the house, then both sides lose.
Put another way, before these entities dole out endorsements they need to work 100x harder to regain trust. What good is an enforcement if no one trusts you? FFS, the reviews on Amazon are more trustworthy than these self-proclaimed journalists.
It would have been OK to decide to forbid endorsements a year earlier or just after the elections.
The timing is extremely suspicious. Both Bezos and Patrick Soon-Shiong (LA Times) pushed this decision through suddenly at almost the same time. I don't believe the reasons given for making the decision suddenly now.
Trump has promised revenge if he wins. They caved under pressure or pivoted. If Trump gets an AG that does exactly what he wants, he will go after his enemies in courts, and other means. Bezos and other billionaires cave in when they face bigger power. Mohammed bin Salman hacked his phone and then killed his employer. Bezos prevented the release of the Jamal Khashoggi document in Amazon Prime so as not to anger MBS.
Ostensibly, the LA Times owner's daughter claims that the decision not to endorse is tied to the Biden-Harris administrations stance on Gaza. Not sure whether to take that at face value or just a cop-out.
The same article notes that the newspaper itself and also the people who resigned from the paper over this say it has nothing to do with Gaza and his daughter was involved in none of the conversations about this.
My best guess is that she tried to use a brief spurt of interest in her family to get attention for a cause she was invested in, but since it was a lie no one else backed her up.
reply