views:

597

answers:

9

Not using operators makes my code obscure.

(aNumber / aNother) * count

is better than

aNumber.divideBy(aNother).times(count)

After 6 months of not writing a single comment I had to write a comment to the simple operation above. Usually I refactor until I don't need comment. And this made me realize that it is easier to read and perceive math symbols and numbers than their written forms.

For example

TWENTY_THOUSAND_THIRTEEN.plus(FORTY_TWO.times(TWO_HUNDERED_SIXTY_ONE))

is more obscure than

20013 + 42*261

So do you know a way to get rid of obscurity while not using operator overloading in Java?

Update: I did not think my exaggeration on comments would cause such trouble to me. I am admitting that I needed to write comment a couple of times in 6 months. But not more than 10 lines in total. Sorry for that.

Update 2: Another example:

budget.plus(bonusCoefficient.times(points))

is more obscure than

budget + bonusCoefficient * points

I have to stop and think on the first one, at first sight it looks like clutter of words, on the other hand, I get the meaning at first look for the second one, it is very clear and neat. I know this cannot be achieved in Java but I wanted to hear some ideas about my alternatives.

A: 

You cannot overload operators in Java, and there's no way around it.

You could use a Java-like alternative JVM language. Groovy is one that is probably closer to Java itself than other JVM languages. See Operator overloading in Groovy.

Jesper
Scala can be written in a near identical manner to Java, while allowing you to branch out into functional programming. Also, James Strachan (creator of Groovy) said that if some had shown him "Programming in Scala" in 2003, he would never have created Groovy <http://macstrac.blogspot.com/2009/04/scala-as-long-term-replacement-for.html>.
geowa4
A: 

There is no way to overload operator in Java. Why don't you switch to C#?! =)

Or try to write shorter named methods in Java:

aNumber.div(aNother).mul(count)
Cipi
switching to C# is not feasible in most applications or most workplaces. especially when there are other jvm languages that can integrate with your existing code.
geowa4
+3  A: 

I had a while ago a similar requirement for using BigInteger. It depends what kind of performance sacrifice you want to do:

For the test code ( no performance requirement ) I created a parser:

Parser.execute("20031 + 42*261");

For the production code I tried to use a clever builder:

ExpressionBuilder e = new ExpressionBuilder();
e.add(20031,e.mul(42,261)).solve();

But at the end of the day, people tends to become quite used to dumb code and even prefer it: you don't have operator overload in jave so live with it and don't try to create "clever" abstraction.

BigInteger a = new BigInteger(20031);
BigInteger b = new BigInteger(42);
BigInteger a = new BigInteger(261);

BigInteger res = a.plus(b.times(c));

Anyway, check whatever works with your team.

EDIT: I didn't comment specifically on your example. But obviously calling 42,FORTY_TWO is not making the code very clear regardless your approach. Chosing proper name for the constant goes a long way clarifying the code:

BigInteger dailyOperatingCost = OFFICE_RENTAL.plus( CONTRACTOR_NUMBER.times(CONTRACTOR_RATE);
vdr
+2  A: 

In Java just get over it, and use the method names as BigInteger as a standard so you get used to them.

Or take a look at Scala.

At least that's what I do.

starblue
A: 

If you're just dealing with numeric values, the standard wrapper classes (Integer, Double, etc) will be automatically unboxed to their primitive types when used in expressions. The following is perfectly valid:

  Integer five = new Integer(5);

  Integer ten = new Integer(10);

  System.out.println(five * ten);

  System.out.println(ten / five);
Fredrick Pennachi
Unfortunately I am dealing with other classes that I wrote :)
nimcap
+2  A: 

I think we all can be very happy, that operator overloading is not supported at all in java.

Frame myFrame = new Frame() + myButton + new JList() / new Separator() - 50;

Who wants to maintain such thing?

pimpf0r
yes I know operator overloading can be abused, but sometimes that is the right thing you need. Any feature can be abused nonetheless.
nimcap
This is a fallacious argument... it's like saying that you're very happy not to have a driver's license because driving a car can kill you. Any powerful language feature can be abused...
Jesper
The real advantage is that *others* don't have a driving license to kill me. One advantages of Java is that it lacks many dangerous features.
starblue
+1  A: 

I like vdr's idea about the language. But you can skip on parsing and build a really simple eval. Here's a stack based eval. Put together in 15 min, and far from perfect, but you get the idea.

import java.util.*;
import java.math.BigInteger;

public class BigEval {

  private static abstract class Op{
    abstract void apply(LinkedList<BigInteger> stack);
  }

  private static Map<Character, Op> charToOp = new HashMap<Character, Op>();

  static {
    Op plus = new Op() {
      void apply(LinkedList<BigInteger> stack) { stack.push(stack.pop().add(stack.pop())); }
    };
    Op mult = new Op() {
      void apply(LinkedList<BigInteger> stack) { stack.push(stack.pop().multiply(stack.pop())); }
    };
    Op dup = new Op() {
      void apply(LinkedList<BigInteger> stack) { stack.push(stack.peek()); }
    };

    charToOp.put('+', plus);
    charToOp.put('*', mult);
    charToOp.put('d', dup);
  }


  public static BigInteger eval(Object ... expression){
    return eval(new LinkedList(Arrays.asList(expression)), new LinkedList());
  }

  private static BigInteger eval(LinkedList expression, LinkedList<BigInteger> stack){
    while (expression.size()>0){
      Object next = expression.pop();
      if (next instanceof BigInteger){
        stack.push((BigInteger)next);
      } else if (next instanceof Number) {
        stack.push(BigInteger.valueOf(((Number)next).longValue()));
      } else {
        charToOp.get(next).apply(stack);
      }
    }
    return stack.pop();
  }

  public static void main(String[] args) {
    System.out.println(
      BigEval.eval(3, 4, '+', 5, '*')
    );
  }

} // end of class
z5h
I like this idea. Your solution reminds me of some of the simple, elegant solutions from my CS classes so long ago. It is easy to get distracted by 'XML-this' and 'web-that' of today. I think your solution would be ultimately more readable and maintainable as it is a general-purpose solution to the scale of this problem.
monceaux
A: 

The easiest way is probably by assigning subexpressions to variable with meaningful names.

   discriminant = b.times(b).plus(four.times(a).times(c));

You may even want to calculate bsquared and ac4 (fourac?) too.

This functions as meaningful comments plus it keeps the length of your source lines down.

Thorbjørn Ravn Andersen
A: 

I was like you, I now find the class names to be a handy documentation so as to do self-documenting code. You're gonna have to work your own way out of the difficulties consequent to the comment markers as that is established practice in Java. As for where your intentions seeks, what that ends up with is sort of a cloud. Now if I were anywhere close to information that has to be protected, the absolute last thing I want is to have customer's data being passed into a cloud by small, tight code. I expand everything, working from post-processor in C and working in native calls for anything in Java that I am actually intent on protecting.

What I see in your original post, though not to take sides, is something where a rather massive code effort can be called thus:

doIt();

Which woe be unto the damnned, is not only asking for candy-code and doing it, but for sure would go nowhere at massive parallel systems running critical code unless you wrote both the compiler and the security domain on which the above runs. I am not being, nor intend on being, even slightly facetious - trust is something you read about on the 6-pm news, and is loved by your competitors who want to take your lunch away from you. There are dozens of languages that do what you ask, why are you asking it in a Java discussion?

Maybe it's time to intro on a linguistic that does that == there are no shortage of api's and supporters thereof that do that. Code should be self-documenting, for Java that's class name as what it does name.

Nicholas Jordan