Variable does not exist while it clearly does
-
Hello !
Still working on my morse training thing, this is really turning out longer than I expected...
Anyway, I coded a function to generate a list of random words in the form of an array or a string :function getRandomWords(nb, //number of words to generate lng, //language selected, 0 for English and 1 for French typ) //typ = 1 for array, 2 for string with spaces if typ == 2 then result = "" else result = [] endif for i = 0 to nb loop if typ == 2 then if !i==0 then result += " " endif > result += langs[lng][random (len (langs[lng]) -1) +1] else result[i] += langs[lng][random (len (langs[lng]) -1) +1] endif repeat return result
But when I run it with typ = 2 it gives me this error :
LINE: 256 (the one with the arrow) FUNCTION: getrandomwords ---------- Variable does not exist: result
I have absolutely no idea what could cause this error in my code.
This is probably very simple but for some reason I've been searching for a long time already and I still can't seem to find, so any exterior help would be appreciated.Thanks ! (and sorry for making such a long post for this, I'll delete it if it was a dumb error of mine)
-
So the faulty line is probably:
result += langs[lng][random (len (langs[lng]) -1) +1]
This line has a lot of code in it, so let's break that down:
language = langs[lng] // this is the selected language array count = len(language) // this is the amount of elements in this language array (0 if none, 1 if one, etc) index = random(count - 1) // if count is 2, then 0 and 1 are the valid indexes, but 2 is to high, so we get a random index using "count-1" word = language[index + 1] // we get a random word using the random index, but we add 1 again result += word // we add the random word to the result.
The above code does effectively the same as the single line, but maybe it already clarifies some of the problems with it:
What happens if the count is 0 or 1? Then you would never get a valid index to work with with the code in it's current state. You could choose not to check it, especially if that would result in the same preconditions in a whole bunch of functions that would never be true. And maybe you actually want an error to occur since the situation is already bad and not getting any better. Those can be considerations not to write defensive code. But in general it's a good practice to consider what code should do when things are not right.
However, I think that the actual issue is that you have a +1 in that line. This means that index 0 is never read, and there is a chance that the index becomes
len(language)
, which is actually too high. If len(language) == 2 then you don't want to read language[2], you want to read language[0] or language[1] :)Hope that helped :)
-
It sounds like it's going out of scope so if you insert
result = " "
at the beginning of the function it should fix it.
-
@PB____
I actually added this because the first (or 0th) value of the language array is the name of the language ("English" or "Français") and so I don't want it to be used as a word by the program. I did this to be able to use all the values in the array except the first one, which is why I added +1 and then -1 to counter the "array out of bounds" error. -
@Richard
That worked, thanks ! Although I don't really understand why... -
I'm sorry, I wasn't well rested when I wrote that reply and didn't think about it that random already excludes the given number.
A code block can be for instance the code that belongs with a loop or an if statement. The block would for example start with the
loop
orthen
keyword and end with respectively therepeat
orendif
keyword. If you use a variable for the first time within such a code block, then that may become the scope of that variable.// global scope example int resultA = 0 // this variable has a global scope, because it's first used in the global scope. function exampleA(test) if test then resultA = 1 endif return void // no need to return resultA, because it's a global variable and can be read anywhere exampleA(true) print(resultA) // function scope example function exampleB(test) int resultB = 0 // this variable has a function scope, because it's only used (and declared) in the function. if test then resultB = 1 endif return resultB // if we don't return the value of resultB, it will be lost, because the variable resultB will no longer exist. int b = exampleB(true) // print(resultB) // this will throw an error, since resultB no longer exists print(b) // this will work // block scope example function exampleC(test) if test then // start of a block int resultC = 1 // this variable only lives within this code block and gets cleaned up when 'endif' is reached endif // end the first block if !test then // start the second block int resultC = 0 // this variable is also called resultC but it lives in a different code block, it's not the same variable. endif // end the second block return void // resultC doesn't exist here anymore, it's value has already been lost
To avoid confusion, I recommend to always declare variables at the scope where you intend to use them, before you actually use them. But you don't have to. You could just as well assign it a value, as Richard mentioned. And all credits to his find as well.
-
@PB____
Thanks for the help ! I think this had already happened to me before, but now I understand why. I wasn't aware you could declare a variable as local to a specific code block. -
Thanks for this post! I'm a programmer in other languages and always want to limit variables with global scope. I hadn't seen scope discuss in any videos or literature yet, so I was concerned about this topic.
-
I just thought of something else on this topic, in regard to "if-else", and it really is a personal preference, but... If I have a value that can only be 1 of 2 values, I do declare it with one of the valid values, then only do the "if then" block for the condition that would set the alternative value. I just don't like the "else" side for only setting a single value.
-
Hmm, I wonder if you gain any execution speed by doing that?