I'm needing to reset some variables in a loop in order to assign the new values (like finding the index of a substring) i cannot reuse the same var so i must unset it and as far as i know the f(var) only works in a shell?
so is there no way to do this in a script?
f() is a shell-only command.
Erlang as a language uses immutable variables, and as such does not allow the resetting of variables within the code itself. The recommendation is to get comfortable with recursion, list comprehensions, mapping, or folding in order to accomplish "loops" which don't exist in the procedural sense in Erlang.
If you must rely on variable state, the closest thing you get to mutable variables is the process dictionary: get/1 and put/2. These are generally discouraged unless there is a good reason for using them.
Related
I've seen in several places that people put at the top of their init.lua: local vim = vim. What is the purpose of this? I could understand aliasings like local v = vim or local g = vim.g but it appears like local vim = vim doesn't do anything.
local name = name is called a localization. There are multiple good reasons to localize variables:
Performance
Recall that for environmental (usually global) variables, name is just syntactic sugar for _ENV.name which in turn is syntactic sugar for _ENV["name"]; acessing a local variable on the other hand is practically a single array access where Lua knows the array index at compile-time (it's either an upvalue or a local, which get stored in different arrays; upvalues of functions are slightly slower).
The array/"register" access will be faster than accessing the hash part of _ENV and searching for "name" (hash map lookup is slower than array access). Technically Lua even has to first check the (implicit) _ENV upvalue (called "function environment" in Lua 5.1 / LuaJIT) to see which table to index.
In conclusion, local variables / upvalues are usually faster than environmental variables; JIT-compilers like LuaJIT might optimize this out, but even LuaJIT has to consider the possibility that _G.vim may be modified, which brings us to our second point:
Semantics
it appears like local vim = vim doesn't do anything
For the most part this is correct, but not quite: local vim = vim means "get the vim environmental (global) variable at the time this line of code is executed (the load time of the script if it's at the top), then store it in a 'private' variable"; without this line, later modifications of the environment (e.g. vim = nil) outside of the script will have an effect because the environment is reindexed. With this line, you get to keep your reference to the vim table no matter what happens later on, which also provides an assurance to Lua / presumably also LuaJIT that it won't change later on.
Additionally, if a metatable is set on _G, _G.name can return different results at different times based on the metamethod that returns it. Again localizing ensures that your local variable doesn't change (unless you explicitly change it).
Code Quality
Localizing all used environmentals makes your dependencies explicit, akin to the "import" statements of other languages. In Lua, require is not consistently used; some libraries are simply part of the global environment _G, such as vim in your example, whereas others have to be required. For require, you'd use local lib = require("lib"), then why not consistently do this for global variables as well, rather than redoing the indexing operation every time?
Environment Changing
This will probably rarely be the reason, but it's worth noting.
If you set a custom environment for your chunk, you will have to find a way to keep accessing global variables.
There are two options for this:
One is to use a metatable with __index = _G (or whatever the parent environment is to be), but this is inefficient and unpredictable; it practically means your environment inherits everything from its parent environment, so e.g. _ENV.math.floor would be _G.math.floor, which may be considered dirty if you want to export your _ENV as API table of a module.
The other is to localize all global variables you use. This doesn't have the drawbacks of the first solution; it is more performant, more predictable, and doesn't force you to have your environment inherit from the parent environment.
In a Roblox game I'm programming, I want to have a table of boolean values to iterate over ensuring that they're all false before making another one true, e.g.;
local bool1 = true
local bool2 = false
local bool3 = false
local bool4 = false
local tbl1 = {}
table.insert(tbl1,boolX) -- where "X" is the number above, did this in interest of shortening
for i,v in pairs(tbl1) do
if v then v = not v end
end
However, as stated in the penultimate paragraph of section 2.1 of the 5.3 manual (knowing, albeit, that Luau uses 5.1 as its base);
Tables, functions, threads, and (full) userdata values are objects: variables do not actually contain these values, only references to them. Assignment, parameter passing, and function returns always manipulate references to such values; these operations do not imply any kind of copy.
That in mind, that means that I'm not actually shoving bool1 through bool4 into the table, just their values; the table would look like {true, false, false, false}. This means that I can't simply write a loop to iterate through the table and invert any trues I find;
local bool1 = true
local tbl1 = {}
table.insert(tbl1,bool1)
tbl1[1] = false
print(bool1)
print(tbl[1])
--output:
-- true
-- false
I should point out that I very well could just shove all my variables into one giant if/else and call it a night, but that is a lot of variables to check, a lot of typing, and I can't think of any other more elgant and less tedious way other than finding a form of iteration over them all.
I want to be able to have an actual reference, in some form, to the actual variables so that I can modify them from within the table and make them iterable.
I've attempted to follow the examples given in the best answer to this question, with no successes. I would need to be able to, and cannot with these examples, substitute for any given variable at any given time, rather than just having one or two I want declated and thus returned as shown. I've attempted wrapping them in a function to provide my table and variable as arguments, but that doesn't seem to have any effect; it either outputs nothing, or nil.
The following answer after has one example that seems like it could work, but overall is pointless for what I'm trying to achieve; I don't want to re-declare or re-assign the variables I already have, I just want to return the specific value.
I've attempted using a key/value pair, making the key the potential variable name and making it equal the variable's value, but I've no way to make that key return a variable of the same name. I even attempted merging this method and the setmetatable method mentioned in the first set of examples to see if I couldn't substitute from there, to no avail.
I should point out that, while I'm not a complete newbie to Lua or Luau, I'm also not an expert in the field by any meaning of the word; I'll catch on quick, but where possible, explain like I'm 10.
The only way to iterate over local variables that are not referenced by table fields, is to use debug.getlocal in a loop.
Opinionated:
But this is a very bad approach to your problem.
You should refactor the code. If you need to update a list of variables have them in a list from the start. Don't be afraid of refactoring. Improving things usually pays off on the long term.
If your codebase is so bad that you are afraid of putting a few variables into a table you should really think over the design.
There is no way to do this in Roblox Luau.
Any potential way to do so in standard Lua is impossible to do in Luau due to how heavily sandboxed the latter is compared to the former.
Possible solutions that were recommended via comments include: making the variables needed available in _G as globals, then using them there; or using a pointer value in the table equivalent to the one you want, even though it won't technically change the value you want itself.
Another answer recommends the use of debug.getlocal() for standard Lua, but doesn't work in Luau; keep this in mind when attempting to use it, as you will get an attempt to call a nil value error.
The recommended way to do this is not to do it at all, and instead have your variables and/or values in your table from the start.
Not only does this provide ease-of-access in many cases, but it will allow you to iterate through them significantly easier than trying to shove them into tables and the like. Refactoring, if you need to do something similar to this, is highly recommended across the board.
I have some proprietary implementation of lua, and all the variables exposed to me are in the form of 'ME.AV123' (for example). What is 'ME'? Is it a namespace? Is it a class? Is there a way to tell? Should I be able to do some sort of type(ME) (which does not seem to work)? In the documentation it says the keyword 'ME' is used to access the objects in the local database.
Follow-up, bonus question - Is there a way to get to all the variables in ME? I.e. - like the global variables use _G[varname], is there an equivalent way to do this for ME?
I apologize if I am not giving you enough. I am new to Lua, and I have relatively limited functionality through this .... thing.
Just to maybe put a finer point on it, and illustrate what I am actually trying to do:
I can interact with some set of variables, which are all in the documentation. All of them are name(addressed?) 'ME.varname'. So, to set 'AV120' to '1', I would say ME.AV120 = 1. I need to set some.. few dozen of these things, and would like a way to loop through all the variables, setting them as I go. I would think something like:
for i,j in pairs(mySettingsTable) do
ME[i] = j
end
Does this make sense?
From the Lua reference manual:
https://www.lua.org/manual/5.3/manual.html#2.1
The language supports this representation by providing a.name as
syntactic sugar for a["name"].
So ME.AV123 is the same as ME["AV123"].
It is just a more convenient form of indexing.
type() returns a string, in case you're wondering why the function does nothing on it's own. print(type(ME)) should work.
Whenever I add new lies to the code (e.g. when computing a different estimate) I do not want to rerun the whole do-file again. However, I often need the values of certain local macros that were generated during the previous run of the do-file.
Is there a way to keep those values? Or I should switch to using more globals instead?
Yes, use global.
But note that you need to be careful with global for the exact reason you are using it: the macro remains in memory until you exit that instance of Stata, or until you reset it within the code.
Some people have very strong feelings about not using global ever (see pp5 and continuing here: http://faculty.chicagobooth.edu/matthew.gentzkow/research/ra_manual_coding.pdf). Once you learn their properties, and to not incur the small number of problems they can potentially cause, you should be fine.
Globals are by no means the only alternative.
First, consider using scalars. A scalar with a permanent name will survive beyond the end of a do-file.
Second, consider converting your do-file to a program and learning about saved results.
Third, you can always consider putting results in a new variable; it's just that it is usually bad style and wasteful on storage.
At a guess, the first is likely to be the most useful for you. Many Stata users are happy to use do-files with many dataset-specific statements. Jumping to writing fully-fledged and more general programs is a big jump and not (at first) trivial.
Are there any downsides to passing in an Erlang record as a function argument?
There is no downside, unless the caller function and the called function were compiled with different 'versions' of the record.
Some functions from erlangs standard library do indeed use records in their interfaces (I can't recall which ones, right now--but there are a few), but in my humble opinion, the major turnoff is, that the user will have to include your header file, just to use your function.
That seems un-erlangy to me (you don't ever do that normally, unless you're using said functions from the stdlib), creates weird inter-dependencies, and is harder to use from the shell (I wouldn't know from the top of my head how to load & use records from the shell -- I usually just "cheat" by constructing the tuple manually...)
Also, handling records is a bit different from the stuff you usually do, since their keys per default take the atom 'undefined' as value, au contraire to how you usually do it with proplists, for instance (a value that wasn't set just isn't there) -- this might cause some confusion for people who do not normally work a lot with records.
So, all-in-all, I'd usually prefer a proplist or something similar, unless I have a very good reason to use a record. I do usually use records, though, for internal state of for example a gen_server or a gen_fsm; It's somewhat easier to update that way.
I think the biggest downside is that it's not idiomatic. Have you ever seen an API that required you to construct a record and pass it in?
Why would you want to do something that's going to feel foreign to any erlang programmer? There's a convention already in use for optional named arguments to functions. Inventing yet another way without good cause is pointless.