death.crafter wrote: ↑February 25th, 2022, 11:54 pmActually, no. You can't do that. As every script measure has it's own environment, which is not global.
I don't like to take no for an answer, but for now, that surely explains the behavior. Thanks for making it clear.
death.crafter wrote: ↑February 25th, 2022, 11:54 pmIf you want to declare a true global variable, the use loadstring e.g.
loadstring("varname = " .. value)()
What you are trying to do can be done using
[&Measure:VariableName], but of you still want a function to retrieve it you can do something like,
Code: Select all
function dostring(str)
local f = loadstring(str)
setfenv(f, getfenv())
return f
end
function GetVar(varname)
return dostring(''return " .. varname)()
end
or even better without the complications,
Code: Select all
function GetVar(varname)
local selfName = SELF:GetName() -- I'm not sure, but there is a method like this
return SKIN: ReplaceVariables(
''[&" .. selfName .. '':" .. varname .. "]"
)
end
Yep, the
loadstring() was the first option I thought of, even before
_G, but in my tests a while ago when I was excited about the function, I forgot to use the
() at the end of your syntax to make it clear that it was a basic function. So, I wrongly rated the method unfeasible because while it worked for "operations" that already resulted in "something", it seemed to fail for simple "passive" stuff like a
print() or getting a table dimension (the latter actually being my usage scenario now, like shown below). Many thanks for the working method and also for making me realize what I was doing wrong before in this case.
Brian wrote: ↑February 26th, 2022, 12:08 am
EDIT: death.crafter beat me to it, however I see no reason to "force" setting the variables to global.
While I am not 100%, I think this is because each measure runs in its own "environment". So the
_G variable is look at the "global" environment, not the "measure" environment.
What you want is something similar to "this" that is used in other programming languages. You can accomplish this in 2 ways.
#1:
Code: Select all
function GetVar(name)
x = 10
setfenv(1, _G)
return tostring(_G[name])
end
#2:
Code: Select all
function GetVar(name)
x = 10
local env = getfenv()
return env[name]
I prefer method #2 over #1 since you are just retrieving the current environment over explicitly setting the environment. The
1 environment is the current environment, while the
0 environment is always the "global" environment.
Note: I placed a
tostring in #1 since there is an error thrown about an invalid "return" type. I think this might happen on the very first load and might be a side effect of
setfenv.
Note 2: In #2,
getfenv() should really be
getfenv(1), but the
1 is default, so I omitted it.
-Brian
Death.crafter provided excellent choices and his 1st method works (the 2nd doesn't probably because Rainmeter can only handle strings, numbers and booleans in its Lua framework) but so does your 2nd, which is slightly more compact and closer to what I envisioned (bar the
_G usage). Below, there's a summary of yours and death.crafter's methods and their success rate - many thanks for your last one, very easy to apply, and probably my favorite.
Also, the invalid return type is
NOT a side effect of
setfenv and it's
NOT specific only to the first load, it has been annoying me for a while, which is why all my functions (which are actually like the "procedures" in other languages in that they don't return anything, they just "do" stuff) have a
return true at the end to get rid of the error. I let a test of the no return function errors at the end for you to investigate if you like (just comment the update dividers in the INI to see that's it's not a load problem)...
Lua:
Code: Select all
function Initialize()
tableone = {1, 2, 3}
tabletwo = {4, 5}
end
-- 1. death.crafter method 1 works! THANKS!
-- function dostring(str)
-- local f = loadstring(str)
-- setfenv(f, getfenv())
-- return f
-- end
-- function GetCount(tablename)
-- dostring('print(' .. tablename .. ')')()
-- return dostring('return #' .. tablename)()
-- end
-- 2. death.crafter method 2 doesn't work
-- function GetCount(tablename)
-- tablevar = SKIN:ReplaceVariables('[&' .. SELF:GetName() .. ':' .. tablename .. ']')
-- print(tablevar)
-- return #tablevar
-- end
-- 3. Brian method 1 doesn't work
-- function GetCount(tablename)
-- setfenv(1, _G)
-- print(_G[tablename])
-- return #_G[tablename]
-- end
-- 4. Brian method 2 works as well! THANKS!
-- function GetCount(tablename)
-- local env = getfenv(1)
-- print(env[tablename])
-- return #env[tablename]
-- end
-- CONCLUSION: I think I'll settle for Brian's method 2, more compact and straightforward
-- X. No Return Function Error Sample
function GetCount(x)
print('a')
end
Ini:
Code: Select all
[Variables]
[Rainmeter]
Update=1000
DynamicWindowSize=1
AccurateText=1
BackgroundMode=2
SolidColor=47,47,47,255
---Measures---
[Script]
Measure=Script
ScriptFile=#@#Script.lua
UpdateDivider=-1
---Meters---
[TCount]
Meter=String
FontFace=Consolas
FontColor=255,255,255,255
Padding=5,5,5,5
FontSize=16
AntiAlias=1
Text="TCount = [&Script:GetCount('tableone')]"
UpdateDivider=-1
DynamicVariables=1