v1→2 Conversion Cheat Sheet
General
- There is no more Auto Execute section. Automatic execution starts at the top and goes around any defined hotkeys 1).
Get rid of ❌ top-level returns, add ✅ auto-execute code below hotkeys (if you want) - You no longer need the boilerplate at the top of each script.
#NoEnv
,SendMode Input
,SetWorkingDir %A_ScriptDir%
, andSetBatchLines, -1
are all defaults in v2.
Get rid of ❌ boilerplate - Legacy assignments (
=
) were removed.
Change ❌var = text
to ✅var := "text"
- Commands do not support a first comma anymore.
Change ❌Sleep, 1000
to ✅Sleep 1000
. - All commands have been turned into functions. Command syntax is just a function call without parentheses (commands can be any function, even user defined ones). Consequently, plain text parameters are gone and all parameters are expressions all the time.
Change ❌MsgBox Hello
to ✅MsgBox "Hello"
or ✅MsgBox("Hello")
- Memory is reserved using
Buffer()
objects notVarSetCapacity()
. Buffer is an Object, which always pass by reference, so you don't pass binary data by reference anymore.VarSetStrCapacity()
exists but ONLY for string optimization.
Change ❌VarSetCapacity(var, capacity, fillByte)
to ✅var := Buffer(capacity, fillByte)
- Ampersand (
&
) is no longer the "address of" operator.
Change ❌DllCall(…, "Ptr", &var)
to ✅DllCall(…, "Ptr", var)
(wherevar
is aBuffer
object) - Guis are fully object-oriented, distinguished by variable reference not by name.
- Multi-value expressions return the last value, not the first value.
Change ❌return (varToReturn, tmp := 1234)
to ✅return (tmp := 1234, varToReturn)
- Single-quoted strings can contain text with double quotes. Doubling up quote marks no longer escapes quotes.
Change ❌var := "Some ""quoted"" text"
to ✅var := 'Some "quoted" text'
or ✅var := "Some `"quoted`" text"
- Variables start as
unset
(which is a state, not a value). Unset variables throw when read. Unset makes a great default parameter.
Change ❌MyFunc(param1, param2 := "") {…}
to ✅MyFunc(param1, param2 := unset) {…}
Change ❌if (param2 != "")
to ✅if IsSet(param2)
Change ❌var := [1, , 2]
to ✅var := [1, unset, 2]
Change ❌FunctionCall(required1, required2, , optional2)
to ✅FunctionCall(required1, required2, unset, optional2)
Change ❌var := "" ; Empty the variable
to ✅var := Unset
(unless you needvar
to be an empty string)
New Stuff
- For loops can iterate values directly. In v1, the variable i will return 1, 2, 3… this is not a problem in v2 and will return a, b c.
for v in ["a", "b", "c"] MsgBox v
ComCall
can iterate through a virtual function table without 3DllCall
s
Functions
- Functions can read Global Variables by default, but not write to them.
- ByRef is now done by ampersand, and must be specified by both caller and callee.
Change ❌MyFunc(ByRef a) {…}
to ✅MyFunc(&a) {…}
Change ❌result := MyFunc(a)
to ✅result := MyFunc(&a)
New Stuff
- First class functions are supported. So you can use
MsgBox
as a function reference.execute(func) { func("a message") } execute(MsgBox)
In v1, you had to pass
execute(Func("MsgBox"))
. - Fat arrow syntax allows easy definition of functions and function objects, so long as those functions can be written as a single return statement.
; This code: ;FAIL() { ; MsgBox "Function Failed" ;} ; Can become: FAIL() => MsgBox("Function failed") ; This code: ;SomeGlobalFunc(x) { ; x *= 5 ; MsgBox "Times 5: " x ; return x ;} ;FuncObj := Func("SomeGlobalFunc") ; Can become (no longer needing a global function): FuncObj := (x) => (x *= 5, MsgBox("Times 5: " x), x)
- Functions can be defined inside functions, forming Closures. Closures are like bound functions, but they bind variables by reference not value meaning they can modify enclosed variables.
closureFactory(valueToBeEnclosed) { myClosure(newValue := unset) { return IsSet(newValue) ? valueToBeEnclosed := newValue : valueToBeEnclosed } return myClosure } myFuncObject := closureFactory(24) MsgBox myFuncObject() myFuncObject(25) MsgBox myFuncObject()
Objects
- Objects now have specific sub-types,
Map
andArray
.
Change ❌var := {"key": value}
to ✅var := Map("key", value)
(unless you are sure you want a basic Object not a Map)
Keep ✅var := []
or ✅var := Array()
(both work) - Objects now have two key value stores, one for Properties and one for Items. The basic object only supports Properties, the Map and Array support Items in different ways. Properties should have set literal names, Items can have dynamic names, like from a variable. Properties are accessed by
object.LiteralName
, Items byobject[variableName]
.data := Map("Count", 1234) MsgBox data.Count ; Access Property "Count" -> 1 MsgBox data["Count"] ; Access Item "Count" -> 1234
Classes
- You do not use
new
to create a class anymore, you just call it by name.
Change ❌inst := new Class()
to ✅inst := Class()
- Classes create both a Global Object and a Prototype now. The global object (
ClassName
) holds items that arestatic
, the prototype (ClassName.Prototype
) is copied to make new instances. In v1, the global object served both purposes. - You can't mix "static" and "instance" class members anymore. Static members can only be called
ClassName.Method()
orClassName.Property
and instance methods can only be calledinstance.Method()
orinstance.Property
. From inside a static method,this
refers to the Global Object. From inside a normal method,this
refers to the instance.
To create a static member, putstatic
before its name.class Test { static Property := 1234 Property := 5768 static Method() { MsgBox "Static Method: " this.Property } Method() { MsgBox "Instance Method: " this.Property } } Test.Method() ; Static Method: 1234 Test().Method() ; Instance Method: 5678
1)
And into the
static __New()
of any class definitions