How to check if a variable has been assigned a value in AutoHotkey? - operators

#Warn
WinActivate ahk_class %PrevActiveClass%
When running the above code, the interpreter throws:
I want to check if PrevActiveClass has been assigned a value, if it has, then run WinActivate, how to implement this logic in AutoHotkey?

If you actually want to check whether or not a variable has been set, you can do that by comparing its address(docs) to the address of a non-existent variable:
var1 := "" ;will return non-existent, this doesn't actually really create a variable
var2 := "hello" ;will return non-empty
var3 := "test" ;now a variable actually gets created
var3 := "" ;but here we set it to be empty, so it'll return empty
var4 := false ;will return non-empty
;var5 ;will return non-existent
MsgBox, % (&Var1 = &NonExistentVar ? "Non-existent" : (Var1 = "" ? "Empty" : "Non-empty")) "`n"
. (&Var2 = &NonExistentVar ? "Non-existent" : (Var2 = "" ? "Empty" : "Non-empty")) "`n"
. (&Var3 = &NonExistentVar ? "Non-existent" : (Var3 = "" ? "Empty" : "Non-empty")) "`n"
. (&Var4 = &NonExistentVar ? "Non-existent" : (Var4 = "" ? "Empty" : "Non-empty")) "`n"
. (&Var5 = &NonExistentVar ? "Non-existent" : (Var5 = "" ? "Empty" : "Non-empty"))
But really, pretty much always (at least if you design your program well) you'll be fine by just evaluating a boolean value from the variable, as shown in the other answer. This way you can easily just check the variable's existence with in an if-statement if (var).
var1 := ""
var2 := "hello"
var3 := "0"
var4 := false
var5 := -1
MsgBox, % !!var1 "`n"
. !!var2 "`n"
. !!var3 "`n"
. !!var4 "`n"
. !!var5 "`n"
The only caveat is that there is no difference between false (and 0 (false is a built in variable containing 0)), "" and an actually non-existent variable.
AHKv2 implements its own built-in function for this:
https://lexikos.github.io/v2/docs/commands/IsSet.htm

Here is the method I typically use to detect empty variables
Code:
;#Warn
^r::
if(!PrevActiveClass){
MsgBox not set yet
}
else{
WinActivate ahk_class %PrevActiveClass%
}
return
^e::WinGetClass, PrevActiveClass, A ; Sets the variable to be the active window for testing
In AHK, an empty variable is treated as a boolean false. As such, you can check it in an if statement to determine whether it contains anything. The one caveat with this method (though it does not apply to your use case) is that it does not work as intended if you on assigning the boolean false value to the var.

Quote from #Warn:
Enables or disables warnings for specific conditions which may indicate an error, such as a typo or missing "global" declaration.
#Warn [WarningType, WarningMode]
WarningType
The type of warning to enable or disable. If omitted, it defaults to All.
UseUnsetLocal or UseUnsetGlobal: Warn when a variable is read without having previously been assigned a value or initialized with VarSetCapacity(). If the variable is intended to be empty, assign an empty string to suppress this warning.
This is split into separate warning types for locals and globals because it is more common to use a global variable without prior initialization, due to their persistent and script-wide nature. For this reason, some script authors may wish to enable this type of warning for locals but disable it for globals. [emphasis added]
#Warn
; y := "" ; This would suppress the warning.
x := y ; y hasn't been assigned a value.
In this case, it's safe to turn off the warning for UseUnsetGlobal:
#Warn
#Warn UseUnsetGlobal, Off
WinActivate ahk_class %PrevActiveClass%

Related

Unbind or undefine a variable in raku

After reading the Raku documentation, I only found this for undefining a variable. I believe that in Raku there are differences between assignment and binding.
Defining and undefining a scalar is easy.
> my $n
(Any)
> $n.defined
False
> $n = 3
3
> $n.defined
True
> $n = Nil
(Any)
> $n.defined
False
When the variable is binded, it's not possible.
> my $k := 5
5
> $k := Nil
===SORRY!=== Error while compiling:
Cannot use bind operator with this left-hand side
at line 2
------> <BOL>⏏<EOL>
> $k = Nil
Cannot assign to an immutable value
in block <unit> at <unknown file> line 1
For arrays or hashes, I can empty it, but the variable is still defined.
For functions, when you define a function with sub, you cannot undefine it, but you can with an anonymous function.
> my &pera = -> $n { $n + 2}
-> $n { #`(Block|140640519305672) ... }
> &pera = Nil
(Callable)
> &pera.defined
False
> my &pera = -> $n { $n + 2}
-> $n { #`(Block|140640519305672) ... }
> &pera = Nil
(Callable)
> &pera.defined
False
> sub foo ($n) { $n + 1}
&foo
> &foo.defined
True
> &foo = Nil
Cannot modify an immutable Sub (&foo)
in block <unit> at <unknown file> line 1
So what's the difference between assignment and binding?
How can I undefine a variable?
Lots of different issues to discuss here.
> my $k := 5;
> $k := Nil;
Cannot use bind operator
This first problem is the Raku REPL. cf your last SO. Have you tried CommaIDE or repl.it?
Your code is perfectly valid:
my $k := 5;
$k := Nil;
say $k; # Nil
Moving on:
my $k := 5;
$k = Nil;
Cannot assign to an immutable value
This is different. After binding 5 to $k, the $k = Nil code is attempting to assign a value into a number. Only containers[1] support assignment. A number isn't a container, so you can't assign into it.
Clarifying some cases you mentioned but didn't explicitly cover:
my #foo;
#foo := Nil;
Type check failed in binding; expected Positional...
While scalar variables (ones with a $ sigil) will bind to any value or container, an # sigil'd variable will only bind to a Positional container such as an Array. (Likewise a % to an Associative such as a Hash.)
Not only that, but these containers are always defined. So they still return True for .defined even if they're empty:
my #foo := Array.new; # An empty array
say #foo.elems; # 0 -- zero elements
say #foo.defined; # True -- despite array being empty
Now assigning Nil to an array:
my #foo;
#foo = Nil;
say #foo; # [(Any)]
If a declaration of an # sigil'd variable doesn't bind it to some explicit Positional type it is instead bound to the default choice for an # variable. Which is an Array with a default element value of Any.
The #foo = Nil; statement above assigns a Nil value into the first element of #foo. The assignment of a value into a non-existing element of a multi-element container means a new Scalar container pops into existence and is bound to that missing element before assignment continues. And then, because we're assigning a Nil, and because a Nil denotes an absence of a value, the Array's default value ((Any)) is copied into the Scalar instead of the Nil.
On to the sub case...
sub foo {}
&foo = {} # Cannot modify an immutable Sub (&foo)
&foo := {} # Cannot use bind operator ...
While a sub foo declaration generates an &foo identifier, it is deliberately neither assignable nor bindable. If you want a Callable variable, you must declare one using ordinary variable declaration.
Unbind or undefine a variable
You can't unbind variables in the sense of leaving them bound to nothing at all. (In other words, Raku avoids the billion dollar mistake.) In some cases you can rebind variables.
In some cases you can bind or assign an undefined value to a variable. If it's not a scalar variable then that's like the # variable example covered above. The scalar cases are considered next.
An example of the binding case:
my $foo := Any;
say $foo.defined; # False
say $foo; # (Any)
say $foo.VAR.WHAT; # (Any)
We'll see what the .VAR is about in a moment.
The assignment case:
my $foo = Any;
say $foo.defined; # False
say $foo.WHAT; # (Any)
say $foo.VAR.WHAT; # (Scalar)
It's important to understand that in this case the $foo is bound to a Scalar, which is a container, which is most definitely "defined", for some definition of "defined", despite appearances to the contrary in the say $foo.defined; line.
In the say $foo.WHAT; line the Scalar remains hidden. Instead we see an (Any). But the (Any) is the type of the value held inside the Scalar container bound to $foo.
In the next line we've begun to pierce the veil by calling .VAR.WHAT on $foo. The .VAR gets the Scalar to reveal itself, rather than yielding the value it contains. And so we see the type Scalar.
But if you call .defined on that Scalar it still insists on hiding!:
my $foo;
say $foo.VAR.defined; # False
say $foo.VAR.DEFINITE; # True
(The only way to force Raku to tell you the ultimate truth about its view of definiteness is to call the ultimate arbiter of definiteness, .DEFINITE.)
So what are the rules?
The compiler will let you assign or bind a given new value or container to a variable, if doing so is valid according to the original variable declaration.
Assigning or binding an undefined value follows the same rules.
Binding
All variables must be bound by the end of their declaration.
If a variable's declaration allows an undefined value to be bound/assigned to that variable, then the variable can be undefined in that sense. But in all other circumstances and senses variables themselves can never be "unbound" or "undefined".
Binding is about making a variable correspond to some container or value:
Variables with # and % sigils must be bound to a container (default Array and Hash respectively).
Variables with the $ sigil must be bound to either a container (default Scalar) or a value.
Variables with the & sigil must be bound to a Callable value or a Scalar constrained to contain a Callable value. (The & sigil'd variable that's visible as a consequence of declaring a sub does not allow rebinding or assignment.)
Assignment
Assignment means copying a value into a container.
If a variable is bound to a container, then you can assign into it, provided the assignment is allowed by the compiler according to the original variable declaration.
If a variable is not bound to a container, then the compiler will reject an assignment to it.
Scalar variables
If you use a scalar container as if it were a value, then you get the value that's held inside the container.
Binding a value (defined or undefined) to a scalar variable will mean it will stop acting as a container. If you then try to assign to that variable it won't work. You'd need to rebind it back to a container.
Footnotes
[1] In this answer I've used the word "container" to refer to any value that can serve as a container for containing other values. For example, instances of Array, Hash, or Scalar.

Determine if a variable in Raku is set

I intentionally avoid the term defined because a variable may very well have a defined value but the .defined method will return false (Failures, for instance).
Is there any way to determine whether a variable has had a value set to it?
my $foo;
say $foo; # (Any), its type object, no value assigned
my Str $bar;
say $bar; # (Str), its type object, no value assigned
my $abc = Str;
say $abc; # (Str), the type object we assigned to $abc
How can we disinguish $bar (no value set, typed as Str) from $abc (value set to Str)?
Given that $bar.WHICH == $abc.WHICH, but $bar.VAR.WHICH !== $abc.VAR.WHICH, and methods like .defined will return false for each, is there any quick and easy way to determine that there is a set value?
I supposed it could be checked against the default value, but then there'd be no way to distinguish between the value being by virtue of unset, versus by being set in code.
Variables are always set to some sort of value.
If you don't set it to a value, a value will be chosen for you.
Specifically it will be set to the default.
(If you don't choose a default, it will be set to the type object.)
my $abc;
say $abc.VAR.default.raku;
# Any
my Int $def = 42;
say $def.VAR.default.raku;
# Int
my $ghi is default(42) = 2;
say $ghi.VAR.default.raku;
# 42
What you're asking for isn't really something that Raku supports.
You could probably fake something close though.
(Every instance of Mu.new is unique.)
sub is-not-set ( Mu $_ is raw ) {
$_.self =:= $_.VAR.default
}
my $abc is default(Mu.new);
my $def is default(Mu.new) = Any;
my $ghi is default(Mu.new) = Mu.new;
say is-not-set $abc; # True
say is-not-set $def; # False
say is-not-set $ghi; # False
The thing is that assigning Nil will also set it to the default.
$def = Nil;
say is-not-set $def; # True
As will looking up the default and assigning it.
$ghi = $ghi.VAR.default;
say is-not-set $ghi; # True
I don't think you should worry about such things.
If you really really need something to happen the first time you assign to the variable, you could do something like this:
my $abc := Proxy.new(
# this FETCH only needs to return the default
# as this Proxy gets replaced upon the first assignment
FETCH => -> $ { Any },
STORE => -> $, $value {
# replace the Proxy with a new Scalar
$abc := do { my $abc = $value };
say 'first assignment just happened'
},
);
say $abc;
# Any
$abc = 1;
# first assignment just happened
say $abc;
# 1
$abc = 2;
say $abc;
# 2
The do block is just there so that $abc.VAR.name returns $abc.
Otherwise you could just write $abc := my $ = $value.
I think both the values are identical, but the containers have different type constraints.
Try
my Str $foo;
my $bar = Str;
use Test;
cmp-ok $bar, &[===], $foo, 'The values are identical';
isa-ok $bar, Str;
isa-ok $foo, Str;
isa-ok $bar.VAR.of, Mu;
nok $bar.VAR.of.isa(Str), 'The container $bar is not of Str' ;
isa-ok $foo.VAR.of, Str;
done-testing();
ok 1 - The values are identical
ok 2 - The object is-a 'Str'
ok 3 - The object is-a 'Str'
ok 4 - The object is-a 'Mu'
ok 5 - The container $bar is not of Str
ok 6 - The object is-a 'Str'
1..6
Is that a general question or an implementation problem? If the latter, maybe (ab)using roles is an option?
role isUnset {};
my Str $a = Str but isUnset;
say $a ~~ isUnset;
# meanwile
$a = 'set';
# ...
$a = Str;
# and then
say $a ~~ isUnset; # Now False
my Str $bar and my $bar = Str result in the same thing, both are of type Str but have no definite values. Str is a type object, not a value.
.defined would return True if you'd give $bar a definite value, such as "Str" (note the quotes surrounding the bareword).
You might try to assign a default value to a variable, instead of keeping it undefined:
my Str $bar is default("");
$bar will be Str only if it's assigned that value type; if its value is deleted via assigning Nil it will default again to the empty string. As a matter of fact, the default for a variable is its type object, so:
my Str $foo;
my $bar = Str;
say $foo eqv $bar
will, in fact, return True.

Make win+m followed by win+p execute code

What shoud I do to execute some code (ie: MsgBox "Hello") by:
Pressing win+m
Unpressing m whithout unpressing win
Pressing p
Seems like there's a good answer already, I just wanted to input what I could think of, so here's a version of the earlier answer, but without Sends.
I'd say a solution without them is always desirable, though, of course, in something as small as this, you'll struggle to find any difference in practice.
;runs after m is released on a LWin+m press
<#m up::
Hotkey, <#p, WinMP_Callback, On ;Enable LWin+p hotkey
KeyWait, LWin ;wait for LWin to be released
if (A_PriorKey = "m")
WinMinimizeAll ;keep win+m functional
Hotkey, <#p, , Off ;disable LWin+p hotkey
return
WinMP_Callback()
{
;do stuff
;add this at the end if you dont want
;to be able to keep running this function
;on subsequent presses of p before LWin is released
;Hotkey, <#p, , Off
}
So pretty much what the difference here is toggling the LWin+p hotkey on and off and just using WinMinimizeAll instead of sending LWin+m, since they're the same thing.
Try this:
<#m:: ; "<#" means "LWin"
LWin_m := true ; assign the Boolean value "true" or "1" to this variable
KeyWait, LWin, L ; wait for LWin to be released
LWin_m := false
return
<#p::
If (LWin_m) ; If this variable has the value "true"
msgbox "Hello"
; else
; do sth else
return
EDIT:
For not losing normal win+m and win+p try this:
<#m:: ; "<#" means "LWin"
LWin_m := true ; assign the Boolean value "true" or "1" to this variable
KeyWait, LWin, L ; wait for LWin to be released
If (A_PriorKey = "m")
Send #m
LWin_m := false
return
<#p::
If (LWin_m) ; If this variable has the value "true"
msgbox "Hello"
else
Send #p
return

Why does `will end` behave differently than `will leave` in program-level scope?

I thought that in the top level of a program that will end and will leave would behave the same way, since there is only one big outer scope to exit/leave from. I thought that either one would be a good way to check a variable's final value.
But with will end it acts like the variable has never been initialized:
my $foo will end { put "Final value for \$foo is '$_'"} = 'bar';
put "\$foo is now '$foo'";
$foo ~= ' baz';
OUTPUT
$foo is now 'bar'
Use of uninitialized value $_ of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
in block at phaser_end.p6 line 1
Final value for $foo is ''
However, simply changing will end to will leave does what I would expect from either one:
my $foo will leave { put "Final value for \$foo is '$_'"} = 'bar';
put "\$foo is now '$foo'";
$foo ~= ' baz';
OUTPUT
$foo is now 'bar'
Final value for $foo is 'bar baz'
Why is there a difference in behavior here?
I am using Rakudo-Star 2017.07.
UPDATE
To get the effect that I'm expecting with will end, I have to use a separate END block:
END block:
my $foo = 'bar';
END { put "Final value for \$foo is '$foo'"};
put "\$foo is now '$foo'";
$foo ~= ' baz';
I guess the real question boils down to why does the END block behave differently than the will end block.
will end block:
my $foo will end { put "Final value for \$foo is '$_'"} = 'bar';
put "\$foo is now '$foo'";
$foo ~= ' baz';
Rewritten
Why does will end behave differently than will leave
It looks like will end has a bug similar to this old and now resolved bug for will begin.
Other than that, everything works as I would expect:
my $leave will leave { say ['leave:', $_, OUTERS::<$leave>] } = 'leave';
my $end will end { say ['end:', $_, OUTERS::<$end>] } = 'end';
my $begin will begin { say ['begin:', $_, OUTERS::<$begin>] } = 'begin';
END { say ['END:', $_, OUTERS::<$end>, $end] }
$_ = 999;
displays
[begin: (Any) (Any)]
[leave: leave leave]
[END: 999 end end]
[end: 999 end]
Is the scope for the block with will end different than the scope of the block with will leave?
They have the same outer lexical scope that corresponds to the UNIT scope.
They run in different dynamic scopes. Leave blocks run as part of leaving the enclosing block. End blocks run after the compiler has completely finished with your code and is cleaning up:
sub MAIN(#ARGS) {
...
# UNIT scope -- your code -- is about to be created and compiled:
$comp.command_line ...
# UNIT scope no longer exists. We compiled it, ran it, and left it.
...
# do all the necessary actions at the end, if any
if nqp::gethllsym('perl6', '&THE_END') -> $THE_END {
$THE_END()
}
}
why does the END block behave differently than the will end block?
Because you used $foo in one and $_ in the other.

Get input and pass variable from an if statement with Haskell

Here is a simplified version of the code I'm working on.
main :: IO ()
main = do
args <- getArgs
if null args
then putStr "> " ; userInput <- getLine
else userInput <- readFile $ head args
let conclusion = userInput
This won't work without do notation, the variable won't pass to conclusion below when I do use it, and the putStr, which I'm trying to use to create a kind of prompt, just makes it mad.
Is there something that I'm forgetting to add somewhere?
There are a few problems here. First, you need to include do after then and else:
if null args
then do putStr "> " ; userInput <- getLine
else do userInput <- readFile $ head args
if in do notation is the same as if everywhere else; you have to put an expression after then and else, not statements, and you need do to turn a bunch of statements into an expression. This still isn't quite valid, though; the last statement in a do block must be an expression, but you have a bind here. After all, every statement has to have a result value, but a bind has none.
The second problem is, as you've observed, that this introduces a new scope, and so you can't access variables you bind from outside. This makes sense if you think about it; after all, you could bind the variable on one side and not the other. The solution is to simply move the bind outside the if:
main :: IO ()
main = do
args <- getArgs
userInput <- if null args
then do putStr "> " ; getLine
else readFile $ head args
let conclusion = userInput
So, the action whose result we bind to userInput is still computed depending on the result of null args, but we bind the variable outside the conditional.
Note that I didn't add a do to the else branch this time; it's not required, since there's only a single expression there. (It's still valid, but it's unidiomatic to use do when it's not necessary.)
This code still won't work unless you put something after the let conclusion = userInput line (since, like I said, do blocks must end with an expression), but presumably you already have code there.
As an additional note, you should avoid using functions like head and tail; head is a partial function (not defined for every argument — head [] will produce an error), and those are generally considered unidiomatic. You should use pattern-matching instead, like this:
userInput <- case args of
[] -> do putStr "> " ; getLine
fileName:_ -> readFile fileName
This is just like the pattern-matching used when defining a function, but for a single value rather than any number of arguments.
Any variable bindings you do in the then and else blocks won't be visible in the outer scope, so you need to bind the result from the if clause itself.
main :: IO ()
main = do
args <- getArgs
userInput <- if null args
then do
putStr "> "
getLine
else readFile $ head args