Hacker News new | ask | show | jobs
by Unosolo 4469 days ago
The essence of the argument here is that Java is a poor language as it doesn't offer simple abstraction to copy standard input into standard output; that Java is too verbose and low-level for the task.

The lack of direct abstraction is not a valid argument, because as a programmer, you shouldn't be writing the logic in Java, Python, C or Scala but rather a higher order domain language implemented in the chosen host language and that's what the process of programming is all about. For the majority of real world programming tasks it's unlikely that a language that fits the domain perfectly already exist, so you have to create one.

In Java one can say:

    copyStream(System.in,System.out);
And then one will have to implement copyStream but only once:

    long copyStream (InputStream src,OutputStream dst) throws IOException {             
        long bytesCopied;
        byte[] buffer = new byte[8192];
        int bytesRead = src.read(buffer);        

        while(bytesRead!=-1) {
            bytesCopied+=bytesRead;
            dst.write(buffer, 0, bytesRead);
            bytesRead = src.read(buffer);
        }

        return bytesCopied;
    }
I prefer programmers taking this approach of implementing domain specific language first and then expressing the logic in its terms instead of trying to express higher order concepts without resorting to available host language abstractions.

Let's say Python or Perl let one express stream copying more concisely straight out of the box. However when faced with real life programming challenges one will very quickly encounter limits of what a language can express out of the box with one-liner. But as a programmer one has the power to create one-liners from scratch!

Disclaimer: I am not a Java expert, so the code above is just to illustrate the idea based on my very limited knowledge of Java.

1 comments

Two things.

First, constantly having to write implementations like this introduces a ton of friction as compared with reusing existing implementations. Languages do have an influence on that.

Second, languages vary in "expressiveness," determining how much code you have to write in order to make an implementation like this. In one language, copying stdin to stdout fits into a natural idiom which also handles other cases naturally. In another language with less care for ergonomics, every task might be equally un-idiomatic.

In other words, a language can offer its own "higher order domain languages" for the core tasks that everyone is doing over and over again as part of their general programming. Or it can choose not to do that, because what it offers is already Turing complete. But then the ergonomics are bad, and it makes a real difference.

It seems wrong that when I am paying for things like long JIT warmups and stop-the-world GC, I am still writing piles of functions with low-level idioms that are no more expressive than C's.

If Java ships with a 'copy from one stream to another' primitive then I'd find that a much more compelling argument than that I can treat myself to reimplementing things like stream copying, sorting and basic data structures on a regular basis. It's unbelievably tedious and wasteful to do this, there's just no reason.

Agree, in Java (and any other language) the main culprit is not the complexity that can eventually be abstracted away, but the trivial noise that cannot be abstracted at all: verbose class definitions, clumsy anonymous functions prior to SE8 (functors), lack of implicit interfaces, lack of infix method call notation, generic type erasure, lack of basic type inference, lack of continuations etc.

My point was that limited expression means of a language are sometimes compounded by inability of a programmer to make a good use of the expression means already available to them.

I also understand the desire for more a expressive language, I am a programmer after all. One has to keep in mind, however, that the more expressive a language is the harder it is on the reader. Java code is trivial for a reader to follow (if not for the excessive verbosity sometimes covering up the true intent); much of Scala code base, on the other hand, is not that trivial to comprehend due to the high expressiveness of the language.