- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
Avtually the String is Life. The Long is the universe, and the HashMap is everything. Funnily enough all this program does is return "42"
Admin
I was under the impression that "deterministic" was not used in the narrower sense here. Repeating my argument from above, I still prefer implicit memory management with many people working on the same code base. Resource management is not trivial in itself and can be done wrong in any language.
But of course the huge backwash of morons is not the fault of the language. Because it is so prevalent in the industry and promoted by the big players (which does not make it dearer...) so many more people try (!) to code in Java than in other languages (that may or may not do some things better) - but there is no ideal language out there, unfortunately. Most of the "plz send me teh codez" comes from the educational side, BTW. When I attended the university, Modula II was the language du jour for educating students. Now it is mostly Java, which is far from ideal in fact. I've had my share of "pleeez give me the codes", only that it was expressed verbally and meant handling over sheets of line printer paper ;o) Ah yes, I'd really like to take up Lisp again, it's been a while... and Ruby and Python are great. But in big distributed systems where you need the whole stack of technologies in all the different layers, they also leave a lot to be desired. Thanks a bundle for the hidden compliment ;o) Still, if I think of the developer teams I come across in different companies, I still prefer GC, no operator overloading and no pointers, thank you very much ;o)Admin
I would argue that the C++ RAII mechanism fits these criteria; it's usually just as readable as making it explicit with a try/finally or an anonymous inner class, just as efficient (if not more so), and shorter.
I understand there's a good reason for it. But it does make some things harder if you know that it won't be called outside of the current function. Um, what? Please translate the following code that uses try/finally to one that uses an anonymous inner class (I make no guarantee that the syntax is correct, but it should be at least plenty clear enough to determine what I'm trying to do):If there is a trivial way of making this use an anonymous inner class, I'm missing it.
That's a matter of style; it often makes sense. That only works if the inner class doesn't have to modify them. You never know what a given function behaves like just by looking at it being used - you have to know it's implementation too. Should we banish functions as syntactic sugar for explicit stack management and a goto as well?(I'm being deliberately inflammatory; functions are clearly much more important syntactic sugar than operator overloading.)
Eventually. When the garbage collector gets around to it. If it does.In other words, no, it's not deterministic.
Admin
No, unfortunately not. This is actually hierarchical, not just a 3-tuple key. We needed to perform operations like deleting all data associated with a particular key at one layer of the hierarchy, etc.
Admin
Hey look, another page.
In Java this is much more true than in C++ (read: operator overloading is much more important in C++) since C++ templates are a lot more powerful. The fact that templates use compile-time duck typing means that you can write a template that uses * and it will operate the same on iterators and pointers, you can write a template that uses [] and it will operate the same on vectors and arrays, or you can write a template that uses + and operates the same on ints and quaternion objects.You could compensate by writing and overloading a bunch of functions (like "int add(int a, int b) { return a + b; }" then call them, but that's much more work. Java is missing some nice syntactic sugar by omitting operator overloading, but if it were removed from C++ it would greatly increase the overhead of doing many things with templates.
Aren't you the person who just a moment ago wrote "The more opportunities you give the people to shoot themselves in the foot, the more guns you will hear going off"?The converse is that if you make it easier to do something right, the fewer guns you will hear going off. I (and others) are arguing that RAII makes it easier to get resource management right.
Admin
Here we go:
I took the liberty to implement it as a template pattern with a hook method that allows processing of each character. Each call to processFile() returns the number of chars in this file. BTW, of course one could do the processing of all files in the local class i.e. move the foreach-loop inside the process-method and return the total count:
The notation of local classes is admittedly something one has to get used to, but it is not more complex than other notations I know from various languages. Real closures would be better though.
It doesn't have to. See above. That's not what I meant. A function/method has a name that (hopefully...) describes what it does. And it does not change semantics compared to some built-in standard behaviour like an overloaded operator does. *If* it does change its semantics, this is within the rules of polymorphic behaviour, i.e. it is either overloaded (then the parameters provide the context) or overridden (which means its behaviour is specialized in the derived class). OTOH an operator which looks like a built-in standard can have completely different semantics if it is overloaded: a = b + c; is perhaps prettier to look at, but if I see a = b.add(c); I'm more likely to suspect that a,b and c are - say - complex numbers or matrices instead of primitives. It is debatable if this de- or increases readability, but still it is nothing but syntactic sugar, whereas functions are of course not. I already answered that in another follow-up. Point taken. I was oversimplifying, because I did not think "deterministic" was used in the correct narrow sense in the post I was answering. Sorry for that.Admin
I'm sorry, I inadvertently omitted the "abstract" keyword:
which is necessary, because I declared the hook method abstract. The class does not have to be static, but for testing purposes we can put it inside the test class - and then it makes sense to declare it static, because this makes it a "top level" class, similar to a class declared in its own file. When using it outside the declaring class, however, the complete name is "Outer.FileProcessor" (i.e. including the enclosing class' name, e.g. "Outer"). If we just use it inside the enclosing class, we could in fact make it private too:
For broad re-use, however, we should normally put it in its own source file and declare it public (and not static, it is "top level" anyway then):
Admin
The best way to do it (read: I think the only way to do it in a suitably generic manner) would probably be to have the function return an Object, then box up the bytes read in this case within the anonymous class, and unbox it at the end.
With generics you can keep static type safety, but it still requires an extra boxing and unboxing step if you aren't just returning a primitive. Still way less convenient than not having to do anything special at all.
This has the same problem. An operator overload also has a name that (hopefully) describes what it does, it's just a funny looking name like "+" that operates in infix notation.(With regards to the next point, the semantics don't really change, you're providing new semantics. The exception to this is like the && and || operators in C++. If you look in style books they caution against overloading them because it breaks short-circuiting and such. You could make a strong case that these shouldn't be overloadable, though I have had use for them in a library where operator overloading vastly, vastly improves readability in locations where it's used.)
Sure they are. What can you do in functions that I can't do in a language that doesn't provide them? Agreed; I saw your post too late to do anything about it there.Admin
The WTF isn't the actual code, here, but two Java quirks:
I sometimes write code like this in C++, but it usually looks like this instead:
shared_ptr<dictionary_t> d(new dictionary_t());
In Haskell, you could just type this:
d <- Data.Map.empty
and let the compiler infer the full type.
The problem here is that the obvious way to piece together bits of generic libraries is way too verbose in Java, compared with other languages.
Admin
"Why hasn't Java got typedef?"
The short answer is: It didn't need them before it got generics.
Admin
"2) If you want to do flexible partial-match searches: use a friggin' DBMS."
I hope that was sarcasm. At last count, using a friggin' DBMS where it's not appropriate is the cause of far more Daily WTFs than Java generics.
Admin
I find this a quite elegant solution - you are free to think otherwise, of course ;o)
Point taken rearding the name. But what I wanted to express is this: you do not have a "standard" version built into the system which behaves in a way everybody expects for each and every method - and then perhaps changes semantics in some but not in all cases. This is true for operators OTOH. Not "in" functions, but "with" them - two words: Structured programming. That does make quite a difference... because missing operator overloading does *not* remove a whole programming paradigm. Go ask Mr. Wirth if this makes any difference ;o)Admin
[quote user="EvanED"][quote user="RobFreundlich"][quote user="EvanED"] [quote]And any Java developer worth shit would be running findbug. Prob Sol.[/quote] For a few of these problems. Will it tell me that I forgot to change the cursor back to a pointer?[/quote] If you set it up correctly, yeah. Else your Unit Tests will.
But on the whole I agree, here is one of the few cases that Closures (Java 7) will help.
Admin
Look, Java does resource management one way (GC, no pointers, etc etc) and C++ does it another way. Take yer pick (or other preferred operating system). I happen to find RAII considerably more elegant than a bunch of "finally"s stuck around the place and some botch-job of vanilla-flavour synchronisation built into the language itself (see Allen Holub for gory details).
But, to syntactic sugar. Ironic that we should be having this discussion over this particular OP, which is a rather fine example of syntactic sugar in Java.
Arguably, anything other than an endless paper roll and a pencil is syntactic sugar -- thus the typical futile arguments about "goto" that infest this site and many others. It depends on what you see as "syntactic sugar." So here goes:
Syntactic sugar is a language artefact that makes little or no difference to the compiled/byte-coded output of the relevant AST.
Functions (in a type-checking language) are not syntactic sugar. Java generics are, and further suntactic sugar with the introduction of a typedef would therefore have been appropriate. Operator overloading sort-of is, and sort of isn't, because, as EvanED points out, it's hugely useful at the points where it intersects with generics (or indeed templates in general) ... for example, with iterators.
This (I think) is an interesting example of "syntactic sugar," because although strictly not necessary to alter the generated code, it is certainly necessary to make the resultant behaviour generic.
It therefore boils down to whether you want to give the programmer the power to do this. In the case of C++ and generics, I don't think you have much choice. In the case of Java, I recognise that a conscious effort was made on the part of the language designers (who were sitting in a small sweaty room at a time where C++ generics were just a gleam in Stepanov's eye) to simplify in this area. The end result, through no fault of their own, is that Java generics are a bit of a botch.
And I rather like the idea that, in C++, it's easy to shoot your foot off. It's pretty bleeding obvious when you do so, too, and then it's time to hire a better C++ programmer. With due respect to your own knowledge of Java (and indeed C++), I don't agree with your argument concerning large systems teams in Java.
If they were all in the top 20%, then, yes. Sadly, they're not. They'll leave just enough cruft and animal turds behind them when they leave for a more Enterprisey job to occupy those who are in the top 20% for the rest of their doomed, language-constricted little lives.
Back to Lisp variants, I suspect.
PS I think you're right about my use of μηδὲν ἄγαν, btw. I had something specific in mind when I inserted it, but then I took another shot of absinthe. (Well, one more can't hurt, can it?)
Admin
@yuumei:
Nothing is wrong with the CODE... it's perfectly reasonable. The WTF is with the LANGUAGE. (Although, in fairness to Java, the coder COULD have encapsulated some of the abstractions in a class just to shorten the syntax.)
Admin
Lots of this C++ vs. Java discussion is centering on things which are non-factors in another environment: C++/CLI. If you don't know much about this, rest assured, it's not C# on a C++ compiler. You want deterministic destruction of managed types? No problem - variables come as either heap-allocated 'gcnew' types, or stack-allocated automatic ones...the difference:
void a() { FileStream^ fs = gcnew FileStream(filename); }
Upon returning, 'fs' is still alive - on the GC heap. But, if you:
void b() { FileStream fs(filename); }
Here, when the call returns, 'fs' is no more.
So, it is trivial to use any type, managed or not, in the classic way of creating auto-reset objects. For example, in drawing code, you may make calls which affect the underlying DC, so you should reset them before you return. As was pointed out earlier, you can use the 'using' construct in C# or VB.Net as such:
using GraphicsResetter gr(e.Graphics) { e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; }
Where, GraphicsResetter stores the start state, and its' destruction at the end of the using statement resets things in the Graphics object. In C++/CLI, this is simpler yet...somewhere before using the Graphics object, you would just create an automatic local:
GraphicsResetter gr(e->Graphics); e->Graphics->TextRenderingHint = TextRenderingHint::ClearTypeGridFit;
No extra block-definition necessary, since 'gr' will be destroyed (i.e. disposed: ~GraphicsResetter() will be called) at the method's closing brace...just like any other stack-allocated C++ object would be.
This is just one small example of the many advantages C++/CLI has over the other .Net languages; in addition to .Net Generics you also have the STL.Net implemention, applicability of typedefs for managed types, hybrid managed/native types for interop, the ability to do simple things like:
DestroyIcon((HICON)cursor->Handle.ToPointer());
...which are impossible in C# without using PInvoke and dealing with the clutter and associated overhead. Overall, C++/CLI provides an excellent environment for programming .Net - and for Windows it's simply the best, hands-down. It's just surprising that so few people appear to be aware of it.
Admin
Admin
The longest generic type I have written has 119 characters for code in production. It could have been longer but that would have been really silly. :)
Admin
In terms of the Java/C++ discussion, I think we did quite a creditable and non-flameworthy job. Perhaps when there's any distinct reason to mention C++/CLI, we'll get round to it.
I'm aware of it. Quite a lot of people are, strangely enough (and I believe that Herb Sutter might even be one of those people).To put it kindly, I'd suggest that it only has value (in a weird and inverse sort of way) as a "glue" language when you need to tie other .Net assemblies together with legacy (or otherwise) C++ code. In which case, I expect that you'd still need "pinvoke" anyway. But in all honesty, I don't really care.
Admin
Admin
However it is still harder (and I mean this in the good sense ;o) to create memory leaks in Java, and that is not because C++ does not deliver the tools like RAII but because of the fact that you can easily produce dirty C code disguised as OO code because it is wrapped inside a class (and admittedly you can even do that in Java, but arguably without lots of the side effect tricks stemming from C which are simply not possible) and do everything else instead of choosing the right construct for the job at hand.
I see it in a different way, namely that "syntactic sugar" does not affect the functionality of the language in *source* - not purely in object code. I could just use machine code directly otherwise. You say... (which is BTW the same I said in a previous post, opposing EvanD's opinion) But with your narrow definition this is not true, because the omission of functions does not make a difference in machine code.I'd say that perhaps basically everything else than lambda calculus and variable assignment is syntactic sugar ;o) which makes your point (that functions are not syntactic sugar) true all the more.
But the sugar is not equally sweet on all levels - some constructs are really unnecessary (think e.g. of those languages which have "while" and "until" loops with only mirrored run and break conditionals), others make for the paradigm of a language (e.g. OO constructs)
D'accord. Hugely useful, yes. But still only a different syntax and more easily misused or misunderstood - that was my main point. *grin* Agreed. Mostly because of the fact that they are implemented as erasures. Amen brother. But that's the problem - it is often hard to find any hires at all, let alone really good or simply better than previous ones... Ah yes, that's the main point where we really differ.As I said above, if you have more constructs which can be misused, it will happen. All the time. Whenever and wherever possible. That's one of the lessons I really learned in quite some years. And that's the reason why I think Java is better in team environments.
Amen again... I see that we do in fact not differ much, except that we think that different approaches remedy for that. Count me in! Ah well, who really cares, it was already good fun to read ancient greek in a discussion on syntactic sugar :o)On my part I hope that I did not write a lot of bollocks in this post, I've only slept 2 hours %o] and it then gets increasingly easy to shoot yourself in the foot (above all linguistically) in a language that's not your mother tongue.
Admin
Well, excuse me for living. I mentioned it because, as I said, it offers most of the 'C++' things, with the exception of const (for managed), that people were complaining were 'missing' from managed languages. But I'll try to make sure I get your permission before I post next time.
While partially true, that statement makes no sense in this context. Why would you only use it to expose native code to managed code, when you can just take care of the managed side right there. Your example assumes that you're going to create client assemblies which will reference this one, so why would you plan on writing them in a less-capable language? Unless, you don't miss typedefs, automatic variables, etc. - in which case, you are obviously not in the group which I was addressing.
Fine by me - sorry for wasting your precious, precious time.
Admin
I've been away, sorry to ignore this nice debate for so long. ;-)
No, only in one place. If I want to count bytes, the way I use the file object is exactly the same as if I want to do something else. I don't have to go into the fstream class and change the destructor.If you don't use the suggestion that the FilesProcessor becomes a generic class FilesProcessor<T> that returns a T, you need to modify FilesProcessor if you want to do something different. This is the part of the code that ensures that you close the file when you are done, the equivalent of the fstream destructor.
If you do use the suggestion, then things look better, but at the same time you will often have to do an obnoxious amount of boxing and unboxing if you modify more than one variable.
Otherwise:
And I don't think that's nearly as good a solution as what you get in C++. I don't think I'd have thought of this; I do like it better the other suggestions. Though would you be able to get multiple return values without boxing them up into a single return value? (Again, Java's lack of either pass-by-reference or mutable boxed primitive types comes back to haunt.)I would still say that the C++ method is better; even with this you have to pull every value out of the inner class explicitly.
No, but you still have conventions. If I have a pseudo-numeric type that lets me write "a.add(b)", by convention that is returning their sum. (Never mind the fact that "a.add(b)" *still* looks to me more like "a += b" than "a + b", but that's another matter.)And Java doesn't have any mechanism for making your add() function not behave that way (because that would be pretty much impossible of course).
Now, this sounds to me like I'm making a sort of argument that I hate which "we can't fix the problem [operations that behave unexpectedly] entirely, so might as well not make an improvement [disallow operator overloading]"... so I don't claim to be entirely consistent. ;-)
I guess I would just say that I think that the benefits of being able to write more natural code ("a + b" no matter whether a and b are ints or complex numbers or vectors, rather than "a + b" if they are ints but "a.add(b)" if they are complex or vector types) outweigh the small loss in unexpectedness. In the C++ code I've worked with, I would say undoubtedly that operator overloading has increased readability rather than decrease it.
From your later post:
I think you said what I was thinking better than I did. ;-)I think the reason this whole syntactic sugar discussion came up was that I really don't like dismissing language features [op overloading] solely on the basis of them being syntactic sugar, because I think that in some cases these can be extremely powerful things.
Even I would not even think of saying that operator overloading is in the same class as functions in general. I would say that, in C++ at least, operator overloading is in the same class as function overloading.
If you're asking what I think you are, Maybe you have legacy C++ code that you don't want to translate to C++.Net? Maybe you have a program that you maintain on multiple platforms and Mono isn't up to snuff?Admin
And using the same complex type multiple times is not so unusual anyway. If you're using, say, a Map<String, String> in several methods, you'll have to declare variables and parameters of that type several times.
Not to mention the (in my eyes annoying) verbosity of the creation of the object in the first place: Map<String, String> = new SomethingMap<String, String>(); At least in C++, if you declare a map<string,string>, you have a map<string,string>, not a useless pointer to (n)one.
Then you used a strange compiler. As I said, all C++ compilers I sort-of know do have methods to make sure the types match. This includes GNU G++ and MS Visual C++.Admin
Admin
I've got sympathy for person writing the crazy generic definition. There is no "typedef" facility in Java and the workarounds for this limitation all have their problems.
Admin
Admin
I still think that this weakness is partly counterbalanced by the virtues of implicit memory management which facilitates program correctness in certain regards. It may admittedly decrease resource management correctness if not used correctly - but which errors are more prevalent and more of a problem in typical C(++) systems - memory leaks or failures to close a file?
There's obviously still room for improvement and there must be some good compromise for these issues and perhaps some lessons can be learned from C# here - C# as a language does have some very good concepts. The main reason why I do not like it is the obvious promotion of the well known MS business model (vendor lock in etc.) by the .net framework... I'm already expecting to get flamed for that by some other readers, but I can take that ;o)
Given modern IDEs I really do not see that as a very big problem, but you are right in stating that local variables are easier to handle in that case. Quite naturally, yes. But firstly, using encapsulated objects is (apart from needing a little more code) the much cleaner way to handle multiple return values. I assume that with "lack of (...) pass-by-reference" you mean primitive method/function parameters. Java objects are of course passed by reference, whether as parameters or return values. But I have to say that I think the use of (primitive) out- or in-out-parameters is one of the worst concepts carried over from procedural languages into OO. I think even in C it is much cleaner if function parameters are only used as in-parameters and multiple return values are wrapped in a struct, even when the standard libs do otherwise a whole lot ;o) Primitive (in-)out-parameters in OO languages are IMHO plain evil. Quite, but with the above concept you will (in most of the cases) pull exactly one scalar value with the specialized method call - it is likely that one only needs one value (e.g. the file length OR the contents). Of course in case you need both, you have to do that little more work of (un)boxing.That the wrapper classes are immutable is one of the single most important design decisions in early Java - they already blew it with java.util.Date, and this leads to many subtle flaws when passing around mutable Date instances without defensively copying them (which is also more work). The same argument also speaks against the possibility to getting the addresses of primitives and passing the pointers around.
I see it just the other way round now, but I do have to admit that I did miss op overloading when switching from C++ to Java ;o) Thanks a lot. If I may deduce from your user name that you are an english native speaker, that's even a greater compliment, because I ain't ;o) D'accord. This view is backed up by the fact that both concepts are called "overloading" after all ;o)Admin
Admin
thanks for info
Addendum 2024-08-19 02:57: If you're overwhelmed with college writing assignments like I was, is the perfect solution. I've used this service several times now for essays, research papers, and other projects, and the quality has always been top-notch. The writers https://essaybox.org/ are skilled in a wide range of subjects, and they always meet deadlines. EssayBox has made my academic life so much easier, allowing me to focus on other important aspects of my education without the stress of looming deadlines.