AutoHotkey_L v1.0.90 and Roadmap
Fixed: UrlDownloadToFile in Unicode builds on Windows < 7.
Fixed: Upper-ANSI characters were sent as Alt+0 in ANSI build.
Fixed: File.Pos was incorrect after attempting to read past EOF.
Fixed: Escape sequences in #If expressions and static initializers.
Fixed: ClipboardAll sometimes crashed the script with certain formats.
Fixed: Transform HTML calculated length incorrectly for NNN; entities.
Fixed: VarSetCapacity now correctly ignores #MaxMem for ByRef variables.
Fixed: FileAppend,,file.txt set ErrorLevel=1 even on success.
Fixed: Match length was miscalculated for RegEx callouts with the P) option.
Fixed (Ahk2Exe): InputBox in x64 scripts.
Fixed (Ahk2Exe): #Include <Lib>.
Integrated Sean's improvements to number handling in COM interop.
Optimized RegExReplace and RegExMatch in Unicode builds.
Downloads etc.
Version Numbering
As you may notice by the title of this post, I've changed the version numbering scheme; dropped .Lnum and bumped the version number up quite a bit. My intention is for the version number to reflect the status; something like v1.0.features.bugfixes. Some users suggested AutoHotkey_L be v1.1 or v2, but as I consider the project somewhat incomplete in its current state, I've opted to save v1.1 for later.
Other Changes
In an attempt to solve the anti-virus false positives, I've removed mpress.exe from the installer and have not compressed the other executables. To compress compiled scripts (which also adds a degree of protection), you may need to download MPRESS and place it in the Compiler directory. If you've installed a previous version of AutoHotkey_L, you probably already have mpress.exe.
Roadmap
I have also reviewed my ever-changing TODO list and turned it into a roadmap of sorts. Feel free to comment on anything in that document, but please don't post feature requests here. I don't have a timeline, but I'll probably work on v1.1 and v2 in parallel, depending on what takes my interest.
NOTE - this increased the Unicode x86 version from 364 -> 855 KB.I've removed mpress.exe from the installer and have not compressed the other executables.
I'm not sure what your current thoughts are here, but one thought might be a conditional/dynamic replace value:[*:3kdq4lbt]RegExReplace callback functionality - needs a lot more thought.
MsgBox, % RegExReplace("autohotkey", "(a|h)(?CFunc)", ReplaceValue) Func(M, C, F, H, N, ByRef ReplaceValue) { ReplaceValue := (M="a"? "A":"H") }
I really like this idea. Not requesting anything here (just thoughts), but would dynamic creation of objects (arrays specifically) be an option?[*:3kdq4lbt]Object default value ...
val = AHK val[1] := "value" ; w/o defining an object MsgBox, %val% ; shows "AHK" MsgBox, % val[1] ; shows "value"*The primary (noobish) benefit being that array[n] would be similar to array%n%
Personally, I strongly oppose this. This is one of my favorite features in AHK, & IMO it makes simple coding more enjoyable.Auto-concat: It might be best to eliminate automatic concatenation ...
And of course, thank you for you continued efforts in developing AHK
This was asked by me and maybe others already. I also released a script that can do that.I'm not sure what your current thoughts are here, but one thought might be a conditional/dynamic replace value:
AFAIK, the PCRE doesn't support it.
This is awesome. Thanks for changing your stance on it.Named parameters: func(x, y, foo: bar).
Meta-operators: allow an object to define what happens when a given operator is used on it and another object or non-object value.
Object default value.
val = AHK val[1] := "value" ; w/o defining an objectThis is IMHO the wrong direction, as it makes very hard to follow the code logic.
I miss some informations about the OOP future. Regarding at this example, I have the basic request, that defining Objects should be possible.
This approach could be solved by precompiler, as fincs already shown, but I would appreciate a offical, native implementation.
For the moment I dont request any kind of Data-Encapsulation - just new keyword/block type for defining classes and automated loading of this "base" Objects, so the following should be possible:
Progress, m2 b zh0, Collectiing dlls... dlls := CollectDLLs() for k,dll in dlls { Progress, m2 b zh0, % "registring " dll.FileName() dll.Register() } MsgBox % "Registered " dlls.Count() " dlls!" exitapp CollectDLLs(){ global dlls := new Collection() loop, %a_scriptdir%\*.dll dlls.Insert(new Dll(A_LoopFileFullPath)) return dlls } class Collection { Collection.Count := "Collection_Count" Collection_Count(this){ i := 0 for e in this i++ return i } Collection(){ ; void constructor } } class Dll { Dll.Register := "Dll_Register" Dll.FileName := "Dll_FileName" Dll.Path := "" Dll_Register(this){ run, % "regsvr32 /s""" this.Path """" } Dll_FileName(this){ fullPath := this.Path SplitPath, fullPath, fileName return fileName } Dll(this){ ; Constructor this.Path := path } }
any change for this direction?
+1
[quote name="IsNull"]just new keyword/block type for defining classes and automated loading of this "base" Objects, so the following should be possible:
[i][color=gray][code snippet omitted for brevity][/color][/i][/quote]
I think there is too much redundance (the "class" name is repeated too many times). I propose this:
[code]class Collection
{
Count() ; implicit this parameter
{
i := 0
for e in this
i++
return i
}
Collection(){ ; or even this() in order to avoid duplicating the class name
; void constructor, which is actually optional
}
}
class Dll
{
Register()
{
run, % "regsvr32 /s""" this.Path """"
}
FileName()
{
fullPath := this.Path
SplitPath, fullPath, fileName
return fileName
}
Dll()
{
this.Path := path
}
}
[/code]
This would work like my preprocessor, except that code generation/tweaking is done at parse time instead.
That was the whole point. See [AHKL] RegExReplace Callout.I'm not sure what your current thoughts are here, but one thought might be a conditional/dynamic replace value:
Your example might be possible since it could allow the array val to have a default value "AHK", but it would not happen automatically. See Default Base.Not requesting anything here (just thoughts), but would dynamic creation of objects (arrays specifically) be an option?
I also feel that way. However, I make a habit of avoiding auto-concat where neither operand is a literal string, so I had considered enabling it only in cases like foo "bar" and "item" x+1, where a literal string is involved.Personally, I strongly oppose [removing auto-concat]. This is one of my favorite features in AHK, & IMO it makes simple coding more enjoyable.
Whether or not PCRE directly supports it is irrelevant. PCRE only handles matching; all of the replacing is done by RegExReplace.AFAIK, the PCRE doesn't support it.
I have the basic request,
AutoHotkey_L objects are prototype-based, not class-based. I think that using the "class" keyword encourages users to think inside the box, so to speak, which is more restrictive. My objection isn't a strong one, but there would have to be community consensus before I implement anything further than what I've written in the roadmap.please don't post feature requests here.
This has the advantage of simplicity, as well as being more directly analogous to the actual implementation. I believe Lua similarly supports function Type:Method(params) … end, but it's probably equivalent to Type.Method = function(params) … end. Inline functions aren't really an option with the current architecture.Syntax sugar for defining object methods; perhaps something simple like Type.Method(params) { … } which would define a function, create an object Type if necessary and store a function reference in Type.Method (all at load time). Type would typically be used as a base for other objects at run time.
Additionally, I thought about the new keyword but was unable to think up any practical benefit of it over simply calling the function and allowing it to create the object. This is how your example might look if I implement only what's on the roadmap:
Progress, m2 b zh0, Collectiing dlls... dlls := CollectDLLs() for k,dll in dlls { Progress, m2 b zh0, % "registring " dll.FileName() dll.Register() } MsgBox % "Registered " dlls.Count() " dlls!" exitapp CollectDLLs(){ global dlls := Collection() loop, %a_scriptdir%\*.dll dlls.Insert(Dll(A_LoopFileFullPath)) return dlls } Collection() { global Collection ; Ideally this wouldn't be necessary. return { base: Collection } } Collection.Count(this) { i := 0 for e in this i++ return i } Dll(path) { global Dll return { Path: path, base: Dll } } Dll.Register(this) { run, % "regsvr32 /s""" this.Path """" ; Ideally: ; run, regsvr32 /s"%this.Path%" } Dll.FileName(this) { fullPath := this.Path SplitPath, fullPath, fileName return fileName }This would also be an option:
c := Collection.New() Collection.New() { global Collection return { base: Collection } }
I agree that Prototype-based is better for AHK, but I would like to see the ability to completely define an object & all it's members in one block. polyethene had mentioned the concept of defining functions within functions. Would something like this be a reasonable option:AutoHotkey_L objects are prototype-based, not class-based. I think that using the "class" keyword encourages users to think inside the box, so to speak, which is more restrictive.
MyObj := SomeObject() MyObj.func() SomeObject() { obj := {} obj.func(this) { MsgBox, Message from SomeObject } return, obj }
I don't see what the fuss is about. If you just lump the function definitions together, what's the difference?I would like to see the ability to completely define an object & all it's members in one block.
That does seem logical, though perhaps more difficult to implement. I'd say it should be feasible, but I'm concerned that users would expect to be able to access local variables of the outer function from within the inner function, as in languages like JavaScript. I don't think closures are feasible with the current architecture, but on the other hand I wouldn't want to allow functions-in-functions now (merely for "tidy" code) then later be forced to break compatibility if closures become possible.Would something like this be a reasonable option:
SomeObject() { obj := {} obj.func(this) { MsgBox, Message from SomeObject } return, obj }
I'll have to reconsider what is needed to allow functions-in-functions; beyond that I think your proposal could work simply by generating a private function definition and assignment, equivalent to this:
SomeObject() { obj := {} [color=darkred]obj.func := "SomeObject_obj_func" SomeObject_obj_func[/color](this) { MsgBox, Message from SomeObject } return, obj }This reminds me of something else I have thought about but haven't really planned: function references. If a function reference can be assigned to a variable and called naturally as var(), that would solve any name-spacing issues for functions-in-functions. However that likely has other implications for compatibility, so should be considered thoroughly for v2.
Its not equivalent. In Lua, : are used as syntax sugar for object creation, i.e. to avoid specifying first argument (i.e. this). The same can be done in AHK, or, you don't even have to differentiate between two cases Lua has (: and . ). You can simply use . the way Lua uses :.I believe Lua similarly supports function Type:Method(params) … end, but it's probably equivalent to Type.Method = function(params) … end. Inline functions aren't really an option with the current architecture.
The colon syntax is used for defining methods, that is, functions that have an implicit extra parameter self. Thus, the statement
function t.a.b.c:f (params) body end
is syntactic sugar for
t.a.b.c.f = function (self, params) body end
+1This reminds me of something else I have thought about but haven't really planned: function references. If a function reference can be assigned to a variable and called naturally as var(), that would solve any name-spacing issues for functions-in-functions. However that likely has other implications for compatibility, so should be considered thoroughly for v2.
+1Personally, I strongly oppose this. This is one of my favorite features in AHK, & IMO it makes simple coding more enjoyable
Isn't form of closure already achievable using _LowLevel and assume static ? One more point IMO, for lowlevel to become part of AHK, apart from other great benefits this library would provide.I don't think closures are feasible with the current architecture,
I also agree with Lexikos that AHK doesn't need full blown class syntax support. The things already in the roadmap should be enough.
Did you mean You don't need it? Thats really the same bad reason as I say I want it.I also agree with Lexikos that AHK doesn't need full blown class syntax support. The things already in the roadmap should be enough.
I agree. But the problem actually is, AHK Community has really a lot of people who don't care about any OOP and just want things easy. On the other hand, if the Language provides more experienced design features, the community might grown/change.My objection isn't a strong one, but there would have to be community consensus before I implement anything further than what I've written in the roadmap.
To be serious, I don't have experience with prototype-based OOD. However, I like to learn new things, but for now any interesting AHK_L Objects which I found try to imitate class design.
As I think at least you, Lexikos, should be experienced in prototype-based Design, can you provide some reference AHK_L OOD examples? I mean there are reasons why I like the class Design - but I dont see any for the prototype-based Design - and before I fight against something, I want to know the motivation.
This was just the basic future question for me, and it's the core point for my decision using AHK(_L) or not. I just wanted to hear "Forget it" or "There may be possibities" :wink:please don't post feature requests here.
No, I don't mean that. I prefer effort to be used on appropriate place that would actually give some new functionality. The other reason is that imposes some limitations on how AHK "objects" could be used. Lets not forget that AHK is script language and its used to create tools, gedgets, admin scripts etc. While those can be large applications they benefit more from "less strict" and "open" environment.Did you mean You don't need it? Thats really the same bad reason as I say I want it
This is personal preference. There are many prototype based languages around, mostly those used for scripting which leads one to believe its actually good thing since so many different scripting languages adopted it. I personally prefer dynamic languages over those that follow strict protocols because you can "reconfigure" particular "instance" of an object on the fly.I mean there are reasons why I like the class Design - but I dont see any for the prototype-based Design
In short I believe that AHK should follow Lua in this regard since it is already hardly influenced by it. Lua concept is proven good as it is used in large object oriented systems, for instance World of Warcraft (this use case proves its OO capabilities are good enough for hard core scenarios like MMO gaming, hence they must be good enough for other uses).
I don't see why you think assume-static allows anything even close to a closure. Do you mean because it allows one to access variables of another function? Only the variables of the top-most instance of the function are available, and only while it is running.Isn't form of closure already achievable using _LowLevel and assume static ?
Well, consensus among the community members that have an opinion, then.But the problem actually is, AHK Community has really a lot of people who don't care about any OOP and just want things easy.
When I added object support, my first and foremost objective was to get it done quickly, and a prototype-based design seemed the easiest to implement while also being flexible. Secondly, I wanted to support COM objects, where AutoHotkey doesn't necessarily know which members it has before they are invoked, therefore the meta-function approach fit best. Finally, I had read about Lua's meta-functions __index and __newindex and therefore knew it could work. However, at that time I had no actual experience with Lua and very little with JavaScript. As for "prototype-based OOD", I'm always more focused on building functionality than following or discussing abstract concepts; maybe that's why I'm interested by this scripting language originally intended for non-programmers.As I think at least you, Lexikos, should be experienced in prototype-based Design,
Also, I like Jethrow's idea of not having to declare arrays. For backwards compatibility they should still be allowed to be declared (at least until v2).
Another note: It would be nice if you included a copy of the 32 bit compiler in the 64 bit install. I have a 64 bit computer and downloaded the 32 for that reason.
Request Video Tutorials Here or View Current Tutorials on YouTube
Any code ⇈ above ⇈ requires AutoHotkey_L to run