new MyClass(arg1, arg2).go();Better example showing some context:
new CustomerFactory().GetAllCustomers().BindTo(theCustomerGrid);Don't always need to keep the classes we create... Factory thrown away, customerCollection thrown away after calling BindTo... which was what we really wanted.
One place this idiom occurs is when a method has been refactored into a separate class (MethodObject). It is also used in main, to create an instance of the class and put it to work:
public class MyClass { public static void main (String[] args) { new MyClass().go(); } }It is also possible to have the constructor do all the work:
new MyClass();Discussion about why this is a Bad Idea can be found in ConstructorDoesTheWork.
C++ equivalent
MyClass(arg1, arg2).go();Java Drawback
If performance is an issue, ThrowawayObjects should maybe avoided. The object needs to be garbage collected, which takes time. See DontCreateGarbage.
new MyClass(arg1,arg2).go()certainly looks a bit misleading as it suggests setting up a mechanism (that's what constructors are for) and then setting it in motion, possibly independently ( that's what a method name like go() suggest). I don't understand why not:
myFunction._(arg1,arg2)_ can be a static method inside myFunction class, and in that method if an object is needed it can be creatd by a call to a private constructor, etc. In other words if it is the implementation that needs an object and not the client that needs an object, why is the client exposed to such an irrelevant detail ?
Why not? Because "_" has no meaning. "go" has very little meaning, but it's a better hint than "_".
But that is precisely the point. That _ has no meaning :) So you focus on the whole phrase. What does myFunction._(arg1,arg2) suggest to you ? Does it suggest somehow calling a function ? Then that's what it truly is. Well, Java does not support function, but you just need to keep in mind that Java is just an implementation detail and a minor annoyance sometimes. ProgramIntoaLanguage says that if a language does not support feature X , we just need to look for the most convenient way to translate feature X into the language at hand. As we all know, there's no perfect language and there will always be feature X or feature Y missing.
If I browse into a class and see a method named "_", I'm going to be stumped. I may not have the context required to decypher its meaning. Once I figure it out, I'll probably rename it.
Not after reading this page, you won't.Whatever meaning you give it, it'll be redundant. If the class is a FunctionObject and is called MyFunction, naming it's method compute() is restating the same thing that can be stated briefly in the JavaDoc for the class.
JavaDoc? Blech. Whatever you would state briefly in the JavaDoc, I would express briefly in the method name. See ToNeedComments.
new MyFunction(arg1,arg2).compute()looks like an unnecessary verbiage when in a decent language the call would be:
myFunction(arg1,arg2);But I (and the next 20 Java programmers who touch the code) aren't using a "decent" language. We're using Java.
What role do "new" and "compute" play in the above code ? Nothing, they're there just to keep the damn java compiler happy. Well I can achieve the same objective with
myFunction._(arg1,arg2);You always read a name in a context. And if the context says the class name is myFunction and it has a single puiblic method called _(arg1,arg2), then it's not rocket science to figure out thatb _ acts just like a function application operator.
It isn't rocket science, but neither is it painfully obvious.
Nor is it good advice, never use _ in or for a method name. Compute plays a role because it's not necessarily the only method in the class, though it may be the only public method, if it were complex enough to make a method object, it probably has a few private methods. Though I'd probably prefer Run or Eval over Compute.
new MyFunction(arg2,arg2).Run(); new MyFunction(arg2,arg2).Eval();is perfectly clear, concise and obvious, no need for JavaDoc, and no wacky method names that can't be spoken properly. When you talk about a function, what words do you use... _, I doubt it... you probably say Run or Eval, so use Run or Eval. --Anonymous
Not at all, when you talk about a function you don't use Run, "run" is a verb used for threads or other kind of processes. You don't use eval either. Eval is for expressions, typically string expessions or S-Expressions you do not "eval" a function, that's just Java ad-hoc mumbo jumbo. When we deal with a function the natural "verb" is the application operator and that's simply:
functionName( ... )or in Scheme like languages :
(functionName ...)In comparison to that, again in :
new FunctionName(arg1,arg2).eval()Both the "new" and the "eval" are absolutely ridiculous visual kludge dictated by the "OO only" view of the world. What is "new" in the object you create ? See the NygaardClassification for some background. There's nothing new, the function stays the same always, we only may choose to apply it to different arguments, but it's the same function. We may choose to consider it's the binding of two arguments that makes it as a new object. That would be more acceptable, if we followed ML conventions of partial application, but it's not about that. For partial application you can use something more suggestive, like:
functionName.bindArg1(arg1)There's no rational reason other than maybe OO thought police that the kuldgy notation new FunctionName(arg1, arg2).call() should be recommended versus the elegant functionName._(arg1,arg2). Boys and girls, grow uop and practice some functional programming languages to get accustomed to the elegance of notation, because Java for sure is heading towards the status of programming language Dinosaur following her illustrous predecessor COBOL.
Just think about the following useful example: let's say that we need to have the static methods in Math as real "function objects" as opposed to static methods, say for the purpose of writing an itnerpreter for a calculator.
Now would you rather prefer to call it:
sin._(x)or would you rather do it as:
new Sin(x).call()Let's just imagine the following invariant:
new Sin(x+y).call() == (new Sin(x).call())*(new Cos(y).call()) + (new Sin(y)).call())* (new Cos(x).call())What an enlghtening experience can be to look at the above formula. Let's try this for a change :
sin._(x+y) == syn._(x)*cos._(y) + sin._(y)*cos._(x)Do you like the last one better ? I thought so. You can almosty think that the language designer played a trick and changed the function application operator from the regular ( ... ) to ._( ... ). It is understandable. After all, even the most basic mathematical sign = has been rewritten as == . --CostinCozianu
I prefer
new Sin(x).call()Your trig identity provided one example why, though not the main reason. You forgot the underbar for the first sin. A missing 'call' is very apparent. Would you have noticed the missing underbar?
Incidentally, I believe the first version can be written
new Sin(x).call() * new Cos(y).call() + new Sin(y).call() * new Cos(x).call()since new has a higher precedence than function calls, which have a higher precedence than operators. That's not all that much worse.
''It is. Much much worse. Try to write the whole thing:"
new Sin(x+y).call() == new Sin(x).call() * new Cos(y).call() + new Sin(y).call() * new Cos(x).call()You could say that this may never hold in Java. But let's try a Unit Test that the difference doesn't go below a delta.
assertTrue( new Sin(x+y).call() - (new Sin(x).call() * new Cos(y).call() + new Sin(y).call() * new Cos(x).call()) < DELTA)versus
assetTrue( abs._(sin._(x+y) - ( syn._(x)*cos._(y) + sin._(y)*cos._(x))) < DELTA )[I'd rather extract a method that names that mathematical function. What does it do? Why should it be less than DELTA? Your code doesn't give me a clue.]
assetTrue( calculateGoobleFlotz(x,y) < DELTA );[and understand that the test wanted to make sure the Gooble Flotz of xy was less than delta. The internals of goobleFlotz() could be full of function objects and I wouldnt't care. I never feel the urge to shorten my method names or use unpronouncable method names because I wrap sequences of calls with descriptive method names.]
Well, bravo for you. But that suggests that you do not deal with mathematical formulas a lot, otherwise, your imagination will soon run out of names. I would expect from a programmer reading (in math notation)
sin(x+y) = sin(x)*cos(y) + sin(x)*cos(y)To understand what that is, without any need for a special name. There simply isn't a special name, why should students be bothered with memorizing extra information by giving name to all formulas ? This formula is what you see is what you get. Other formulas have special names like Newton's binomial or Cauchy-Buniakowski-Schwartz, or Lagarange polynomial, or what have you, but there's no need to give everything a dedicated name, nor is it important, nor is it useful. We could if we want name it SinusOfXPlusY, but that's just silly. Generations of highschool students learnt it just as: [ sin(x+y) = sin(x)*cos(y) + sin(y)*cos(x) ] and didn't make so much fuss about it.
[I would expect 1 in 20 programmers to understand what that is from the math notation, based on my experience. I prefer to code for the other 19.]
Author's intention is pretty clear: to get sin(x). Again you are not looking at the whole phrase: sin._(x) makes it abundantly clear what the intention is. As symbols "sin", "cos", "tan", "ln", etc. have enough name recognition on their own.
[And that's why they are the names of static methods on the Math class in Java. We were talking about the general case of function objects, though. I believe that "_" is perfectly clear to you. I also believe that "call" will be more understandable to more programmers.]
But that's the important difference between two schools of thought. One school of thought is that PL idiosynchrazies are paramount, and another school of thought (that include people like EwDijkstra, Knuth and many others) who thinks that PL are at best secondary.
My secondary complaint (and secondary only because I don't think it'll hold much weight for you) is that it's disrespectful to your fellow programmers. Languages are more than just parsers and semantics. They're communities too, and communities have sets of shared expectations and common knowledge and ways of doing things. I highly recommend LambaTheUltimate? Political Party by KentPitman? (http://www.nhplace.com/kent/PS/Lambda.html) for a good paper on this.
By programming C++ in Java, you're making your peers relearn all the conventions and idioms that they've acquired. The point of programming isn't to show off how many advanced languages and language features you know. It's to work together and build something useful. If you can teach your coworkers a bit too, that's great, but that means introducing concepts gradually and showing them how it'll make them be better Java programmers, not how it brings them one step closer to being a ML programmer. -- JonathanTang
The point is neither to show off, nor to blindly follow idiosyncratic non-sense like
new Function(x,y).call()But the whole point is that BeautyIsOurBusiness. I know it's in the eye of the beholder, but a lot of people will recognize that: the above is simply an bulky, kludgy overall ugly notation. --Costin
Grumpy question from a C++ veteran -- If we don't really need the instance, why wasn't the go() method static? (Two possible reasons: we didn't write some_class; something wonderful happened in the constructor) -- AnonymousDonor
One major reason is testing. Since in Java, statics don't inherit, the tests can't override any of the functions used by the go() method to provide mock implementations. -- JeffBay
The go() method may have called various other member functions, which may have used instance variables to communicate state. We could not make them all static without breaking re-entrancy. In other words, we did need the instance, but only for the duration of go().
This idiom is used widely within the STL. For example, temporary FunctorObjects are passed to algorithms to encapsulate sorting rules or predicates. C++ has strict rules as to when a temporary object is destroyed -- at next the sequence point after their construction, not before or after -- allowing all sorts of cunning tricks to be performed by ThrowawayObjects in conjunction with the ResourceAcquisitionIsInitialization idiom. For example, a smart pointer can automatically lock/unlock its pointed-to object by returning another, temporary smart pointer that acquires the lock in its constructor and releases it in its destructor.
[And we may need the object. A good example is Java's Thread object. I often start a thread like this:]
new Thread(new Runnable() { public void run() { // do something here } }).start();[The code that starts the thread throws the object away, but the VM keeps using it.]
The top line of this page used to read:
This JavaIdiom is obvious to Java programmers but looks insane (like a memory leak) to C++ veterans:
new SomeClass(arg1, arg2).go();Actually, C++ has scoped varibales.
To express the same thing in C++, we just do:
SomeClass(arg1, arg2).go();No fuss, no muss, no operator new.
This page mirrored in JavaIdioms as of April 29, 2006