Problem using a variable outside of the if statement its defined in

dagwood

New member
Hi there.

I'm having problems accessing a variable outside of an if statement. I'll try to explain a bit clearer....

I have 2 characters I play, and for breaky they both drink 9 bottles of the dusty wine that gives 5-7 adventures. The bottle is different for each character, so I do an if statement to identify who I am, then set the variable "dusty" accordingly. I then call the function "booze", and pass it the variable "dusty".

The problem I have is that if I call the function "booze" outside of the if statement, I receive an error saying "Unknown variable 'dusty' " (As in the code attached).

However, if I call the booze function immediately after I set the variable (within the if statement), it works. For some reason, it isn't passing the dusty variable beyond the if statement. I know the easy answer is to just do it this way, as it works.. but it just seems messy, and I want to use the variable more.

Does anyone have any ideas or recommendations? Any help is appreciated.

Thanks.

Code:
///// Breakfast /////

void booze(item dusty) {
	if(my_inebriety() == 0) {
		if ( item_amount(dusty) < 9 ) {
			buy((9 - item_amount(dusty)), dusty);
		}
		drink(9, dusty);
	}	
}

void main() {
	if (my_name() == "Character1" ) {
		item dusty = $item[dusty bottle of Pinot Noir];
	}
	if (my_name() == "Character2") {
		item dusty = $item[dusty bottle of Marsala];
	}

	booze(dusty);
}
 

Veracity

Developer
Staff member
Variables are valid inside the block in which they are defined. Once you leave that block - the closing curly brace - the variable is not visible, as you noticed.

Try this:

Code:
void main() {
	item dusty;
	if (my_name() == "Character1" ) {
		dusty = $item[dusty bottle of Pinot Noir];
	}
	if (my_name() == "Character2") {
		dusty = $item[dusty bottle of Marsala];
	}

	booze(dusty);
}
 

dagwood

New member
Thanks for the suggestion.

I've already tried defining the variable before the statement. At the end of the if, the item is "none". It still considers it freshly defined.

Didn't know thats how its supposed to work, that they are not available outside of the braces.
 

fronobulax

Developer
Staff member
At the end of the if, the item is "none". It still considers it freshly defined.
In your original example there are actually three different things all with the name "dusty". The value passed to booze() will be undefined or uninitialized and you will not get the expected result. If that is what you are saying then try veracity's rewrite. If you are saying something else or saying it based upon running the rewrite then please provide more information. It may be that your if statements are not doing what you expect, for example, which would not be a scope problem.

The times when a variable is declared, defined and has assigned values comes under the general concept of "scope" when talking about programming languages. A quick look at the wiki does suggest that the concept of "scope" in ash is not well documented.

My personal approach is to define every variable I use at the beginning of the routine that uses them. That is a hold over from programming languages that required all variables to be declared before use. The justification then was that the resulting code was more "efficient". I have retained the habit because it helps me organize my code and thinking and I don't introduce scope related bugs.
 

Veracity

Developer
Staff member
I've already tried defining the variable before the statement. At the end of the if, the item is "none". It still considers it freshly defined.
You didn't actually try what I recommended, did you? I suggest you look a little more closely at it. You will see that I not only defined the variable before the if statement, but I also removed your overriding definition of the variable inside the block, which is the source of your bug.

I disagree with fronobulax about always defining things at the top of the routine, but that's a personal choice. It would save you, if you don't understand "scope", but you're not going to get far in programming without understanding that concept...
 

dagwood

New member
I see it now, sorry about that Veracity. I looked over your code a few times for placements of braces, didn't notice that you'd removed the re-defining. Don't know how I missed that.

Thanks for your help.
 

fronobulax

Developer
Staff member
I disagree with fronobulax about always defining things at the top of the routine, but that's a personal choice.
:)

The days when I could justify that choice because the optimizing compiler generated code that fit in CPU pipeline cache if it did not have to allocate storage on the fly are long gone, but there was a time when it was a technical trade off and not just a personal preference.

My personal comfort zone leans towards strong typing and quasi-global scope but that is me.

My advice, which I am unlikely to follow personally, consistently, would be to declare something so that it has the minimum scope necessary to do its job. Declarations close to the point of use usually make for more readable code. I also advise the use of globally unique names so that there is no confusion between variables with the same name but (obviously) non-overlapping scope.

I note the veer and possible irrelevance of this response but I hope it will serve to remind me to look at what the wiki says about scope and possibly write something, once StDoodle finishes the masochistic labor of love.
 

StDoodle

Minion
I note the veer and possible irrelevance of this response but I hope it will serve to remind me to look at what the wiki says about scope and possibly write something, once StDoodle finishes the masochistic labor of love.

Heh, knock yourself out! Such things are rather far down the list for me, actually, so we're unlikely to conflict.

There are actually a lot of similar low-level concerns I have for the wiki, but I'm going to try to keep most of that to the wiki itself & the specific thread here. ;)

But if you think this kind of scope-discussion is confusing, just try to wrap your head around "ByVal" vs. "ByRef." Again, I'm not actually a programmer (just someone who has the minimum amount of knowledge necessary to be dangerous), but I can't for the life of me understand why you would use "ByRef" instead of just giving your variables a higher-level scope. Meh. (But I'm sure there's a good reason, since it's the default in VB, and no MS-associated programming could ever make a bad coding choice, right?)
 

fronobulax

Developer
Staff member
But if you think this kind of scope-discussion is confusing, just try to wrap your head around "ByVal" vs. "ByRef."
It has been so long since I had to think about that...

Basically if a parameter is passed by value, no matter what called routine does, the parameter remains unchanged in the calling routine. By reference and the called routine can change the value for the calling routine.
Code:
void calle(par) {par = 5}
...
par = 3
print calle(par)
If it is by value then the print statement prints 3. If it is by reference then we see 5.

I am hard pressed to come up with examples outside of "ancient" languages (C, C++, Fortran, Assembler) where there is a good reason to call by reference and I am equally at a loss to show something that can only be done by a call by reference. While coding style can get very personal, it is usually easier to document and maintain call by value code because there are no non-obvious side effects. The best case for call by reference may be when you want to return several parameters from a routine call and you don't want to define some kind of data structure to be returned.
 

xKiv

Active member
Hah. Now try ByName ...

f(byname a, byname i) {
i++;
return a;
}

f(some_array[k],k);
...

The best case for call by reference may be when you want to return several parameters from a routine call and you don't want to define some kind of data structure to be returned.
Even with the structure, you are actually more likely to pass around a pointer to the object ... which is both byval and byref, depending on your point of view.
 
Top