1

Take the following code in C/C++, for example:

int foo[] = {0, 0, 0, 0};

No magic numbers, right?
Now, the Python "equivalent" of that would be:

foo = [0, 0, 0, 0]

Still no magic numbers.
However, in Python, that same thing can be written like this:

foo = [0] * 4

And now we DO have a magic number. Or do we?
I'm guessing this and other similar things are present on these and other languages.

Gerardo Marset
  • 803
  • 1
  • 10
  • 23
  • 6
    I have no idea what you are talking about. – Andrew Jaffe Mar 16 '11 at 00:07
  • Whats the question here? – AbiusX Mar 16 '11 at 00:08
  • 3
    I don't think this deserves to be closed, but I also don't think much of the quality of the question. It's too unspecific to have a good answer. – Omnifarious Mar 16 '11 at 00:08
  • This is a poor question, but it's senseless to close it before even giving the person a chance to clarify what he's talking about. – Glenn Maynard Mar 16 '11 at 00:17
  • The question is "Does the concept of “magic number” change from language to language?". I see no need for clarification. – Gerardo Marset Mar 16 '11 at 17:35
  • @Gerardo: But what is a "magic number"? – Andrew Jaffe Mar 16 '11 at 20:40
  • @Andrew: It's not something I randomly made up. I don't see how saying "magic number" is different from saying "Python", for instance. Granted, "magic number" has more than one meaning, however if you know the meanings you should be able to know which one I'm referring to by the context, just like you probably did when you read "Python" (which also has more than one meaning). And by the way, I don't mean to be rude, it's just what I think. – Gerardo Marset Mar 17 '11 at 21:27

5 Answers5

11

Not every number is a magic constant. The reason 4 and the four 0 are magic numbers (in any language) is that it's entirely unclear why that number is 4 and not any other number.

For example in the context of a game that is played with the well known six-sided die

def roll_die():
    return random.randint(1,6)

this code has no magic numbers, because it's very easy to see where the numbers came from.

On the other hand it can be hard to guess which numbers other programmers know. For example, not everyone might know the number of cards in a deck, so it makes more sense to use a named constant there.

It entirely depends on the context if a number is "magic" or not, it has nothing to do with the language. When in doubt, name your constants just to be on the safe side.

Jochen Ritzel
  • 104,512
  • 31
  • 200
  • 194
5

How's that different from (in C or C++):

int foo[4] = {0};

?

The size of the array is a magic number in all these cases.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • so we have to exclude array sizes explicitly from the definition of what a magic number is in order not to use one implicitly when using literals, right? – flying sheep Mar 16 '11 at 00:09
  • @flying sheep: If there's some structure to the initializer, then the size is no longer "magic", but meaningful. But there's no visible structure here, the size appears arbitrary. – Ben Voigt Mar 16 '11 at 00:12
  • 1
    Except `int foo[4] = {1}; //[1,0,0,0]` whereas `foo = [1] * 4 //[1,1,1,1]` – Andrew Marshall Mar 16 '11 at 00:12
  • @Andrew: So? The point is that all languages mentioned allow specifying the dimension explicitly. – Ben Voigt Mar 16 '11 at 00:13
  • The Python example isn't setting the dimension explicitly, it's explicitly initializing the variable to a specified array (`[0]*4`), the dimension is implied based on the size of that array. In the C/C++ example, the dimension is explicitly stated and the initial array is explicitly stated separately and need not have the same dimension as was specified. – Andrew Marshall Mar 16 '11 at 00:20
0

Magic numbers, by the way I understand them, are domain values (used in calculation, indexes in mapping elements). The idea of them is consistent throughout any language. In your example, it depends on what these arrays are for.

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
0

See the below code. It is a c language feature.

  int arr[] = { [0 ... 4]=3,[7]=7,[8 ... 12]=12,[15]=0};

is same as

int arr[] = { 3, 3, 3, 3, 3, 0, 0, 7, 12, 12, 12, 12, 12, 0, 0, 0 };

Prince John Wesley
  • 62,492
  • 12
  • 87
  • 94
-1

All your question shows is that the concept of "magic numbers" and rules against using "magic numbers" in your program are completely and utterly idiotic. Rules against magic numbers are poor approximations, by people who don't understand what they're doing, of a much saner rule against hard-coding in multiple places values which must agree or which depend on one another. For instance, this code is perfectly reasonable, as long as the buffer length does not need to match anything else in the program or real world:

char buf[100];
snprintf(buf, sizeof buf, ...);

But this code is highly bad:

char buf[100];
snprintf(buf, 100, ...);

Of course in the real world there probably is something you want the buffer size to match, for instance the max number of digits needed to print an integer of some particular size. In this case, you might want something like:

char buf[3*sizeof(int)+3];
snprintf(buf, sizeof buf, ...);

And if you consider CHAR_BIT to be variable then you might want to replace 3 with a formula in terms of CHAR_BIT. In any case, the constants appearing in the expression are not "evil magic numbers".

In your example, if the dimension of the array is dependent upon some other variable, then all three of your array definitions are bad practice. But if the dimension 4 is fundamental to what you're doing, I don't see anything wrong with it.

Of course, what you're doing can sometimes change during the lifetime of code, but that's what documentation is for. Code cannot be expected to handle ever possible future change-of-purpose without some level of modification, and as long as you documented what its original purpose and contracts are, it should not be hard for someone changing those to find the parts of the code that need changing.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 3
    @R: Whilst the second code snippet's certainly worse than the first one, I don't personally find either reasonable. The first snippet still makes anyone reading it question why the buffer is of length `100` - that information isn't contained anywhere in the code. It might well be unimportant, but the reader doesn't know that - it's important to tell them one way or the other (use a named constant, or at the very least a comment...) Code that doesn't document its assumptions wastes people's time and can lead to unnecessary bugs at a later date. – Stuart Golodetz Mar 16 '11 at 03:02
  • When you get the requirement to change **some** of the 100's to 256, how do you know which ones to change? – Bo Persson Mar 16 '11 at 13:19
  • I think I followed up on that in the third example. An explicit constant formula in terms of whatever the size is based upon is best. – R.. GitHub STOP HELPING ICE Mar 16 '11 at 15:58