5 ms·
Java (at least prior to Java 7), has some severe limitations in how code can be abstracted. As an example, it doesn't allow you to pass functions as arguments t
by T-R 13y ago
Java (at least prior to Java 7), has some severe limitations in how code can be abstracted. As an example, it doesn't allow you to pass functions as arguments to other functions directly. As a result, the canonical way to handle situations where you would do this (such as passing a comparison operator to a sort function), is to declare an interface, define the function in a class that implements that interface (command pattern, etc.), and then instantiate an instance of the class and pass that. Closures are imitated by explicitly passing data to class constructors and storing it in member variables, and currying imitated through patterns like the onerous abstract factory pattern.
Additionally, the abstraction features Java does offer are implemented with some heavy language syntax, and often can't be generated at runtime or pre-compile time, at least not easily, and so there's a limit to the abstraction, even taking into account Java Generics. That's something where homoiconic languages like Clojure have a particular advantage.
As a result, abstracting things in these ways (which in other languages is incredibly common) gets to be painfully verbose. Often, things that would be beautifully abstracted in these ways are just left unabstracted (as in-line boilerplate) - the verbosity introduced makes the code less readable, rather than more, and so there's a stigma against "over-abstracted" code. The result is that code that does, or could, make use of these things takes exceedingly more code in Java than in a language like Clojure. Of course, conventions in Java of, e.g., giving each curly brace its own line aren't helping its case in line counts, either.
- thaumasiotes 13y ago> Of course, conventions in Java of, e.g., giving each curly brace its own line aren't helping its case in line counts, either. My comment is basically a free-association from this. In C and Java both (and, um, CSS), the people I've encountered seem to strongly prefer giving each matched pair of curly braces one line (that is, the opening { doesn't get its own line, but the closing } does). In lisps (to my knowledge) it's more normal to have all your closing )s stuck together at the end of the previous line. Using a clump of )))))s to discern exactly which scope you're in afterwards is tricky (I'm pretty sure that's exactly the "problem" that the C/Java style is trying to solve), so you look at the indentation instead. Python formalized the indentation-is-scope paradigm, which means a malicious programmer can't trick you into believing you're looking at a different scope than you are, but my Python code always ends up being a lot taller than I feel it should be, so I have a lingering sense that Python took it a little too far. It turns out that I occasionally appreciate the option you get with lisps to put a short bit of code all on one line and mark the parse tree with parens instead of with line-breaks-plus-indentation. (All that said, I do like Python a lot.)
- prof_hobart 13y agoAs we're already off-topic, I'll chip in with my view. I personally hate the opening { stuck on the end of the line in C/Java. For me it goes on a line on its own pretty much every time. I've lost count of the amount of times there's been a subtle bug introduced by incorrect scope as a result of a { being missed from the end of a line and not being noticed due to the code being formatted as if it was there. With a { sat on its own, directly lining up with the }, that's pretty much impossible to miss.
- _pmf_ 13y ago> I personally hate the opening { stuck on the end of the line in C/Java. It's an abomination.
- krapp 13y agoI've always put it on the end of the line and found it easier to parse visually than when its on a separate line. To me that just seems like a waste of space.
- prof_hobart 13y agoHow do you quickly check to make sure that all of your closing braces match up with the relevant opening brace, rather than, for example, an if statement that you forgot to put the { on? Hopefully the formatting will work for this - For example, if (isOK) for(thing in list { doSomething(thing); } } Screams out to me at very first glance that I've missed a {, whereas if (isOK) for(thing in list){ doSomething(thing); } } needs me to scan to the end of each conditional line to see where the problem is.
- krapp 13y agoFor me, it's the other way around.. the second instance is easier to spot because the visual cue of associating the block with the statement is more obvious if you assume beforehand that each statement has to end with the brace. As for closing braces, I associate them with the start of the statement itself (the if and for) and not the opening brace, assuming the indentation is consistent. I'm not arguing one is necessarily more right than the other - just that I prefer the way considered less right by consensus.