Autohotkey iterate through loop, but only return value if key matches input - autohotkey

Suppose I have the following
^!r::
InputBox, input, Enter the string
if (input = "trip")
{
TripFunction()
}
else if (input = "leave")
{
LeaveFunction()
}
else
{
Msgbox, That word isnt defined.
}
Return
But, anticipating having to add a lot of different cases to test for, I figure the best idea is to put this into an array, and iterate through the array, looking for the matching key, returning the value (the function), and no longer iterating through the dictionary. So now, I have something like this:
^!r::
InputBox, input, Enter the string
dict = { "trip": TripFunction(), "leave": LeaveFunction() }
for k, v in dict
{
...
see if k = "trip", if so, return TripFunction(), if not, go to next
item in array
...
}
Return
The trouble I'm having is once it successfully matches akey in the dictionary, it will return all of the associated values. What should I put in the brackets to do what I intend?

You're using the wrong equal sign operator (use := for non-literal assignments instead of =)
Also, in the line dict = { "trip": TripFunction(), "leave": LeaveFunction() }, tripfunction aind leavefunction are executed, which you probably do not want.
Try:
^!r::
InputBox, input, Enter the string
dict := { "trip": "TripFunction", "leave": "LeaveFunction" }
for k, v in dict
{
if(k==input) {
%v%() ; documentation: https://autohotkey.com/docs/Functions.htm#DynCall
break
}
}
Return
TripFunction() {
msgbox trip
}
LeaveFunction() {
msgbox leave
}

Related

Method returns unit instead of string in scala

I am trying to get the string out of the Set type in Scala. However, no matter what I try it is returning Unit as a return type instead of a string.
if (!validationMessages.isEmpty) {
dataTuple = (parsedJson.toString(), for (s <- validationMessages.toString()){
s.toString()
})
println(dataTuple)
}
else {
dataTuple = (parsedJson.toString(), "some string...")
}
Basically, I am trying to return a tuple like (String, String). What am I missing?
The value of a block is the value of the last expression in the block. In this case the value of the if part is
println(dataTuple)
and the value of the else part is
dataTuple = (parsedJson.toString(), "some string...")
Both of these expressions return Unit so the result is Unit.
The quick fix is to make dataTuple the last statement in each branch:
if (!validationMessages.isEmpty) {
dataTuple = (parsedJson.toString(), for (s <- validationMessages.toString()){
s.toString()
})
println(dataTuple)
dataTuple
} else {
dataTuple = (parsedJson.toString(), "some string...")
dataTuple
}
But also consider something like this as a simpler solution:
val msg =
if (validationMessages.nonEmpty) {
validationMessages.mkString(", ")
} else {
"some string"
}
(parsedJson.toString, msg)
The mkString is an attempt to replace this code:
for (s <- validationMessages.toString()) {
s.toString()
}
This code appears to be trying to create a string by combining all the validation messages, but it actually returns Unit because the for does not have a yield. mkString calls toString on each element of the Set and then creates a string by putting ", " between each element. This seems to be roughly what is wanted and should be easy to modify to the actual requirement.
Why is the code behaving like this?
That code has return type Unit, because that is the return type of both branches of the if statement.
The if branch ends with println(dataTuple), which returns Unit.
The else branch ends with dataTuple = ..., which is variable assignment, which returns Unit. If you wanted it to return the tuple stored in dataTuple, you'd just have to add dataTuple to the end.
What do you probably want to do instead?
(parsedJson.toString, validationMessages.mkString("[", ", ", "]"))
That will return a tuple containing first parsedJson as a string, and second, each element of validationMessages, in arbitrary order (because Set is unordered), starting with [, with a , between consecutive elements, and ] at the end.
So if parsedJson was {"key1": "value1"} and validationMessages was Set("unexpected key: key1", "missing key: key0") this would return ("{"key1":"value1"}",["unexpected key: key1", "missing key: key0"].
If you don't want to put something special at the beginning/end of your .mkString, you can call it with only the middle argument (the delimiter).
If validationMessages is empty, then validationMessages.mkString("delimiter") returns an empty string, and validationMessages.mkString("start", "delimiter", "end") returns "startend".
One of the beautiful things about scala is how you can do complex things in a single line (as long as you know the language well enough).

Scoping problem when trying to assign vector of strings in DOORS DXL

I want to be able to send a selector value to a function, and have the function create a string array of values for use in subsequent operations. The problem I'm running into is that the DXL rules don't "see" a declared variable inside an "if {} " block, even when I've guaranteed that in all cases my string array would get initialized. Example:
string tryme( int thechoice){
string outit
if (thechoice == 1){
outit = "you chose one"
}
else if (thechoice ==2){
outit = "you chose two"
}
else { outit = "bad choice"}
// do a bunch of stuff with "outit" values
return outit
}
// that works, but this doesn't
string trymore( int thechoice){
if (thechoice == 1){
string outit[] = {"you chose one","and one"}
}
else if (thechoice ==2){
string outit[] = {"you chose two","and two", "and three"}
}
else { string outit = "bad choice"}
// do a bunch of stuff with "outit" values
return outit
}
I could use dynamic arrays, thus allowing me to declare the array prior to the "if{}", but then I'm forced to write loops inside each case, using put to load the array.
I know DXL has a limited capability, but if anyone knows a better approach please let me know.
additional constraint
In the end, I want to be able to call the function repeatedly from a loop, changing "thechoice" each time. That is why I can't declare the string array in the parent script, because once declared ( string outit[] = {'a','b'} ) , DXL cannot delete or resize the array.
It's easier than that, tho' a bit counterintuitive . I need to declare a string vector with out assigning anything, then generate a temporary string vector, then set my desired variable equal to the temp. Like this:
string trymore( int thechoice){
string outit[]
string whatdone
if (thechoice == 1){
string foo[] = {"you chose one","and one"}
whatdone = "did one"
outit = foo
}
else if (thechoice ==2){
string foo[] = {"you chose two","and two", "and three"}
whatdone = "did two"
outit = foo
}
else {
string foo[] = "bad choice"
whatdone = "nogood"
outit = foo
}
print "outit " outit[0] "\n"
// do a bunch of stuff with "outit" values
return whatdone
}
DXL will not allow you to assign the values to outit , crying "length mismatch", but will allow you to set outit equal to the fully defined foo

How to change empty input value to empty array?

var input = [readLine() ?? ""]
If I just entered, input has [""]
If I do not input anything, I want to make the input an empty list.
How can I do it?
This is because I want the count of the input to be zero when the input is empty.
You can use an IF statement to check if the input was an empty string and if so, then set the input to an empty array. There may be a better way to do this but I think this will work.
if input == [""] {
input = []
}
I hope this helped.
Another way to do this is to define your own function that reads the line or returns an empty array:
private func myReadLine() -> [String] {
let line = readLine()
if line == [""] {
return []
} else {
return line
}
}
And then at the call site you can write:
var input = myReadLine()
Which keeps the logic separated from the calling code and is easier to read. It also has the added advantage of being a lot easier to change if you want to amend your input handling conditions later on.
Simply filter out empty values:
input = input.filter { !$0.isEmpty }
or even:
let input = [readLine()]
.compactMap { $0 } // remove nil
.filter { !$0.isEmpty } // remove empty strings

know the Datatype in Swift

i am new to swift i just started with the basics. In one of the Blog i saw a simple task which goes like this read a line from the stdin and check whether it is a integer,float,String.
I tried with the following code
let input = readLine()
var result = test(input)
print (result)
func test (obj:Any) -> String {
if obj is Int { return "This input is of type Intger." }
else if obj is String { return "This input is of type String." }
else { return "This input is something else. " }
}
when the input of 3245 is given it stores in the string format. and returns output as string.
how to overcome it..?
The readLine function returns a value of type String?. So your input variable can only be a String. It will never be Int or anything else.
If you want to see if the entered value is a valid number, you can try to convert the string to an Int.
if let input = readLine() {
if let num = Int(input) {
// the user entered a valid integer
} else {
// the user entered something other than an integer
}
}
As others have pointed out, readline() always returns a String?. It's up to you to parse that into whatever format you use it.
This is how I would do this:
let line = readLine()
switch line {
case let s? where Int(s) != nil:
print("This input is of type Intger.")
case let s? where Float(s) != nil:
print("This input is of type Float.")
case let s? where s.hasPrefix("\"") && s.hasSuffix("\""):
print("This input is of type String.")
default: print("This input is something else. ")
}
It exploits the ability of Int and Float's initializers to test the validity of a String, which almost entirely defeats the purpose of this exercise. But hey, it works, right? 😄
You can find of the type of object as
if let intt = obj as? Int {
// obj is a String. Do something with intt
}
else if let str = obj as? String {
// obj is a String. Do something with str
}
else {
//obj is something else
}

Iterate over part of String in Swift

Why in the world are Swift String operations so complex and tiresome to work with?
I have to iterate over a String in reverse but ignoring the first char. Now this could be done like following:
var firstTime = true
for i in textBefore.characters.reversed() {
if firstTime {
firstTime = false
} else {
if String(i).personalFunction() {
// something
} else {
// something else
}
}
}
But really I just want to do something like:
textBefore = textBefore.characters.reversed()
for i in 1...textBefore.characters.count {
if textBefore.get(i).personalFunction() {
// something
} else {
// something else
}
}
So why can't we get index as int. And why is textBefore.characters.reversed() not a String or simply have String have a reverse function. All these issues just makes it so frustrating to work with Strings in Swift and makes us do stupid stuff as converting a String to an array of chars :S or stuff like my proposed solution above... Also we can't make for loops in the old fashion... I simply need some Swift guru to point my brain in the right direction for this stuff.
string.characters is a collection of characters.
Use reversed() to access the elements in reverse order, anddropFirst() to skip the initial element of the reversed collection:
let string = "a🇨🇷b😈"
for ch in string.characters.reversed().dropFirst() {
print(ch)
// `ch` is a Character. Use `String(ch)` if you need a String.
}
Output:
b
🇨🇷
a
You can do something like your second one. After you enter the for, you can just get the index directly from the string. In Swift, a string is just an array of characters.
textBefore = String(textBefore.characters.reversed())
for i in 1...textBefore.characters.count {
if textBefore[i].personalFunction() {
// something
} else {
// something else
}
}