I am not able to find the required solution. I want to call a function and want to use some variable which is being declared in that function(I don't want to return that variable). I just want to make it global.
func foo(){
temp:=30
}
func main(){
foo()
// How to use temp without returning or without declaring it outside foo and main
}
You can't. You can only declare a package variable (aka global variable) in package scope. You can modify it from inside a function, but you can't declare it inside a function. This is because anything else referring to that variable has to have that reference resolvable at compile time. Otherwise, what happens when Bar() tries to reference the variable before Foo() could declare it? That would break compile-time safety that Go guarantees.
That said, the solution is simple; just declare it in package scope. It's unclear in the question why you wouldn't want to do that - if you want a global, that's what you do.
Related
This is a question about closures in Lua. I stumbled across a problem (and workaround) while trying to make an object registrar object as follows:
tracker = {
objList = {},
myRegister = function(self, obj)
table.insert(self.objList, obj)
return "hello"
end,
myInit = function(self)
local i, obj
for i, obj in ipairs(self.objList) do
obj:init()
end
end,
}
-- Note: As written, this does *not* work.
-- It *will* work if I separate the line into two parts as follows:
-- local myvar
-- myvar = tracker:myRegister({
local myvar = tracker:myRegister({
init = function(self)
-- This will generate an error complaining that myvar
-- is a global variable with a "nil" value
print("myvar = " .. myvar)
end,
})
tracker:myInit()
It seems that if I declare the local variable, "myvar", in the same statement which creates a closure, then the local variable is not accessible from the closure. If, however, I merely assign to an already-existing local variable, then that variable is accessible from the closure.
Obviously, I know how to fix this: Just declare myvar separately.
My question, however, is this: Why is this necessary? Is this by design, or is it a bug in the compiler and/or virtual machine? If it's by design, where is it documented? I'm particularly interested in whether this behavior has other implications, and what those might be, and I'm hoping that the documentation (again assuming this is the intended behavior) will shed some light on this.
Yes, this is the intended behavior.
It is documented in the Lua manual §3.5 – Visibility Rules
This feature allows you to write the following code:
print"Beginning of log"
do
local print =
function(...)
print(os.date"%T", ...) -- Here you're invoking global "print"
end
-- inside this do-end block "print" is automatically adding current time
print"Some event"
print"Another event"
end
print"End of log"
In other words, while the shadowing object is being created, the original object is still accessible.
This is quite useful.
My understanding is that variable types are "checked" before run-time for statically typed languages.
I take this to mean that a var of type int can't ever be type string? Does this mean variable type can't change (within the same scope) throughout the program (in a statically typed language)?
Somebody mentioned "variable shadowing" but I'm pretty sure that only applies in different scopes.
var i = 'hi';
function foo() {
var i = 1;
}
My understanding of var shadowing is that i in the global scope is a different variable than i in the foo function scope and therefore their types are permanent and unrelated (in a static language, which JS is not). Is that right?
Somebody mentioned "variable shadowing" but I'm pretty sure that only applies in different scopes.
It depends on your definition of "scope", Rust, for example, allows the kind of shadowing that you're talking about, even within a single block:
fn main() {
let a: str = "hello";
let a: i32 = 3;
}
It could be argued that the declaration of a shadow variable implicitly ends the scope of the previous variable. But to quote from the Rust book:
Note that shadowing a name does not alter or destroy the value it was bound to, and the value will continue to exist until it goes out of scope, even if it is no longer accessible by any means.
Is there any way that we can use variable declared in one module and use that variable in a function defined in other module?
Yes. Declare a variable at module level like this:
Public myvar As String
It can then be accessed from other modules.
Note, however, that global variables like this are almost never a good idea.
This question already has answers here:
Difference between . and : in Lua
(3 answers)
Closed 8 years ago.
I'm still playing around with lua modules and I've found the following "interesting" issue that occurs depending on how you create your methods / functions inside a module.
Note the following code in a file called test_suite.lua:
local mtests = {} -- public interface
function mtests:create_widget(arg1)
print(arg1)
-- does something
assert(condition)
print("TEST PASSED")
end
return mtests
Using the above code, arg1 is always nil, no matter what I pass in when calling create_widget(). However, if I change the definition of the function to look like this:
function mtests.create_widget(arg1) -- notice the period instead of colon
print(arg1)
-- does something
assert(condition)
print("TEST PASSED")
end
then, the system displays arg1 properly.
This is how I call the method:
execute_test.lua
local x = require "test_suite"
x.create_widget(widgetname)
Can you tell me what the difference is? I've been reading: http://lua-users.org/wiki/ModuleDefinition
But I haven't come across anything that explains this to me.
Thanks.
All a colon does in a function declaration is add an implicit self argument. It's just a bit of syntactic sugar.
So if you're calling this with (assuming you assign the mtests table to foo), foo.create_widget(bar), then bar is actually assigned to self, and arg1 is left unassigned, and hence nil.
foo = {}
function foo:bar(arg)
print(self)
print(arg)
end
Calling it as foo.bar("Hello") prints this:
Hello
nil
However, calling it as foo:bar("Hello") or foo.bar(foo, "Hello") gives you this:
table: 0xDEADBEEF (some hex identifier)
Hello
It's basically the difference between static and member methods in a language like Java, C#, C++, etc.
Using : is more or less like using a this or self reference, and your object (table) does not have a arg1 defined on it (as something like a member). On the other way, using . is just like defining a function or method that is part of the table (maybe a static view if you wish) and then it uses the arg1 that was defined on it.
. defines a static method / member, a static lib, Which means you can't create a new object of it. static methods / libs are just for having some customized functions like printing or download files from the web, clearing memory and...
: Is used for object members, members that are not static. These members change something in an object, for example clearing a specified textbox, deleting an object and...
Metamethod functions(Functions that have :) can be made in lua tables or C/C++ Bindings. a metamethod function is equal to something like this on a non-static object:
function meta:Print()
self:Remove()
end
function meta.Print(self)
self:Remove()
end
Also, with . you can get a number/value that doesn't require any call from a non-static or static object. For example:
-- C:
int a = 0;
-- Lua:
print(ent.a)
-- C:
int a()
{
return 0;
}
-- Lua:
print(ent:a())
same function on a static member would be:
print(entlib.a())
Basically, each non-static object that has a function that can be called will be converted to : for better use.
I have a question about variable scope in TCL, I have the following code:
namespace eval ::hello {
variable player
variable name
namespace export *
}
proc ::hello::setPlay {value} {
set ::hello::player
}
proc ::hello::getPlay {} {
return $::hello::player
}
proc ::hello::setName {value} {
set ::hello::name
}
proc ::hello::getName {} {
return $::hello::name
}
proc GET_NAME {} {
#here I have a variable called name as well
set name "RON"
return $name
}
in the GET_NAME,if I set the variable name as "RON", does it will set the variable name declaired in namespace? can I have the same variable name in GET_NAME and namespace? And if I add this line variable name in GET_NAME, does this mean, it will set the variable declaired in name space?
Variables in procedures (and lambda expressions) default to being local to that procedure. If explicitly declared to be something else (e.g., with global, upvar or variable) then that actually couples a local variable to another variable elsewhere so that acting on one (e.g., reading or writing) is exactly like acting on the other. If you use a variable name with :: in it, that is a reference to a namespaced variable (the global namespace is just ::) which might be resolved either relative to the current namespace or the global namespace, depending on whether the name starts with :: or not. (Think of it a bit like a slash in a filename.)
When executing code inside namespace eval, always use variable to declare variables before using them. This avoids problems with global variable shadowing that are really horrible but necessary to keep due to some existing code depending on them. (Technically, you don't need to do this in namespace eval :: as global variables can't shadow themselves, but it doesn't hurt.)
Dealing with specifics:
in the GET_NAME,if I set the variable name as "RON", does it will set the variable name declaired in namespace?
No, not with the code you wrote.
can I have the same variable name in GET_NAME and namespace?
You can use the same name of variable in the two places. This can be confusing, but it limits surprises overall.
And if I add this line variable name in GET_NAME, does this mean, it will set the variable declaired in name space?
Yes. Exactly that. (It couples the two together precisely.)