[HN Gopher] Java in the Small
___________________________________________________________________
Java in the Small
Author : crummy
Score : 382 points
Date : 2024-12-18 20:42 UTC (2 days ago)
(HTM) web link (horstmann.com)
(TXT) w3m dump (horstmann.com)
| wing-_-nuts wrote:
| I remember reading horstmann's books in college and it doesn't
| surprise me at all that java is the hammer he reaches for given a
| particular nail.
|
| I have to say I find it an odd choice for small replacements for
| bash scripts. I think python or golang are probably better
| choices for that purpose. Java is one of those 'enterprise'
| backend languages which lend itself to making a _team_ productive
| over making the individual productive, and I say this as a java
| / go dev who's most comfortable with java for most backend work.
| ggerules wrote:
| Dr. Horstmann was my advisor in college, San Jose State.
|
| I just loved his lectures, very dry sense of humor, and
| extremely funny.
|
| He was just getting started writing books in the early 90s. He
| has this awesome way of thinking about programming, that I
| imparted to my own students when it came my turn to teach
| programming. I wish there some videos of his classes that I
| could go back to and share with people.
|
| Good website also, https://horstmann.com/
|
| The picture on the website with him in the row boat has a funny
| story with it. When asked why he is in a row boat, he would
| reply, "Students are in the row boat with me, learning to
| program. At some point I push them out of the boat into the eel
| infested lake. The ones who are clever enough to make it back
| to the shore will be good programmers." All of this said with a
| faint hint of a German accent and a sly smile.
|
| If you happen to read this, Dr. Horstman. I made it to shore.
| Thanks! It has been an awesome journey!
| spike021 wrote:
| That's an interesting experience. I also had him as a
| professor a while back and he was awful. He was always
| looking at his phone or computer especially during project
| presentations and completely ignoring what anyone said. He
| also didn't seem to know much course material in general.
|
| What I remember most is his obsession with Emacs.
|
| There was one time that I was grateful though, I had to buy a
| few of his books and one of them had a defect from the
| printer, so he helped me get a new copy from the publisher
| for free.
| anitil wrote:
| > lend itself to making a team productive over making the
| individual productive
|
| That's a really insightful way of presenting this. I think if
| that's how I'd been introduced to Java I might even have
| tolerated it.
| PaulHoule wrote:
| I learned to code "single file Java" when I was working through
| Hacker Rank before they added features to the JDK to make it
| easier. Certainly if you want to do whiteboard coding sorts of
| problems it is good to know.
| losvedir wrote:
| I've been using Java 21 for Advent of Code this year, and I've
| been surprised at how much less clunky it is than I remember.
| `var` and `record`'s are especially nice for how I like to code.
| It's still not perfect, but it's not something that I hate
| programming in now.
|
| These were some neat tricks. I've been using the `java
| myfile.java` approach for running the AoC problems. I didn't
| realize the "implicit class" thing where you could have top level
| statements and methods, though, with the automatic import of
| java.base. That's pretty slick for this.
| papercrane wrote:
| Records being allowed in methods has been great for me when
| doing things like path finding. Makes it easy to write
| something like: record Node(int cost, int
| row, int col){} var pq = new
| PriorityQueue<Node>(Comparator.comparingInt(Node::cost));
| gf000 wrote:
| This is actually a natural extension of classes being allowed
| inside, which is not well-known for some reason. Nonetheless,
| I also really like this feature with records.
| dehrmann wrote:
| > which is not well-known for some reason
|
| Really? A whole generation of Java programmers wrong
| functor classes in-line.
| danhau wrote:
| Those are anonymous classes, if we're thinking of the
| same thing. Java also supports named classes bound to a
| method's scope (local classes).
| roncesvalles wrote:
| It's allowed because Record automatically implements methods
| called cost(), row(), and col().
| user_of_the_wek wrote:
| Just to be clear, the implicit class thing is still a preview
| feature as of Java 24, which should come out next March. It
| might be finalized for Java 25, in the coming September. But no
| guarantees. Until then you'd need to explicitly enable it with
| a cli parameter.
| ansgri wrote:
| So it's almost as good as C#? Which would be my favorite
| language if not for strong ties to MS ecosystem.
| Nijikokun wrote:
| Java is still great, same for PHP and they have only been getting
| better.
| lxgr wrote:
| Great is pretty domain-specific!
|
| Java has been great for larger projects for a while, but I
| think smaller things like one-off scripts have been firmly out
| of reach so far.
|
| It's good to see that change, as being able to use it in the
| small has obvious synergies.
| riku_iki wrote:
| > but I think smaller things like one-off scripts have been
| firmly out of reach so far.
|
| why specifically?
| lxgr wrote:
| The article lists several good reasons:
|
| Having to compile every time (or at least there not being a
| convenient wrapper that compiles and runs at once), the
| boilerplate of having to define a class and main method,
| exception handling, and most of all having to deal with
| Maven.
| riku_iki wrote:
| you don't need to deal with Maven if Java standard
| library(which is huge) is enough for you. Also, not sure
| why such big resistance against maven.
|
| Other pointers are either opinionated or minor. From
| another hand, if dev has experience in Java, benefit of
| not learning some new language/ecosystem is kinda huge.
| never_inline wrote:
| For CLI scripts, PicoCLI with Graalvm seems to be a good
| option now.
| HaroldCindy wrote:
| I wasn't aware that single-file Java without a top-level static
| class was possible now, that + JBang seems quite useful for small
| tasks.
|
| One nit:
|
| > Python programmers often use ad-hoc dictionaries (i.e. maps) to
| aggregate related information. In Java, we have records:
|
| In modern Python it's much more idiomatic to use a
| `typing.NamedTuple` subclass or `@dataclasses.dataclass` than a
| dictionary. The Python equivalent of the Java example:
| @dataclasses.dataclass class Window: id: int
| desktop: int x: int y: int
| width: int height: int title: str
| @property def xmax(self) -> int: return self.x +
| self.width @property def ymax(self)
| -> int: return self.y + self.height w =
| Window(id=1, desktop=1, x=10, y=10, width=100, height=100,
| title="foo")
| qsort wrote:
| This is obviously valid, but it's definitely more common in a
| language like Python to just dump data inside a dict. In a
| dynamic language it's a far more flexible structure, it's the
| equivalent of HashMap<? extends CanBeHashed,
| LiterallyWhatever>, which is obviously a double edged sword
| when it comes to consuming the API. Luckily more rigid
| structures are becoming more popular at the API boundary.
| bcoates wrote:
| That's deranged, just use a namedtuple and some functions. Even
| decorators for something this simple are a code smell.
|
| What do you do when another module needs ymin, inheritance?
|
| OO is dead, leave it buried umourned.
| lxgr wrote:
| It's of course always a good idea to read the article before
| posting, but doubly so here - I was getting ready to yell about
| all of the annoyances making this infeasible to anyone with a
| less-than-extreme pain tolerance, but it turns out Java has
| changed a lot since I last used it around six years ago :)
| Shakahs wrote:
| After years of Python and TypeScript, I've started using Java as
| my default for everything. It's just so much more productive. The
| ancient developer memes that Java is slow and clunky don't apply
| anymore.
|
| Postgres also had a long-held reputation for being slow and
| difficult, but it made incremental improvements for decades and
| now it's the default choice for databases.
|
| I see Java in the exact same position, as the Postgres of
| languages.
| agumonkey wrote:
| what parts do you enjoy now ?
|
| I do agree that new ecosystems (js for instance) makes you miss
| some of the old big languages development feel. less churn
| sdf4j wrote:
| First time I hear those claims about Postgres. Was that the
| sentiment 30 years ago?
| dannyobrien wrote:
| It was definitely initially seen as big and cumbersome
| compared to MySQL, but sentiment shifted.
| cryptos wrote:
| MySQL was kind of a fast toy database in the early days,
| but it was good enough to power simple PHP based websites.
| Tostino wrote:
| If say it was only about 15 years ago that the Postgres is
| slow stuff started dying off. Right around 2010.
| bcoates wrote:
| 14 years or less. Any version of Postgres before 9.0 was a
| nightmare to administer as a real production transactional
| dbms, at least the off the shelf version without a whole lot
| of tweaking without a (then very rare) pg expert.
| fulafel wrote:
| I don't remember that. But I remember having basic DB
| features like transactions while MySQL didn't.
| cflewis wrote:
| The problem with Java since Java 8 has never been Java. It's
| been about the appalling ecosystem that infected it with
| reflection frameworks. It was bonkers that "POJO" was ever a
| thing that had to be defined.
|
| It feels like these frameworks are now just falling away, which
| is great. I'm not even hearing about Spring anymore, and if
| there is any reason to not use it, it would be this cringe "how
| do you do fellow kids?" blurb I just saw on their front page:
|
| > Level up your Java(tm) code
|
| > With Spring Boot in your app, just a few lines of code is all
| you need to start building services like a boss.
|
| I personally would reach for Go by default, but I have no ill-
| will to Java.
| MattPalmer1086 wrote:
| Ahhhhh, yes. Java itself isn't bad and has been getting
| better. The frameworks made me want to scream.
| arez wrote:
| which ones specifically? I like Spring Boot tbh
| MattPalmer1086 wrote:
| Hibernate mostly. Spring too, but it has been a while.
| Mostly I just find the abstraction isn't worth it .
| Alupis wrote:
| The way you write this makes be think you rawdog'd
| Hibernate and Spring Framework. Don't do that... you will
| hate yourself.
|
| Boot is something entirely different. You write very
| little code and get a _ton_ done. The trade off is you
| are firmly now a "Boot" codebase, but once you learn how
| Boot works it's not a big deal.
| fiddlerwoaroof wrote:
| I've had to maintain a couple Spring Boot apps and I
| absolutely cannot stand them: they pull in a whole pile
| of random dependencies and do weird things to your build
| with little explanation. Then, all the functionality
| involves a ton of classpath scanning and annotation-based
| DI that makes it hard to figure out how all the things
| fit together.
| gf000 wrote:
| I mean, have you learnt the framework before attempting
| to do that?
|
| Frameworks are frameworks, not libraries. You can't just
| start writing/understanding them - frameworks are
| different from libraries precisely because _they_ call
| your code, not the reverse.
| lproven wrote:
| That's a great explanation. Thanks for that.
| fiddlerwoaroof wrote:
| Yes, the problem is exactly that the framework calls your
| code instead of being called by you code.
| Alupis wrote:
| That's how _all_ frameworks work though. This is not a
| criticism of Spring Boot. You are criticizing the use of
| a framework at all.
|
| Some people hate to write the same basic things over and
| over. That's where a framework excels. Write only the
| glue/logic you need to make your app work.
|
| The way you have described your experience with Spring
| Boot seems to imply you did not take the time to learn it
| at all, and therefore its' unsurprising to us you had a
| hard time of it.
| fiddlerwoaroof wrote:
| Not writing the same thing over and over again is a
| feature of abstraction. A framework is a user-hostile way
| to abstract because it makes the source code opaque to
| developers. There's no reason why a library-based
| approach has to be more repetitive than frameworks.
| gf000 wrote:
| CRUD backends have well-understood requirements, in a
| way, a significant part of the work is done for you. You
| are there to customize certain parts only.
|
| How else would you architect with this in mind? Given
| that literally every other framework is quite similar
| (RoR, PHP's solutions, etc).
|
| There is another niche, the HTTP server libraries, but
| they are much more low level.
| Alupis wrote:
| Right, so you cobble together 48 different libraries,
| wrangle all of their configurations and stitch them all
| together yourself.
|
| You do this 18 times because you have 18 different apps
| with similar requirements but deal with different
| data/endpoints/whatever.
|
| On your 19th app you decide to standardize how you cobble
| together all of these libraries so that you don't have to
| start at ground zero every single time.
|
| Now you've invented a framework.
| MattPalmer1086 wrote:
| I was working with legacy code bases where the original
| Devs loved frameworks. Massive performance problems and
| nobody could understand how it all fit together at
| runtime.
|
| Hibernate eventually got entirely nuked, Spring we
| couldn't entirely unwind easily; it had caused a whole
| bunch of crappy architectural issues and was too much
| effort to rewrite from scratch.
|
| Although the code _looked_ simpler using the frameworks
| and annotations, it was actually a huge rotten mess that
| didn 't work well at all, with workarounds for all kinds
| of weird things in it.
| Terr_ wrote:
| I find pretty much every ORM in any language is
| problematic. The best you can hope for is a certain
| amount of internal design consistency, so that even if
| you can't do what you want it's at least clear what you
| are doing.
| cryptos wrote:
| Since I had the "joy" to use TypeORM (node.js stuff), I
| really value Hibernate, although there are some little
| corner cases I'd like to be better. But ORMs solve a
| really hard problem and I haven't seen anything better
| than Hibernate so far (and don't come up with JOOQ or
| MyBatis!).
| qsort wrote:
| > The problem with Java since Java 8
|
| I agree with the sentiment, but I'd move up to a version with
| type inference at least. I have nothing against static types
| and in fact in a vacuum I prefer them, but the particular
| brand of OO and "weak" generics that Java and C# have feels
| like filling forms in triplicate. "var" alleviates that
| significantly.
| neonsunset wrote:
| Generics in Java and C# are _vastly_ different.
|
| .NET has true generics with full type information and
| struct type parameter monomorphization which works the same
| way generics do in Rust.
|
| Edit: C# _does_ have type inference for generics, just not
| the full HM one. It is also quite more capable for lambdas
| which is a bit frustrating because it does not resolve
| nested generics otherwise. I miss it - F# does it the way
| it always should have been.
|
| There are many other differences small and big that arise
| from the way Java does generics and the fact that
| primitives can't participate - you will never see
| `IntStream` kind of workarounds in C#. Some libraries abuse
| and misuse generics for no profit (looking at you Azure
| SDK), but it's not as widespread. Shallow generic types are
| always inferred from arguments.
| qsort wrote:
| yes, this is true. I was talking more about the UX of how
| to use them, which in both cases is quite painful without
| type inference.
| throwaway03452 wrote:
| > you will never see `IntStream` kind of workarounds in
| C#.
|
| You may not see that in Java in the future either. Java
| will have value objects from the Valhalla project, and
| part of the plan is to replace Integer with a value
| object. Then there will be less of a reason to use raw
| int primitives, because the JVM can treat value objects
| much more efficiently than normal objects.
| neonsunset wrote:
| The difference is that C# has been designed with proper
| generics since version 2 (pushed by F# research group
| with Don Syme) and is now on version 13. At the same
| time, structs have been present since version 1.
|
| All APIs and collection types build on this foundation,
| with standard library leveraging generic monomorhpization
| for zero-cost abstractions. Code that would have needed
| C++ implementation in the past is naturally expressed in
| pure C#. Generics are fully integrated into the type
| system at IL level, avoiding special-cased types or
| bespoke compiler handling (besides monomorphization).
|
| This enables numerous zero-cost features: tuples
| (unnamed/named), structs with controlled mutability and
| record structs, pattern matching, stack buffers that do
| not rely on escape analysis, structs with byref pointers
| for slice types (Span<T> and friends) which a good two
| thirds of the standard library accepts. Numeric and
| vector primitives are used in a simple way without setup
| requirements like Panama Vectors.
|
| While project Valhalla will get Java's foot in the door
| in some domains, it will remain a less optimal choice
| than C#, C++, Rust, etc. Java's evolution primarily
| serves its ecosystem's needs, whereas C# benefits from
| being a newer language that learned from both Java and
| C++ and got influenced by F# and other research projects
| inside MS. This makes C# more idiomatic and terse. The
| historical drawbacks - platform lock-in, being closed-
| source, and having _relatively_ weak compiler - have been
| resolved over the past ~9 years.
| layer8 wrote:
| Any competent Java IDE automatically generates you a
| variable declaration from the expression you want to assign
| to it. It's actually less keystrokes than having to type
| "var". Unless you only use a simple editor that doesn't
| perform static analysis, less typing is not a good excuse
| for using "var".
|
| Conversely, in Java you often use the diamond operator like
| in: List<String> items = new
| ArrayList<>();
|
| (Half of which, again, is code completion in your IDE.)
|
| That doesn't work with "var". You'd have to write:
| var items = new ArrayList<String>();
|
| while losing the ability to constrain your variable to a
| narrower type.
|
| The loss of directly seeing the type information in
| statements of the form var foo = bar(x,
| y);
|
| should meet a very high bar, IMO.
| bcrosby95 wrote:
| I've found var preferable when reading code.
|
| I've wrought my hands over this and eventually came to
| the conclusion that developers in every language that
| started with local type inference have embraced it. So
| I've mostly ignored my concerns and gone with "var for
| everything".
|
| If you have trouble with a type then rename the function
| or variable (AKA your "foo" and "bar" example. The names
| are bad, _fix them_. Context matters, _we have none
| here_. No one has an editor that displays a _single line
| of code at a time_.). But in general we haven 't had
| issues on our projects.
|
| Beyond that, my IDE (Intellij) makes it easy to uncover
| the inferred type if I really need to be 100.00% sure
| what it is. In general I don't, because in general I
| don't care, and even before 'var' I was generally
| ignoring the type anyways.
| gf000 wrote:
| I think there is a tasteful way to selectively use var
| where it makes sense.
|
| Even in your example, narrowing the variable doesn't make
| much sense - you are in a local scope, you control
| everything. Narrowing is more meaningful in fields, where
| var won't work by design.
|
| Locally a well-named variable is often significantly more
| important than some long, somewhat useless type
| signature, especially when the right hand side makes it
| clear.
| gf000 wrote:
| Spring boot is itself also very different than Spring, so
| depending on what was your last experience with these
| frameworks, you might be surprised.
|
| Given, they are still quite reflection-heavy and full of
| POJOs and annotations, it supports compile-time resolution
| for many things now.
|
| Also, you would be hard-pressed to find a more productive
| developer than a well-versed Spring boot guru for typical
| backend jobs. You might dislike the framework, but credit
| where it's due, it is a workhorse and the amount of time
| someone makes a POC, you can make it with spring properly, in
| a way that you can build your prod app on top. Like, it's
| easily as productive as RoR and similar.
| p2detar wrote:
| Serious question - what could Spring Boot give me for
| POC/prototyping that Javalin or Micronaut couldn't? I
| really struggle to understand why most of Java shops out
| there have set themselves on the Boot path. Is it
| technology-based decision or politics?
| Alupis wrote:
| Boot has an "app" (err, lib) for everything. It's fully
| featured, and highly opinionated.
|
| Pretty much any modern computing problem you have, Boot
| has you covered[1].
|
| So while you may not have ever used a Streaming library
| before, if you know Boot, then the Spring Boot Streaming
| library will already be familiar.
|
| [1] https://spring.io/projects/spring-boot
| ivan_gammel wrote:
| It's established patterns. Javelin or Micronaut are
| probably great, but not a lot of people understands how
| to build a real project with them. With Spring Boot you
| don't even think about it.
| le-mark wrote:
| I'm not familiar with either of those frameworks so can't
| comment on them specifically, but 10+ years ago not using
| spring/boot entailed glueing together a lot of disparate
| libraries to do things spring boot had built in. Spring
| boot includes pretty much everything. Plus reliability,
| battle tested, easy to hire people with experience using
| it.
| gf000 wrote:
| Spring Data can be ridiculously productive. It _is_
| definitely in the magic category, but you can just have
| an interface with methods named in a specific way, and
| then just call that from a controller class, and you have
| a REST API that calls into your DB for any of the usual
| CRUD queries immediately. And it 's not even just a hack
| that works on the easy case, you can annotate it with
| complex hand-written SQL (both db-independent, but feel
| free to use native queries), and easily extend them with
| real implementations if you need more control.
| throwaway03452 wrote:
| I choose Spring Boot anytime I have to create a service,
| just for that reason.
|
| The eco system is a huge force multiplier, and is
| constantly evolving. Spring Boot simplifies that a lot by
| simplifying the setup to the point where you often only
| have to add a single dependency, and everything is
| configured with default configurations (which you can
| change if necessary of course)
|
| Just look at all the different projects under the Spring
| banner: https://spring.io/projects
|
| One example is the new Spring AI, where they have
| abstracted a lot of functionality and you can change
| providers (OpenAI, Mistral, AWS, Azure, Google) easily.
| vips7L wrote:
| The ecosystem factor is real. I was looking at
| implementing the SCIM protocol [0] in our user management
| app, and if we were on Spring I could have just added an
| Apache boot-starter dependency and been done in a few
| days. However my company uses the Play framework and it's
| going to take me weeks to implement it by hand.
|
| [0] https://scim.cloud
| throwaway03452 wrote:
| If I ever found a startup I will mandate that we use
| Spring Boot (java/kotlin) until we grow big enough to
| afford the extra overhead with other frameworks. Spring
| Boot is truly a Get Stuff Done framework
|
| It would be hard to convince some people of this, because
| "everyone knows Spring is enterprise". Unfortunately many
| only have experience with legacy companies, bad code or
| through reading old blog articles, and base their
| opinions on that.
|
| It's actually something you need to have experienced
| yourself to recognize the possibilities.
|
| It may sound strange, but I enjoy going through the long
| list of projects in the Spring web site. I almost always
| find something cool and is surprised at how much they can
| simplify complex functionality
|
| The learning threshold is also relatively low, because
| they tend to use common best practices in the framework.
| vips7L wrote:
| I've spoken about this before but choosingg Play and not
| Spring has been my companies biggest mistake. It has lead
| us down so many half documented custom solutions that
| would have just worked out of the box if we had chosen
| the more popular stack.
|
| I like Kotlin, but the lack of checked exceptions really
| kills it for me. Exception safety is a bigger thing for
| me than null safety.
| simonw wrote:
| Wow: void main(String[] args) {
| println("Hello world"); }
|
| I just saved that as "hello.java" and ran it (using OpenJDK
| Runtime Environment Homebrew (build 23.0.1) which I happened to
| have on my Mac already) like this: java --enable-
| preview hello.java
|
| This is SO MUCH less crufty than the old "public static void
| main(String[] args)" thing. I always felt that was a terrible
| introduction to programming, when Hello World included a whole
| chunk of boilerplate and a class that didn't need to exist.
| jimbob45 wrote:
| I disagree. Working through each keyword until you understand
| the full signature felt great when learning.
|
| It's the Python if __name__ == __main__ trash that was the
| worst. You'll never understand it and it doesn't fit in the
| language.
| Comma2976 wrote:
| In my humble and correct (trumping anyone else's) opinion,
| they are both garbage.
| Quekid5 wrote:
| You're not wrong... but for different reasons :)
| exe34 wrote:
| you don't need it until you get to importing modules.
|
| hello world in python is literally just print("hello world!")
| dvdkon wrote:
| You don't even need it afterward, unless you want a file to
| be both an importable module and an executable script.
|
| Arguably you could be a happy Python programmer without
| this capability.
| jraph wrote:
| I never understood why people bother with this when
| writing their python main file, which is never going to
| be imported because it doesn't make sense in the first
| place.
| elteto wrote:
| Because I dislike interspersing executable statements at
| module level with function definitions. I'd rather have
| all code live inside functions and have one main entry
| point for the script. It's just a personal preference,
| nothing wrong with not doing that though.
| jraph wrote:
| But you could have a single main() call without the if
| statement, couldn't you?
| telotortium wrote:
| REPL-based development. You might be developing a script,
| but notice a bug. If you import your script as a module,
| you can run the function you're debugging, figure out
| what's wrong, edit the file, and then reimport the module
| (using importlib.reload).
| jraph wrote:
| Okay, that's quite convincing, thanks!
| usrusr wrote:
| Isn't that hugely elaborate compared to languages where top
| level statements are a function, functions return their
| last statement, and the return value of the entry function
| is sent to stdout unless invoked in special ways? That
| print() around the "hello world!" does not appear any less
| superfluous than all the public static void you can throw
| at a javac 1.0
| driggs wrote:
| You mean a language like... Python? >>>
| 'hello world' 'hello world'
| usrusr wrote:
| Exactly like that (well, almost exactly: if python
| includes the quotes then it's not really equivalent to
| print()).
|
| The point was that by including that print(), people
| already do say yes to including "like you'd do in a real
| program" ceremony in their supposedly minimal examples.
| dajtxx wrote:
| Python seems to have started with 'why do those other
| languages have all this trash' and then spent the time since
| then learning why and coming up with worse versions.
|
| I use python a lot these days, and like it, but it's pretty
| funny seeing stuff like the above and type hints.
|
| I hate not knowing what types a function takes and returns.
| nayuki wrote:
| > Python seems to have started with 'why do those other
| languages have all this trash' and then spent the time
| since then learning why and coming up with worse versions.
|
| This seems true to me too. Examples:
|
| * if __name__ == "__main__": main()
|
| * Private members being marked by convention with leading
| underscore (e.g. def _foo()) instead of being a language
| feature
|
| * @staticmethod as a decorator instead of being a language
| feature
|
| * Duck typing vs. abstract base classes
|
| * Static type hints got retrofitted to the language
| gradually, one feature at a time
|
| * Reference-counted garbage collection seems to be more
| deterministic than tracing garbage collection and ensures
| that unreachable resources have their finalizers run as
| soon as possible... except it's not true
|
| * Having a GIL instead of being truly multi-threaded from
| day one
|
| * Various OOP concepts that are much better explained in
| Java than Python: __eq__(), __hash__(), monitor wait() and
| notify(), object finalizers, thread safety, weak references
|
| * Distinction between str and bytes. This is the biggest
| change from Python 2 to 3 and caused a lot of
| incompatibilities. Java separated String and byte[] from
| the start (though the use of UTF-16 is unfortunate).
| Quekid5 wrote:
| The whole switch/pattern matching thing is a true
| abomination borne from: Well, things in statement
| position can't be expressions (or however Pythonistas
| might phrase it), so clearly switch/pattern matching
| _must_ be a statement... It 's such an own goal and
| undermines the main point of pattern matching.
|
| (I do realize that there was opposition on this, but that
| the Clearly Wrong side won out is baffling.)
| nayuki wrote:
| Yeah, it's a shame for Python. I am extremely impressed
| that Java 14's switch expression (
| https://openjdk.org/jeps/361 ) is a generalization of the
| switch statement (since Java 1.0); it's like they took a
| page from Rust's language design. I have found the switch
| expression to be quite useful in my work.
| Quekid5 wrote:
| Probably from ML/Haskell, but yes :)
| cutler wrote:
| Same principle behind Python's crippled lambdas.
| deaddodo wrote:
| Your quibbles show either a) a fundamental
| misunderstanding of Python or b) are just flat out
| incorrect.
|
| > * * if __name__ == "__main__": main()
|
| So, don't use it. Python is frequently run as a scripting
| language (something Java is fundamentally bad at) and
| this stems from that. All it does is box logic off when a
| file is being run directly vs imported. It's a user
| convention and not a language one....ignore it if you
| hate it so.
|
| > * Private members being marked by convention with
| leading underscore (e.g. def _foo()) instead of being a
| language feature
|
| This is all very well explained in the PEP. The quick run
| down, Python doesn't do anything to hide logic from
| users. Contracts are just conventions and python treats
| it that way; so the developer can say "you _shouldn 't_
| use this directly, here's a notation to let you know",
| but nothing will stop a developer from doing what they
| want. In Java they'll just write a wrapper class, inherit
| the base class, and expose that logic. Or worse, fork the
| library just to edit the class' functionality in some
| minor way. In Python they'll just call it directly.
|
| > * @staticmethod as a decorator instead of being a
| language feature
|
| @staticmethod is a built-in, it is a language feature. It
| just doesn't follow your preferred syntax.
|
| > * Duck typing vs. abstract base classes
|
| You can do both in Python:
|
| https://docs.python.org/3/library/abc.html
|
| The concepts aren't mutually exclusive or even directly
| related. Java just happens to be bad at one of them, due
| to it's weirdly non-effective (for a VM'd language, at
| least) reflection system; so you think it's bad.
|
| > * Static type hints
|
| You're complaining about reflective programming and then
| complaining about a feature that essentially exists
| because you can't reflect. It's circular.
|
| > * Reference-counted garbage collection seems to be more
| deterministic than tracing garbage collection and ensures
| that unreachable resources have their finalizers run as
| soon as possible... except it's not true.
|
| GC arguments have run for decades and everyone has their
| opinions.
|
| > * Having a GIL instead of being truly multi-threaded
| from day one
|
| Python was created in 1989. Java was created in 1996. Can
| you guess what major change in computer history was
| happening around the latter's time?
|
| Everything was GIANT-locked when Python was designed,
| unless it was specifically intended for SMP mainframes.
| The entirety of the FreeBSD operating system had a GIANT
| lock on it at the time, for instance. Linux didn't even
| exist. Mac OS and Windows both were fundamentally single
| threaded and cooperatively multitasked. Commercial Unices
| that supported SMP were only ~4-5 years old and a very
| small niche.
|
| You might as well be complaining about "why didn't the
| x86 architecture just have 64-bit capabilities from the
| outset?"
|
| > * Various OOP concepts that are much better explained
| in Java than Python: __eq__(), __hash__(), monitor wait()
| and notify(), object finalizers, thread safety, weak
| references.
|
| In other words: "it's not Java, so it's bad".
|
| Java is a pure-OO language; Python is a procedural
| language with OO as an optional feature. To that end, it
| exposes OO-features in an optional manner versus forcing
| you to use them against your will.
|
| So if the basis of all your arguments is "OO is better in
| Java", well the the response is "yeah I'd _hope_ so,
| since you have no other choice as it 's the _fundamental_
| paradigm ". Guess what? Haskell is much better at
| functional programming than Java; that _also_ doesn 't
| make a valid argument about whether either is good or
| bad.
|
| > * Distinction between str and bytes. This is the
| biggest change from Python 2 to 3 and caused a lot of
| incompatibilities. Java separated String and byte[] from
| the start (though the use of UTF-16 is unfortunate).
|
| Java was developed 7 years later and during a time that
| Unicode was becoming the standard over ASCII. Python was
| designed when everything was still ASCII and Unicode a
| mere glint to the general computer science realm.
|
| As you pointed out, even Java made a bad decision here
| due to their premature adoption of the standards (as any
| modern designed language is quick to point out).
| nayuki wrote:
| And your reply is half right, half wrong. Let me address
| the wrong parts.
|
| > Duck typing vs. abstract base classes / You can do both
| in Python
|
| I'm saying that the original intent of Python was duck
| typing, but then people realized that abstract base
| classes play an important role - e.g. isinstance()
| testing, static type annotations. So they still ended up
| where Java started.
|
| > Static type hints / I don't even know what that means.
|
| I'm saying that Python was designed with no type
| annotations on variables (though values did have types),
| and then they realized that people wanted this feature...
| and ended up where C/C++/Java/C# have been all along.
| Python became "enterprisey".
|
| And then, Python implemented type hints rather badly from
| 3.0 through 3.10 and beyond. It doesn't include types in
| the official documentation, so now you have to guess what
| open() returns (it's typing.BinaryIO/typing.TextIO). It
| doesn't have an official type checker, instead relying on
| third-party tools like mypy. It moved items between
| typing and collections.abc. It requires `from future
| import __annotations__` for non-trivial programs. It
| changed typing.List to just list in 3.9. It introduced
| the | (union) operator in 3.10. And a bunch more little
| things I can't recall; it just had a bad out-of-the-box
| experience and kept tweaking things over the decade.
| Documenting generics and especially protocols in Python
| takes effort.
|
| > Python was created in 1989. Java was created in 1996
|
| Wrong. Java was created in 1991, and the first version
| released in 1996.
| https://en.wikipedia.org/wiki/Java_(programming_language)
|
| Python 1 was released in 1994, and 2 in 2000. They had
| their chance to make breaking changes.
| https://en.wikipedia.org/wiki/History_of_Python
|
| While you're right that Python predates Java, it's not by
| as many years as claimed.
|
| > Various OOP concepts that are much better explained in
| Java than Python
|
| To exemplify, here is how you figure out how to override
| `==`: https://docs.python.org/3/library/stdtypes.html#com
| parisons , https://docs.python.org/3/reference/expression
| s.html#express... . Notably, there is no documentation
| for object.__eq__().
|
| Here is the Java version: https://docs.oracle.com/en/java
| /javase/23/docs/api/java.base...
|
| Now for __hash__() / hashCode(), the Java version is
| clearer: https://docs.python.org/3/reference/datamodel.ht
| ml#object.__... , https://docs.oracle.com/en/java/javase/
| 23/docs/api/java.base...
|
| Python __del__ is buried in the "Data model" page: https:
| //docs.python.org/3/reference/datamodel.html#object.__...
| . Java's finalize() is easily found on Object: https://do
| cs.oracle.com/en/java/javase/23/docs/api/java.base... .
| Furthermore, Joshua Bloch's book "Effective Java" has a
| chapter titled "Avoid finalizers and cleaners" that
| explains in detail why finalizers are problematic.
|
| Python explains a lot less about weakref than Java:
| https://docs.python.org/3/library/weakref.html , https://
| docs.oracle.com/javase/8/docs/api/java/lang/ref/pack...
|
| > Java is a pure-OO language
|
| Extremely wrong. Java has primitive numeric types, which
| do not have methods or fields, and undergo painful
| boxing/unboxing conversions to interoperate with the OO
| world. Whether the performance benefits are worth it or
| not is debatable, but what's not debatable is that Java
| is not pure OOP. Some say that Java is a bad copy of
| Smalltalk, which I heard is fully object-oriented.
|
| > Python is a procedural language with OO as an optional
| feature
|
| Wrong. Every Python value is an object that can be
| inspected (dir(), .__dict__, etc.). And in the CPython
| API, every Python value is a PyObject*. I have ample
| grounds to believe that Python is more OO than Java.
| ivan_gammel wrote:
| >Wrong. Java was created in 1991, and the first version
| released in 1996.
|
| Gosling and others started working on it in 1991, but
| does it really matter? First public release is when you
| can learn about it and borrow ideas. It doesn't make your
| point less valid, of course - Java made a lot of hype
| back then.
| deaddodo wrote:
| > Python 1 was released in 1994, and 2 in 2000. They had
| their chance to make breaking changes.
| https://en.wikipedia.org/wiki/History_of_Python
|
| You're purposefully fudging dates to make the argument
| more favorable to your point. If you want to argue
| initial source release, then you can maybe make the point
| for 0.9:
|
| > In February 1991, Van Rossum published the code
| (labeled version 0.9.0) to alt.sources
|
| And say that Python had it's initial release just
| slightly before Java had begun design specs. But Python
| was in use before that and Rossum had developed the
| initial version well before that (again, 1989):
|
| > The programming language Python was conceived in the
| late 1980s,[1] and its implementation was started in
| December 1989[2] by Guido van Rossum
|
| It's ironic that you're trying to make that same argument
| for Java and dismissing it for Python, when Python was
| very much in public use pre-1.0 and Java was not (outside
| of internal teams).
|
| > Wrong. Every Python value is an object that can be
| inspected (dir(), .__dict__, etc.). And in the CPython
| API, every Python value is a PyObject*. I have ample
| grounds to believe that Python is more OO than Java.
|
| I feel like, just based on this point, you've done
| nothing more than open the CPython source code and
| searched for "object". This naming was in place well
| before Python even had any of the OO-functionality that
| exists today (new-style classes derived from the Object
| type). If you're going to argue for "old-style" classes
| being OO in any way but name, you're probably going to
| fundamentally disagree with any OO fundamentalists, the
| designers of Python itself, _and_ the Java community
| /designers. You might as well argue that structs with
| function pointers in C make it an OO-language, as that's
| functionally all they are.
|
| PyObject doesn't correlate to a Python class/Object. It's
| a container data structure to allow for their
| duck/dynamic typing. Object is a type of PyObject; but it
| contains an additional layer of functionality to _make_
| it a Python Object (specifically PyMethodObject and
| PyTypeObject, and their correlative functionality).
| Again, to allow for the reflection /introspection and GC
| that you so bemoan; and due to the lack of C generics at
| the time (or really, even today). Being able to
| introspect a type has nothing to do with it's "OO-ness",
| although it can be very useful in such languages (such as
| C#).
|
| As to your other point, sure...using "pure" was probably
| going too far. But by that same argument, even Haskell
| isn't pure-functional (nor do any really exist) due to
| it's need to interface with IO. But Java is about 90%
| there and strives for it. Python most definitely isn't
| nor does it make any intentions to do so.
|
| Again, fudging the history/facts/topics to try and make
| your point. It's not worth discussing with someone who so
| fundamentally converses in bad faith. Especially since
| I'm making no claims to which is _better_ , just
| outlining the flaws in your complaints. I really don't
| care about "better" languages.
| p1necone wrote:
| Really Java has always been kinda okay - the really horrible
| part of Java was always the "enterprise OOP" programming
| patterns that were basically a given in any commercial codebase
| - little things like pointing out the verbosity of a basic
| single file project are just shorthand for "look at all this
| shit people have written".
|
| As the adage goes - Java programmers can write Java in any
| language.
| Terr_ wrote:
| ... But if they do make it in Java, at least you have the
| tools to analyze and refactor it.
| bzzzt wrote:
| You mean stuff like in the 'Design Patterns' book by the Gang
| of Four? That was originally written for C++ programmers and
| predates Java by a few years.
|
| Seems 'Java programmers' were already writing Java before
| Java's release ;)
| fuzztester wrote:
| Python programmers be like: from __past__
| import JavaProgrammer /usr/bin/python: error:
| line 0: not a chance
| watwut wrote:
| That is something yet different.
| trallnag wrote:
| Is the problem design patterns or opaque frameworks that rely
| on a ton of reflection?
| watwut wrote:
| Afaik, at the time issue was a lot of programming in xml -
| where those frameworks are configured in various xmls and
| hard to understand and maintain. Reflection based
| frameworks are later development.
| mercutio2 wrote:
| "In XML" is neither here nor there.
|
| The massive amounts of indirection which the IDE wouldn't
| help you understand was the difficult thing. What
| encoding you use for that is pretty irrelevant. JSON
| would have been worse.
| jjice wrote:
| Anecdotal, but I had an intro to programming class in high
| school and the teacher was a wonderful woman, but not a
| programmer. She didn't know that this was a function
| declaration or its meaning, so she would just have us repeat
| out loud "public static void main string box args". I get a
| laugh whenever I think of that. I hope she's doing well.
| keyle wrote:
| I had an Excel class 20-25 years ago where a teacher
| explained click and double click every class, and emphasising
| "DOUBLE CLICK" out loud every time she did the action...
| There were a few facepalms.
|
| The next class was assembly programming, where the teacher
| didn't bother to show for 4 months and then resumed the class
| as if we "self-taught up until this point". We were utterly
| lost in that one.
|
| I imagine things have changed greatly today but back then it
| was a complete roller coaster.
| ElevenLathe wrote:
| In elementary school we had a "class" with the "computer
| teacher" once a week. He was just one of the only adults on
| the school district payroll who knew how to turn on and off
| an Apple //e. Nice guy (he also volunteered at the same
| community theatre I did), but "computer class" was just
| letting us loose with copies of Fraction Munchers and
| helping us if we jammed the disk drive or whatever.
| nickpeterson wrote:
| I remember being 10 and going to a computer lab full of
| power macintoshes and playing sim city 2000, kid pix, and
| Carmen San Diego. This was in between looking at a cd
| encyclopedia (encarta?), old computers were awesome ;)
| hobs wrote:
| Wow, you reminded me of two experiences at once.
|
| I wasn't good at getting educated, but I ended up at a
| community college to "get my generals" - my first class of
| the day was computer something or other, and the class was
| led by a man in extremely thick glasses who said that our
| general approach in the course was going to be:
| * perform actions with the computer * take a
| screenshot * paste the screenshot into mspaint
| * print out the screenshot as proof that we had completed
| the thing * put that in a folder * he would
| review the folder for completion
|
| (for anyone paying attention, anyone could just print out
| multiple copies)
|
| While it was a significantly younger and less experienced
| me who quit this bullshit in an absolute huff, I don't know
| if I could go through it today.
|
| Fast forward a few years later, and I was training folks on
| tech support(a random reversal) and I had a lady who should
| have taken his class... every time I told them to click on
| something she asked "is that right click or a left click?"
| and each time I would respond "its a left click unless I
| tell you otherwise" (she didn't last long.)
| xienze wrote:
| A lot of Java professors did that in the past, because the
| "not hello world" parts of "hello world" require a bit more
| understanding, and in the spirit of getting people started,
| the idea is to just say "hey memorize this boilerplate stuff,
| eventually you'll understand what it means."
| riku_iki wrote:
| > than the old "public static void main(String[] args)" thing
|
| you forgot surrounding class definition.
| geokon wrote:
| I haven't written Java in a million years.. so I'm trying to
| understand better.
|
| But what does this code even mean..? Isn't Java's whole
| simplifying model that everything lives in "Objects"? This
| seems to break that fundamental paradigm and makes the language
| more complicated. If you needed something like global functions
| then in vanilla Java as I remember you'd stick it into static
| final Objects that acts as a namespace of sorts. So you don't
| need to worry about functions floating around in a global
| namespace soup.
|
| If you're gunna just have free floating functions in your
| file.. then why not just cut to the chase and have a
| println("Hello world");
|
| floating in your file..? (I mean... you don't have REPL so
| maybe that wouldn't be too meaningful...)
| int_19h wrote:
| It's implicitly still a class, you just don't need to write
| all the scaffolding to indicate that. The functions are still
| methods of that class etc.
|
| But, yes, with static imports, you can just write "println"
| like that and have it work.
| almostgotcaught wrote:
| > It's implicitly still a class, you just don't need to
| write all the scaffolding to indicate that.
|
| did you know that every function in a python script is
| actually an attribute of that module (which is basically a
| class). so my point is: who cares.
| imtringued wrote:
| geokon's point still stands. This is meaningless syntax
| sugar that does not change anything fundamental about Java
| except add one more special rule into the language aka it
| is one more thing to learn. Rather than being helpful, it
| just becomes friction when an old developer uses the old
| method and a new developer uses the new method.
|
| You still need to know what a main class is, so that you
| can reference it in your build.gradle file.
| losvedir wrote:
| If you're using a build.gradle file then you probably
| won't see any benefit to this implicit class, yes.
|
| But it's useful for little one-off scripts, where you
| just go `$ java foo.java` from the command line.
| semiquaver wrote:
| > you don't have REPL
|
| (ahem) https://docs.oracle.com/en/java/javase/23/jshell/intro
| ductio...
| spullara wrote:
| only since 2017 :) people basically judge java based on
| what you learn in AP CS which is basically (a dumbed down
| version of) java 6 (released 2006).
| vips7L wrote:
| It's honestly the only programming language that will get
| its 1996 version compared to a new 2025 version of
| another language. And the only language that will be
| criticized by someone who last used it in 2006.
| homebrewer wrote:
| PHP gets the same treatment all the time.
| AmpsterMan wrote:
| PHP and Laravel are amazing.
| mey wrote:
| I have been developing Java for a long time and my brain
| tends to stay stuck in Java 8 mode a lot of the time.
| james_promoted wrote:
| Definitely not the only language. Other long-lived
| languages like C++ get this treatment too.
| motorest wrote:
| > And the only language that will be criticized by
| someone who last used it in 2006.
|
| You don't sound like you work with Java. I know for a
| fact that even some FANGs, with their army of software
| engineers, still use Java8 for most of their Java
| projects.
| throwaway03452 wrote:
| Historically an upgrade could cause issues if the code or
| dependencies used undocumented functionality (like Byte
| code manipulation) or calls to native code, or the
| transitions to modules in v9. Upgrades after version 11
| should be less "risky" and be easier to argue to
| management.
|
| From what I can tell, there are 4 main reasons why some
| don't upgrade.
|
| 1. They have legacy software and are afraid of breaking
| it, sometimes with good reasons.
|
| 2. The devs don't know or care enough about the new
| versions to bother with it. Noone is promoted because of
| an upgrade. Work to live, and don't live to work
|
| 3. The ones who don't have buy in from management to
| spend time fixing something that works
|
| 4. They are using version 11+ that should be much safer
| to upgrade than earlier versions, but they are still in
| the mindset of 1 or 2 above
|
| There have been huge improvements not only in the
| language itself, but also performance and memory use.
| They could save money if they upgrade, but in some cases
| this is acceptable because they can make more money by
| spending time on a new feature, than an upgrade.
|
| In my last 3 workplaces, they usually tried to use the
| latest LTS versions. But to be honest, some of the
| services were in maintenance mode and we didn't get
| enough benefits to upgrade, so we were sometimes falling
| behind. Today we have a mix of v17 and v21. Anyone can
| upgrade anytime they want but noone cares about a service
| that you seldom work with. I feel kind of bad for that,
| but not enough to bother. I focus mainly on the services
| that I work with daily, and make sure they are using the
| latest versions
| motorest wrote:
| > From what I can tell, there are 4 main reasons why some
| don't upgrade.
|
| You missed the most obvious reason to not upgrade: there
| is no good reason to do it.
|
| > There have been huge improvements not only in the
| language itself, but also performance and memory use.
|
| That's debatable, and even if we blindly assume that then
| it's debatable whether the upgrade justifies the gains.
|
| More often than not, it doesn't.
| vips7L wrote:
| > That's debatable, and even if we blindly assume that
| then it's debatable whether the upgrade justifies the
| gains
|
| This is not debatable. It's a factual truth. Every single
| actual performance review concludes that modern Java
| vastly out performs the decade old Java 8 runtime.
|
| For an example here is a quote from Hazelcast when
| comparing performance of modern Java on data heavy
| workloads [0]:
|
| > JDK 8 is an antiquated runtime. The default Parallel
| collector enters huge Full GC pauses and the G1, although
| having less frequent Full GCs, is stuck in an old version
| that uses just one thread to perform it, resulting in
| even longer pauses. Even on a moderate heap of 12 GB, the
| pauses were exceeding 20 seconds for Parallel and a full
| minute for G1. The ConcurrentMarkSweep collector is
| strictly worse than G1 in all scenarios, and its failure
| mode are multi-minute Full GC pauses.
|
| This is from 2020 and the gap has only gotten wider.
|
| [0] https://hazelcast.com/blog/performance-of-modern-
| java-on-dat...
| vips7L wrote:
| I work in Java every day and have upgraded my entire
| companies fleet of services to Java 21. FANGs are nothing
| special. And every actual survey shows that there are as
| many people on a runtime > 8 as there are people on 8:
|
| https://www.jetbrains.com/lp/devecosystem-2023/java/
| motorest wrote:
| > And every actual survey shows that there are as many
| people on a runtime > 8 as there are people on 8:
|
| I don't think you even bothered to read the sources
| you're quoting, and you're just trying to make baseless
| assertions.
|
| The very first question on JetBrain's survey is "Which
| versions of Java do you regularly use?", and 50% answered
| Java 8 with around 2% mentioning Java 7 and 1% answering
| Java 6. On top of that, Java11 alone comprised around
| 38%.
|
| And you're talking about Java21? It doesn't even register
| in the survey at all.
| vips7L wrote:
| I'm not talking about Java 21 when referring to that
| data, I was refuting your baseless claim that I don't
| work in Java. I don't think you even bothered to actually
| read or comprehend my comment.
|
| The data there clearly shows that the ecosystem has as
| many users running a modern version. Which directly
| counters your assertion that everyone is just running 8.
| motorest wrote:
| > people basically judge java based on what you learn in
| AP CS which is basically (a dumbed down version of) java
| 6 (released 2006).
|
| I don't think people realize Java8 was until very
| recently the dominant java version in production
| software, and currently close to 90% of all java projects
| still run on java11 and earlier.
|
| Edit: after checking New Relic's 2024 report on the java
| ecosystem, it sounds like java11 and earlier is now at
| slightly over 60%, with java17 being used in around 35%
| of the projects.
| spullara wrote:
| For software written in that era currently under
| maintenance mode, I don't expect people to upgrade their
| java language version though upgrading their JVM is a
| good idea.
| sgt wrote:
| Try doing a cold load of JShell though. Can easily take 2
| seconds on a rather fast machine. People will never use it
| as a quick REPL for that reason.
| vips7L wrote:
| I use it as a repl all the time. IntelliJ can load your
| projects classpath into too. It's really awesome.
| sgt wrote:
| Thanks, I'll give it a shot in IntelliJ.
| vips7L wrote:
| docs if you're interested:
| https://www.jetbrains.com/help/idea/jshell-console.html
| Quekid5 wrote:
| I'm having such a hard time figuring out whether this is
| satirical.
|
| (My guess: It is.)
| Joker_vD wrote:
| I know, right?
|
| > So you don't need to worry about functions floating
| around in a global namespace soup.
|
| Because having _classes_ floating around in a global
| namespace soup is fundamentally different and should give
| no worries to anyone. Yet this was argument made in earnest
| back when arguments about Java 's strengths and weaknesses
| were much more popular.
| lmz wrote:
| There's always going to be a namespace soup but at least
| in Java there's only one kind of thing in the soup.
| Joker_vD wrote:
| The famous "anemic namespace soup" language design
| pattern.
| lazide wrote:
| Hey, it could be Perl!
| gf000 wrote:
| As others mentioned, there is an implicit class here in play.
|
| Basically, imagine a `class Temporary4738 {` and `}` written
| above and below the .java file's content, that's roughly how
| it will behave.
|
| It not having a fixed name is deliberate, so if you decide to
| build a bigger system you won't use this mechanism in a hard
| to maintain way, and also it needed a good semantic model for
| "top-level" variables/fields.
|
| But with this implicit class model, top-level definitions are
| just fields of the class.
| motorest wrote:
| > As others mentioned, there is an implicit class here in
| play.
|
| The same strategy is also followed by C# with their top-
| level statements. And yes, it's syntactic sugar.
|
| https://learn.microsoft.com/en-
| us/dotnet/csharp/fundamentals...
| winrid wrote:
| Because this is the entrypoint? Having code exec out of an
| explicitly defined entry point that's an entire file sucks.
| dkarl wrote:
| > This seems to break that fundamental paradigm and makes the
| language more complicated
|
| Welcome to the last 10+ years of Java. They're trying to play
| catch-up to other languages that made fundamentally different
| and better choices, making Java more and more complicated in
| the process. They are so deeply entrenched in the enterprise
| back end space that programmers put up with it, nay, even
| feel grateful for it. People who are stuck using Java for the
| rest of their careers are happy to see it grow to accommodate
| 21st century programming techniques, even if it means that it
| becomes so complicated and crufty that no beginner will touch
| it ever again.
| x0x0 wrote:
| In java's defense -- and I share your criticisms -- it
| offers some very nice things that no other language has.
|
| eg want to run code for 6 months at a go managing hundreds
| of gigs of data, tens of thousands of threads, at high
| load, with sustained gigs a second of garbage generation?
| the jvm will just silently tick away doing just that while
| being nearly bulletproof. As much as I love ruby and
| python, you ain't doing that with them.
|
| With hot code loading, introspection, etc. All the stuff
| that makes developing super-robust long-lived systems way
| easier.
|
| And the flip side of the clunky language is your code from
| 20 years ago still works.
| woooooo wrote:
| Also, conservative feature adoption works in the long
| term.
|
| Scala mainstreamed a bunch of concepts that java was slow
| to adopt, but the end result was java only took the good
| ideas and didn't take the bad ideas.
| dkarl wrote:
| Fortunately, you don't have to use Java to use the JVM.
| There's Kotlin, Scala, Clojure, etc., all of which are
| simpler languages.
| NBJack wrote:
| It doesn't surprise me; that sounds exactly like how C++
| has progressed (sans the enterprise beans, hopefully).
|
| 10+ years ago I considered myself proficient at C++. It
| made sense, I didn't mind the pointers, and while the std
| library still felt clunky, it was fine. But I tabled these
| skills, and they indeed rusted a bit, but surely I could
| bring them out when needed again, right?
|
| Smart pointers with multiple variants, judicious use of
| macros, rampant use of double colons to ensure proper
| namespace resolution (which IMHO makes the code an absolute
| eyesore), to name a few. I won't argue these changes aren't
| necessary, but it isn't pretty.
| foobarian wrote:
| Song version: https://www.youtube.com/watch?v=yup8gIXxWDU
| globalnode wrote:
| what did i just witness....
| klez wrote:
| One of the best metal band Italy has on offer, that's what
| you just witnessed.
|
| SEMICOLON!!!
| AiTricky wrote:
| Thanks for sharing this. I watched it while both enjoying and
| cringing at it.
| Phelinofist wrote:
| this is actually fucking amazing :D
| rottc0dd wrote:
| I agree that can serve as terrible intro to programming. But,
| often when we have tools either designed for a purpose in mind
| or a dominant paridigm or reaction to existing set of tooling,
| this can result in understandable yet extreme abstractions.
|
| Java is designed with OOP in mind and it kind of makes sense to
| have the user to think in terms of lego blocks of interfaces.
| Every method or class needs to have clear understanding of its
| users.
|
| public - software handle is for all users
|
| protected - software handle for current and extending classes
|
| default - software is exposed to current package
|
| private - software is restricted to be used in current class
| alone and nowhere else
|
| So, the beginning of java programming starts with interface
| exposed to the user or other programmers. Is it weird and
| extreme. Yes. At least, it is consistent.
| brokenmachine wrote:
| >less crufty than the old "public static void main(String[]
| args)" thing. I always felt that was a terrible introduction to
| programming
|
| I somewhat agree, but it was kind of exciting to learn what
| each of those previously meaningless words meant.
|
| Kind of a sneak preview... Tune in for next week when we learn
| what static means!!
| fulafel wrote:
| It's a good local improvement, but the other hand that old
| traditional syntax was a good effective "keep away" sign in
| Java that saved many CS students from being fed Java as a first
| language. And it's still a bad first language after this
| change. I wonder if this small improvement might make things
| worse in the big picture.
| thayne wrote:
| And yet it is still the first language taught in many
| programs.
|
| Although my high school programming class was c++, which is
| even worse as a first language.
| user_of_the_wek wrote:
| These features are explicitly to make teaching Java as a
| first language easier. From https://openjdk.org/jeps/463
|
| Goals:
|
| Offer a smooth on-ramp to Java programming so that
| instructors can introduce concepts in a gradual manner.
|
| Help students to write basic programs in a concise manner and
| grow their code gracefully as their skills grow.
|
| Reduce the ceremony of writing simple programs such as
| scripts and command-line utilities.
|
| Do not introduce a separate beginners' dialect of the Java
| language.
|
| Do not introduce a separate beginners' toolchain; student
| programs should be compiled and run with the same tools that
| compile and run any Java program.
| themaninthedark wrote:
| I learnt to program using Pascal, then C++ in Highschool.
|
| In collage, CS101 and 102 required me to learn and use
| JAVA, which I felt was a huge step backwards in usability
| and a lot of excess typing.
|
| But as I reflect on it now, I think my feeling were because
| I came from knowing how to do some things and therefore not
| requiring the framework that JAVA offed to first time
| programmers.
| fulafel wrote:
| I think the sins of Java as a first language are twofold:
|
| 1. The obvious excess incidental complexity
|
| 2. and more important, the enterprisey culture that's
| much less compatible with the intellectual curiosity,
| looking under the hood, etc attitude that's needed to
| become a decent programmer.
| BeefWellington wrote:
| They've also done quite a bit of work to make things such as
| hosting a web service much much simpler, through the addition
| of things like SimpleFileServer, as well as some better
| convenience methods.
|
| It makes it far far closer to the python experience.
| user_of_the_wek wrote:
| You don't need the args! void main() {
| println("Hello world"); }
|
| should work just as well.
| jillesvangurp wrote:
| You might also like Kotlin script. #!
| /usr/bin/env kotlin println("Hello world")
|
| You have to brew install kotlin for this to work of course. But
| it's a great way for using a lot of Java stuff as well.
| Kotlin's Java interoperability is excellent if you are using
| Java from Kotlin.
|
| IMHO Kotlin is underused as an alternative to python currently
| for data science stuff. It's surprisingly capable out of the
| box even with just the standard library and there are a lot of
| nice data science libraries that make it more useful. Not for
| everyone; but fairly easy to get started with.
|
| Kotlin scripting is unfortunately not necessarily very user
| friendly (e.g. imports can be a bit tedious and IDE support is
| a bit meh). But it can be a nice way to embed some kotlin stuff
| in a script. Generally, Jetbrains could give this topic a lot
| more love and attention and it wouldn't even take that much to
| level up the experience.
|
| KTS works in jupyter as well (there is a kotlin engine for
| that). And that of course is nice if you want to use Java
| libraries in jupyter. And developing kotlin DSLs for stuff and
| then using them in a script is kind of a power move.
| a57721 wrote:
| > Kotlin scripting is unfortunately not necessarily very user
| friendly (e.g. imports can be a bit tedious and IDE support
| is a bit meh). But it can be a nice way to embed some kotlin
| stuff in a script. Generally, Jetbrains could give this topic
| a lot more love and attention and it wouldn't even take that
| much to level up the experience.
|
| Kotlin has been pretty bad at scripting and REPL, and
| unfortunately the team decided to drop both:
|
| https://blog.jetbrains.com/kotlin/2024/11/state-of-kotlin-
| sc...
| GTP wrote:
| Based on that page, they're dropping the REPL in favor of
| notebooks, but their're not dropping scripts. They are
| dropping some script-related functionality to focus on
| others.
| jillesvangurp wrote:
| Also worth noting that notebooks and kts overlap quite a
| bit. They use the same mechanism for imports and defining
| remote repositories, for example. A notebook is
| effectively a kts script. And of course gradle uses kts
| as well for its Kotlin dialect. These things actually
| overlap quite a bit.
| a57721 wrote:
| Yes, they are not dropping scripts completely, at least
| because of Gradle, but they are removing some parts of
| scripting support and advise against using Kotlin for
| scripting. And I would prefer a true command line REPL
| instead of the notebooks. IIRC they were promising
| various improvements in both scripting and REPL for
| several years, and now they just gave up, I guess because
| of shifting the focus to K2 and KMP. I find this quite
| disappointing.
| pragma_x wrote:
| It took almost 30 years to get here. I never thought I'd see
| the day.
|
| What really threw me for a loop is the article author mentions:
| "I knew plenty of professors who were bothered by [the public
| static void main thing]." I could have sworn that OOP die-hards
| in academia _wanted_ the formal class boilerplate in the
| original design. Maybe they aged out? Perhaps, times are
| changing.
| forty wrote:
| You might also want to look at scala and ammonite [1]
|
| [1] https://ammonite.io/#ScalaScripts
| eweise wrote:
| exactly my thought. If you think java makes a good scripting
| language, you will be really happy with scala
| dropofwill wrote:
| Also scala-cli https://scala-
| cli.virtuslab.org/docs/getting_started
|
| I still like to use Ammonite as a REPL, but scala-cli has
| replaced it for me in those cases where i get fed up writing
| bash.
| vvillena wrote:
| Scala-cli would be even better. It explicitly supports Java
| too!
| brundolf wrote:
| Very cool to see all these quality of life improvements. I
| haven't kept up with Java for several years. Still, the
| dependencies thing seems like an issue (as it is in Python)
|
| Deno has been my go-to scripting tool lately. Similar benefits to
| Java as used by the OP, but it also allows you to import
| dependencies directly by URL, which means you can have your
| script self-define dependencies without a separate manifest file
| qsort wrote:
| Python packaging continues to be a pain, but you can specify
| dependencies for single-file scripts with inline script
| metadata, see:
| https://packaging.python.org/en/latest/specifications/inline...
| nesk_ wrote:
| Remembers me the "Java for Everything" blog post:
| https://www.teamten.com/lawrence/writings/java-for-everythin...
|
| Also, thank you for sharing! I do appreciate Java and I'm glad to
| see it can be used for scripting nowadays.
| neonsunset wrote:
| Still long way to go before it reaches .NET levels of
| productivity (especially so if you use F# for scripting, but C#
| is no slouch either) :P
| pjmlp wrote:
| Depends on the platform, some don't have any .NET productivity
| available. :)
| neonsunset wrote:
| These platforms are not being considered here nor have much
| relevance anymore. You cannot seriously claim this unless you
| don't use the tooling side by side at all.
|
| The difference is so stark it's no longer amusing. Performing
| setup for complex Java projects has me go through similar
| steps as if they were written in C++. Performing setup for C#
| projects of comparable complexity usually requires just
| cloning and hitting 'dotnet run', much like it usually
| happens with Rust or Go (some may claim I undeservedly bash
| it but credit is where credit is due).
| pjmlp wrote:
| Like my phone, or those used by US military?
|
| I love your identity with .NET ecosystem, to the point of
| nothing else being in the way.
|
| See latest JetBrains Developer Surrey about platforms.
|
| .NET is a great ecosystem, but lets be real where it stands
| outside Microsoft shops, across everything that has a CPU
| on them, and the various ecosystem where sadly it doesn't
| even get a tier 1 support.
|
| Programming languages are tools, a toolbox has space for
| plenty of them.
| mike_hearn wrote:
| Are you comparing "complex Java projects" against just
| ordinary "C# projects"? Because ordinary Java projects will
| also be "./gradlew run" or the Maven equivalent, that's
| nothing special.
| neonsunset wrote:
| And in many other situations "./gradlew run" just doesn't
| work. Hell, Gradle does not even let you quickly scaffold
| it without pre-existing knowledge and community advice!
| (if you want to avoid pitfalls and have the best
| "streamlined" experience) Something that is not an issue
| in Rust or Go. Maven is even worse.
|
| Meanwhile I can 'git clone https://github.com/ryujinx-
| mirror/ryujinx && cd ryujinx/src/Ryujinx && dotnet run -c
| Release' and it works on the first attempt (though takes
| a moment to pull nuget packages, it's a big project).
|
| The Java ecosystem has incredible projects from the
| technical point of view (GC implementations, OpenJDK's
| JIT compiler), but the tooling and application packaging
| and distribution seem like the painful parts.
| mike_hearn wrote:
| It usually works in my experience, since the toolchains
| feature was added, as that takes the Java version mostly
| out of the equation.
|
| There is "gradle init" to scaffold a project, or of
| course IDEs offer a GUI over that.
|
| Additionally, your "dotnet run" does require the dotnet
| tool to be installed and of the right version. The
| Gradle/Maven equivalents now no longer do, because they
| bundle scripts into your repository that will download
| and run the build tool itself of the right version. They
| just need some moderately modern Java installed.
| Everything the project needs including possibly a newer
| Java will then be downloaded.
|
| I'm not sure what the point of naming individual projects
| is. I can point at dozens of projects off the top of my
| head where you can just clone and run them without
| incident.
|
| There _are_ painful parts of both Gradle and Maven.
| Absolutely. They are very far from perfect build systems.
| But this is partly because they do a lot more than tools
| like cargo does.
| neonsunset wrote:
| > "dotnet run" does require the dotnet tool to be
| installed and of the right version
|
| It only needs an SDK installed on the system. If you have
| the necessary framework dependency, it will just work. If
| it's missing - the command output will specify this,
| which is solved by doing `sudo apt install dotnet-
| sdk-{version}` or just `dotnet-runtime-{version}`
| (because newer SDKs can build most older targets). You
| can also usually roll-forward the applications without
| retargeting them or installing older runtime (which is
| trivial still). It's a reliable and streamlined process.
|
| Probably one of the best approaches to managing the SDK
| and framework dependencies that does not rely on any form
| of help from external tooling or IDEs.
|
| Gradle and Maven need JDK installed in either case. I had
| Gradle that shipped with the code crash on me because it
| was sufficiently old to have issues on newer OpenJDK
| versions. Solved it by installing properly, but you can
| see how it can be an error-prone process.
|
| ------------------------------------
|
| Ultimately, if you're an expert and it's a long-term
| project - none of this matters, solving odd breaks and
| tooling issues is part of the job. It's nice when things
| work, it's not unexpected when they don't. Some languages
| have more of this and some less, but at the end of the
| day due to business constraints and company environment
| none of this is a showstopper per se - you just deal with
| it.
|
| Do I think the CLI tooling, dependency management,
| packaging and distribution is painful in Java or Kotlin?
| Yes, it's what also precludes either from being
| productive scripting languages unless you have nailed the
| setup that works around all of these. Does it matter for
| writing complex applications? Not really, project and
| environment setup for such is mostly one-time thing. It's
| coincidentally where Java ecosystem shows its strength.
| My rant here is posted because I believe we can discuss
| pros and cons without stating that specific issues don't
| exist when they do or vice versa.
|
| Among everything I tried Cargo, .NET CLI and Go had the
| smoothest experience of things mostly working and when
| they weren't - not requiring to dig through heaps of
| documentation, possibly dumped into a language model to
| catch the exact specific piece that would help to solve
| the puzzle. I heard good things about Python's uv. If
| actively maintained, Node.js projects also work reliably,
| not so much when they aren't though. Some C++ projects
| are kind enough to offer build scripting that works out
| of box on Unix systems - props to the maintainers, which
| is also the case with Java projects. But whenever either
| of the last two didn't work, it often took me the most
| effort and swearing to get either working, unlike other
| languages.
| throwaway03452 wrote:
| I don't share your experience. I have no problems
| importing a Maven project git clone
| https://github.com/... cd somedir mvn
| spring-boot:run
| gibspaulding wrote:
| I'd be curious to hear more about how you're using F#? I've
| previously used Python for scripting, but just started
| developing for a company pretty deeply entrenched in .NET.
| Currently they're migrating a lot from VB to C#, but I've
| missed having a handy scripting language like Python for small
| tools or test applications. Do you think F# could fill that
| roll?
| stackskipton wrote:
| Powershell is probably best fit for that role. You have to
| learn a new scripting language but since it runs on .Net you
| can actually bring in .Net Classes if you need a little more
| power.
|
| https://learn.microsoft.com/en-
| us/powershell/module/microsof...
| neonsunset wrote:
| It should be able to! F# has "gradual typing" and full type
| inference which means you often do not need to specify the
| types at all, and it also happens to be whitespace-sensitive
| language much like Python is. Both of these aspects should
| make it feel quite familiar while also giving you full
| advantages of static typing.
|
| One thing to note is I find `dotnet fsi {some script
| name}.fsx` taking more time to start than ideal - up to 800ms
| is just too much, normal .NET applications usually start in a
| fraction of this.
|
| I recently posted a submission here for "FSharpPacker"
| written by my friend that lets you compile F# _scripts_ to
| standalone applications (either runtime-dependent, self-
| contained or fully native binaries, much like Go), it also
| has some comments on getting the best mileage out of it:
| https://news.ycombinator.com/item?id=42304835
|
| Probably the best feature that also comes with scripting
| (both C# and F#) is "inline" nuget references e.g. #r "nuget:
| FSharp.Control.TaskSeq" which will automatically pull the
| dependency from nuget without ever dealing with manually
| installing it or tinkering with build system in any other
| way.
|
| Some additional links:
|
| https://learn.microsoft.com/en-
| us/dotnet/fsharp/tools/fsharp...
|
| https://github.com/dotnet-script/dotnet-script (C# is _also_
| a quite productive language for scripting and small programs
| because of top-level statements, record types, pattern
| matching and many other functional features though perhaps
| not as strongly represented as in F#, it 's just very
| unfortunately abused in enterprise world, with teams often
| going out of their way to make the code far more bloated than
| necessary, against the language design intentions)
|
| https://github.com/waf/CSharpRepl
| taberiand wrote:
| F# is a leap if it's your first functional / ML style
| language (but worthwhile). Modern C# is good for small tools
| and scripting, there is the dotnet-script tool for running
| single .csx files
| singpolyma3 wrote:
| > Java has many features that make it well suited for large,
| long-lasting projects
|
| Already disagree, haha
| whtsthmttrmn wrote:
| I'll bite. Explain, please.
| KyleBerezin wrote:
| There are reasons to not like Java, but this isn't one of them.
| Java is a fantastic language for large long lasting projects. I
| can't think of a more suited language for large long lasting
| projects in fact.
| mongol wrote:
| I don't think Java is fit for "the small". And there is nothing
| wrong with that. My go-to language for "the small" is Go. Java is
| good for enterprise heavy-lifting, not for quick and nimble
| tools.
| Pet_Ant wrote:
| For the small I like Groovy. Especially as Grapes is like Maven
| but in annotations that you include in the script file. Being
| Java-based means that if it goes from "in the small" into
| something larger you are already on a stable foundation.
| jknoepfler wrote:
| and you get a nice little portable binary that doesn't force
| someone to install a compatible version of an
| interpreter/virtual machine to run.
| mongol wrote:
| Exactly
| vips7L wrote:
| That's if they're on the same architecture and operating
| system as you. Half the people I know are on mac, half of
| them are on arm. The other half are on windows and x86.
| Terr_ wrote:
| Now I'm having flashbacks to porting a whole stack of
| applications from x86 to a customized Linux distribution
| running on a big-endian PC platform. A mishmash of C/C++,
| Java, Node-JS, Python...
|
| It was really dumb, but that's what the client needed. So
| much cross compiling.
| evantbyrne wrote:
| Go has cross compilation.
| hiAndrewQuinn wrote:
| Actually, you can specify to build portable binaries for
| all 3 of these platforms. You can even make them totally
| static, so that deployment is as easy as "copy the
| executable file with windows/Linux/Mac/etc in the name and
| run it".
|
| This is part of my standard Go build.sh script. You just
| never know who might want to run a given thing where.
| jknoepfler wrote:
| Who the heck is on ARM (outside data centers)? But yeah,
| with golang that's just:
|
| GOOS=linux GOARCH=amd64 go build
|
| GOOS=linux GOARCH=arm64 go build
|
| GOOS=darwin GOARCH=amd64 go build
|
| Which again, let's me distribute a binary to my end user as
| a single file, without directing them to install java or
| python3 or whatever.
|
| (The ARM question is kinda immaterial, but I'm curious)
| mrkeen wrote:
| Who the heck is on ARM (outside data centers)?
|
| Mac people, for a few years now.
| tmiku wrote:
| Can you tell us about how you use Go in the small? I like Go,
| but it doesn't strike me as particularly nimble for scripty use
| cases like this - error handling is part of it, but I know
| that's fixable with the Must() pattern.
| mongol wrote:
| I just write a small Go program. I agree that error handling
| is a weak point, but the tooling is well integrated. The
| article mentions that Java does not know about Maven. The go
| tool is much more versatile in that sense.
|
| Also, go run is almost like running a script.
| ricardobeat wrote:
| You can quickly whip up a single-file go program anywhere,
| without any boilerplate or setup: package
| main import "fmt" func main () {
| fmt.Println("hi") } // go run file.go
|
| You can write this in any text editor, but using one with LSP
| support means that `import` statement is added automatically,
| and with CoPilot or another assistant, the `main` function
| writes itself as well as any `if err ...` statements. Go is
| extremely well suited to code generation due to how
| predictable it is.
|
| Adding dependencies with `go mod` is uneventful.
|
| It will never be as 'scripty' as JS or Ruby, but the
| readability, safety and performance are totally worth it.
| Capricorn2481 wrote:
| I don't really see how this is different from `dotnet run`,
| `python main.py`, or `lua main.lua`. Like the commenter, I
| don't find Go very nimble.
|
| Is limited features (Go) gonna be better for AI generation
| then breadth of examples? (C#). I'm not sure.
| yxhuvud wrote:
| I see 3 or four lines of boilerplate in your example,
| depending on if the closing brace is counted or not.
| Compare with the following equivalent program in ruby or
| crystal (it is valid in both): puts "hi"
|
| And the crystal version is just as typesafe and performant
| as the go version. I also find it more readable, but that
| is a very individual metric.
| mongol wrote:
| I don't think minimal examples are so useful. I reach for
| Go when bash is insufficient. That means there is a
| minimal starting size that is large enough that package
| and imports boilerplate are insignificant, all things
| considered
| ricardobeat wrote:
| I love Crystal and have been a sponsor for a long time,
| but it's not comparable yet. Compiling is much slower,
| you have to manually add dependencies to shards.yml,
| cross-compilation is not as simple. And when it comes to
| scripts and tools, popularity / stability is a main
| concern.
| gf000 wrote:
| This is literally longer than the java version mentioned in
| the article, and that can be started just as simply with a
| single command.
| ricardobeat wrote:
| The question I responded to was 'how you use Go in the
| small', not a comparison to the post.
|
| As I mentioned, yes, it's verbose, but simple and worth the
| effort and _peace of mind_. My primary language is JS, I
| 've written a fair share of shell and Ruby but would still
| choose go a lot of the time, just because it doesn't pull
| in any extra complexity.
| booleandilemma wrote:
| Go refuses to compile if you have an unused variable and that
| is the opposite of quick and nimble.
| gf000 wrote:
| Go is severely less expressive than Java, so.. disagree. You
| will end up with longer files with more boilerplate for
| questionable benefits.
|
| Also, in many areas Java's standard library is more expansive.
| lenkite wrote:
| Every function call is 4 lines in Go. No basic error
| propagation support means Go code bloats up very fast in line
| count. result, err := callFoo() if err !=
| nil { return nil, err }
|
| No collection streams means LOTS of mind-numbing/eye-glazing
| for loops. Things have improved _slightly_ with the slices and
| maps package but these are just hacks. Maybe with the new
| iterator support, Go will slowly and steadily get a bit more
| expressive.
|
| Go is good for middleware coding thanks to Go-routines and and
| excellent networking support in the standard library but is
| cumbersome slow and inexpressive for scripts.
|
| Also go.mod does NOT separate dev/test/prod dependencies -
| unlike Java Maven or Rust Cargo. You don't want your script
| dependencies coming into production code.
| dajtxx wrote:
| I started with Java 1.0 and thought it was great. I still do,
| although I haven't used it since 2020.
|
| The only thing I don't like is how there is no built-in JSON
| package which seems like a necessity these days.
|
| Removing the public static void main(String[] args) business
| seems like pandering to a non-existent audience, or at least a
| miniscule and insignificant one. Anyone who is going to use Java
| for a real project is not going to be worried about that, and
| anyone who thinks that's too difficult to deal with is never
| going to be a good programmer anyway.
| Zu_ wrote:
| The last part seems like a very 'gate keepy' point of view.
|
| If you want to introduce someone to programming, you probably
| don't want them to worry about what all those 'magic words' do.
|
| At least for their first steps, they won't need to know what a
| class is or what `public` and `static` mean.
| znpy wrote:
| > If you want to introduce someone to programming, you
| probably don't want them to worry about what all those 'magic
| words' do.
|
| I learned Java when i was 15 or 16, reading some random book
| first and then I stole 35 euros from my mother's purse and
| bought a copy of "Java how to program" by deitel and
| deitel[1]. The recommended version at the time was Java 5,
| and the SJCP certification was still issued by Sun
| Microsystems.
|
| I can tell you, "public static void main" is not going to be
| the problem.
|
| [1]: looking back (i'm in my 30ies now) sometimes I wonder if
| i would have been better off buying weed or alcohol (or both)
| acbart wrote:
| So you believe that your experience is a universal one for
| all learners? Cognitive load is a real consideration in
| teaching, and having to ignore and filter text is
| challenging for some folks.
| twic wrote:
| The boilerplate around a main function is 10 units of
| load. Everything else you have to know to write a simple
| program is 500-600 units of load. The boilerplate is a
| rounding error, and just does not matter.
| dgfitz wrote:
| Yes, all people are different, and some are smarter than
| others. Education funding won't change that.
|
| Way to disparage a random person on the internet.
| znpy wrote:
| Mostly yes. Given how much there is to learn, public
| static void main is not going to be "the problem".
| jknoepfler wrote:
| Yeah, you want to start with basic imperative programming
| with as little cargo-cult nonsense in the way as possible.
|
| Your csci 101 kids will not benefit from unpacking what it
| means to compile an object-oriented language down to bytecode
| to run on a virtual machine. It's not that it's not valuable
| knowledge, they just won't have the context to make
| meaningful heads or tails of it.
|
| related: I still puke a little remembering the requirement
| that students work on assignments in emacs on terminal
| machines rather than their text processor of choice(which was
| fine for me, but why on god's green earth would you put
| usability warcrimes like 'hjkl' in the way of someone just
| starting to learn? No wonder nobody in the early naughts
| wanted to learn to program...).
| dustyventure wrote:
| A lot of people learn to program from declarative languages
| like spread sheets. We should all be happy we have access
| to defective versions of assembly at too high a level but
| be angry that we had to use too low level an editor?
| anthk wrote:
| Emacs doesn't use 'hjkl'. I think you weren't there in the
| 90's...
| cutler wrote:
| Evil mode ;-)
| fijiaarone wrote:
| You shouldn't try any modern programming language until
| you've mastered GOTO and GOSUB and know why lines are
| numbered in multiples of 10.
| lproven wrote:
| I think this is a really important point, even though I
| suspect you're joking.
|
| Along with all the BS boilerplate text this specific post
| talks about eliminating, which is great, we simply forget
| how much legacy tech BS we just assume.
|
| Beginner programmers should not have to know what a
| "file" is, or what an "editor" is, or that they need an
| "editor" to "edit" a "file". This is technical debt:
| these are implementation details which should be
| invisible.
|
| This goes double for "compilers" versus "interpreters"
| and "source code" versus "binary code". FFS the noun
| _code_ means _a system for rendered text unreadable_.
|
| You have a computer. You are talking to it in words,
| words which resemble English because that is one of the
| simplest world languages when you think about scripts --
| writing systems -- as well as sounds. Hangeul is easier
| but only works for Korean which is harder than English.
| Grammatically Chinese is simpler, but spoken Chinese has
| tones which are very hard, and written Chinese is insane.
| Typed Cyrillic is no harder but handwritten gets weird
| and complicated and Russian is much harder than English.
| And so on.
|
| English wins and so we talk to computers mostly in
| English.
|
| So, you have a computer, and you type on it in English.
| That is all you should need to know: how to enter text,
| how to correct it when you get it wrong, and that is it.
|
| BASIC has a great virtue which all the Unix and even the
| Lisp fans forget:
|
| It's designed to work at a command prompt. Type a
| command, the computer does it. Give it a number, it
| remembers it for later.
|
| This is a _profound and important_ metaphor. It
| eliminates all the 1960s /1970s legacy BS about "files"
| and "folders" and "editors" and "compilers". Beginners
| don't need that. Let them learn that later if they prove
| to have real aptitude and want to pursue this.
|
| Type a bare expression, the computer does it. Number it,
| the computer remembers it for later. _That is all you
| need to get writing software_.
|
| And just like Python sorted out the problem of spoiled
| whiny little baby C programmers whinging about their
| pathetic obsessions with indentation patterns by _making
| indentation semantic_ so _everyone has to comply_ , line
| numbers in BASIC are a vital simplifying unifying
| mechanism, so lean on them: for beginners, make line
| numbers syntactic.
|
| Don't force kids to learn pro tools like nomenclature and
| hierarchies. Give them a toy that they can get started
| with.
|
| At first, they can structure their programs with line
| numbers, and they learn about leaving space, about
| RENUMBER commands, about LIST x TO y ranges, and stuff
| like that, because we are not using a bloody Commodore 64
| any more.
|
| But give them IF...THEN...ELSE and WHILE...WEND and
| REPEAT...UNTIL and named procedures so they can learn
| structure and not GOTO.
|
| All the rest is baggage and should be deferred as late as
| reasonably possible.
| smaudet wrote:
| Agreed.
|
| I still feel like the author is missing the forest for the
| trees. Bash is not great to write e.g. a red black tree in or
| do complex image processing, but you don't have to maintain a
| Java install, download libraries, or setup an editor with an
| LSP (and really, calling java script.java 10 asdf? Why do I
| need to invoke Java at all? At that point, I'm probably going
| to wrap it in a script anyways...)
|
| Python has its own issues but it's a small, embedded install
| that you don't have to accept 5 different licenses for and
| worry about it being able to get the same version...
|
| And bash? That's what pacman -S jq is for - anything I can't
| easily do in bash or batch I just offload to a small utility
| written in python or rust.
|
| Java is, at it's core, just too heavy, IMO.
| fijiaarone wrote:
| Some people write programs that do more than simple scripts
| gf000 wrote:
| pacman -S jdk-openjdk, this is the reference java
| implementation and it has the exact same license as the
| Linux kernel. And java has never done such a breaking
| change as python did.
|
| There is also jre-openjdk-headless, for 140 MB. How is that
| any different than Python?
|
| This "java too heavy" is like 30 years out of date, if it
| has ever been true.
| smaudet wrote:
| Quick check via msys2:
|
| "error: target not found: jdk-openjdk"
|
| > And java has never done such a breaking change as
| python did.
|
| I'm not really sure that's true? Java 8 to afterwards,
| there are breaking changes that mean a lot of old
| enterprise stuff can't easily move forward, or worse,
| bytecode incompatibilities mean source-code-less stuff
| can't be used anymore...
|
| The whole thing about Graal is mentioned almost as an
| afterthought, my point is that the language etc. is so
| poorly designed as to be prohibitive to interface with
| unless...well you're on Java. Yes there are bridges etc,
| but a _big_ point of the shell, bash, etc. is _easy_
| interoperability between many programs, etc.
|
| Java is still today stuck in a mentality of "it doesn't
| exist if its not in Java", which is why yes, 30 years
| later, it is still "too heavy". Assuming you are the
| effective Operating System is an extremely heavy
| assumption.
| smaudet wrote:
| > and it has the exact same license as the Linux kernel
|
| Also, I neglected to touch on this point more, perhaps
| license is not the right word, as much as distribution -
| I don't know if you have ever tried building the JDK (not
| simple), or worked with the official JDK vs the open one
| (not the same functionality), or tried to access old
| versions of the SDK on the official websites, or had to
| deal with their installers, etc.
|
| Giant headache and all around.
|
| Not to mention, even if your pacman command works, this
| is still simply not comparable, the example I used was
| for installing a jq binary because JRE simply doesn't
| include this functionality by default...
|
| And now you need the overweight pom/gradle mess to
| interface with the Java libraries because <insert
| technical debt reasons here>
| gf000 wrote:
| The official JDK is the OpenJDK for several years.
|
| Under Sun there were differences, but Oracle open-sourced
| every last difference and now there is only some Oracle
| branding logo as the only difference (and maybe some tiny
| proprietary codec, but your code _will_ run on both the
| same way).
| jraph wrote:
| I think gp is right, and I don't think it's gatekeeping. I
| thought this about Java, it was easy to criticize its
| verbosity, but I realized how insignificant this is when
| actually practicing it. There's probably way more interesting
| and deeper criticism to make about Java.
|
| About the first steps of a newcomer, there's always going to
| be some level of "don't worry about this now, we'll see what
| this means later" for any language. I remember this to be the
| case for every tutorial I read to learn a language. And it's
| fine, as long as you can try stuff and it doesn't get in the
| way.
|
| I'd say it's more important for a language and its vocabulary
| to be well structured and well documented for a newcomer and
| Java does quite good on this front.
| AnimalMuppet wrote:
| As mongol said in a top-level comment, Java isn't a great
| language for programming "in the small". It's not a great
| language for a casual user - or rather, there are languages
| that are significantly better. If you want to introduce
| someone to programming in a semester course, "public static
| void main" isn't going to be a significant hurdle. If you
| want to introduce someone to programming as a 14-year-old,
| maybe don't start with Java.
| gf000 wrote:
| Why? Java is a small language with not many concepts, that
| is typed so many of your first attempts will be caught with
| helpful messages at compile time, and it fails safely at
| runtime with error messages pointing to an exact line
| number. Besides, it is a language that is actually used in
| the industry and has one of the biggest ecosystems. It's
| also plenty performant, can be low-level enough for
| learning about all kinds of data structures/algorithms,
| including concurrent ones and has probably the best tooling
| (IDE, debugger, etc)
|
| What other language would you start with?
|
| And isn't it easier to introduce concepts one at a time?
| For that reason implicit classes makes sense, and also for
| the occasional scripting, as in doing something one-off,
| but it is not as trivial that I can do it with piping 3
| commands together.
| AnimalMuppet wrote:
| > Java is a small language with not many concepts
|
| True. But you need to know too many of them to get
| anything to run.
|
| > that is typed so many of your first attempts will be
| caught with helpful messages at compile time
|
| But it doesn't feel that way. It doesn't feel "helpful",
| it feels nitpicky. It feels like I have to get everything
| exactly right before _anything_ will run. For a raw
| beginner, that 's very frustrating. It is (emotionally)
| better to have something run as far as it can run, and
| then crash. (I agree that exceptions pointing to the line
| number are very nice.)
|
| Again, for a semester class, the startup overhead for
| learning Java is too small to worry about - it's maybe a
| day or two. But for someone on their own, not in a class,
| a day or two is a _huge_ investment to put in before they
| can get something running!
|
| What would I start with? Something with a REPL. (It could
| be a language that is normally compiled, but there needs
| to be a REPL. Raw beginners need to be able to get
| something, _anything_ , to work as quickly as possible.)
| unclad5968 wrote:
| GP is right. If the words public static keep you from
| learning how to program you were never going to learn anyway.
| If I introduce someone to soccer and they quit because they
| couldn't figure out how to put their shoes on, chances are
| they werent going to learn how to play no matter what.
| norir wrote:
| Did you know that the first thing John Wooden did with
| incoming freshman collegiate basketball players at the most
| prestigious program in the country was teach them how to
| properly put on their socks?
| smaudet wrote:
| I think the converse(?) to this though is that the words
| public static are inconsequential.
|
| Sure, if you are incapable of learning what a couple
| adjectives mean you won't go far, but that holds for much
| more than software.
|
| Rather it's not important that the ball is big and blue so
| much as that you can kick it across the field - learning
| what the ball means can come later, but it's just
| unimportant noise (to start).
|
| Java is pretty bad at this, though, insisting on specifying
| unimportant details up front rather than allowing for
| qualification. This is OK for a large monolithic
| application with complex requirements and a litany of edge
| cases, but inappropriate for many smaller use cases.
| cbsmith wrote:
| javax.json has been around since Java 7.
| theandrewbailey wrote:
| It's part of Java/Jakarta EE.
|
| https://jakarta.ee/specifications/platform/10/apidocs/jakart.
| ..
| cesarb wrote:
| > It's part of Java/Jakarta EE.
|
| If it's part of J2EE, it's in practice "part of Java" since
| the JDK comes with the J2EE packages built-in...
|
| That is, it came with the J2EE packages built-in, until
| Java 11 decided to break everything, and force people to
| get each piece of J2EE from a separate upstream project,
| with AFAIK no "all of J2EE" uber-jar you could simply copy
| into your project to restore the status quo. It's no wonder
| so many projects are to this day stuck on Java 8.
| klez wrote:
| > since the JDK comes with the J2EE packages built-in...
|
| Are you sure about that? I just downloaded the Java 8
| JDK, and javax.json is not there. And the documentation
| doesn't mention it either. What am I missing?
| cbsmith wrote:
| The JDK doesn't include all the J2EE goodness:
| https://docs.oracle.com/javaee/7/api/javax/json/package-
| summ...
| II2II wrote:
| > Removing the public static void main(String[] args) business
| seems like pandering to a non-existent audience, or at least a
| miniscule and insignificant one.
|
| Perhaps the audience doesn't exist because of that business.
| There are many times when I would have used Java over Python to
| write simple programs for no other reason than having the
| ability to create a GUI without resorting to third-party
| libraries. Yeah, Python has tk but it has never clicked with me
| in the sense that Swing does. Unfortunately, cramming every
| last thing into an OOP model means that simplicity is rapidly
| lost. (The same can be said of Python, except Python has not
| forced it. Java, historically did.)
| msgilligan wrote:
| I agree that for experienced programmers working on large
| projects a little bit of verbosity around `main` is
| insignificant. But first impressions matter, especially when
| there is pervasive word of mouth about "verbosity".
|
| Pretend you are a college student and you are taking your first
| programming class (e.g. CS 1) and your friends have told you
| that Java is "verbose". You start with "hello world" and you
| have to type `public static void` etc. One of your friends
| shows you the same code as a Python 1-liner.
|
| Or similarly you're a beginning programmer in the workforce and
| your employer asks you to solve a problem using Java. You've
| heard Java is verbose and when you start with "hello world" you
| find that what you heard was true.
|
| This is not a non-existent/minuscule audience. They should have
| fixed this decades ago. Better late than never.
|
| I've been impressed with the modernization of Java over the
| last 10+ years. Simplifying "hello world" is a minor change
| relative to the others, but still an important one.
| dgfitz wrote:
| > But first impressions matter, especially when there is
| pervasive word of mouth about "verbosity"
|
| I watched most of my comp sci 101/102/201 classmates fail out
| because they didn't want to understand how things worked,
| they just wanted to make a lot of money.
|
| Edit: hn even helped me prove the point:
| https://news.ycombinator.com/item?id=42457515
|
| Teach that to a 10 year old, where their primary keyboard
| experience is a phone.
|
| More than that, if rust is the future, which I have seen
| espoused before, picking on the Java keywords and syntax is
| highly amusing.
| bigstrat2003 wrote:
| I _did_ cut my teeth on Java back in middle school-ish. It
| never bothered me at all, I was too busy having fun learning
| to program. I agree with GP, the mandatory class is a
| completely overblown complaint about Java.
| fijiaarone wrote:
| If you think Java boilerplate is bad, wait until you have to
| learn about ELF file formats in order to execute almost
| everything else.
| voidhorse wrote:
| I'm of two minds about it. On the one hand, the verbosity is
| arguably noise if you are first learning to program, or just
| want to write something quick, so I can see why people dislike
| it.
|
| On the other hand, viability, classes, and "staticness" are all
| fundamental structural concepts in Java. Hiding them for a
| special case is sort of like lying, and, in the long term, I
| can actually see this special case causing more confusion for
| new learners. It's sometimes better to be upfront and
| transparent and force your users to work with the paradigm and
| semantics they chose to adopt, rather than pretend it doesn't
| exist. If Java had been designed to allow for top-level
| functions from the start, it'd be a different story. I think
| special casing is a generally bad way to evolve a programming
| language.
| gf000 wrote:
| But there is absolutely no hiding, the design is very smart!
|
| You simply get an unnamed implicit class like `class Tmp367
| {` written at the top, and the _runtime loader_ has been
| modified to be more accepting of main methods. There was
| basically a tiny language change, and no bytecode change,
| java semantics are just like they always were.
|
| The Main loader just simply will accept an instance method
| named 'main' for a class with an empty constructor with no
| args, instead of psvm.
| klez wrote:
| It's hidden from the newbie who never used java before,
| that's what we're talking about. As you said, all that
| stuff is done implicitly. The user never sees any of that
| unless they go digging.
| norir wrote:
| The problem is when java is used as a first language, this is
| needless complexity that gets in the way of the actual
| fundamentals of programming. Access privileges are irrelevant
| for a beginner who is hopefully not writing libraries that will
| be consumed by anyone. The distinction between an instance and
| static method is also confusing and irrelevant. It's just
| pointless ritual for the student.
|
| Now, if one is learning java as a second language, that's a
| different story.
| scotty79 wrote:
| For error handling they could add error propagation operator `?`
| from Rust. In Java it could propagate "throws" from the
| expression it's applied to the signature of a method that
| contains it. In Rust it's a bit awkward becuse you need to adjust
| return type. Since Java tracks exceptions separately it would be
| completely unobtrusive and ultraconvenient.
| deergomoo wrote:
| It's not a popular choice for it, but PHP is also fantastic for
| the sort of things described in this article. A relatively recent
| version is pre-installed on many *nixes, it has a decent enough
| (and gradual) type system, and standard library absolutely chock
| full of functionality (albeit very self-inconsistent in naming
| and structure) for dealing with files, JSON, making network
| requests, etc.
|
| And because it's not compiled, you can just whack a hashbang at
| the top of the file and chmod it to be executable.
| Terr_ wrote:
| I agree it'll work, but from a broader ecosystem perspective it
| feels like a mismatch, given PHP's historic focus on webstack
| stuff, and the projected likelihood that someone maintaining
| the system will know PHP versus Python etc.
|
| But perhaps we can both agree that it shouldn't be in JS/Node.
| :p
| macspoofing wrote:
| That's true for every other mainstream interpreted language. Is
| PHP better than Ruby or Python for those use-cases?
| AtlasBarfed wrote:
| Groovy is still far far far better at cli scripting in javaland.
|
| You don't even need main methods and class wrappers, can import
| libraries with annotations with Grape, etc.
|
| The real failing of cli and scripting in jaba and groovy is
| running cli commands with access to stdin stdout stderr streams.
| I have figured out the dark art for groovy but it takes quite a
| few stack overflows to get there.
| socksy wrote:
| Maybe it's sort of not the same because it's compiled with
| graalvm and so not trivial to add any arbitrary Java
| dependency, but the tech that scratches that itch for me is
| babashka -- a proper REPL, because it's a lisp, sensible
| Clojure syntax, and easy IO. And all the core Java libraries,
| available in a much snappier form than Clojure or other
| compiled languages
| brabel wrote:
| The Groovy shell can be really fast if you use GroovyServ:
| https://kobo.github.io/groovyserv/quickstart.html
|
| It feels instant, no need for GraalVM.
| e12e wrote:
| Interesting. Anyone have an opinion on how this compares to using
| Kotlin for similar tasks?
| mdaniel wrote:
| Seems very similar https://kotlinlang.org/docs/kotlin-tour-
| hello-world.html although I haven't ever used Kotlin like a
| "script replacement" (e.g. https://kotlinlang.org/docs/run-
| code-snippets.html#command-l... ) to compare and contrast
|
| Overall, I think Kotlin is a vastly superior language to Java
| and spanks Scala in discoverability and legibility _(less
| magick moar bettar, IMHO)_
| norir wrote:
| I've abandoned the jvm, but I found Scala much better
| designed than Kotlin. Things in Kotlin felt consistently ad
| hoc and I would frequently run into weird special casing
| whereas Scala actually had general principles that could be
| applied to more use cases.
|
| Kotlin on the other hand had better IDE support in intellij
| for obvious reasons. That was not nearly compelling enough
| for me.
| therealdrag0 wrote:
| What'd you switch to from JVM?
| occz wrote:
| I'd consider it equal or better in all regards.
|
| - Top-level functions/main is supported - data classes are
| approximately as good as records - A scripting mode comes built
| in, and can use annotations to import and use dependencies
| within the same file - There's a repl - The keyword 'var'
| exists, and the keyword 'val' is more ergonomic than 'final
| var'
|
| The only thing I remember missing from the article is the
| implicit imports which I don't remember Kotlin having.
| Regardless, I'd reach for Kotlin every time. I think funnily
| enough Java never fully clicked for me until I started using
| Kotlin, which in many ways is "Java, except many best practices
| are on by default".
| jillesvangurp wrote:
| Also, see my comment about kotlin scripting (kts) elsewhere in
| this thread.
|
| But, in short, you can write kts shell scripts; import any
| library you want, use anything in the JVM or the Kotlin or Java
| library ecosystem that you need, etc.
|
| Works on the command line (you need a jvm and kotlin installed
| from your favorite package manager). The Kotlin Jupyter kernel
| also uses kts and this is a nice way to use Java stuff in
| jupyter.
| anthk wrote:
| On Java, a lot of 1.2/1.3 era games are half-broken and threads
| fail a lot with interpreter from Java 2SE (>1.6/OpenJDK 6) and
| beyond.
| msgilligan wrote:
| For those interested in the rationale for the simplified main
| methods (and the rationale for _not_ simplifying further), the
| relevant JEP is a good read.
|
| JEP 495: Simple Source Files and Instance Main Methods (Fourth
| Preview) https://openjdk.org/jeps/495
|
| The parent article mentions and links JEP 477 -- the 3rd preview
| of the same feature-set. JEP 495 is the 4th preview and is
| included in JDK 24 which is in "stabilization" mode for release
| in March 2025.
| aardvark179 wrote:
| I regularly end up using Jshell when I'm analysing things like
| profiling data. Partly because I have access to libraries that
| parse those formats, but also because typing and autocomplete
| make it really effective for this sort of interactive thing.
| driggs wrote:
| Lightweight Java has always been a thing for those who appreciate
| Java-the-language but despise Java-the-ecosystem.
|
| You don't need to fool with Gradle or Maven or Ant if you'd like
| to incorporate third-party or your own custom dependencies in
| single-file "Java scripts".
|
| Just copy some .jar files into ~/lib, and in your `.bashrc`:
| export CLASSPATH=~/lib;$CLASSPATH
| miuramxciii wrote:
| Ah.. the old days of java programming - set up your CLASSPATH
| and done.. Nowadays; however, most libraries have tons on other
| dependencies and doing this manually is tedious and a pain in
| the neck - download the wrong version of the dependency, and
| you are in for a rabbit-hole trying to figure out the
| compilation errors. Do not get me wrong, Maven is ugly and
| disgusting(so are the other dependency managers for java), but
| gone are the days of CLASSPATH.. unless you avoid using
| libraries bloated 3rd part libraries at any cost.
| rmgk wrote:
| If you like to have most of the simplicity of just setting
| classpath, but still have convenient dependency resolution, I
| highly recommend checkig out coursier: https://get-
| coursier.io/
|
| Its a cli based artifact fetching tool for the JVM ecosystem,
| and you can have it just make up classpath strings for you,
| i.e., to use some Apache dependencies with the single file
| simplified java running you could just:
|
| java --enable-preview --class-path (cs fetch --classpath
| org.apache.commons:commons-collections4:4.4) program.java
|
| Also, maybe do have a look at scala-cli: https://scala-
| cli.virtuslab.org/ It does work just fine with Java files,
| and allows you to write single-file programs that include
| dependencies as special comments. The tool has some
| idiosyncrasies (like a background compiler server), but
| overall works extremely well if you need some of the power of
| a build tool, but without having a complex project structure.
| oftenwrong wrote:
| Also, see this project that is in a similar space as
| Coursier:
|
| https://github.com/bowbahdoe/jresolve-cli
|
| https://github.com/bowbahdoe/jresolve
| palmfacehn wrote:
| java -cp .:* OneOffTestCase.class
| d_burfoot wrote:
| I use Java extensively for my personal work and never use
| Gradle/Maven/Ant. I run Python scripts that marshal javac and
| java calls, it works great. I do cute tab completion tricks
| that examine the class layout and extend based on what it
| finds. I even have a "SmartCompJava" script that finds .java
| files that have newer modtimes than their corresponding .class
| files and just compiles them - a bit dangerous if you're not
| careful, but it's super-fast!
| oftenwrong wrote:
| >Lightweight Java has always been a thing for those who
| appreciate Java-the-language but despise Java-the-ecosystem.
|
| I always disliked Java until I was converted by some developers
| of that group in a past job. I suppose it is fair to judge a
| language by the overall flavour of its ecosystem, but it is a
| bit disappointing. I wish more people could see how simple and
| _good_ it can be when you use the JDK itself, and not go
| through other overcomplicated systems to use it. For example,
| Spring Boot is basically a massive pile of hacks (regardless of
| whether you consider it good or bad), and Java only really
| serves as an underlying support technology for it.
| w10-1 wrote:
| Launching without compiling, a main interface... a Mark Reinhold
| story
|
| During jdk 1.1 development, there was obviously no consensus on
| test suites (i.e., JUnit), and the JavaSoft JCK tests required a
| ridiculous amount of html documentation for tracing to specs.
| Mark Reinhold, the jdk tech lead, refused to have his team write
| tests in JCK form, so instead he wrote a small harness with a
| compiling class loader: point the harness at a directory tree of
| .java files, and it would run them all, compiling as needed. The
| test interface was just a main function, and if it threw an
| exception, it failed. Pure and simple.
|
| But probably the best magic trick for Java programmers is
| debugger hot reload. You write some empty methods, start the
| debugger, and then code iteratively, reloading as needed. (Set up
| the data and interfaces right, and change method bodies as you
| wish.) It's so much easier than recompile-println when you're
| just getting started, and after you've grown up and out, it's
| easier than rebuild/redeploy when you're working on a big system.
| jaccarmac wrote:
| > debugger hot reload
|
| Hey, that's (close to) the traditional Smalltalk introduction-
| trick! And this has been available since 1.1? How does one
| concretely do that in Java and why is it not widely known?
| gf000 wrote:
| Well, it doesn't sit that well with mutable global/local
| state. There is a saying that hot reloading works better if
| you can replace at a smaller, atomic granularity. In the JVM,
| this kind of reload is at the method granularity, which may
| or may not be ideal.
|
| But the JVM still has a few tricks up its sleeve, e.g. the
| class loader can dynamically re-load a newly compiled version
| of a class at runtime - jrebel is a proprietary extension
| that uses both tricks, but this latter can also be used by
| spring for hot swapping many parts of a running system.
|
| Basically, in the JVM a class is unique within the class
| loader, so with a new class loader you can load as many class
| instances of the same, or slightly different class as you
| wish.
| mike_hearn wrote:
| 1. There's no way to react to hot reload in the normal Java
| API, so you can't easily clear state.
|
| 2. The JDWP protocol lets debuggers redefine nearly anything,
| but HotSpot doesn't implement the full protocol. In practice
| many kinds of reload don't work.
|
| 3. To fix those issues app frameworks went with classloaders
| for partial app reloads instead, or reimplemented hotswap
| logic themselves (see JRebel).
|
| There's no fundamental reason these can't be fixed, and in
| fact the Espresso JVM fixes both 1 and 2:
|
| https://www.graalvm.org/latest/reference-
| manual/espresso/hot...
|
| You can write JVM plugins that are invoked after redefinition
| occurs, allowing you (really your app framework) to do
| something sensible like partially reload state. And it
| implements the full protocol, so many more kinds of
| redefinition work.
|
| Using it is easy. Just install Espresso as your JDK, point
| your build system at it, then debug your app. Recompiling
| what attached will cause hot reload.
| JavierFlores09 wrote:
| Interesting, I've never heard of Espresso, I've always just
| used Jetbrains Runtime[1] instead which is the successor of
| DCEVM[2] in a way. As for plugins I used HotswapAgent[3] at
| times however I found it to be rather clunky, does Espresso
| improve on this aspect?
|
| 1: https://github.com/JetBrains/JetBrainsRuntime
|
| 2: https://dcevm.github.io/
|
| 3: https://hotswapagent.org/
| rramadass wrote:
| > But probably the best magic trick for Java programmers is
| debugger hot reload. You write some empty methods, start the
| debugger, and then code iteratively, reloading as needed. (Set
| up the data and interfaces right, and change method bodies as
| you wish.)
|
| Do you have any example you can point to for this ?
| easylion wrote:
| I totally agree. I use java for every possible coding script or
| task. I have been using it in my company for last 5+ years and
| have understood the language too well to be able to switch to
| something else and learn its caveats. In my comfort zone with
| java and I love that its being actively developed and improved
| every day.
| trallnag wrote:
| Are you in the comfort zone with Spring as well?
| throwaway03452 wrote:
| I can only speak for myself, but I was lucky to be exposed to
| Spring Boot back in the v1.5 days after spending a few years
| creating Java programs without any framework. No XML at all,
| configuration by code, and opinionated default configuration
| that covers most use cases.
|
| The learning curve was not that hard, and I got comfortable
| with it.
|
| In contrast, I find React, Next.js and other frameworks more
| complex, and it takes a lot longer to be comfortable
| joeevans1000 wrote:
| Take a look at Clojure and also Clojure Babashka.
| lebski88 wrote:
| Babashka is truly wonderful and has taken over almost all my
| scripting projects. But the author started by saying they
| didn't want to use a language without types so Clojure is
| probably out!
| Kwpolska wrote:
| > I am pretty sure [working around checked exceptions] will never
| be a part of the JDK, because it is arguably bad for large and
| serious programs.
|
| And yet so many programming languages, including JVM languages
| like Scala or Kotlin, just don't do checked exceptions, and the
| world hasn't caught fire yet (and in fact, I can't think of
| another mainstream language that does have them). Java could just
| drop them altogether and everyone (except maybe the most devout
| Java fans) would be happier.
|
| > The file gets compiled on the fly, every time that I run the
| script. And that's just the way I want it during development or
| later tinkering. And I don't care during regular use because it's
| not that slow. The Python crowd never loses sleep over that, so
| why should I?
|
| Java takes significantly longer to compile than Python does. My
| Python takes ~40 ms at first startup of a hello world script, ~20
| in later attempts. `java hello.java` is in the 360-390 ms range.
| klez wrote:
| > `java hello.java` is in the 360-390 ms range.
|
| That's still pretty negligible. I don't think he's making a
| strict comparison, just saying that in both cases it's barely
| noticeable.
| vips7L wrote:
| Checked errors are not unique to Java. Rust, HNs darling baby,
| is praised on this forum every day for checked errors. Swift,
| F# and countless other languages have checked errors.
|
| There is nothing wrong with checked exceptions and there is
| really no difference between a Result and a function with a
| checked exception. fn a() -> Result<String,
| SomeError> String a() throws SomeException
|
| The issue is not with checked exceptions but with Java's
| syntax. They have not given programmers the language syntax to
| easily deal with checked exceptions. You cannot easily escape
| them without boilerplate and they don't work correctly across
| lambdas. This is why Rust ships with ?; Swift has shipped with
| try!, try?; and Scala ships with try as an expression and is
| experimenting with checked exceptions that work across high
| order functions [0].
|
| Programmers across every language ecosystem are moving towards
| checked errors and away from unchecked runtime crashes. Even
| Kotlin, a language that shipped with unchecked errors, is
| planning on adding a form of checked error handling [1].
|
| [0] https://docs.scala-
| lang.org/scala3/reference/experimental/ca... [1]
| https://youtrack.jetbrains.com/issue/KT-68296
| exabrial wrote:
| > JTaccuino
|
| Shame the link is broken, looked fascinating!
| d_burfoot wrote:
| It's worth observing that languages significantly over time,
| usually for the better. I remember writing Java when it was slow
| and had no generics. Now it's one of the fastest languages, and
| has not just generics but also (simple) type inference, which
| cuts down significantly on boilerplate. The point is: if you have
| a foggy memory from ten years ago of hating some language, many
| of the problems may have now been fixed.
| mattgreenrocks wrote:
| It's hard to fault Java at this point: arguably the best
| runtime of them all from a perf perspective, great tooling from
| JetBrains, large, high-quality ecosystem whose quality far
| exceeds npm on average, and sealed classes as an acceptable sum
| type. My only remaining issue is how prevalent nulls are, but
| there's some work in progress on improving that. Until then,
| I'll prefer Kotlin slightly.
|
| Definitely one of those things where the comment section is
| only good at spouting ancient memes with little regard to the
| truth of them.
| Xeoncross wrote:
| > It's hard to fault Java at this point: arguably the best
| runtime of them all from a perf perspective
|
| The JVM is a massive memory sink compared to the tiny
| (actual) runtime in Go or the total absence of a VM or
| runtime in Rust or Zig. I allocate at least 5x more memory
| for Java tasks, but sometimes its more.
|
| Java is great compared to scripting languages or writing raw
| C, but not compared to modern compiled languages from a
| syntax (null, thrown exceptions, inheritance, etc..), library
| selection, CVE/security, memory usage or raw computer power
| perspective.
| pron wrote:
| Many times the "massive" memory sink is because people give
| the VM more memory than it actually needs (or they use the
| default, which is to take up to 25% of RAM whether or not
| it's really needed for the required performance). I.e.
| people will say a process "takes" 1gb, when the same
| program could run just as well if they tell it to use, say,
| 300mb. The more memory, the faster it could run. The GCs
| offered by the JVM are more advanced than Go's by a couple
| of tech generations (the Go-like GC was removed from the
| JVM when it was superseded by two generations of newer
| GCs), and memory consumption is already going down with
| compact object headers [1] and will go down even further
| with Valhalla.
|
| All in all, Go may take up _a little_ less memory for
| similar performance, but the JVM is more flexible (and more
| observable), offering you better performance if you need
| it. And the footprint will continue dropping, as it has
| done for years [2].
|
| C++, Zig, or Rust are not really an apples-to-apples
| comparison. Sure, they take up significantly less RAM, but
| their performance is more expensive per unit of effort, and
| it's not a one-time cost, either. It's a permanent tax on
| maintenance, not to mention Java's superb observability.
|
| Don't get me wrong -- I'm a fan of Zig, and C++ is the
| language I still program in most, but you can't really
| compare them to Java. Java makes you pay for certain things
| -- especially in RAM -- but you do get your memory's worth
| in exchange, and in a way that translates to pretty
| significant time and money. If you can't spare the memory
| as you're running in a constrained environment that's one
| thing, but if you can, it's all a matter of what you want
| to use it for: do you want to use it all just on data, or
| do you want to spare some to reduce maintenance
| costs/increase development speed and improve performance?
|
| BTW, I'm not sure what is actually meant by a "lack of
| runtime" for C++/Rust/Zig. They all have standard
| libraries, just like Java. Rust even has a (crude) GC in
| its runtime that most Rust programs use (and, like Java, it
| compiles down to a VM). I think what people mean is that
| compilation to native is typically AOT rather than JIT, but
| that has both pros and cons.
|
| [1]: https://openjdk.org/jeps/450
|
| [2]: E.g. https://openjdk.org/jeps/254
| needlesslygrim wrote:
| I'm interested by your characterisation of Rust. I assume
| 'crude GC' is a reference to Rc/Arc, but I would be
| interested to see some statistics for the claim most
| programs written in Rust use them extensively. Also,
| Rc/Arc arent a part of any Rust 'runtime', but rather the
| standard library, and are not available when they eould
| not be suitable for the target, e.g. UEFI. Moreover,
| rustc compiles to LLVM IR, but LLVM is not a JVM/CLR VM,
| and rustc is not the only Rust compiler (though the
| others are admittedly not production-ready yet).
| pron wrote:
| > I assume 'crude GC' is a reference to Rc/Arc, but I
| would be interested to see some statistics for the claim
| most programs written in Rust use them extensively.
|
| Yes, Rust's GC is used through Rc/Arc, and I never said
| it is used _extensively_ by most programs, only that most
| programs do use it. It is _because_ it is not used
| extensively that it can be crude and designed to minimise
| footprint rather than offer good performance.
|
| > Also, Rc/Arc arent a part of any Rust 'runtime', but
| rather the standard library
|
| What's the difference between a standard library and a
| runtime? In the three decades I've been programming,
| they've been used interchangeably. A language runtime
| means some precompiled-code that programs use but is not
| compiled directly from the program.
|
| > rustc compiles to LLVM IR, but LLVM is not a JVM/CLR VM
|
| I never said that LLVM was a JVM -- these virtual
| machines have very different instruction sets -- but like
| a JVM, LLVM is a VM, i.e. an instruction set for an
| abstract machine.
|
| Now, it is true that Rust is typically (though not
| always) compiled to native code AOT while Java code is
| typically (though not always) compiled to native code
| JIT, but I don't understand why that difference is stated
| in terms of having a runtime. One could have an AOT-
| compiled JVM (and, indeed, that exists) as well as a JIT-
| compiled LLVM (and that exists, too).
|
| It is also true that Rust programs can be compiled
| without a runtime (or a very minimal one) while Java
| programs can choose to have more or less in their
| runtime, but even the most minimal runtime is larger than
| the most minimal Rust runtime.
| whytevuhuni wrote:
| > What's the difference between a standard library and a
| runtime? In the three decades I've been programming,
| they've been used interchangeably.
|
| First of all, you're right. But despite its definition I
| think people tend to look at it differently.
|
| A runtime is generally thought of as a platform on top of
| which your code runs on; it needs to start first, and it
| manages your code. Or perhaps it runs in a side thread.
|
| A language that has a runtime is hard to embed into
| something via just the C ABI, because a function call
| wouldn't use just the standard platform calling
| convention; it would have to start that runtime, perhaps
| marshal the parameters into something supported by that
| runtime, and then finally the runtime runs your
| function's code.
|
| Take for example cgo, for which you'd need to start the
| garbage collector first (among other things), hence why
| the cgo FFI is expensive. Take as another example an
| async Rust function, which would require e.g. a Tokio
| runtime to be started first. Another example is Java, for
| which you'd have to start the whole JVM first.
|
| A language that has no runtime, or a minimal runtime, can
| be called via the C ABI directly. All the function needs
| is to follow the calling convention, and then its code
| starts running immediately.
|
| This is just my opinion of other people's opinions, I may
| be wrong.
| pron wrote:
| > A runtime is generally thought of as a platform on top
| of which your code runs on
|
| That's not a well-defined thing.
|
| > A language that has a runtime is hard to embed into
| something via just the C ABI, because a function call
| wouldn't use just the standard platform calling
| convention
|
| But Java can be embedded in native code or embed native
| code. It has a specified FFI in both directions.
|
| > Take for example cgo, for which you'd need to start the
| garbage collector first (among other things), hence why
| the cgo FFI is expensive.
|
| Well, Java doesn't quite work like that, and its (new)
| FFI is free in most important cases (i.e. same as a non-
| inlined C-to-C call). Also, "starting the garbage
| collector" is not well-defined. What "starts" Rust's
| garbage collector?
|
| I understand what you're trying to get at, but things
| aren't so simple. There are, indeed, differences
| especially around JIT vs AOT, but it's not as simple as
| saying "having a runtime" or not, nor is everything
| similar in all languages (Rust and C don't work the same
| vis-a-vis the C ABI, and Java, C#, and Go interop with
| native code are all quite different from each other).
|
| > A language that has no runtime, or a minimal runtime,
| can be called via the C ABI directly.
|
| A Java program can easily expose any method via the C ABI
| to be called directly if the process has been started
| from Java -- i.e. it's easy for Java code to give native
| code a function pointer to Java code. Going the other
| way, i.e. embedding Java in a C program, is somewhat more
| involved, but even C++'s interop with C, not to mention
| Rust or Zig, is not always straightforward. Like in Java,
| certain functions need to be marked as "C-interopable".
| whytevuhuni wrote:
| > But Java can be embedded in native code or embed native
| code. It has a specified FFI in both directions.
|
| Most languages have an FFI, but I am talking specifically
| about the C ABI and the platform calling convention; or
| more specifically, about starting from scratch, and what
| is necessary to do from there until your code can finally
| run.
|
| Anything more complex than the C ABI is what makes people
| say there is a runtime. It's some layer between your code
| and the other language's code, inserted there by your
| language. There's usually no way to remove it, and if
| there is, it severely limits the language features you
| can use.
|
| > What "starts" Rust's garbage collector?
|
| Nothing; it doesn't start unless the function itself
| wants to start one, and the function can choose which one
| to start, through your code (rather than what the
| language's required runtime provides).
|
| > A Java program can easily expose any method via the C
| ABI to be called directly if the process has been started
| from Java
|
| In that case, the runtime has already been started, and
| is being reused.
|
| > Going the other way, i.e. embedding Java in a C
| program, is somewhat more involved
|
| That part is the most important part, and is generally
| why people say Rust has a minimal runtime; it can be
| embedded with very little setup. The code you write
| starts executing almost immediately. Java calling C may
| add a management layer on Java's side, but
| C/C++/Rust/Zig/etc need very little (hence, minimal
| runtime).
| pron wrote:
| > Anything more complex than the C ABI is what makes
| people say there is a runtime.
|
| But Rust (or Zig, or C++ for that matter) don't use the C
| ABI, either, except for specifically annotated functions.
|
| > In that case, the runtime has already been started, and
| is being reused.
|
| True, but I'm trying to say that the notion of "starting"
| the runtime (or the GC for that matter) is not really
| well-defined. HotSpot does need to be "started", but,
| say, Graal Native Image, which is sort of an AOT-
| compiled, statically linked JVM, isn't really "started".
|
| > Java calling C may add a management layer on Java's
| side, but C/C++/Rust/Zig/etc need very little (hence,
| minimal runtime).
|
| In some implementations of Java this may be the case in
| some situations, yes. I would go further and say that
| that's the _typical_ case, i.e. if you want to embed the
| stock HotSpot, you will need to call some initialisation
| functions.
|
| If that's what's meant by "runtime", then it's mostly
| correct, but it's more an implementation detail of
| HotSpot. Even without it there will remain more important
| differences between C++/Zig/Rust/C and Java, and this
| matter of "runtime" is not the most interesting aspect.
| For example, that Java is usually compiled JIT and Rust
| is usually compiled AOT is a bigger and more interesting
| difference.
| whytevuhuni wrote:
| > But Rust (or Zig, or C++ for that matter) don't use the
| C ABI, either, except for specifically annotated
| functions.
|
| Not only that, but Rust, C, Zig also require some setup
| before their `main()` can start as well.
|
| That is why people say they have a "minimal runtime",
| rather than "no runtime". There is still a bit of setup
| there, without which the languages cannot function, or
| can only function in a limited mode.
|
| Otherwise agreed on all your other points.
| neonsunset wrote:
| FWIW Cgo FFI is expensive not because of GC but because
| Go uses virtual threads (goroutines) and prioritizes the
| simplicity of runtime implementation. The lower bound of
| FFI cost in .NET is roughly equivalent to direct not-
| inlined calls in C, despite the GC support.
| mavelikara wrote:
| These other languages do not have the programing
| affordances of Java (generics, easy memory safety). Tooling
| is a big factor in favor of Java - IDEs, debuggers,
| observability etc. Also, the quality and availability of
| libraries is also a debatable point (although, it depends
| on the application at hand),
| Xeoncross wrote:
| I actually disagree with all of these points and I write
| Java at work.
|
| Memory safety isn't possible in Java (unlike Rust).
|
| Tooling: they all have debuggers and observability
| tooling (pprof, pprof-rs, etc..). Rust even has zed now.
|
| Libraries: Rust has really high quality packages. On the
| flip side, Go has almost everything built into the
| stdlib. Java requires a ton of third party packages of
| varying quality and guarantees even for basic things like
| logging or working with JSON. You have to constantly be
| on the lookout for CVE's.
|
| In fact, 75% of the cloud-native foundations projects are
| in Go. K8s and docker are Go. Go is much more web-app or
| microservice focused than Java is actually. Most Java
| apps are deployed into the cloud using Go.
|
| Meanwhile, Zig makes using the universe of C/C++ code
| easy.
|
| I highly recommend you try Zig, Rust, or Go out. They
| weren't created out of ignorance of Java, but because
| Java and C++ had areas that could be improved.
| pron wrote:
| Zig or Rust neither attempt to nor have any chance of
| directly competing with Java or any other high level
| language, other than on the margins (they have a hard-
| enough time competing with C++, which is unfortunate,
| because both are better than C++ -- Rust slightly so and
| Zig significantly so, IMO). They are for low-level
| development and target a domain where both the calculus
| of cost and value is vastly different from the high-level
| application space.
|
| It is usually just as easy to write a program in a low
| level language as it is in a high-level one, and this is
| true not only for Zig and Rust, but also for C++. Even in
| 1998 it was just as easy to write a program in C++ as it
| was in Java. But the maintenance later -- when you have a
| large 10-year-old codebase -- is significantly more
| costly, and necessarily so. In a low-level language, i.e.
| one where there's more direct control over memory
| management, how a subroutine uses memory may affect its
| callers. Whether the correct use in the caller is
| enforced by the language, as in Rust, or not always, as
| in Zig, changes in low-level languages require touching
| more code than in high-level ones, and can have a bigger
| impact.
|
| The low-level domain is, and will continue to be,
| extremely important. But the market share gap between
| low-level and high-level languages/domains has only grown
| over the past decades, and there are no signs of the
| trend reversing.
|
| Now Go is a different beast altogether, and is a high
| level language. But it has both pros and cons compared to
| Java. The tools it includes in the SDK are more user-
| friendly, but they, like the language, are less flexible
| and more limited than in the Java world. Nevertheless,
| the out-of-the-box experience is nicer, something we
| should definitely improve in Java, but you pay for that
| simplicity later in lost flexibility. Performance also
| isn't quite as good as Java's, and neither is
| observability.
| tonyg wrote:
| > Memory safety isn't possible in Java (unlike Rust).
|
| This is obviously some strange use of the phrase "memory
| safety" that I wasn't previously aware of.
| switchbak wrote:
| I agree with you on the memory sink side. For some kinds of
| applications the combo of startup time and memory
| consumption make it unsuitable - think of many small
| services or short-lived functions. Yes, Graal and such are
| amazing innovations, but they're very incomplete and poorly
| supported solutions and not something that's a good plan to
| bank your future on. This has limited our cloud deployment
| options to a significant degree, and I know I'm not alone.
|
| Being a memory hog was not such a big deal in the pre-cloud
| era, but we pay real money for that (far too much!) these
| days, and leaner approaches are worth a lot in real
| monetary terms.
|
| I wish push back on some of your other points. Java has
| evolved quite a lot lately, with improved syntax, much
| improved runtime (Loom!), better GCs, lots of libraries,
| etc. The community is a bit stale though, and it's viewed
| as the Oldsmobile of languages. But that old language still
| has a skip in it's step!
| throwaway03452 wrote:
| > The JVM is a massive memory sink
|
| Java tends to prefer using available memory, before it has
| to clean it. This results in memory usage growing more than
| it actually needs.
|
| Services often run in containers, so this is less than a
| problem today than it was before, because the allocated
| memory to the container is fixed anyway. Try configuring
| the JVM to only use 75% of the container memory. In many
| cases, it will trigger an early GC and run better with
| smaller memory instances
|
| There are of course some overhead for objects compared to
| primitives, but the Valhalla project is working to reduce
| the difference significantly on many cases.
|
| You can also reduce memory usage and startup time by
| compiling to a binary image
| mtrovo wrote:
| Few languages pull off the balancing act Java does, supporting
| decades of code while rolling out big new features like project
| Loom in a backward compatible way. Oracle's work really feels
| like a lesson in how to evolve a language.
| egeozcan wrote:
| I use Java/JavaScript/TypeScript at work but I do most of my
| scripting with .NET using LINQPad. Being able to use LINQ makes
| scripting so much easier.
|
| Python? Huge respect, huge ecosystem, however I don't know if
| it's just me but I find it mighty hard to read. PHP with the "->"
| and Python with the space-sensitivity... Not sure why but it's so
| hard for me to overcome.
| dominicrose wrote:
| PHP syntax does add to the line widths, so breaking long lines
| in multiple lines by extracting variables can help with
| readability. Using return, continue and break early reduces
| indentation so that helps too, as well as creating smaller
| functions.
|
| I use Ruby for scripting because it has a big standard library
| (unlike javascript) and an expressive syntax. The syntax is
| also very readable and short. It's also easy to install gems
| globally and use them. Things only need to be imported once.
|
| I wouldn't say these things are qualities for big projects
| though. I like Typescript for big projects.
| nprateem wrote:
| They should adopt the tag line for Java: "Not as bad as you
| remember"
|
| I was also surprised when I looked at it again a year ago.
|
| I would have used it for my latest Web app but django just beat
| Spring boot.
| riskable wrote:
| Have a look at any "mature" Java project on Github and you'll
| quickly come away with the opposite:
|
| "Wow! It's even worse than I remember!"
|
| "Wow! How many files and directories does this project NEED?
| It's like someone decided that it's easier to manage files than
| code..."
|
| ...and there's still XML everywhere :(
| brabel wrote:
| > As of Java 23, three methods are automatically imported from
| java.io.IO: println, print, readln
|
| I thought they had just hallucinated `java.io.IO`, but apparently
| it's a new type, available in Java 23 with --enable-preview:
| https://docs.oracle.com/en/java/javase/23/docs/api/java.base...
| mtrovo wrote:
| It looks like they took lots of inspiration from Kotlin with
| these new implicit imports and their structure.
| brabel wrote:
| Groovy and Scala already did that way before Kotlin.
| roncesvalles wrote:
| I just had this thought recently.
|
| Java is a fantastic "scripting" language as long as you're fine
| running it in an IDE. Clean and typed syntax, powerful standard
| library (especially for data structures), great performance. A
| better choice in these respects than say Python, Bash, or Go.
|
| I've used it for scrapers, Advent of Code, plain ole data munging
| and of course programming interviews.
|
| That being said, I would never write a webserver in Java in 2024.
| va1a wrote:
| > but the Python API isn't all that wonderful, and dynamic typing
| means that I spend too much time debugging
|
| I don't know, this just seems more like inertia. "I'd rather
| stick to what I know best than this popular thing." Which is
| fine, and I'm glad Java has made improvements making it easier to
| hit the ground running. But blaming the use of Java on the
| inadequacies of Python? The python API can do just about
| anything, it has regex toolings, I've never found myself needing
| anything else. And the typing complaints? Yeah it can be annoying
| if you're not good at keeping track of your own typing hints, but
| modern python supports type annotations and linters like mypy[1]
| catch everything related to that just fine. I've always admired
| many of Java's features, but let's not act like the reason for
| using Java for scripting is the pitfalls of Python. It's just
| because of an underlying preference for Java.
|
| 1. https://mypy-lang.org/
| BeefWellington wrote:
| > Yeah it can be annoying if you're not good at keeping track
| of your own typing hints
|
| If you write all the code you deal with, then sure. My
| experiences on big projects tend to be typing problems
| introduced by libraries. The kind where documentation and the
| decorators suggest it'll only ever return some specific value
| type, but then very occasionally it'll return a tuple of that
| value type and a message.
| va1a wrote:
| Fair, but in the context of scripting, which seems to be the
| focus of this article, how often are you dealing with complex
| library code? When I write scripts for file manipulation /
| simple automation, I'm usually not dealing with complex
| library objects. Plenty of os method calls, plenty of regex
| matches, but little else in this context. Big projects are
| another thing entirely. There's a plethora of reasons why you
| may want to use a different language for a certain project
| type. But it doesn't seem fair to imply that python is
| uniquely handicapped (or otherwise inferior to Java) for
| scripting and simple automation use-cases.
| pliuchkin wrote:
| As for my experience, nothing beats nodejs for fast scripting.
| Its literally just `npm install x y z` and then fire it up `$
| node script.js`. But Im giving Java a chance.
| bArray wrote:
| Spent a while trying to get (OpenJDK's) JShell to work, it seems
| like a buggy mess. I would currently not recommend using it for
| anything serious.
___________________________________________________________________
(page generated 2024-12-20 23:02 UTC)