I thought there was and better nice way to write this but I can't remember.
Is there an nicer way to write this in Lua?
if curSwitch == "shapes" then
curSwitch = "colors"
elseif curSwitch == "colors" then
curSwitch = "shapes"
end
Works only if possible 2 values:
curSwitch = (curSwitch =="shapes") and "colors" or "shapes"
How about this.
Start with
oldSwitch = "colors"
curSwitch = "shapes"
Then flip the switch with
curSwitch, oldSwitch = oldSwitch, curSwitch
Note, I don't know Lua.
Usually, for a trigger, you use XOR operation.
Like, whatever B has (0 or 1), when you calculate1 XOR B it will invert the B.
1 XOR 1 = 0; 1 XOR 0 = 1.
You probably can create a map with integer (ideally, a bit) and string and put there {0:"shapes"; 1:"colors"} and then work with the number.
Or, you could just use a true/false for the curSwitch, then it'll look like this (ternary op):
curSwitch ? "shapes" : "colors"
But that's not that fancy if you repeat that everywhere.
Good luck! :)
You can implement such a simple switch using a table.
switch = { shapes = "colors", colors = "shapes" }
curSwitch = "colors"
curSwitch = switch[curSwitch]
print(curSwitch) -- "shapes"
The problem is that if the value does not exist in the table you simply get nil.
curSwitch = "garbage"
curSwitch = switch[curSwitch]
print(curSwitch) -- nil
This can be remedied by an overloaded __index metamethod which triggers an error in the case of absent keys.
m = {
__index = function(t,k)
local v = rawget(t,k) or error("No such switch!")
return v
end
}
setmetatable(switch, m)
curSwitch = "garbage"
curSwitch = switch[curSwitch]
print(curSwitch) -- error!
Related
I would like to know if there is a alternative to using a normal if statement in lua. For example, in java there are switch statements but I cant seem to find that in Lua
Lua lacks a C-style switch statement.
A simple version of a switch statement can be implemented using a table to map the case value to an action. This is very efficient in Lua since tables are hashed by key value which avoids repetitive if then ... elseif ... end statements.
action = {
[1] = function (x) print(1) end,
[2] = function (x) z = 5 end,
["nop"] = function (x) print(math.random()) end,
["my name"] = function (x) print("fred") end,
}
The frequently used pattern
local var; if condition then var = x else var = y end
can be shortened using an and-or "ternary" substitute if x is truthy:
local var = condition and x or y
if test == nil or test == false then return 0xBADEAFFE else return test end
Can be shorten up to...
return test or 0xBADEAFFEE
This works even where you dont can do: if ... then ... else ... end
Like in a function...
print(test or 0xBADEAFFE)
-- Output: 3135156222
...or fallback to a default if an argument is ommited...
function check(test)
local test = test or 0xBADEAFFE
return test
end
print(check())
-- Returns: 3135156222
In Stata I am trying to repeat code inside an if qualifier using perhaps a forvalues loop. My code looks something like this:
gen y=0
replace y=1 if x_1==1 & x_2==1 & x_3==1 & x_4==1
Instead of writing the & x_i==1 statement every time for each variable, I want to do it using a loop, something like this:
gen y=0
replace y=1 if forvalues i=1/4{x_`i'==1 &}
LATER EDIT:
Would it be possible to create a local in the line of this with the elements added together:
forvalues i=1/4{
local text_`i' "x_`i'==1 &"
display "`text_`i''"
}
And then call it at the if qualifier ?
Although you use the term "if statement" all your code is phrased in terms of if qualifiers, which aren't commands or statements. (Your use of the term "statement" is looser than customary, but that doesn't affect an answer directly.)
You can't insert loops in if qualifiers.
See for the differences
help if
help ifcmd
The entire example
gen y = 0
replace y = 1 if x==1 | x==2 | x==3 | x==4
would be better as
gen y = inlist(x, 1, 2, 3, 4)
or (dependent possibly on whatever values are allowed)
gen y = inrange(x, 1, 4)
A loop solution could be
gen y = 0
quietly forval i = 1/4 {
replace y = 1 if x == `i'
}
We can't discuss whether inlist() or inrange() would or would not be a solution for your real problem if you don't show to us.
I usually don't like - in Nick's terms - to write code to write code. I see an immediate, though not elegant nor 'heterodox', solution to your issue. The whole thing amounts to generate an indicator function for all your indicators, and use it with your if qualifier.
Implicit assumptions, which make this a bad, non-generalizable solution, are: 1) all variables are dummies, and you need them to be == 1, and 2) variable names are conveniently ordered 1 to N (although, if that is not the case, you can easily change the forv into a 'foreach var of varlist etc.')
g touse = 1
forv i =1/30{
replace touse = touse * x_'i'
}
<your action> if touse == 1
I need to create a function that replaces a letter with the letter 13 letters after it in the alphabet (without using encode). I'm relatively new to Python so it has taken me a while to figure out a way to do this without using Encode.
Here's what I have so far. When I use this to type in a normal word like "hello" it works but if I pass through a sentence with special characters I can't figure out how to JUST include letters of the alphabet and skip numbers, spaces or special characters completely.
def rot13(b):
b = b.lower()
a = [chr(i) for i in range(ord('a'),ord('z')+1)]
c = []
d = []
x = a[0:13]
for i in b:
c.append(a.index(i))
for i in c:
if i <= 13:
d.append(a[i::13][1])
elif i > 13:
y = len(a[i:])
z = len(x)- y
d.append(a[z::13][0])
e = ''.join(d)
return e
EDIT
I tried using .isalpha() but this doesn't seem to be working for me - characters are duplicating for some reason when I use it. Is the following format correct:
def rot13(b):
b1 = b.lower()
a = [chr(i) for i in range(ord('a'),ord('z')+1)]
c = []
d = []
x = a[0:13]
for i in b1:
if i.isalpha():
c.append(a.index(i))
for i in c:
if i <= 12:
d.append(a[i::13][1])
elif i > 12:
y = len(a[i:])
z = len(x)- y
d.append(a[z::13][0])
else:
d.append(i)
if message[0].istitle() == True:
d[0] = d[0].upper()
e = ''.join(d)
return e
Following on from comments. OP was advised to use isalpha, and wondering why that's causing duplication (see OP's edit)
This isn't tied to the use of isalpha, it's to do with the second for loop
for i in c:
isn't necessary, and is causing the duplication. You should remove that. Instead you can do the same by just using index = a.index(i). You were already doing this, but for some reason appending to a list instead and causing confusion
Use the index variable any time you would have used i inside the for i in c loop. On a side note, in nested for loops try not to reuse the same variables. It just causes confusion...but that's a matter for code review
Assuming you do all that right it should work.
"if then statement in VBA" I'm writing a program that puts a number in a cell in Excell if a variable reaches a certain value. I understand how to declare variables but I don't know how to tell excel to write x if A1 =34. Thanks
Add a listener to your worksheet to capture a Range. You can make the range [A1] if you are only watching a specific column/row, or you can add a range like I have below.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim KeyCells As Range
Set KeyCells = Range("A:A")
If Not Application.Intersect(KeyCells, Range(Target.Address)) _
Is Nothing Then
If Target.Value = "34" Then
Cells(Target.Row, 2) = "X"
Else
Cells(Target.Row, 2) = ""
End If
End If
End Sub
Change "x" to if you want variable x and not literal x.
If your goal is to change the value of the cell to "X" (Literal X), and you are not having macros run constantly or with each cell change, you can use the following function (or similar) in each cell in which you have a conditional.
See the Microsoft support on this topic https://support.microsoft.com/en-us/kb/213612
It's not clear what you wish to do, but let's say you want to write the current value of your variable, x, into cell B2... if cell A1 is 34.
In the above case, you would do this:
If [a1] = 34 then [b2] = x
Private Sub CommandButton1_Click()
Dim lr As Long
lr = Worksheets("New").Range("A" & Rows.Count).End(xlUp).Row
Worksheets("New").Range("T2").Formula = "=LEFT(B2,2)"
Worksheets("New").Range("T2").AutoFill Destination:=Worksheets("New").Range("T2:T" & lr)
Worksheets("New").Range("U2").Formula = "=(T2&0&0)"
Worksheets("New").Range("U2").AutoFill Destination:=Worksheets("New").Range("U2:U" & lr)
Worksheets("New").Range("V2").Formula = "=IF(AND(a2=A1,U2=U1),"",A2")" (HOW TO AUTO FILL THIS FORMULA IN A CELL)
Worksheets("New").Range("V2").AutoFill Destination:=Worksheets("New").Range("V2:V" & lr)
End Sub
The software we use LanDesk Service Desk uses Boo Language calculations to allow for dynamic windows.
I have a drop down list on a form that has one of two options. "Acute" and "Ambulatory". Based on which is chosen, one of two possible fields will no longer be hidden and will be set to mandatory. I have managed to get this to work, but I'm afraid if the number of options grows on future forms that the code will get a little wordy. Do any of you have any suggestions for alternatives. Thank you,
import System
static def GetAttributeValue(Request):
isAcuteHidden = true
isAcuteMandatory = false
isAmbulatoryHidden = true
isAmbulatoryMandatory = false
if Request._PharmacyType != null and Request._PharmacyType._Name == "Acute":
isAcuteHidden = false
isAcuteMandatory = true
elif Request._PharmacyType != null and Request._PharmacyType._Name == "Ambulatory":
isAmbulatoryHidden = false
isAmbulatoryMandatory = true
return String.Format(":SetHidden(_AcutePharmacy, {0});:SetMandatory(_AcutePharmacy, {1});:SetHidden(_AmbulatoryPharmacy, {2});:SetMandatory(_AmbulatoryPharmacy, {3});", isAcuteHidden, isAcuteMandatory, isAmbulatoryHidden, isAmbulatoryMandatory)
A few pointers:
It appears that for both pairs, the is?????Hidden and corresponding is?????Mandatory will always be opposite values. If so, you don't need two separate boolean variables to track them.
If you're going to end up with a lot of blocks that look basically like this one, the proper way to handle it in Boo is with a macro, like so:
macro HiddenOrRequiredValues:
ControlStrings = List[of String]()
ArgVarNames = List[of ReferenceExpression]()
counter = 0
for arg as ReferenceExpression in HiddenOrRequiredValues.Arguments:
argVariable = ReferenceExpression("is$(arg)Hidden")
yield [|$argVariable = true|]
yield [|
if Request._PharmacyType != null and Request._PharmacyType._Name == $(arg.ToString()):
$argVariable = false
|]
ControlStrings.Add(":SetHidden(_$(arg)Pharmacy, {$(counter)});:$(arg)Mandatory(_AcutePharmacy, {$(counter + 1)})")
ArgVarNames.Add(argVariable)
counter += 2
resultString = join(ControlStrings, '')
resultCmd as MethodInvocationExpression = [|String.Format($resultString)|]
for varName in ArgVarNames:
resultCmd.Arguments.Add([|$varName|])
resultCmd.Arguments.Add([|not $varName|])
yield [|return $resultCmd|]
Then the entirety of your method becomes:
static def GetAttributeValue(Request):
HiddenOrRequiredValues Acute, Ambulatory
It's more work to set it up, but once you have the macro in place, adding in more values becomes much, much easier. Feel free to modify the macro to suit your needs. This should be enough to get you started, though.