I'm not sure I see the problem here. You haven't declared or assigned a value to $foo the first time you call PutFoo(). The language is following your statements in the order in which they appear. If you are going to use a global variable like that, you need to declare it before starting the block that calls subroutines that depend on it.
's code does by subverting BEGIN. But that makes the code harder to follow. Debugging is a lot easier when you keep the parameters for a routine in the call to the routine, like PutFoo( $foo ), and then use shift (or @_) to get the argument(s) in sub PutFOO {}.