What happens when I try to copy an object with `thecopy := object` instead of object.Clone()? - autohotkey

thearray := [6,77,4,3,66,11]
thecopy := thearray
MsgBox % thecopy.Length() ; 6
thearray := function(thearray)
MsgBox % thecopy.Length() ; 0
MsgBox % thearray.Length() ; 6
Why is thecopy "ruined" when thearray is changed by a function? My guess: The function changes the thearray. Therefor thecopy, which I guess is some kind of reference (?) to the same array as 'thearray' was, is invalid or something. Is this the right way to think about this? I'm all new to this reference thing or whatever it is.
And by the way, if .Clone() is added in the end of the second row thecopy remains intact.

Related

A weird For To Loop in Codesys

I was trying to create a timed loop into an array but than I discovered something was not working right so I got back to a simpler example. Now I discovered that my loop skips all the time 1 index and places a value. So I get in index0, index1, index3 only values. I do not understand why this is happening, I'll show my code.
FOR vCount := 0 TO 9 DO
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
vCount := vCount +1;
END_FOR
The result will be:
vVsample[0] = value vVin
vVsample[1] = did not change the value and is therefore 0
vVsample[2] = value vVin
vVsample[3] = did not change the value and is therefore 0
vVsample[4] = vVin
etc up to vCount = 10
I'm using Codesys V2.3 and tested this in simmulation mode
FOR loops already do increment the iterator, thus the vCount := vCount +1; line is the problem. Just remove it:
FOR vCount := 0 TO 9 DO
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
END_FOR
Or change to a while loop:
vCount := 0;
WHILE vCount <> 10 DO
vVsample[vCount] := INT_TO_REAL(WORD_TO_INT(vVin));
vCount := vCount +1;
END_WHILE
I have found the answer by myself allready it is not needed to count up vCount by 1.
When doing this it will skip always one index of the array.
Silly mistake by me

Issue returning proper mouse cords

In this problem setXTowerLocation() is called, a message box than appears after exiting the message box the function getXCords() is called in which it continuously scans checking the keyState of Lbutton once it detects that its pushed down the getxCords() function returns the x value of the cords of the mouse, which in turned gets set to a global variable in the setXTowerLocation() function before returning and displaying the x cord in a message box. Every time i run it the message box comes up blank, i have tested aspects of the code and they all seem to work individually so i believe it must be an error in syntax?
The ending message box is only for testing purposes. Thanks in advance :)
SendMode Input
Global xTowerLocation =
setXTowerLocation()
MsgBox, 0, MessageBox, %xTowerLocation%
getxCords()
{
xCord =
Loop,
{
GetKeyState, state, Lbutton
if(state = "D")
{
MouseGetPos, xx, yy
xCord := %xx%
return
}
}
return xCord
}
setXTowerLocation() {
MsgBox, 0, MessageBox, Begin?
IfMsgBox OK
xTowerLocation := getxCords()
return
}
Yes, syntax error in that xCord is referenced to a variable named after the contents (the mouse coord). Fix these two lines in getxCords() so xCord holds the value of the variable xx as follows:
xCord := xx
return xCord
And then no xCord on that later return (at end of the function).
EDIT: For even more fun, make the above xCord line as follows:
xCord := "x= " . xx . " , y= " . yy

How do I use the contents of an array as a variable name?

Currently I store the contents of an array into a variable, then set that variable up using two % and store a value. My current code looks like this:
Test := {asdf: "blah"}
Temp := Test["asdf"]
%Temp% := "boo"
; above line is be the same as blah := "boo", but blah came from a variable
msgbox %blah% ; outputs "boo"
I don't like having to use the Temp variable like this.
The following compiles but blah stays blank:
(Test["asdf"]) := "boo"
%Test%["asdf"] := "boo"
The following gives me a compile error:
%(Test["asdf"])% := "boo"
I have a vague idea that it should be possible but I just can't find the syntax for it. How do I directly use the array instead of having to put it in a temp variable?
Just figured it out.
The problem here is creating variables using dynamic data may cause invalid variable names to be created. All sorts of ways to screw up here (spaces, UTF-8 code, etc).
One safer way is to use Associative Arrays:
Output := Object()
Test := {asdf: "blah"}
Output[(Test["asdf"])] := "boo"
msgbox % Output["blah"]
There are less restrictions on keys than variable names.
globalWrapper(NameOfTheGlobalVar, LocalVar) {
global
%NameOfTheGlobalVar% := LocalVar
}
Test := {asdf: "blah"}
globalWrapper(Test["asdf"], "boo")
msgbox %blah% ; outputs "boo"

Series of Variables by name

In AHK script:
Code for finding a value between great numbers of variables above, for one variable:
If (Variable1 = "sin (90°)")
MsgBox Value is reached
How searching by this method between series of variables with different value of number in their names? From Variable5 to Variable15, Variable51 to Variable105, etc.
How modify this code if number from 5 to 15, 51 to 105, or 74 to 117 etc?
number = 5
If (Variable%number% = "sin (90°)")
.............
Is %Variable%number%% acceptable and will works surely?
And here may also be useful Associative Arrays. What is it by simple examples?
Best practice here would probably be to use an array in the first place.
myArray := []
myArray[1] := "bla"
myArray.Push("bla2") ;by using this you don't need to worry about the index number
myArray[3] := "sin (90°)"
myArray[4] := 63456
Loop % myArray.MaxIndex()
{
If (myArray[A_Index] = "sin (90°)")
{
MsgBox Value is reached
}
}
... another example
anotherArray := []
Loop, read, C:\Files\prog.txt
{
If (A_LoopReadLine = "FileRead, OutputVar, C:\Files\prog1.txt")
{
anotherArray.Push(A_LoopReadLine)
MsgBox, An interesting code line was found. And was added to the array.
}
Else If (A_LoopReadLine = "blablabla")
{
anotherArray.Push(A_LoopReadLine)
MsgBox, An interesting code line was found. And was added to the array.
}
Else If (A_LoopReadLine = "some other text line")
{
anotherArray.Push(A_LoopReadLine)
MsgBox, An interesting code line was found. And was added to the array.
}
;Else
;{
; MsgBox, Nothing important was found.
;}
}
Loop % anotherArray.MaxIndex()
{
currentArrayEntry := anotherArray[A_Index]
MsgBox, %currentArrayEntry%
}
In an expression you can use variable expansion to modify the name of the variable to use:
number = 5
If (Variable%number% = "sin (90°)")
.............
But consider using arrays instead.
Is %Variable%number%% acceptable and will works surely?
Not. More right way
% Variable%number%
but it may have a problem.
Possible way is use Var := expression
Variable:= number
may be.

With Maple how can i prompt the user to answer a boolean expression?

The exact question would be "is the equation you want to use x=f(Xo)". This is in an if statement already so if true then continue if not then prompt user to enter a different function.
Your bit about its already being inside an if statement isn't very workable because that doesn't allow for an alternative value to be assigned to something in the case that the initial response is negative.
You should be able to work with something like this. Call p(), and assign its result to a ans, say, and then work with that value (and/or test it for some properties).
restart:
p := proc()
local answer, oldprompt, res1, res2;
oldprompt := interface(':-prompt'=``);
try
printf("Is the equation you want to use x=f(Xo)? (y/n)\n");
res1 := readline(-1);
if member(res1,{"y;","y","yes;","yes"}) then
answer := x=f(Xo);
elif member(res1,{"n;","n","no;","no"}) then
printf("Enter your equation.\n");
res2 := readline(-1);
answer := parse(res2);
else
printf("Response not recognized\n");
end if;
catch:
finally
interface(':-prompt'=oldprompt);
end try;
if answer='answer' then NULL else answer end if;
end proc:
ans := p();
[edited below]
It is possible to get it a little closer to your original. With procedure p as below the returned result will be one of true/false/FAIL and could be used in a conditional. In the case that the return values if false (because of the response to the initial query) then a second query is made about the choice of another expression.
This version of p takes two arguments, the first is the suggested initial equation. The second is a name which can be assigned any alternative.
restart:
p := proc(candidate, resultvar)
local result, oldprompt, res1, res2;
oldprompt := interface(':-prompt'=``);
try
printf(sprintf("Is the equation you want to use %a? (y/n)\n",
candidate));
res1 := readline(-1);
if member(res1,{"y;","y","yes;","yes"}) then
result := true;
assign(resultvar,candidate);
elif member(res1,{"n;","n","no;","no"}) then
result := false;
printf("Enter your equation.\n");
res2 := readline(-1);
assign(resultvar,parse(res2));
else
printf("Response not recognized\n");
result := FAIL;
end if;
catch:
finally
interface(':-prompt'=oldprompt);
end try;
return result;
end proc:
Now we can test it out.
p(x=f(X0), 'ans');
ans;
We could also use the call to p inside an if statement. Eg,
if p(x=f(X0), 'ans') then
"accepted";
else
"new choice made";
end if;
ans;
Here, answering "n" to the first query will make the conditional test see a false value, but the named argument ans will get assigned to as a side-effect.