Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

>In my Eiffel days, I was encouraged to write "integer", not "int", "character", not "char", and so on. I believe Java encourages this practice too. Supposedly clarity is maximized. But how can this be if we do the opposite when we speak? Do you say “taxi cab”, or “taximeter cabriolet”? Redundant utterances are tiresome and worse still, obscure the idea being expressed.

I see this argument a lot, and they strike me as people complaining because they don't use tools their language provides.

Typedefs are the answer to excessive name length, and they're nearly everywhere. Just create a couple typedef files, and import them as needed - future programmers get the full names easily, while you can program in your pseudo-K version of C for maximum keyboard efficiency. I have a handful of such files, they're endlessly useful - why write `Pop_froM_lIsT_WhIch_COntaiNs_speCiFik_type_X`, doing battle with naming-scheme-X that only employee-Y uses (and their associated spelling errors) when you can do so once, and write `pop` from then on, unambiguously?

The upside of typedefs for this comparison is that they're precisely what we do with spoken language - nobody knew what a "taxi cab" was until someone told them it the shorter version of "taximeter cabriolet", or until the full phrase was well enough known that it could be inferred accurately by the average person.



Given that Java doesn't have typedefs how would you reduce the verbosity of : ConcurrentHashMap<String, Integer> foo = new ConcurrentHashMap<String, Integer>();


Do something like the Google Collections Library does:

    HashMap<String, Integer> foo = Maps.newHashMap();
The return type of newHashMap is determined by the type of foo, so you don't need to repeat the generic types in angle brackets.

  public static <K, V> HashMap<K, V> newHashMap() {
    return new HashMap<K, V>();
  }
http://google-collections.googlecode.com/svn/trunk/javadoc/i...

(I'm not a fan of Java myself, but there are some tricky ways to cut down on its verbosity)


The Collections class built into Java has a lot of timesavers like this too--singleton, singleonList, singletonMap, and Arrays has stuff like Arrays.asList( ... ).

Also it's rarely important that you know the actual type of Map you're using (the interface is what's important), so you can just call

Map<String, Integer> foo = Maps.newHashMap();


There you're largely screwed, but Java is well-known for being extremely verbose, and of course there will be languages that don't have basic features others have had for decades.

The closest you can get in Java is to wrap it in a private, internal class. Which also lets you rename some verbose or frequently-combined operations, say:

  foo.someoneCouldntComeUpWithAShorterName() -> wrapped.succinct()
  -- or --
  foo.store(val);
  foo.store(val);
  foo.store(val); // I hate void functions...
  -> wrapped.store(val,val,val);
But yes, it's a pain. Java's largely a pain.


I see your Java, and raise you Objective-C:

    NSString *thing = [NSString stringWithFormat:@"Result: %@", [foo someoneCouldntComeUpWithAShorterNameWithZipcode:08205 name:@"larry" parcels:5]];
    NSDictionary *request = [NSDictionary dictionaryWithObjectsAndKeys:@"iphoneapp/0.1", @"User-Agent", @"news.ycombinator.com", @"Host", nil];
This isn't to kick off pet language wars, by the way, just to point out that my OCD tic to wrap to 80 characters has absolutely zero place in Xcode. Or Java.


While it can get a bit silly sometimes, I've come to really appreciate the verbosity of Obj-C method calls. Explicit parameter names make them very self-descriptive, and grouping the entire call within brackets makes structure obvious. Compare:

  canvas.drawImage(kittens.subImage(vec2(10,10),vec2(20,20)),vec2(30,30))
vs

  [canvas drawImage:[kittens subImageAt:vec2(10,10) withSize:vec2(20,20)] at:vec2(30,30)]


Yes but some of the examples of obj-c I've seen look ridiculously wordy compared with the smalltalk equivalents (even if you ignore op overloading). (setObject: forKey:) vs (at: put:). for ex.


disclaimer: I have not tried these. Totally pulling these from a quick googled-refresher of macros.

  #define withZip someoneCouldntComeUpWithAShorterNameWithZipcode 
  #define dictWith dictionaryWithObjectsAndKeys
  or 
  #define dictWith NSDictionary dictionaryWithObjectsAndKeys
  so you can [dictWith: key, value, key, value]
:) I forget, does XCode intelligently handle macros? Or does using a macro destroy its helpful features, like code completion?

I actually have a "hashWith" utility function for my .NET code. Saves me a ton of ugh-induced headaches.


Doing that is probably fine if you are working alone and nobody will ever read your code. Reading Objective-C is already enough of a challenge without having to context switch to a header just to mentally resolve symbols.

Instead of using a macro for the selector:

    NSDictionary *frob = [NSDictionary macroHere:v1, k1, v0, k0, nil];
It would probably be far more efficient to macro the entire call using C99's variadics:

    NSDictionary *frob = DICT(v1, k1, v0, k0);
Still wouldn't walk that road, personally.


The reason I went for the selector is because it makes the macro into essentially a function-typedef. I don't know any languages which allow typedefs to specify things like `Class.short = Class.super_long_name_here`, even though it's essentially the same concept, especially if looked at from a C standpoint. It's a minimally-intelligent text replacement.

IMO, something like `[NSDictionary with:key,val,key,val,nil]` is far less brain-taxing than `DICT(key,val,key,val)`. It fits without modifying the language or the syntax, it merely makes something long shorter, and the usage implies it does nothing "shiny" - you even keep the class name you're calling, making it clearer what you should be expecting, and it still allows access to all other parameters without modification or even thinking differently. DICT(...) is ambiguous about what kind of dictionary it's returning.


Yup, macros are a bad idea in that regard. Had to work on a codebase where the prior programmer had fancy defs like _dict k1, v1, k2, v2, k3, v3 dict_

I wasn't too happy about that :/


I haven't worked a lot with XCode, but I remember using macros without problem.


"just to point out that my OCD tic to wrap to 80 characters has absolutely zero place in Xcode. Or Java."

Dude. Are you still using CGA? Unless for your IDE you're running emacs on your wristwatch or phone there's no place for that shit in the real world, and you have no excuse.

Ditch that green cathode ray tube, here, have 50c and go buy yourself a real monitor. :D


Lines longer than 80 chars are harder to scan, and sticking to this rule allows tiling of windows. Maximising code windows on a widescreen is a huge waste. Even with long lines the average line length will be far shorter.

This is Guido's reasoning for keeping PEP8's rule to 80 chars.


I work on a 27" iMac with a 27" second monitor, and a third 19" on a Linux box with Synergy. My primary language is Python, so I do have a place for that shit in the real world.


It is fascinating to see people having 24+" monitors -- and seeing ca 30 lines of code on their screen, because of the real estate eaten by their IDEs.

To add maiming to injury, these guys write in modern Cobol (a.k.a Java).

Not to mention that they can't print the code -- since it is 150+ chars wide(!) -- and browse it at a cafe. (I love my iPad, but It'll be iPad 3 before it is half as nice for browsing code [edit: as paper].)

I have about 2 full pages of code on the same size of monitor. Of scripting language. I doubt that I have abnormally bad memory or write too complex code... I just like to be productive.

Edit: oK, downvote if you want. But please also add a counter argument for wasting all that screen area?


"Not to mention that they can't print the code -- since it is 150+ chars wide(!) -- and browse it at a cafe."

You can't print code longer than 150 characters wide?

Since when?


Sigh, are you trolling or new? OK, I'll answer.

The point of printing and browsing code is that it is easier and nicer than to read it on a screen (you'll have a portable with you at the cafe anyway to search, annotate, etc.) If you get lots of broken lines, it isn't readable.

Point was, you lose a capability with long lines -- a nice way to go over code. This is important for many of us.

Edit: Point jedsmith, write it off as grumpy-old-man syndrome. Sigh, I just can't get that this isn't understood by everyone, anymore.


Broken lines?

We no longer live in the days of typewriters or daisychain printers with fixed column widths.

We now have these wonderful things called laser printers which can print using fonts.

Fonts are resizeable. Even to the point that 150+ columns could be fit on one unbroken line.

And even lines that long can be quite readable if you print in landscape.


Let me first not that printing was a little sub point.

Second, in what you quote from: easier and nicer than to read it on a screen.

So your argument seems to be that it is equally nice to read fewer lines of paper in a smaller font. Huh? Also, my eyes can't handle 4 pages on a page any more -- and your eyes won't be able to do that after 40, either.


You could have made that point without the personal attack.


Yeah, and congrats, now you have to hire people who already know what a foo is.

The great thing about ConcurrentHashMap<Long,String> isn't writing it, it's reading it. Even if you're not a Java programmer you know exactly what that is (and FWIW it's world-class on implementation). We could do with some syntactical sugar to make that constructor line a little simpler, but declaring the type and calling a specific constructor, not masking either with personal shorthand are both Good Things if someone's going to have to read that code later.


I am skeptical of the claim that verbosity for its own sake aids comprehension. To borrow an example from Rob Pike, reading

  buf[thisVariableIsTheLoopIndex] = foo(...);
is no more obvious than

  buf[i] = foo(...);
and indeed is more likely to slow the programmer down by killing his train of thought and mental flow.


The problem with that example is how contrived and narrow it is. All it proves is that verbosity doesn't aid loop indices.

ConcurrentHashMap<K, V>, on the other hand, says everything it needs to in the name. As does NSMutableArray, and so on. Apples and oranges, here.


Personally, I find "thisVariableIsTheLoopIndex" to be a terrible loop index variable name. But "i" isn't great either. "index" seems to be closer to the sweet spot to me. Or "fooIndex" and "barIndex" if loops over foo and bar collections are both in play. That beats the hell out or trying to parse "i" and j" as indexes over two collections.

The simple rule is that the larger the scope of the variable the longer the name - i.e. the more widely references to the var occur, the further they are from the definition, the more descriptive the name has to be.


So I suppose this leads Rob Pike to use one-character names for all the variables and functions in his programs?

Such programs must be a joy to read.


His code actually _is_ a joy to read and use. Some of it requires more than a passing scan. But that's true of any code worth reading - if you don't need to scan it twice, it's most probably useless and bureaucratic, and could be done away with if a better design is used.


I very much doubt his code is both a joy to read and made up exclusively of one-character variable and function names.

It's one or the other.


His local indices are usually one letter (i, j, k), his local counters are usually one letter (m, n). His accumulators are sometimes one letter - much like math expressions.

He gives a more descriptive names to variables that live for more than a 10 lines or code or so.

And that's way more of a joy than reading a Java sourceful of "indexThatGoesSourceThe2ndArray"


I really don't get what you're driving at here.

Are you claiming there's a java language requirement that array indices are named with more than one letter? That's not what the screen in front of me says.

"He gives a more descriptive names to variables that live for more than a 10 lines or code or so."

Ok, now we're talking. I like go and Rob Pike's reputation speaks for itself but don't put words in the guy's mouth, go has strong typing in a way that's much more similar to Java than whatever your pet language is, the major difference is syntactical sugar that infers types more often, and a looser contract for interface (both of which I agree with).


> Are you claiming there's a java language requirement that array indices are named with more than one letter?

No, but it _is_ common practice to name things with long names, rather than one letter, even if they are loop indices. E.g., in the FLTK source code, most objects inside a short loop are called "o", e.g., things like

   for (Widget o = window->first(); o; o = o->next()) {
     o->activate();
     o->show();
   }
I think that is extremely readable, 'o' in my mind stands for object in the same way that 'i' stands for index. Have you ever seen Java code in the wild that follows such a convention? I haven't -- it's always things like theWidget or even theChosenWidget instead.

> I like go and Rob Pike's reputation speaks for itself but don't put words in the guy's mouth

Please don't put anything in my mouth. I'm paraphrasing pike, you may disagree with the paraphrasing, but I was referring to, http://www.lysator.liu.se/c/pikestyle.html , specifically the section titled "Variable names". It's about C, and predates Go by some 18 years (and Java by 6). Not any "pet language" of mine.


Ok, well I was talking about type systems. You were talking about the fact that it's dumb to have long variable names for loop indices.

I agree. Everyone on earth agrees with you. I don't know if I've ever in my whole career seen a >1 character loop index variable name. Congrats.


Close. Which is what I don't like about the samples that I have seen in his Go language. Code like "Fmt.PrintF" seems a step backwards to me.


I think the verbosity complaint here isn't about the length of the name, it's about having to repeat the type and generic arguments.


Yeah, repeating the generics is cumbersome and we could do with a better syntactical sugar for that.

Typically, the type's only reapeated if you're assigning to the same exact type as your constructor. In most cases, Map<K,V> foo = new ConcurrentHashMap<K,V> is more idiomatic than typing ConcurrentHashMap twice. Although concurrent is a little special because it's an implementation detail that you sometimes want to enforce via types.


Doesn't Java have any kind of type inference for variables yet? C# allows you to say

  var foo = new Dictionary<string, int>();
and foo's type is infered as Dictionary<string, int>


I would argue that you don't really need to, since auto-completing code editors and displays with enough resolution to support more than 80 columns are pretty ubiquitous.


Just declare a new class with a short name that extends ConcurrentHashMap<String, Integer>.


I'd write the code in Python (or indeed any sensible modern language).

   foo = {}


What if you want to create an instance of other type of dictionary? {} works only for built-in dicts.


and then you get an int instead of a string and your python app explodes. let's not start on "sensible modern" languages.


Yes, you do get bugs in Python due to variables being the wrong type... however the time it takes to fix them is vastly less than the time it takes to write the reams of boilerplate that Java requires (not to mention the cognitive overload caused by said reams of boilerplate).

My ideal would be an optionally typed language.


I don't think it is an issue of technology (typedef, etc...) as much as an application target issue. Using short names in a language without any kind of namespace support can only work for a certain type of applications and developmenent organization.

C really shines for low-level programming: while something like Linux Kernel is extremely complex, it has relatively simple needs as far as interface goes. The public interface is very small (defined by system calls - I don't know the count, but suffice to say the most trivial python libraries will often have more functions). Same thing can be said for other applications where C has been very successfull for.

But something as fundamental as a lack of any namespace in C really hurts when you need to handle very large applications which cannot be easily split in very well defined components with small interfaces. Complex GUI and browsers come to mind, which is exactly the kind of things where C++ is a well accepted choice.


> But something as fundamental as a lack of any namespace in C really hurts when you need to handle very large applications which cannot be easily split in very well defined components with small interfaces.

There is a degree of namespacing in C. Each compilation unit introduces own, anonymous (cannot be addressed/indicated directly) namespace. Symbols defined `static' (``having static linkage'', actually) reside only in it, and are not visible outside of that namespace. Symbols with external linkage are the API of the namespace. It may sound strange, but it's perfectly OK to have symbols with same name in several namespaces, as long as they are static (residing only in it); no conflict because they are not addressible from outside. In a way, a C's compilation unit is similar to C++'s class -- static (C) / private (C++) elements are visible only from this compilation unit (C) / class (C++).

So yes, you can easily split any C application into well defined components with small APIs, without risk of collision between names of private symbols. You only need to ensure unique naming among the `public' API symbols.

Linker use and linkage is a lost art those days, eh ;-(


I know very well about the use of static within compilation unit, but I was referring to "public API" (more exactly: API between components of your application).

This is especially excruciating once you need to use various libraries outside your control.


I also tripped over this argument in the first chapter, but it should be emphasized it's an exception of a bad argument in the book, not the rule. The author would have been wise to avoid this red herring.


I don't know for Java (luckily haven't been using it much) but for C I dislike typedefs. I need to know what data I'm working with. A typedef hides that information from me behind a shiny but uninformative name.


I mostly agree, except for function pointers. The C idiom of typedefing a function-pointer type results in code that looks more readable to me (e.g. prototypes of functions that take a function-pointer parameter have "typename varname" syntax) compared to the somewhat odd syntax you get if you scatter around function-pointer types inline.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: