====== 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 ((And into the ''%%static __New()%%'' of any class definitions)).\\ 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%'', and ''SetBatchLines, -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 not ''VarSetCapacity()''. 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)'' (where ''var'' is a ''Buffer'' 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"'' - Hotkeys are now functions. They do not need a ''return''. You //only// need you to specify global variables that you modify. s:: { global varWritable MsgBox "Hi " varReadable MsgBox "Bye " (varWritable := "Jeff") } - 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 need ''var'' 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 3 ''DllCall''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'' and ''Array''. \\ 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 by ''object[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 are ''static'', 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()'' or ''ClassName.Property'' and instance methods can only be called ''instance.Method()'' or ''instance.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, put ''static'' 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