POV-Ray : Newsgroups : povray.off-topic : Java is verbose Server Time
1 Nov 2024 03:15:54 EDT (-0400)
  Java is verbose (Message 1 to 8 of 8)  
From: Invisible
Subject: Java is verbose
Date: 10 Apr 2012 08:10:50
Message: <4f84234a$1@news.povray.org>
I realise this is a radical and controversial thing to say, but it is. :-P

Suppose, for example, that I wanted to implement a lambda expression 
interpreter. For those who don't know, a lambda expression has one of 
three possible forms:

   1. A variable name.
   2. A lambda function. This consists of a lambda, followed by a 
variable name, followed by an arrow, followed by any valid lambda 
expression.
   3. A function application. This consists of any two valid lambda 
functions, separated by an empty space.

Usually brackets are used to disambiguate when such expressions are 
written as text. But conceptually, the above exactly describes the form 
of a lambda expression.

Now, suppose we want to define a data structure for storing such 
expressions, and a way to convert one into text. (Converting /from/ text 
is obviously much harder.)

In Haskell:

   data Expression =
       Variable String                |
       Lambda   String     Expression |
       Apply    Expression Expression
     deriving Show

This defines our data structure. The final line tells the compiler to 
auto-generate the code for conversion to text. However, if you don't 
like the way the compiler's auto-generated code does it (and we don't, 
in this case), it's not hard to write it yourself:

   lambda_text :: Expression -> String
   lambda_text e =
     case e of
       Variable n   -> n
       Lambda   n e -> "λ " ++ n ++ " → " + lambda_text e
       Apply    e f -> lambda_text e ++ " " ++ lambda_text f

In reality, you /probably/ want to make it insert some brackets and 
stuff, but the above is the gist of it. If we remove the "deriving" 
line, we have a total of 10 lines of code here.

Now let's try the same thing in Java:

   public abstract class Expression {}

   public class Variable extends Expression
   {
     private String Name;

     public Variable(String n) {this.Name = n;}

     public String toString() {return this.Name;}
   }

   public class Lambda extends Expression
   {
     private String     Variable;
     private Expression Body;

     public Lambda(String v, Expression b)
     {
       this.Variable = v;
       this.Body     = b;
     }

     public String toString()
     {
       return "λ " + this.Variable.toString() + " → " + 
this.Body.toString();
     }
   }

   public class Apply extends Expression
   {
     private Expression LHS, RHS;

     public Apply(Expression l, Expression r)
     {
       this.LHS = l;
       this.RHS = r;
     }

     public String toString()
     {
       return this.LHS.toString() + " " + this.RHS.toString();
     }
   }

If your screen is anything like mine, that lot doesn't even fit on one 
page. This is /a lot/ of code. And yet it doesn't even "do" anything, as 
such. It just lets you construct data structures, and print them out. 
The same thing as the 10 lines of Haskell code did. I count 44 lines. 
Or, if you're feeling generous, 36 non-blank lines. And I even tried to 
scrunch Lambda.toString() onto one line, even though it's really too big.

Now suppose that, for some strange reason, I want to be able to check 
whether two expressions are the same. (Realistically, I can't think why 
you'd want to do that for anything except variables.) In Haskell, I can 
simply append "deriving Eq", and the compiler will write the code for me 
in the obvious way. In this instance, it does the right thing. In 
Java... well OK, I'll go easy on Java and only write the code for 
Variable. Here goes:

   public class Variable extends Expression
   {
     private String Name;

     public Variable(String n) {this.Name = n;}

     public String toString() {return this.Name;}

     public boolean equals(Object obj)
     {
       if (obj == null) return false;

       if (obj instanceof Variable)
       {
         Variable v = (Variable) obj;
         return this.Name.equals(v.Name);
       }

       return false;
     }

     public int hashCode() {return this.Name.hashCode() + 9;}
   }

OK, so only 14 lines of actually new code. The hashCode() override is 
not /strictly/ necessary, but the IDE whines like hell if you don't, and 
it's highly likely that you're going to put variables as keys into a 
HashMap at some point, in which case hashCode() had better work correctly!

In Haskell, you can simply say

   e `equals` f =
    case (e, f) of
      (Variable x, Variable y) -> x == y

and you're done.

In Java, you have to check whether the argument is null. (Impossible in 
Haskell.) You have to check whether the argument is of a comparable 
class. (Haskell's static type checking does that for you at 
compile-time. Actually Java's generics could do that too if they 
extended it a teeny weeny bit... but they haven't.) Then you have to 
actually type-cast it. (Unnecessary in Haskell due to static checking.) 
Then, and only then, can you do the actual test. But because it's Java 
and it sucks, you can't just say this.Name == v.Name; that would do a 
pointer comparison, not a string comparison. So you must instead do 
this.Name.equals(v.name), which is obviously far more readable. :-P

On the plus side, the IDE will generate some of this code for you. On 
the minus side, you still have to /read/ it. And perhaps the worst thing 
about the above Java code isn't that it's 44 lines, but that it's in 4 
separate files, when /obviously/ it's notionally a single entity. (Then 
again, I think if you make the classes private - excuse me, "package 
scope" - then they may all be put in one file.)

In consequence to the above, I just spent an entire morning coding in 
Java, and all I actually have to show for it is a boat-load of classes 
which can hold data and generate a graphical representation of 
themselves. They have no actual /behaviour/ yet. It's taken me this long 
just to do that... Man, Java is a blunt knife! (But oh so hard to hurt 
yourself with... yeah, right!)


Post a reply to this message

From: Invisible
Subject: Re: Java is verbose
Date: 10 Apr 2012 08:16:32
Message: <4f8424a0@news.povray.org>
On 10/04/2012 01:10 PM, Invisible wrote:

> OK, so only 14 lines of actually new code. The hashCode() override is
> not /strictly/ necessary, but the IDE whines like hell if you don't, and
> it's highly likely that you're going to put variables as keys into a
> HashMap at some point, in which case hashCode() had better work correctly!

Also, the IDE complains if you don't write "@Override" in front of every 
method that overrides an inherited one. I don't know why. (And I'm not 
actually sure how that's valid Java syntax, come to mention it...)

This /does/ have the nice side-effect that if you rename the method in 
the superclass or something, the IDE starts yelling "hey, this says 
@Override, but it doesn't!"


Post a reply to this message

From: nemesis
Subject: Re: Java is verbose
Date: 10 Apr 2012 09:57:50
Message: <4f843c5e@news.povray.org>
Em 10/04/2012 09:10, Invisible escreveu:
> Suppose, for example, that I wanted to implement a lambda expression
> interpreter.

I don't think most java programmers would want that. :p

but kudos for installing and configuring netbeans just for that... :)


> In reality, you /probably/ want to make it insert some brackets and
> stuff

you really can't spell parenthesis, huh? ;)


> , but the above is the gist of it. If we remove the "deriving"
> line, we have a total of 10 lines of code here.
>
> Now let's try the same thing in Java:
>
> public abstract class Expression {}
>
> public class Variable extends Expression
> {
> private String Name;
>
> public Variable(String n) {this.Name = n;}
>
> public String toString() {return this.Name;}
> }
>
> public class Lambda extends Expression
> {
> private String Variable;
> private Expression Body;
>
> public Lambda(String v, Expression b)
> {
> this.Variable = v;
> this.Body = b;
> }
>
> public String toString()
> {
> return "λ " + this.Variable.toString() + " → " + this.Body.toString();
> }
> }
>
> public class Apply extends Expression
> {
> private Expression LHS, RHS;
>
> public Apply(Expression l, Expression r)
> {
> this.LHS = l;
> this.RHS = r;
> }
>
> public String toString()
> {
> return this.LHS.toString() + " " + this.RHS.toString();
> }
> }
>
> If your screen is anything like mine, that lot doesn't even fit on one
> page. This is /a lot/ of code.


Java is very obviously verbose, and it doesn't help when people even go 
further and write damn "public" all over in every occasion!

class Apply?  Really?  The name itself and the behaviour conveying an 
action shouldn't be best served as methods of Expression?


> And yet it doesn't even "do" anything, as
> such. It just lets you construct data structures, and print them out.
> The same thing as the 10 lines of Haskell code did. I count 44 lines.
> Or, if you're feeling generous, 36 non-blank lines. And I even tried to
> scrunch Lambda.toString() onto one line, even though it's really too big.

Now try to write an object system in haskell.


> Now suppose that, for some strange reason, I want to be able to check
> whether two expressions are the same. (Realistically, I can't think why
> you'd want to do that for anything except variables.) In Haskell, I can
> simply append "deriving Eq", and the compiler will write the code for me
> in the obvious way. In this instance, it does the right thing. In
> Java... well OK, I'll go easy on Java and only write the code for
> Variable. Here goes:
>
> public class Variable extends Expression
> {
> private String Name;
>
> public Variable(String n) {this.Name = n;}
>
> public String toString() {return this.Name;}
>
> public boolean equals(Object obj)
> {
> if (obj == null) return false;
>
> if (obj instanceof Variable)
> {
> Variable v = (Variable) obj;
> return this.Name.equals(v.Name);
> }
>
> return false;
> }
>
> public int hashCode() {return this.Name.hashCode() + 9;}
> }
>
> OK, so only 14 lines of actually new code. The hashCode() override is
> not /strictly/ necessary, but the IDE whines like hell if you don't, and
> it's highly likely that you're going to put variables as keys into a
> HashMap at some point, in which case hashCode() had better work correctly!
>
> In Haskell, you can simply say
>
> e `equals` f =
> case (e, f) of
> (Variable x, Variable y) -> x == y

as far as I can tell, this is not the same code as the java one:  you're 
not checking here if the variables have the same name too, only if they 
are instances of the same type.

>
> and you're done.
>
> In Java, you have to check whether the argument is null. (Impossible in
> Haskell.)

it's about the same as checking for an empty list.

BTW, that check could be at the base class in an ancestor method.  But 
you wrote it as abstract for whatever reason...


> You have to check whether the argument is of a comparable
> class. (Haskell's static type checking does that for you at
> compile-time. Actually Java's generics could do that too if they
> extended it a teeny weeny bit... but they haven't.)

I'm sorry, but if you wanted at least some type checking in java, 
shouldn't you do:

public boolean equals(Expression obj)

instead of

public boolean equals(Object obj)

?

The compiler then would warn you whenever you passed something like 
exp.equals(2) (which, yes, reads kinda weird since a number literal like 
that should be an expression after all).  Then again, even as is it 
already should warn you, since it expects an instance of Object...


> In consequence to the above, I just spent an entire morning coding in
> Java, and all I actually have to show for it is a boat-load of classes
> which can hold data and generate a graphical representation of
> themselves. They have no actual /behaviour/ yet. It's taken me this long
> just to do that... Man, Java is a blunt knife! (But oh so hard to hurt
> yourself with... yeah, right!)

all in all, it read like object oriented code from a C programmer...

now, I'm not a java programmer nor enjoy it.  But people frequently 
enjoy making it sound actually worse than it is.


Post a reply to this message

From: Invisible
Subject: Re: Java is verbose
Date: 10 Apr 2012 10:33:29
Message: <4f8444b9$1@news.povray.org>
>> Suppose, for example, that I wanted to implement a lambda expression
>> interpreter.
>
> I don't think most java programmers would want that. :p

And I care because...? ;-)

> but kudos for installing and configuring netbeans just for that... :)

Well, not /just/ for that. It was the smallest example I could think of 
off the top of my head. The /real/ application I'm trying to build would 
take way longer to explain.

>> In reality, you /probably/ want to make it insert some brackets and
>> stuff
>
> you really can't spell parenthesis, huh? ;)

I really can't *pronounce* that out loud, no.

Besides, why use 7 syllables when 2 will do? ;-)

>> Now let's try the same thing in Java:

>> If your screen is anything like mine, that lot doesn't even fit on one
>> page. This is /a lot/ of code.
>
> Java is very obviously verbose, and it doesn't help when people even go
> further and write damn "public" all over in every occasion!

It's part of the language syntax. (Amusingly, you're not actually 
/allowed/ to declare a class as private...)

> class Apply? Really? The name itself and the behaviour conveying an
> action shouldn't be best served as methods of Expression?

It denotes an expression where a function is applied to an argument. 
It's part of the parse tree. It's data. That's what an object is 
supposed to be: data.

Now, if this was an airline booking system, and somebody wrote a class 
implementing the process of applying for a ticket, then, yuh, that's not 
a sensible design. That's an action. Objects aren't supposed to be actions.

> Now try to write an object system in haskell.

That's not even hard. :-P

Functions are first-class, right? So you can create a "class" which is 
simply a data structure that contains "methods" as fields with function 
types. The result is something like JavaScript's notion of objects.

Or, if you don't want to do it that way, you can use Haskell's existing 
type-class system to do it more naturally. Even mutable objects aren't 
especially hard. And the module system easily gives you public and 
private methods and fields.

Dynamic upcasts and downcasts are a bit more work. You can use 
Data.Dynamic to implement that. And Haskell already has "generics" out 
of the box. :-P Even multiple inheritance is no real problem. (Or at 
least, implementing multiple interfaces. Actually /inheriting/ stuff 
without implementing it more than once is mildly harder.)

In short, it's not hard to implement a weak language in a stronger one. 
Try implementing a Pascal compiler in 1980s era BASIC. Good luck with 
that. Now try implementing a BASIC interpreter in Pascal. Pretty easy, 
isn't it?

>> Now suppose that, for some strange reason, I want to be able to check
>> whether two expressions are the same.

>> OK, so only 14 lines of actually new code. The hashCode() override is
>> not /strictly/ necessary, but the IDE whines like hell if you don't, and
>> it's highly likely that you're going to put variables as keys into a
>> HashMap at some point, in which case hashCode() had better work
>> correctly!
>>
>> In Haskell, you can simply say
>>
>> e `equals` f =
>> case (e, f) of
>> (Variable x, Variable y) -> x == y
>
> as far as I can tell, this is not the same code as the java one: you're
> not checking here if the variables have the same name too, only if they
> are instances of the same type.

Wrong.

"e" and "f" are lambda expressions. If they are both variables, then "x" 
is the variable name of "e", and "y" is the variable name of "f". The 
line "x == y" does what you'd imagine it does - i.e., it checks whether 
the names are the same.

>> In Java, you have to check whether the argument is null. (Impossible in
>> Haskell.)
>
> it's about the same as checking for an empty list.

Except that, when you're not dealing with a list, then you never have to 
worry about it being empty, do you? :-P

> BTW, that check could be at the base class in an ancestor method. But
> you wrote it as abstract for whatever reason...

I'm not even sure what that's supposed to mean.

>> You have to check whether the argument is of a comparable
>> class. (Haskell's static type checking does that for you at
>> compile-time. Actually Java's generics could do that too if they
>> extended it a teeny weeny bit... but they haven't.)
>
> I'm sorry, but if you wanted at least some type checking in java,
> shouldn't you do:
>
> public boolean equals(Expression obj)
>
> instead of
>
> public boolean equals(Object obj)
>
> ?

Unfortunately, Object.equals() is defined to take Object as a parameter, 
not any more specific subclass. So, no, you can't do that.

(Or rather, you can, but now you're not overriding Object.equals(), 
you're just creating a new, unrelated method of your own.)

> The compiler then would warn you whenever you passed something like
> exp.equals(2) (which, yes, reads kinda weird since a number literal like
> that should be an expression after all).

Have your forgotten? This is Java. 2 is not an object. Therefore it can 
never be passed to something expecting Object.

>> Man, Java is a blunt knife! (But oh so hard to hurt
>> yourself with... yeah, right!)
>
> all in all, it read like object oriented code from a C programmer...

...which is ironic, given how hopeless I am at C. :-P

Seriously, I know how to write object-oriented code. I've been doing it 
for years. I have certificates to prove it. I'm just saying, Java makes 
everything /so/ much work, it takes forever to actually get anything done.

> now, I'm not a java programmer nor enjoy it. But people frequently enjoy
> making it sound actually worse than it is.

Right now I'm only talking about real, actual problems that I'm running 
into right now as I try to write my code.

I almost feel like I should be writing a "compiler" that takes the 
3-line version saying what data structure I want, and generates the 
5-file 44-line monstrosity that the Java compiler expects. It would save 
me a bunch of typing, and then I could go in and write the actual code 
that turns it into more than just a dumb data structure...


Post a reply to this message

From: Darren New
Subject: Re: Java is verbose
Date: 10 Apr 2012 21:02:42
Message: <4f84d832$1@news.povray.org>
On 4/10/2012 7:33, Invisible wrote:
> Have your forgotten? This is Java. 2 is not an object. Therefore it can
> never be passed to something expecting Object.

At least they figured out auto-boxing 95% of the way.

> I almost feel like I should be writing a "compiler" that takes the 3-line
> version saying what data structure I want, and generates the 5-file 44-line
> monstrosity that the Java compiler expects. It would save me a bunch of
> typing, and then I could go in and write the actual code that turns it into
> more than just a dumb data structure...

Ah, good old code generation. Hope you don't have to track down a bug in the 
generated code anywhere.


-- 
Darren New, San Diego CA, USA (PST)
   "Oh no! We're out of code juice!"
   "Don't panic. There's beans and filters
    in the cabinet."


Post a reply to this message

From: Invisible
Subject: Re: Java is verbose
Date: 11 Apr 2012 04:48:15
Message: <4f85454f$1@news.povray.org>
>> I almost feel like I should be writing a "compiler" that takes the 3-line
>> version saying what data structure I want, and generates the 5-file
>> 44-line
>> monstrosity that the Java compiler expects. It would save me a bunch of
>> typing, and then I could go in and write the actual code that turns it
>> into
>> more than just a dumb data structure...
>
> Ah, good old code generation. Hope you don't have to track down a bug in
> the generated code anywhere.

Well, there's code generation, and there's code generation.

It depends whether you're using a generator to quickly build a skeleton 
for you to fill in, or whether you're using a generator so that you can 
code in the source language and not the destination one. ;-)


Post a reply to this message

From: Invisible
Subject: Re: Java is verbose
Date: 26 Apr 2012 10:07:27
Message: <4f99569f$1@news.povray.org>
On 10/04/2012 03:33 PM, Invisible wrote:

> Objects aren't supposed to be actions.

...and then I saw this:

http://docs.oracle.com/javase/tutorial/uiswing/misc/action.html

As an aside, if anybody thinks *Haskell* is hard, try frigging 
understanding the Java APIs! That stuff is just *insane*... >_<


Post a reply to this message

From: Invisible
Subject: Re: Java is verbose
Date: 7 Jun 2012 08:08:29
Message: <4fd099bd@news.povray.org>
>> but kudos for installing and configuring netbeans just for that... :)
>
> Well, not /just/ for that. It was the smallest example I could think of
> off the top of my head. The /real/ application I'm trying to build would
> take way longer to explain.

The real application, obviously, was Logic Box. ;-)


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.