I wrote about how Record Patterns along with Pattern Matching for Switch can be used to write things like Tree-Rewrite rules in AST analyzers/program optimizers efficiently if anyone is curious:
This is how Spark's optimizer Catalyst works in Scala
Do you know if these are just Java features, or if they're backed by new JVM bytecode intrinsics to ensure that these destructuring matches are able to be performed efficiently? (Think e.g. Erlang's recent "fused checks", where it can figure out whether something is an integer and whether it's non-negative using a single abstract-machine instruction.)
That is, for languages that already have features like this (e.g. Scala), will those languages be getting any benefits as a byproduct of Java getting these features?
It's just too bad they could not come up with an extended enum-as-tagged-union syntax. Using sealed classes for that pattern works but is still messy to write. It feels like writing enums with classes back in JDK 1.4 days.
I'm impressed with how Java is shaping up. With records, pattern matching, destructuring, and virtual threads all arrived or arriving, what advantages do Kotlin and Scala bring?
It's the small things that make kotlin awesome. Not microscopic things like removing semicolons, but the left-to-right of .as?, .let and friends that allow simple things to remain simple instead of littering the code with almost-single-use names. Give those trivial intermediates a name when you think the name will be helpful, not when the syntax is unhappy without. Those aren't astronaut level language features to treat someone's Haskell-envy, but simple things that just happen to add up really well.
The stdlib of kotlin with immutable types, lots of good extension functions on for instance lists etc is hard to beat. Especially with the nice lambda syntax it makes it a joy to write functional code compared to streams and having to call separate functions by wrapping instead of chaining.
Operator overloading can be misused, but for certain things it makes stuff much prettier as well.
Kotlin provides modern features in the Android development Java land stuck on the ancient Java 6.
Scala was an academic experiment on how to match nicely object oriented world with functional programing paradigm that got some hype because Java development was crawling like a snail. I am not sure if this experiment was successful after all, though.
Until Java finally includes real nullability guarantees in its language (and its standard library) I'll stick to Kotlin when I can.
These improvements are still nice for when you're stuck dealing with Java code, but in my experience getting projects to run on the latest version of Java isn't very easy with various dependencies all needing support first.
I rather focus on the disadvantages of additional layers to debug, with their own set of libraries, and on Kotlin's case, a way to sell InteliJ licences.
Meanwhile using Java, means using JDK out of the box with no extra sugar. Pretty healthy.
Don't know anything about Scala. Kotlin has null safety and a bit cleaner syntax, but other than that, I don't see too much advantage over Java for backend. In Android, Java is still lagging behind a lot. Also, Jetpack Compose, a declarative UI framework is Kotlin only. Kotlin is also working on wasm (so is Java I think, but Kotlin has working examples with wasm GC) and Jetpack Compose is going multiplatform, including wasm. This video has some examples in description https://youtu.be/oIbX7nrSTPQ
I can give perspective as someone who enjoys modern Java, writes Kotlin at their dayjob (and loves it), and also likes Scala 3.
Here are the things that if Java had, I probably wouldn't see a reason for other languages:
1. Lack of first-class lambda syntax. In Kotlin/Scala you can write something like:
fun doSomething(handler: (String, Int) -> Foo): Blah
In Java, all you have are the "Function<>" and related interfaces, which are clunky to use.
2. Opaque types (Scala 3). These have been one of the most impactful programming features I've ever used, and I sorely miss them in languages that lack them.
object Foo:
opaque type UserId = Int
opaque type Email = String
def mkEmail(s: String): Email = s
def findUserIdByEmail(email: Email): UserId = 42
import Foo.*
val email: Email = mkEmail("foo")
val valid: UserId = findUserIdByEmail(email)
val invalid1: UserId = findUserIdByEmail("bar") // error: can't use String as Email
val invalid2: UserId = 123 // error: can't use Int as UserId
3. Union types (Scala 3). You can emulate them in Java/Kotlin with Sealed Types but it's much more verbose.
type JsonScalar = String | Int | Boolean
type Json = JsonScalar | Map[String, JsonScalar] | List[JsonScalar]
// Makes writing functions that take multiple argument types much easier:
def handle(it: String | Int | Boolean): Unit = ...
4. Context-oriented programming with "given/using" in Scala 3 and "context-receivers" in Kotlin.
This one is harder to explain succinctly but essentially it allows you to decorate methods/classes with required "contextual" args.
Instead of passing them as regular function arguments, you must invoke the function inside of an "environment"/"context" where the requirements are satisfied.
This makes threading dependencies through your code much easier, and eliminates the need for dependency injection frameworks in many cases.
interface Logger {
fun log(message: String)
}
object ConsoleLogger : Logger {
override fun log(message: String) = println(message)
}
ctx(Logger)
fun doSomething(): Int {
log("Hello")
return 42
}
fun main() {
val logger = ConsoleLogger
with (logger) {
doSomething()
}
}
5. First-class support for asynchronous programming. With "suspend" in Kotlin and a current prototype being done in Scala 3:
I don't see much advantage from Kotlin unless you are stuck with an old jdk (like the one from Android), still, the latest jdk is still far away from current Scala.
Feature soup is kind of meaningless. The open source community has whatever it needs now.
Many "alot" of java programmers in the US cant code to JDK8 already. I love the JVM but these Java releases are not being adopted on any real scale for a reason. They break things. And syntax sugar is boring and unnecessary for a crew of software engineers that have no real ethos surrounding records or any of these features.
They are just being rolled out to appease devs from other ecosystems. They will not form a new or better method for building systems or improve performance.
This question is fundamentally flawed. People don't use Kotlin just as "a better Java" (maybe they did in 2017), Kotlin is an independent language that runs on the JVM, as well as other targets. Most Kotlin devs don't see Java and Kotlin in competition with each other or wish to use Java if it only had feature X.
Your pop-over to join the newsletter and continue reading won’t allow someone to continue reading without signing up for your newsletter. There’s no way to close the pop-over modal. This is user hostile behavior. When scrolling, it reappears over content. Very anti-user behavior.
This is equivalent to forced purchase required to use the restroom at a venue. Don’t be like that. Compassion is good for business.
I’m impressed. One of the big hurdles of extendable types is figuring out which subtype a parameter is. Overloaded methods are a blunt tool that involves lots of indirection. Generics force you to structure classes in a specific way. Pattern matching is the cleanish solution to the problem of “what type so I have here and what do I do with it?”
Seeing Java getting these features is a breath of fresh air. I wonder how this will impact Kotlin.
Being compatible with Java was one of the goals for Kotlin. We soon have a lot of features in the JVM mother language that are solved different in Kotlin. For example:
- Data Classes vs Java's Records
- Nullability
- String Templates
Not diverging from the core language is what made TypeScript successful on a long term. This won't work for Kotlin (and was not a goal). It will be interesting to see whether the languages will diverge even more - maybe to an extend where they will become incompatible - or the interop will converge somehow. Diverging languages will certainly make the interop harder.
Kotlin still has a lot for itself, with the scope functions, the delegation with "by", the syntax that make it very easy and lightweight to create a DSL (infix functions are great for asserts).
I think it's a very expressive and elegant language if you use its syntax properly.
Maybe some of kotlin's "workarounds" will be converted into the JVM equivalents in the backend.
The relationship between Kotlin and Java is not the same as TypeScript and JavaScript. TypeScript is intentionally a syntactical superset of JavaScript. It only adds type annotations and nothing else. This allows TypeScript to be easily compatible with JavaScript, with very little risk of future breaks in compatibility.
Kotlin cannot choose the same route as TypeScript, since Java is already statically typed (even if that typing is not always very strong). There is no point in adding type annotations to it. Most of the improvement that Kotlin originally sought (and still seeks) to have on Java are in syntax and semantics. This means Kotlin has to modify the syntax and cannot just be a simple transpiler that naturally incorporates new Java language features.
The interop strategy that Kotlin has chosen instead is:
1. Keep track on what Java is doing.
2. Add compatibility to Java language features when they are released.
3. Avoid introducing incompatible features too quickly when Java is developing the same thing.
4. If the Java development direction is settled but the feature is not released yet, introduce features that have a clear upgrade path for compilation and interop on new Java releases.
Kotlin is already compatible with Java records (just add the @JvmRecord annotation to a data class). This annotation forces the Kotlin data class to be immutable and the compiler will generate a java record for you if you target the JVM.
Nullability marking is not something that is currently being worked on for Java. Some publications have misleadingly modified the title for "JEP 401: Flattened Heap Layouts for Value Objects (Preview)" [1] to "JEP 401: Null-restricted types", because this very early proposal mentions possible interactions with null-restricted types - but the null-restricted proposal doesn't even exist yet. It's quite hard to predict how Kotlin would be compatible with a feature that may or may not come around 2030.
String templates are still a preview feature in Java 21, so don't expect to see them in production before Java 25 in September 2025. String Templates, like string interpolation, is essentially syntactic sugar, but it provide a better story for type-safety and flexibility than classic string interpolation. Kotlin already solves the simple interpolation cases with its string interpolation, but I agree it leaves some things to be desired (multi-line handling is especially painful[2]). The type-safety/flexibility story is generally handled in Kotlin with type-safe builders[3], and it's often a better solution in my opinion, but there many cases where a string template would be more readable.
The main reason Kotlin might need to support string templates, is that all this syntactic sugar has an interface: the StringTemplate interface. Java libraries may rely on it on the far future[3], and then Kotlin will need to maintain compatibility somehow. JetBrains are not ignoring this issue of course. You will find multiple tickets on their tracker talking about custom string interpolation, that even predate the String Templates JEP[5], but it's currently a wait-and-see-approach.
I think the most important set of features for Kotlin to look at is Project Valhalla[6]. It's an even bigger revolution than project Loom. Kotlin is already preparing for this, with value classes[7]. I believe the main reason that value class usage in Kotlin is so highly restricted in Kotlin right now, is that they are waiting for Project Valhalla, and do not want to give up interop later.
You can also think of other past examples when Kotlin did introduced a future earlier than Java, and then gradually made it interoperable. The best example is closures. Kotlin supported closures since its early beta versions (before Java 8 was released), and for a long time supported generating Java 6 bytecode. Since Java 8 closures relied on a new JVM bytecode instruction (InvokeDynamic), Kotlin used a different mechanism to implement closures. When Java 8 was released, they could easily maintain API compatibility with Java, since they are always invoked through an interface. Kotlin eventually added support for generating lambdas in the same style as Java, but they only made this default in Kotlin 1.9[8], to maintain maximum compatibility. This didn't affect interop (which was already resolved since Java 8 was released), it only had impact on bytecode size and perhaps a small performance impact in some cases.
I think this list show that Kotlin is currently handling future interop quite well.
[4] Java is a conservative language and most Java deployments are many versions behind the latest LTS. Until last year (https://newrelic.com/resources/report/2022-state-of-java-eco...), most of the Java systems in production were running Java 8, and only recently Java 11 started becoming the dominant version, with Java 8 strongly trailing behind. Java 21 is coming out this year, but Java 17 is barely deployed anywhere. For this reason, you'll find most libraries target still target Java 8 or Java 11, and avoid Java 17 features like record. Since String Templates will be out only in 2025, I don't expect to see libraries requiring them in production before 2030.
I am sure they are very good reasons for it, but even after reading part of the latest valhala design document i still don't quite understand by nullability and/or identity are used as key differential between value types and "regular" class type. It seems to make the design and integration of value object very convoluted and is basically representational flatness as a mere consequences instead of being the central defining factor of a value object.
> basically representational flatness as a mere consequences
And that’s exactly what they are going for, AFAIK.
You as a programmer should first and foremost care about the semantics that you want to express in your programs. In many cases it means that an object you use has and need an identity. But you may find so that it doesn’t make sense in a given case, like a date, or a coordinate — so you can express that it doesn’t have identity, allowing for more freedom on the compilers part.
Finally, you may even say that an implicitly zeroed object makes sense as a default for your class, and when this particular case happens and your object can’t be null, the compiler can even completely inline/flatten your data. But the performance improvements are generally not the goal themselves, they are neat advantages you may get by restricting your semantics.
I'm curious to see how structured concurrency feels in production. I'm still leaning towards C#'s async and TPL syntax. Manual context, fork and unwrap syntax might feel cumbersome. I enjoy the await sugar and implicit context handling but the explicit scopes solves the bugs you see in C# where the default thread pool is abused.
This comment was childish but I'm struggling with Java at work. People who fight over whether to implement visitors, adapters, methods or services for the same thing
I refuse to believe Java has gone through 20 major revisions since 1.0
I remember when 1.5 came out and Sun's marketing folks insisted it be called Java 5. I think thats when they jumped the shark, and haven't corrected course back since, versioning-wise
And I wonder if someone keeps track of what the proper traditional Java major version should be now. I'd guess its on 2.x or 3.x at best
If you keep to the standard edition platform and never used internal APIs, you could argue Java never broke backwards compatibility, effectively having a 1. before every version number.
In practice, you could say that Java had only one major version bump: from 8 to 9, when it closed down internal APIs with Jigsaw and gave away Java EE to become Jakarta.
[+] [-] neonate|2 years ago|reply
[+] [-] gavinray|2 years ago|reply
This is how Spark's optimizer Catalyst works in Scala
https://gavinray97.github.io/blog/what-good-are-record-patte...
Kind of wild to believe this is valid modern Java:
These two are my favorite new JDK features by miles, along with Sealed Types.[+] [-] derefr|2 years ago|reply
That is, for languages that already have features like this (e.g. Scala), will those languages be getting any benefits as a byproduct of Java getting these features?
[+] [-] speed_spread|2 years ago|reply
[+] [-] hamandcheese|2 years ago|reply
[+] [-] usrusr|2 years ago|reply
[+] [-] matsemann|2 years ago|reply
Operator overloading can be misused, but for certain things it makes stuff much prettier as well.
[+] [-] piokoch|2 years ago|reply
Scala was an academic experiment on how to match nicely object oriented world with functional programing paradigm that got some hype because Java development was crawling like a snail. I am not sure if this experiment was successful after all, though.
[+] [-] jeroenhd|2 years ago|reply
These improvements are still nice for when you're stuck dealing with Java code, but in my experience getting projects to run on the latest version of Java isn't very easy with various dependencies all needing support first.
[+] [-] pjmlp|2 years ago|reply
Meanwhile using Java, means using JDK out of the box with no extra sugar. Pretty healthy.
[+] [-] mhfu|2 years ago|reply
[+] [-] jdm2212|2 years ago|reply
(I say this as a Java dev who occasionally gets tempted to try to help out in repos that are Kotlin/Scala, and gives up very quickly.)
[+] [-] gavinray|2 years ago|reply
Here are the things that if Java had, I probably wouldn't see a reason for other languages:
1. Lack of first-class lambda syntax. In Kotlin/Scala you can write something like:
In Java, all you have are the "Function<>" and related interfaces, which are clunky to use.2. Opaque types (Scala 3). These have been one of the most impactful programming features I've ever used, and I sorely miss them in languages that lack them.
3. Union types (Scala 3). You can emulate them in Java/Kotlin with Sealed Types but it's much more verbose. 4. Context-oriented programming with "given/using" in Scala 3 and "context-receivers" in Kotlin.This one is harder to explain succinctly but essentially it allows you to decorate methods/classes with required "contextual" args.
Instead of passing them as regular function arguments, you must invoke the function inside of an "environment"/"context" where the requirements are satisfied.
This makes threading dependencies through your code much easier, and eliminates the need for dependency injection frameworks in many cases.
5. First-class support for asynchronous programming. With "suspend" in Kotlin and a current prototype being done in Scala 3:- REPO: https://github.com/lampepfl/async | SLIDES: https://github.com/lampepfl/async/blob/main/scalar-slides.pd... | YOUTUBE TALK: https://www.youtube.com/watch?v=0Fm0y4K4YO8
6. Passing arguments by name, rather than positionally.
7. Tuples (Scala). They're like anonymous data classes/records.[+] [-] mm007emko|2 years ago|reply
[+] [-] re-thc|2 years ago|reply
That it's not Java. It's a huge thing with some developers not wanting to touch Java for <insert reason> but would be fine with Kotlin or Scala.
[+] [-] haspok|2 years ago|reply
Or maybe I'm missing something in which case would you point me to a JEP or an article about destructuring in Java?
EDIT: nevermind, I should have checked JEP 440, which is about destructuring record patterns...
Aside from that, immutable / readonly collections and null safety are two big reasons for Kotlin or Scala.
[+] [-] eeperson|2 years ago|reply
- higher kinded types
- null in types
- for comprehensions
- macros
- opaque types
- implicits/type classes
- persistent immutable collections
- EDIT named & default params
[+] [-] AlexITC|2 years ago|reply
[+] [-] social_ism|2 years ago|reply
Many "alot" of java programmers in the US cant code to JDK8 already. I love the JVM but these Java releases are not being adopted on any real scale for a reason. They break things. And syntax sugar is boring and unnecessary for a crew of software engineers that have no real ethos surrounding records or any of these features.
They are just being rolled out to appease devs from other ecosystems. They will not form a new or better method for building systems or improve performance.
[+] [-] kernal|2 years ago|reply
Elvis operator. Drops mike.
[+] [-] listenallyall|2 years ago|reply
[+] [-] ActorNightly|2 years ago|reply
Yet literally none of those things actually matter for any sort of real world application.
What matters is how quickly you can get code to do what you want, and Java/Kotlin lost that plot almost a decade ago.
[+] [-] ArturSkowronski|2 years ago|reply
You can find mirror on Substack: https://vived.substack.com/p/the-compact-overview-of-jdk-21s...
EDIT: We did the redirection to the Substack mirror.
[+] [-] gabereiser|2 years ago|reply
This is equivalent to forced purchase required to use the restroom at a venue. Don’t be like that. Compassion is good for business.
[+] [-] jaxrtech|2 years ago|reply
[+] [-] dexwiz|2 years ago|reply
[+] [-] nikeee|2 years ago|reply
Being compatible with Java was one of the goals for Kotlin. We soon have a lot of features in the JVM mother language that are solved different in Kotlin. For example:
Not diverging from the core language is what made TypeScript successful on a long term. This won't work for Kotlin (and was not a goal). It will be interesting to see whether the languages will diverge even more - maybe to an extend where they will become incompatible - or the interop will converge somehow. Diverging languages will certainly make the interop harder.[+] [-] LelouBil|2 years ago|reply
I think it's a very expressive and elegant language if you use its syntax properly.
Maybe some of kotlin's "workarounds" will be converted into the JVM equivalents in the backend.
[+] [-] unscaled|2 years ago|reply
Kotlin cannot choose the same route as TypeScript, since Java is already statically typed (even if that typing is not always very strong). There is no point in adding type annotations to it. Most of the improvement that Kotlin originally sought (and still seeks) to have on Java are in syntax and semantics. This means Kotlin has to modify the syntax and cannot just be a simple transpiler that naturally incorporates new Java language features.
The interop strategy that Kotlin has chosen instead is: 1. Keep track on what Java is doing. 2. Add compatibility to Java language features when they are released. 3. Avoid introducing incompatible features too quickly when Java is developing the same thing. 4. If the Java development direction is settled but the feature is not released yet, introduce features that have a clear upgrade path for compilation and interop on new Java releases.
Kotlin is already compatible with Java records (just add the @JvmRecord annotation to a data class). This annotation forces the Kotlin data class to be immutable and the compiler will generate a java record for you if you target the JVM.
Nullability marking is not something that is currently being worked on for Java. Some publications have misleadingly modified the title for "JEP 401: Flattened Heap Layouts for Value Objects (Preview)" [1] to "JEP 401: Null-restricted types", because this very early proposal mentions possible interactions with null-restricted types - but the null-restricted proposal doesn't even exist yet. It's quite hard to predict how Kotlin would be compatible with a feature that may or may not come around 2030.
String templates are still a preview feature in Java 21, so don't expect to see them in production before Java 25 in September 2025. String Templates, like string interpolation, is essentially syntactic sugar, but it provide a better story for type-safety and flexibility than classic string interpolation. Kotlin already solves the simple interpolation cases with its string interpolation, but I agree it leaves some things to be desired (multi-line handling is especially painful[2]). The type-safety/flexibility story is generally handled in Kotlin with type-safe builders[3], and it's often a better solution in my opinion, but there many cases where a string template would be more readable.
The main reason Kotlin might need to support string templates, is that all this syntactic sugar has an interface: the StringTemplate interface. Java libraries may rely on it on the far future[3], and then Kotlin will need to maintain compatibility somehow. JetBrains are not ignoring this issue of course. You will find multiple tickets on their tracker talking about custom string interpolation, that even predate the String Templates JEP[5], but it's currently a wait-and-see-approach.
I think the most important set of features for Kotlin to look at is Project Valhalla[6]. It's an even bigger revolution than project Loom. Kotlin is already preparing for this, with value classes[7]. I believe the main reason that value class usage in Kotlin is so highly restricted in Kotlin right now, is that they are waiting for Project Valhalla, and do not want to give up interop later.
You can also think of other past examples when Kotlin did introduced a future earlier than Java, and then gradually made it interoperable. The best example is closures. Kotlin supported closures since its early beta versions (before Java 8 was released), and for a long time supported generating Java 6 bytecode. Since Java 8 closures relied on a new JVM bytecode instruction (InvokeDynamic), Kotlin used a different mechanism to implement closures. When Java 8 was released, they could easily maintain API compatibility with Java, since they are always invoked through an interface. Kotlin eventually added support for generating lambdas in the same style as Java, but they only made this default in Kotlin 1.9[8], to maintain maximum compatibility. This didn't affect interop (which was already resolved since Java 8 was released), it only had impact on bytecode size and perhaps a small performance impact in some cases.
I think this list show that Kotlin is currently handling future interop quite well.
[1] https://openjdk.org/jeps/401
[2] https://youtrack.jetbrains.com/issue/KT-46365/Multiline-stri...
[3] https://kotlinlang.org/docs/type-safe-builders.html
[4] Java is a conservative language and most Java deployments are many versions behind the latest LTS. Until last year (https://newrelic.com/resources/report/2022-state-of-java-eco...), most of the Java systems in production were running Java 8, and only recently Java 11 started becoming the dominant version, with Java 8 strongly trailing behind. Java 21 is coming out this year, but Java 17 is barely deployed anywhere. For this reason, you'll find most libraries target still target Java 8 or Java 11, and avoid Java 17 features like record. Since String Templates will be out only in 2025, I don't expect to see libraries requiring them in production before 2030.
[5] https://youtrack.jetbrains.com/issue/KT-16366
[6] https://openjdk.org/projects/valhalla/
[7] https://youtrack.jetbrains.com/issue/KT-42434/Release-inline...
[8] https://youtrack.jetbrains.com/issue/KT-45375
[+] [-] mooreds|2 years ago|reply
[+] [-] idlewords|2 years ago|reply
[+] [-] soulbadguy|2 years ago|reply
[+] [-] kaba0|2 years ago|reply
And that’s exactly what they are going for, AFAIK.
You as a programmer should first and foremost care about the semantics that you want to express in your programs. In many cases it means that an object you use has and need an identity. But you may find so that it doesn’t make sense in a given case, like a date, or a coordinate — so you can express that it doesn’t have identity, allowing for more freedom on the compilers part.
Finally, you may even say that an implicitly zeroed object makes sense as a default for your class, and when this particular case happens and your object can’t be null, the compiler can even completely inline/flatten your data. But the performance improvements are generally not the goal themselves, they are neat advantages you may get by restricting your semantics.
[+] [-] arein3|2 years ago|reply
[+] [-] xyst|2 years ago|reply
[+] [-] mooreds|2 years ago|reply
Useful lesson, but until you have massive traffic happen once, it's overengineering :) .
[+] [-] ArturSkowronski|2 years ago|reply
We experienced an astounding increase in traffic, nearly 100 times our usual volume
You can find mirror on Substack: https://vived.substack.com/p/the-compact-overview-of-jdk-21s...
[+] [-] jayd16|2 years ago|reply
[+] [-] akkad33|2 years ago|reply
[+] [-] akkad33|2 years ago|reply
[+] [-] syngrog66|2 years ago|reply
I remember when 1.5 came out and Sun's marketing folks insisted it be called Java 5. I think thats when they jumped the shark, and haven't corrected course back since, versioning-wise
And I wonder if someone keeps track of what the proper traditional Java major version should be now. I'd guess its on 2.x or 3.x at best
[+] [-] joaonmatos|2 years ago|reply
In practice, you could say that Java had only one major version bump: from 8 to 9, when it closed down internal APIs with Jigsaw and gave away Java EE to become Jakarta.
[+] [-] faangsticle|2 years ago|reply
[+] [-] emodendroket|2 years ago|reply
[+] [-] dexwiz|2 years ago|reply
[+] [-] vbezhenar|2 years ago|reply
[+] [-] thfuran|2 years ago|reply
What does that even mean?
[+] [-] too_damn_fast|2 years ago|reply
[+] [-] avgcorrection|2 years ago|reply
The only seeming standard is that big integers are bad. ;) But don’t tell Chrome that.
[+] [-] kernal|2 years ago|reply
What's your take on Chrome and Firefox?