A Guide to Naming Variables
a-nickels-worth.blogspot.com
a-nickels-worth.blogspot.com
I have real trouble with single-letter variable names like "c", for any function more than, say, 2-3 lines. I scan the code and it increases my mental load because I have to remind myself what it means.
Obviously a lot of people don't have problems with this, but I do. Anybody else?
Maybe it's because I jump around a lot from function to function?
Unless it's a very obvious index for a for loop I am against single letter variable names. Hell even if it's a for loop, if the code is so long within the loop that I have to scroll then I think the variable names need to be more obvious to keep the context with it as you scroll away from the declaration of the for loop.
Or you could use a decent editor, that keeps track of variable scopes.
Are you suggesting doing a find / grep inside the context of a current scope? Or just color codes / indents / marks in some way the scope? That works to a degree if an editor can do that though that still doesn't ultimately help the fact that it's a single file that you may need to search around for something. Plus not every environment will have your favorite editor setup how you like it.
At least IntelliJ will highlight all uses of the currently selected variable/method/whatever, and will quickly allow you to jump to any of them.
If I'm searching for something by name then it's almost always because it's in use somewhere, and a ctrl+click will take me there instantly, without getting bogged down in false positives.
> Plus not every environment will have your favorite editor setup how you like it.
Sure, but how often do you actually have to work with your regular codebase in such an environment? Sure, such a rule has its uses, but in 97% of cases it's just a symptom of a poor editor setup.
If there were more than one collection, or we weren't using it in a way that makes it obvious it must be a collection, I would want a better name.
If you see collection.size(), you don't even need to think; the meaning is right there in your field of vision and you don't need to dedicate one part of your extremely limited short-term memory to remembering what c stands for. I can't see any advantage to shortening it to c, apart from saving a trivial amount of typing.
Although there are some single characters that do have meaning due to long time convention such as 'i'.
For example:
function flip(func) {
return function(x, y) {
return func(y, x);
};
}
function compose(func1, func2) {
return function(x) {
return func1(func2(x));
};
}
Code like this is completely generic; we know absolutely nothing about `x`, `y`, etc. other than they're distinct arguments; we don't even know their type (they're "parametrically polymorphic").Would it be better to call them something like `arg`, or `arg1` and `arg2`? The fact they're arguments is obvious, so that would be just as redundant as something like `int int1 = ...`.
This kind of generic "plumbing" appears all the time when using a functional style, where our function's job is to take in a bunch of values and combine them in some way, without caring what they are.
Also, I would even argue that x and y are not meaningless in this context. There's a reason you didn't write:
function flip(gnarf) {
return function(t, m) {
return gnarf(m, t);
};
}
function compose(bip, boop) {
return function(blep) {
return bip(boop(blep));
};
}
The sequences {a, b, c}, and {i, j, k}, {m, n}, {p, q}, {x, y, z} are all well-established "abstract" variable names that most of us remember from high school algebra, and all have different baggage and expectations:- a, b, and c tend to be generic labels for things, not numbers
- i, j, and k are used for indices and tend to be natural numbers (or more rarely for complex numbers/quaternions, where they are floats)
- m and n are used in matrices and also are used for natural numbers
- in maths, p and q are often fractions
- x, y, and z tend to represent coordinate systems and/or floating numbers
We can combine this to create variable sequences, with subtly different meanings. For example: compare (x1, y1), (x2, y2) with (xa, ya), (xb, yb). To me, if I see foo(x1, y1, x2, y2) that implies either top left, bottom right in an axis aligned bounding box, or perhaps the first point and the second point of a line or vector, or some other situation where the two points are somehow connected in one object or shape. Using (xa,ya) and (xb, yb) however suggests I'm dealing with two distinct points.
function compose(f, g) {
return function (x) {
return f(g(x));
};
}There are a few situations when this is the case: on top of my head, (i) function arguments, (ii) implementations of mathematical formulae that already have standard conventions for notation, (iii) cases when longer variable names are not well chosen and don't tell us much (e.g. his "processElements" function is far, far easier to read than "doSomethingWithCollectionElements"), (iv) situations when there are multiple long names that only differ in the last few characters -- again, I would much rather see "in_x" and "in_y" than "ThisHereInputCoordinateX" and "ThisHereInputCoordinateY", particularly if these are a part of a formula with a few other variables involved.
Might be just me and how I read things, of course -- e.g. I usually print stuff in the smallest readable font, so that I can see more of the logic at the same time, and this is definitely not the case for all people.
In general, much prefer languages where I don't ever have to index. E.g. list comprehensions are much more expressive
-loops (for i = 0; ...)
-scientific variables, in which case they should probably be constants anyway (c = speed of light in a vacuum)
bool productPricingUpdatedAfterDeliveryFailedButEmailSent = false;
I've seen variables with names like the above. It would have been better explained in a comment and used a short variable name. Unless you like typing it forces you to use an editor with autocomplete (which you are crazy not to use one), and IMO pollutes the code. Variables should be easy to type and read. It's a trade off.Single letter variable names are okay for loop iteration variables, or e.g. x and y when dealing with 2D coordinates (i.e. if within the context a single letter name has useful meaning - I suspect physicists and the like find themselves in that situation often).
But trying to give variables short names (which is a good thing) should not be an excuse to give them obscure names.
As an extreme example, think of Perl, which has a "default variable", that has basically no name at all ($_). When used properly, one can, I guess, write marvelously succinct code, but I try to avoid it and use explicit names.
The older I get, the more I tend to agree with Aristotle's general approach to ethics: Avoid extremes, seek a middle ground/moderation. I am not sure if it is a good ethical principle, but in many cases where ethics don't matter, it is a good guideline.
So for Identifiers: Be short, but clear. When in doubt, choose clarity over brevity, but keep in mind that what might be clear to you could be highly obscure to somebody else. If at that point I was still in doubt, I would pick a name based on how the variable is used: The more rarely it used, and the more significant it is to the program, the more reasonable it becomes to use a verbose name, especially when it is a global variable. For locals, one can always use a short name and a comment to explain what role it plays.
This kind of thing can be broken into multiple Booelan variables:
bool pricingUpdated;
bool deliverySucceeded;
bool emailSent;
These can be initialized or assigned at various points in the flow. Then later we can have: if (pricingUpdated && !deliverySucceeded && emailSent) ...Also, on the flip side, if say my chunk of code is solely dedicated to operating on a single object I'm totally fine using a one-letter name for those vars as well. Like say 'Person p' or 'WebView w' etc.
These are notable exceptions though, at least as far as I'm concerned.
Here's how you calculate the absolute value of an integer: -> "if it's non-negative, return it; if it's negative return its opposite".
Here's how you calculate the absolute value of an integer if you're using any programming language written in 60 years: -> "if (argument <= 0) return argument; else return argument * -1." (or some variation)
There is literally no way to refer to "it" instead of "argument" except by changing "argument" to read "a" (or "i" or "x" or "$_" or...)
My point is that it's literally impossible to write "if (it > =0) return it; else return (it * -1)" if you've just mentioned "it" and you are there to check and correct the IDE if it's wrong. (Oh, wait, I should write "to correct the IDE if the IDE is wrong.")
I bet 90% of human languages have a way to refer to something you've JUST mentioned without repeating a word for it. (Words like it, that, etc.) I bet 0% of computer languages let you write "it" for the last thing you just referred to, even if there is literally 1 choice in the whole function, as in my absolute value example.
Ridiculous!
I bet it's harder than you think.
Also, IDEs are better than they used to be - I stopped using them because they caused problems in the late 20th Century. There was a proliferation of them until Eclipse got good enough to not cause problems. Eclipse still had less text editing power than some just-plain-old-editors from the 1980s. So I only use an IDE if it's the only logical choice for a development system. It usually isn't.
If, as in one shop at which I worked, you constantly write, say EMACS macros and use them a lot, you will evolutionary drift away and it will make your team more and more ... linguistically isolated, which has costs in onboarding and this sort of mild narcissism about your setup.
I think that dependence on an IDE is mostly a weakness, not a strength.
OTOH, I don't remember which one does that, and its a pretty-much completely search-proof topic.
Wolfram includes the % keyword for the last result generated, IPython has something similar within their notebooks, R has the .Last.value keyword, Matlab has ans, and many other languages often used from a REPL probably have similar constructs.
0: https://developer.apple.com/library/mac/documentation/AppleS...
#include <stdlib.h>
#include <stdio.h>
#define dry(x, test, if_true, if_false) ({ \
typeof(x) _x = (x); \
(_x test) ? if_true(_x) : if_false(_x); \
})
#define abs(x) dry(x, < 0, -, )
int main(int argc, char **argv) {
if (argc == 1) printf("usage: %s num [num]...", argv[0]);
for (int i = 1; i < argc; i++) {
char *string = argv[i];
int num = atoi(string);
printf("string '%s', num %d, abs %d\n",
string, num, abs(num));
}
return 0;
}
$ gcc -std=gnu99 -Wall -Wextra -O3 -g dry.c -o dry
$ dry 2 1 0 -1 -2
string '2', num 2, abs 2
string '1', num 1, abs 1
string '0', num 0, abs 0
string '-1', num -1, abs 1
string '-2', num -2, abs 2Two years from now, I'm not going to be able to remember "c" from "v" without having to think harder than I have to.
If I name the variables something like what they actually mean or do, however, that's much better. I know what "particle_count" is more so than "p".
You should look at old school DSP code some time. :) Some of that is translating from variable names in mathematics papers.
Also - for us old guys, you could take typing or you could take a math class, so many of us never really learned to type properly. So typing can be an actual consideration. Schools adapted to this later.
I feel that is sort of a valid exception. If it is common notation in the field you need to be familiar with anyways or you are implementing from a specific source, not using short names adds another layer of mental translation. If I'm implementing an algorithm from a paper I put an "implementation based on: <citation/URL>" on top and try to match it as closely as possible. (DSP code probably doesn't do the latter, because performance, but where possible)
for c in customers:
do_something(c)List<Host> hosts = hostService.fetchMatchingHosts(hostFilter);
Set<JVMVersions> versions = JVMServiceFactory.factory(region).getApprovedVersions(),
List<AvailabilityZone> zones = RegionFactory(region).getZones();
return hostUpdater.updateJVM(hosts, versions, zones);
to this
List<Host> hs = hostService.fetchMatchingHosts(hostFilter);
Set<JVMVersions> js = JVMServiceFactory.factory(region).getApprovedVersions(),
List<AvailabilityZone> zs = RegionFactory(region).getZones();
return hostUpdater.updateJVM(hs, js, zs);
The top version means I can read the return line by itself and get a feel for what it does without having to skip back up a few lines. And while there definitely is a tax on longer variable names, I usually don't feel that way with single words.
The brain chunks small common words, so hs probably takes just as much if not more working memory than hosts.
Footnote : Just while writing this I had to look up a couple of times to remember hs, js, and zs. But I never hard to look up to to remember hosts, versions, and zones.
If you're grepping/ag'ing for c you've got another issue, because I can't think of the context that you would grep c in a function that fits on less than 2 24-row terminal screens. At worst, /c and a few presses of 'n' is all you need once you get to the function.
If you're outside the function grepping, it's because you saw printNFirstIntegers(4, someOtherVariableName). You'll hardly have named the variable (or collection literal) "c". So you'll be using ag printNFirstIntegers.
To me, your request is akin to the last time I had a code review for a rake task and someone complained about the 'f' in:
FileList['deploy_assets/ebextensions/*'] do |f|
@helper.process_template(f, ".ebextensions/#{File.basename(f)}")
end
Calling it File is horribly obvious and annoying.Edit: The function name probably should be run_erb_on or something like that. None of us are free of naming sins. Lol.
There are some cases where short variable names make sense. In the example the loop index is called "i", and that's good. It's good because it's just an index. The only reason it's there is because the looping construct isn't expressive enough for the desired loop semantics, so the short name means you don't have to care about it.
The use of "n" is also alright. It describes a number, for which "n" is a convention.
"c", on the other hand, is a horrible name. It's worse than "collection", because it's important and the scope is large enough that it's hard to skim for. "collection", however, is also bad. The variable doesn't just refer to a collection, it refers to a collection of integers. Why not call it "integers", or "numbers"?
I find conventions around this to really influence the readability of the average code in different programming languages. Lots of Haskell code can get away with short variables in small functions. Their scopes are small, their purpose is incredibly generic. C code often uses short variable names despite not being concise nor generic, making it unnecessarily hard to read. Common Lisp tends to use descriptive names. It's dynamically typed and contains little type information, and yet you always know what you're working with.
Avoid Over-used Cliches
In addition to not being Teutonic, the following variable names have been
so horribly abused over the years that they should never be used, ever.
val, value
result, res, retval
tmp, temp
count
str
Cliches? If you are trying to communicate, these names are well known ways to do that. If there is something more specific to put in there, by all means, but I often find these names useful, combined with a good function name and docs of course. Thoughts?https://en.wikipedia.org/wiki/Swap_(computer_science)#Using_...
When I'm mapping an array of line items with lodash, the predicate parameter is usually named "item" because it is short and perfectly adequate in context.
Let's say you're writing C and you want to return status information from processes as integers. Instead of:
> return retVal;
where retVal could be 0, -1 or -2 to indicate success or failure of the function, how about:
> return functionStatusCode;
? Or be even more specific (let's say the function tried to parse some text) with parserStatusCode.
All of those are more helpful than retval, because they give you some sort of idea as to what you're returning. You'r enot returning how many values were parsed, or some sort of information about what you parsed, you're returning the status of the parsing function.
The meaning of those values is probably a little harder to encode in the variable names (especially if there are many such values), but that's what the comments are for.
Let's say it's Python now, and for some reason I'm still returning 0, -1 or -2. Then 'statusCode' would be a good name for the variable I guess. The code part indicates that it's a codified version of the status. The smarter way might be to just return a status object or something, in which case perhaps 'statusObject' is better? Not sure.
I guess one thing I took away from the article is that it would be nice to be able to encode _how_ the data is being returned in the name of the return value. This saves me going and finding when the variable was created to get its type, or when the variable was assigned to.
Now, if the internal variables require a "data dictionary" level set of comments, that's another matter. Something is (usually) wrong in that case.
But, sometimes I use generic names on purpose, so that I can factor the code into something general.
Repeating that in the return value variable is then redundant.
I like naming my result variables `result`. It makes it clear when you first see it what it's for, without having to read the function to the end.
But "value" is horrible. You really don't know what it is? You might as well name it "variable". "Str" is in the same boat, unless it's short for "tmpstr".
What if I don't? Some of us program more abstract things than the others. For example I might want to write a function, that given a tree, and, well, a value, returns a tree where all nodes that have this value are removed. Doesn't matter that the tree in question will in practice be a tree of Flooblooators, I'd rather write reusable code that works for everything.
(Similarly with data: lots of times, I've seen specs where a composite structure had a part called "data". Whether or not that is good naming in the spec, if I'm implementing the spec, using "data" for the element in the program corresponding to that part of the composite in the spec is clearly the exactly right thing to do.)
> I declare The World's Worst Variable Name to be:
$data
> I declare The World's Second Worst Variable Name to be: $data2
I would lump in "value" with those two.[1] http://archive.oreilly.com/pub/post/the_worlds_two_worst_var...
int sum(Collection<Integer> c)
{
int retval = 0;
for(int i = 0; i < c.size(); i++){
retval += c.get(i);
}
return retval;
}
What the hell should I call retval? If I call it sum, that's redundant with the method name. Also, while it might work in Java, it would be more dangerous in a language like Ruby where the equivalent code: def sum(c)
sum = 0
c.each do |e| retval += e end
sum
end
would, due to lexical scoping, make it impossible to call the method recursively.- "val" in "retval" carries no meaning. Everything stored in a variable is a value.
- "ret" is an annoying abbreviation for "return" that makes it harder read.
- "return" focuses on an implementation detail—that the function produces its value using the language's "return" statement. It doesn't matter how the result is emitted, just that it is.
If a function is simple enough that the variable storing the result doesn't need a more specific name, "result" is a good default. You could call it "sum" here, but that shadows the function itself—a common problem for result variables—and doesn't really tell us anything we don't already know. We know we're inside a "sum" function.
One of the best ways to calculate something is to build it up line by line. It makes the code really easy to follow. Also see my other comment about languages lacking "it", "that", etc. Result is sometimes a good substitute!
const int timeout = strtol(argv[2], NULL, 10);
send_and_waitfor(&msg, timeout);
When I read this code, should I take for granted that the caller and callee are using the same order of magnitude that's intended?If instead I see
const int timeout_ms = strtol(argv[2], NULL, 10);
send_and_waitfor(&msg, timeout_ms);
then I can quickly audit whether the inputs and outputs actually preserve the convention.It's a shame that C ... Java like languages became dominant, in that they "hide" identifier names after the type types, rather than putting the identifiers at the start of a line where they are more visible. (thank God for type inference, I guess, in newer languages)
Also, I find CamelCraps an impediment to scanning the names in code, as well. This is less of an issue when the name is one word, but "we" sure seem to like our AdjectiveAdjectiveAdjectiveNoun names in Java-land :-(
E.g. -
qualifier qualifier AdjectiveAdjectiveAdjectiveNoun adjectiveAdjectiveAdjectiveNoun = new AdjectiveAdjectiveAdjectiveNoun(42)
Or was I supposed to @AutoInject that?Please, just shoot me now.
Compare for example English with Spanish, Italian and Portuguese:
en es it pt
I go voy vado vou
He/She goes va va vai
We go vamos andiamo vamos
They go van vanno vao
While the Romance Languages are very similar, English is completely different. int printFirstNPositive(int maxToPrint, Collection<Integer> c)
The method name uses "N", but the param for N is named "maxToPrint". Confusing and also violates his/her wasted space rule.Instead:
int printFirstNPositive(int n, Collection<Integer> c)
I think the short variable names "n" and "c" are fine since they are part of the method signature and have unambiguous meaning, and also because the implementation is so short (so no problem remembering that n and c are the inputs. for fruit in fruits:
assert fruit is not 'apple'
print(fruit)
assert 'banana' not in fruits
etc. Especially in Python, it makes code flow very much like English.Edit: It also goes with the "don't put the type in the name" point, which I agree with in most cases. Depending on your use case, it most likely won't matter if fruits is a list, tuple, set, generator, whatever. The plural implies an iterable interface. However, if the type does matter, I will often use it in the name (in a dynamic lang like Python).
This is also useful when you have two types of collections in the same place, such as an array and dictionary.
for fruit in fruit:
print(fruit)
My brain is screaming at me right now that the above doesn't make sense. Even with a click glance, it sticks out like a sore thumb. I'm not entirely sure why, but I'd guess it's because it mimics natural language more, so my eyes are more used to parsing that for mistakes?`movie_collection` vs `movie_collections` is a bit trickier
> It also goes with the "don't put the type in the name" point, which I agree with in most cases.
Is that a problem in practice in Python? That's the whole reason Perl uses different sigils to denote different types of variables, which Python specifically rejected. Personally I prefer being able to tell if something is a collection, and which core type of collection, at a glance (barring refs).
That actually does allow the same name to be used as a scalar, an array and a hash, but it's considered very bad practice.
# Valid perl, but will get you nasty looks from coworkers
my @fruit = qw( apple banana banana apple apple mango apple mango banana );
my %fruit;
for my $fruit ( @fruit ) {
$fruit{$fruit}++; # increment %fruit hash item $fruit
}> I prefer being able to tell if something is a collection, and which core type of collection, at a glance (barring refs).
Not really a problem, but if you're writing more than a one-off script, such as a module you plan on sharing, it may be common that you get a mixture of concrete types coming in depending on the app and platform. I think in practice, it's actually beneficial to assume you do not know the core type of collection (if your operations will work with many/all of them).
For example, a range object or generator in Python 3, but a list in Python 2. And then someone else comes along and uses your modules with sets.
So with "fruits" (or something like "fruit_iter" for anyone who disagrees with plural naming), you know that you can safely iterate through it. But you may not be able to do random access, or reassignment of elements. There might be times when this matters, in which case you'd want to enforce a specific type.
The only thing I do not like about this is that in Python strings are also iterables. So the difference between passing "Apple" and ["apple"] can be quite large, and yet your program will iterate through "a", "p", "p", "l", "e" with no complaints. The worst experience I've had with this was working with a web API that would return either an array of strings, or only a string if there was one result (not a 1-element array), or a dictionary of objects if there were many results. 99% percent of the time it returned the array of string, and since strings and dictionaries are iterable, it took me a while to notice the bug.
I ought to learn Perl, because that's pretty cool. You're right that that example is terrible to read, haha, but I'm sure there are scenarios where it's helpful.
This touches on a big pet peeve of mine, and coincides with some ranting I was doing on the Scala Native post the other day. :)
Languages that support coercion should try to make sure they don't overload core operators for different types of operations for different core types. E.g. '+' for numerical addition and string concatenation (one is commutative, the other is not, and if you decide on which action to take depending the order of variables, that's confusing), or ==/!= for string equivalence and numerical equivalence (10.0 and 10 are numerically equivalent, but for strings we generally want an exact match).
Having an iterating operation work on a string without any preparation is one of those things that seems simple and useful, but likely causes a lot of confusion in dynamic languages in practice because you lose track of exactly what it's possible a variable can hold because it's often dependent on the return value of someone else's function. I imagine exposing a method on strings that returned an iterable interface, and requiring that be the method you iterate over a string, would reduce that confusion quite a bit.
> I ought to learn Perl, because that's pretty cool.
I think it's worth picking up the core concepts for anyone, because there's a few concepts (e.g. context) it implements as core parts of the language that are still rarely used elsewhere. Unfortunately, its hybrid beginnings mean that you can largely miss the importance of things like context early on because the code looks enough like what you are used to that you assume it works the exact same way, and 95% of the time that's true. The other 5% will leave you scratching your head and wonder why Perl seems so stupid or inconsistent, when really your mental model is wrong. List and scalar context and how they apply to the core types should be the first learning item on a new Perl programmer's list if they know another C-like language.
Are you sure? I could have sworn that I'd seen this as actual style advice in the Camel book. A trip through `perldoc perlvar` (http://perldoc.perl.org/perlvar.html) shows that, at the very least, Perl itself doesn't abide by this convention; for example, we have the scalar `$ARGV`, the list `@ARGV`, and the filehandle `ARGV`.
Sigils allow you to separate variables into different namespaces. It's
possible–though confusing–to declare multiple variables of the same name
with different types:
my ($bad_name, @bad_name, %bad_name);
Though Perl won't get confused, people reading this code will.
There are plenty of things that are shown as possible in the Perl docs, and only slightly less things recognized as generally a bad idea in most circumstances. Instead of Python's one way to do it, there's really more 1 to 3 accepted, idiomatic ways to do it, and another 2-3 that are considered "situationally acceptable" (those odd cases where it actually makes things more readable, etc). There's often a couple ways that are deemed generally just a bad idea, or at a minimum, still waiting for that special case where they can shine. ;)1: http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf (But you should buy it if you are interested, chromatic knows what he's talking about).
Notice, though, that I'm not talking about the Perl docs merely noting that it's possible—I agree that the spirit of the docs is more "look what I can do!" than "look what you should do." I'm talking about what Perl itself does (with the use of `$ARGV`, `@ARGV`, and `ARGV`—although maybe `$_` and `@_` is a better illustration).
chromatic is an excellent programmer, and I certainly respect his voice on Perl over, say, mine, but I feel that he is rather strict, and I do not take his opinions as necessarily representing those of the larger Perl community, as exemplified, among many others, by Wall, tchrist, Conway, and/or merlin.
I suspect that's a combination of Perl's influence from awk (@ARGV), wanting something easier than awk's ARGIND for the current index in ARGV, and wanting to try out some of these new features Perl had in the beginning. I also suspect that things like this may be on the list of things Larry regrets about early Perl choices. I believe he's on record as saying he regrets the choice of sigil variance for array/hash and array/hash access (@foo as $foo[0] instead of something like @foo[0]). He's got good reasoning for why he chose what he did (based on language, it makes sense), but it's just overly confusing for beginners.
> although maybe `$_` and `@_` is a better illustration
I'm willing to give them a special case, because they are unique, as variables go (well, less so than they should be given Perl's many magic variables, but I think you understand my point). That said, I don't think many Perl programmers would argue that @_ was a better choice than @ARGUMENTS, or something equivalent.
As for assuming the docs in general reflect the current best practices.. I'll just note that the perlopentut man page still uses bare filehandles in the majority of its examples, and to my mind that was decided long ago as a community to be downplayed in favor of lexical filehandles (but for more practical reasons than what we are discussing, bare filehandles are globally scoped).
> chromatic is an excellent programmer, and I certainly respect his voice on Perl over, say, mine, but I feel that he is rather strict
I'm not going to argue with that. I respect chromatic's opinions on style and Perl 5, but I'm not entirely sure he's capable of being entirely objective with Perl 6 yet (which I can understand). He is rather adamant about what he believes are better approaches to a topic.
> I do not take his opinions as necessarily representing those of the larger Perl community, as exemplified, among many others, by Wall, tchrist, Conway, and/or merlin.
Fair enough, but I wasn't sourcing that believe from Modern Perl, just pointing to it as evidence. To be honest, I haven't read Modern Perl (but I've read a lot of chromatic's writing from his blog back in the day when he was writing it), I just assumed it might have something to back up my view, so looked in it. My view on variable naming here is perfectly capable of being more my own opinion that the community, and I was projecting. It's hard to know in Perl unless there's a discussion (and sometimes even after that), as what's acceptable is often a mostly overlapping set of best practices from person to person, but rarely are the sets of preferences entirely equivalent. :)
That said, Conway's Perl Best Practices suggests "Name arrays in the plural and hashes in the singular." It doesn't address our topic directly, but I don't know where my copy went (I sourced that from one of the many two page reference PDFs for PBP) and I don't recall the reasoning he used for that one. I wouldn't fault you for disagreeing with him though, I've shifted my view on some of his suggestions over the year towards or away from his suggestions (notably not using parens on built-ins, but I'm more in-line with his thinking now than I was a decade ago).
* it's a book for novice programmers, people with perhaps six months of practical programming experience
* it's a book for novice Perl programmers, people who don't have voluminous experience with the language itself
I believe programming is an exercise in making tradeoffs based on incomplete information. You can't teach the kind of good judgment that's based on experience, but I can try, at least, to guide novices away from some of the traps that they're likely to fall into. The subtleties of separate namespaces are difficult enough to learn on your own that it seemed worthwhile to advise strongly against name cognates.
I don't expect that Larry, Tom, Damian, or Randal follow my advice. I don't even follow it in my own code many times. It's not advice for experts.
I always enjoy your writings on Perl, even if I sometimes disagree with specific opinion-based recommendations (as is, almost by definition, the prerogative of Perl programmers), and I hope that I didn't seem to be knocking you or them. I was not even disagreeing with this particular advice, just saying that it didn't necessarily establish the attitude of the broader Perl community on punning in variable names. (There always will be code golfers who will value cleverness over maintainability—and there should be; without them we would never have such gems as `[$a => $b]->[$b <= $a]` for `min($a, $b)`.)
I like type systems when I play around with personal projects in well-typed languages
In addition you have some words that don't pluralize well such as fruit or Lexus.
In my opinion the more verbose and unique you can make your variable names the better, even if that means adding redundant words.
https://elms.wordpress.com/2008/03/04/lexical-distance-among...
I also love it when people use primitives for time spans along with the units in the name or comment instead of TimeSpan/std::chrono.
However, I disagree with the chapter "Remove Thoughtless One-Time Variables". I much prefer having a variable I can check in the debugger than having the result of some function passed into another function without being able to see what the value is. Any halfways good optimizer will remove the varibale anyway so there is no performance hit.
(And never use 'l' as a variable name; but you knew that already.)
Not only is this vaguely racist; it's also wrong, which is worse.
- English is, in fact, a Germanic language.
- Using more specific words (and English has lots of words) is the opposite of vagueness. A "sick house" could be a house that contains sick people, a house that is sick itself (rotten beams?), a noble family ("house") whose fortunes have turned, etc. A "hospital" is, unambiguously, a facility where the sick are given professional care. Of course, in a different timeline "sickhouse" could have been the word for "hospital", but then it would have been a word of its own, taking up the same amount of space in your mental dictionary as "hospital" does.
- Romance languages are, arguably, less vague even in their grammar. You know that thing where you just jam two words together and call it a day? You see very little of that in Romance languages. Instead, you put a preposition in there, which forces you to be more specific about the exact way in which the two things are related.
- Of course, a "Teutonic" fan would then say that this is a problem with Romance language, and the ability to jam words together is what makes a language truly rich. (Because it's easier to form new words? In which case, see item 2.) And sure, it's ok to have preferences. But if you're going to be a Grammar Nazi, or a literal Nazi, you better have a clue what you're talking about.
On your other point, at least German is very specific with how compounds work grammatically, namely that they follow a head-right principle which defines genus and declination and which essentially relegates everything left of the head to the status of further defining the head. Additionally, none of your examples work in German for the term "Krankenhaus" (sick house/hospital) for that very reason: a sick house (a house in disrepair) would have to be a krankes Haus following general rules of declension, which would also be the grammatically correct (though completely non-idiomatic) version for a fallen noble house. And while there is a very specific way that defines how stems of a compound are related, German can mark grammatical units differently from English (and akin to Latin) by requiring the agreement of case/numerus/genus between say an adjective and a noun, specifically making it grammatically impossible for krankes Haus to be understood as hospital or Krankenhaus to be understood as a dilapidated house.
edit: the above holds true for Norwegian and Danish as well, by the way.
(defun print-first-n-pos (n seq)
[(opip (take n)
(keep-if [orf zerop plusp])
(progn
(mapdo (op put-string `@1 `) @1)
(put-line)
@1)
(- n (length @1)))
seq])
$ txr -i first-n-pos.tl
1> (print-first-n-pos 4 '(-1 2 3 4 5 6))
2 3 4
1
2> (print-first-n-pos 5 '(-1 -2 3 4 -5 6))
3 4
3
Well, @1 is technically a variable. :) take n (filter (> 0) xs)In small functions, I wish variable names were automatic based on type. If a function has only one local of type T, it should automatically get name t or something.
For your standard crud app you could have a database record with field ORD_NUM, service layer with property OrderNumber, and in javascript orderNumber.
If all I do is live in one part of the stack this may not bother me. But when I have to add a new field and propagate it through the stack I cringe at every mapping.
Is it too late to camel case everything?
"Where does this idiom come from?" you might ask. Well, if I recall it's mostly due to languages like Fortran which implicitly typed identifiers starting with I through N as integers.
For me, the second block is more readable than the "good" example. It has issues, but it's more readable.
[EDIT add paragraph: Simonyi's overarching idea was to implement a novel solution to a familiar problem which I'll try to state as succinctly as possible: if two programmers are independently given the same programming task, and they turn out to write down the exact same code, you have won. Maintenance and working on other people's code is now solved if it's the same code you would write yourself. That's the problem he is trying to solve while also, incredibly, speeding up the process of independently writing code.]
https://msdn.microsoft.com/en-us/library/aa260976(v=vs.60).a... (please read past dr. dimento's introduction)
Pay particular attention to his notions of "type" that lead his naming system quite logically to very opposite conclusions as OP. He's not talking about underlying implementation types, he's talking about the properties of the abtract types that you keep in your head and only attempt to capture in code. Absolutely DO encode them in the name of the variable so it is completely unambiguous what you mean, so it's a contract you will live up to; not for communicating to the compiler, for communicating to other human beings: your compiler talking to other human beings is not that effective.
As a simple example, how many times have you said to your coworker "you need to pass me the file" to which they'll respond, "the file handle (by which they mean POSIX), the file name, the file path, relative, absolute, socket, URI, or do you mean the FILE pointer?" These are all notions of type that are best resolved with a shorthand unambiguous (and yes, local) language which is precise about type.
It helps you track meaningful distinctions and shed meaningless.
Bear in mind that this system comes from "the age of C"; as such, it helps make simple concepts that many programmers find disturbingling confusing: if "ch" means "it's a character", and p- as a prefix means "it's a pointer", then a "ch" and a "* * ppch" will have the same type. What are the attributes of that character type? You need to learn them or define them; I never said it was a C char and you shouldn't think that either; it will be only if those are the type attributes that are useful to your abstract type.
A discussion of what he actually said will be more interesting than a discussion of what you misunderstand.
But in response to the point you raised, the purpose of Simonyi's system is NOT to avoid compilation errors (what you call redundant). The naming convention encapsulates precisely what programmers need to keep in their heads while they code; humans are not compilers, and the type information involved is NOT THE COMPILER OR LANGUAGE TYPE, it is the abstract (human) type.
It is to (1,2,3 might not be all or the only reasons) (1) speed the coding task for the human (2) speed the maintenance task for the human and (3) enhance programmer understanding of the code to eliminate errors of human logic.
Easier perhaps, but certainly not solved. I often have trouble maintaining and working on code I wrote.
As a result I mostly ignore blogspot links. But this seems up my alley (http://akkartik.name/post/readable-bad). Anybody else run into these issues? Anybody have suggestions or workarounds? Why do technically savvy folks not notice how crappy blogspot has gotten?
Edit: PSA for blogspot owners https://productforums.google.com/forum/m/#!topic/blogger/8hN...
Same with Google Groups and some other Google products. It's super weird, they sit on a pile of money, hire thousands of 'best of the best' and can't get some simple things right.
Edit: Firefox on Android seems to eat much of the article in readable mode, while Chrome or Opera on Android seem to have none. So I'm back at square one..
And now, I want to highlight how difficult was for me to be an understanding and constructive member of society right now, and try to explain why you may be right in some cases, instead of why you're wrong in some other possibly larger number of cases, while foaming at the mouth with an eye twitching, which is what my first internet instinct was.
Nothing's ever perfect. But code can anywhere in a spectrum from good to bad, and we should always strive to reach the good side.
The age-old wisdom holds of course for so many cases, but writing code isn't always software engineering. Wouldn't you grant that it would be a mistake to instil the value that all code written must be carefully crafted? There'd be a ton of missed opportunities for creativity if the act of coding was so sacred.
There no argument for absolute quality in code, only value relative to its use case and context. Outside of correctness of behaviour and acceptable performance, the human-readability of code probably carries the most value in most situations.
Sure you can get by without it, but code that is readable will ultimately be more valued/reviewed/supported/improved.