conversion logic, v1 = -> v1 := -> v2, two-way compatibility

Discuss the future of the AutoHotkey language
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

10 Nov 2017, 18:27

:arrow: list.new(1,5)
Is the point to make code unconditionally run on both v1 and v2? Otherwise, you can do double-deref in v2, and single-deref in v1,

Code: Select all

v2 := true
text := "a,b,c,d,e"

delimiter := ","
del := v2 ? "delimiter" : delimiter
 
loop parse, text, %del%
	str .= A_LoopField  "`t" A_Index "`n" 

numLoops := 5
N := v2 ? "numLoops" : numLoops

Loop %N%
	str .= A_Index " "
msgbox str	; add % for v1
Cheers.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

10 Nov 2017, 18:40

- Well done Helgef. Because of being loath to try the deref approach, and because of periodically remembering and forgetting to try it, it could have been months before I tried it, so I'm most grateful for your example, and you've done a really nice job of it.
- One of my goals with two-way compatibility, is that it shouldn't be too ugly, and using dereferences in that way seems a bit ugly. It is very effective and simple though, and a worthwhile solution to mention.
- Whereas the for loop approach had an air of legitimacy about it, that you might even want to do it in that way, by choice. In fact, it even had the advantage of allowing you to name the loop variables, i.e. to use names other than A_Index/A_LoopField, something I had been curious about, and to use numbers others than '1,2,3,...'.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

10 Nov 2017, 19:09

It is probably a bit wasteful to use the for loop in the case where you might break the loop early. I don't know if the parse loop pre-processes the whole haystack before the first iteration, I'd be surprised if it did though.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

11 Nov 2017, 17:53

- @Helgef: Interesting comment.
- @guest3456: Thanks for sharing. Yes, I came across that before, looking at your GDIP conversions, I don't know if I mentioned it on this thread or not. To me, in the world of AHK v2 conversion, it's already a classic of the genre.

WinExist = WinGetID. It even says this on the AHK v2 help index. I don't mind keeping both, it's a bit like obj := [] and obj := {} (both create identical arrays, but the writer signals the expected kind of keys), just use whichever is most logical, one assumes existence (WinGetID), one checks for existence (WinExist).

Btw I think the WinWait/WinWaitActive functions should return an hWnd. I always wanted a function that would wait until a window existed, and then return the hWnd, or 0 if it timed out.

[EDIT:]
- It turns out that for SendMessage in AHK v2, you have to retrieve the return value direct from the function, and not from ErrorLevel. This is pretty inconvenient to convert, and it would have to be done manually, but I think it's the right thing to do. Also, this is more consistent with using SendMessage via DllCall.
- As a rule of thumb, and it's a bit of a generality, I should expect not to see ErrorLevel anywhere in my scripts, (at least in scripts proper, custom functions aside,) anyway it's a useful paradigm to consider.
- I already have the rule of thumb that in my main scripts, not function libraries, I should never see DllCall anywhere.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

15 Nov 2017, 10:25

jeeswg wrote:- The only problems I've had with two-way compatibility are double quotes (there are workarounds) and Loop (no workarounds currently). There may be other problems that I'm as yet unaware of.
GUI ?

User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

15 Nov 2017, 11:03

- You're right. Just that in all of my function libraries I never use the Gui command because it causes persistence, and so I tend to forget about the GUI issue. And in all of my serious GUI scripts, I've wanted certain things to be either available, or easier to do, and so I was using my own GUI functions.
- IIRC lexikos had stated that the AHK v2 GUI objects would be available for AHK v1 in a custom library at some point, in a similar way to my functions library.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

16 Nov 2017, 13:18

we've used some of the ideas in this thread to restore v1 backwards compatibility to my AHKv2-Gdip library
https://github.com/mmikeww/AHKv2-Gdip/issues/11

as for the GUIs used in the /Examples/ folder, i instead just commented the lines out and will let users swap the commenting. i guess yes you could just create your own GUI functions. the fact that AHK allows us to directly DllCall means that ultimately we can fall back on that and just replicate the AHK source if you care enough about backward compatibility

User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

24 Nov 2017, 23:34

- Re. loops, you can use Explorer to list the files in a folder.
259-char path limit workarounds - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 82#p184682
- So now we have Loop, LoopParse, LoopRead (via FileRead and LoopParse) and LoopFiles all with two-way compatible workarounds, which leaves LoopReg, and as I said before I wrote a script that replicates LoopReg.

AHK via DllCall: AutoHotkey functions as custom functions - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=7&t=37871
registry: list keys/values via DllCall - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=38191
- And just to repeat, it's nice to know that some of these methods are available, but I won't necessarily use them in my scripts/libs, they're more as a method of last resort.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

26 Nov 2017, 02:39

OBJECTS V. VARIABLES REVISITED

- I was working on this library, and had come up against the question of arrays v. variables.
GUIs via DllCall: get/set internal/external control text - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=40514
- I noticed here, the same problem being considered.
v2-thoughts
https://autohotkey.com/v2/v2-thoughts.htm
- I thought it made sense that WinGetControls/WinGetControlsHWND/WinGetList moved to arrays instead of pseudo-arrays.
- However, in 'control get text' functions, there was a dilemma. Get text for an Edit control, get an array for a listview? But what if you just want the focused item of a listview, variable or one-item array?
- This is why, in my functions, I went with all variables by default, LF-delimited text by default, with the option to use an array. It's simple, you know it's text unless you specify an object.
- I think it might be good to have an 'A_' variable, that sets a variable/object mode for ControlXXX functions, and RegExMatch and StrSplit.
- I know arrays are better for a lot of things, but I know that I also like/prefer variables for many things. Both are good.
- I think this idea could please a lot of people.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

26 Nov 2017, 06:57

AHK v2 is meant to remove Pseudo Arrays among other things.
Here is a list of reasons why Pseudo Arrays are bad:
-Pseudo Arrays can't be returned
-Pseudo Arrays clutter the scope
-Pseudo Arrays can't get restructured easily ( e.g. you can't put one Pseudo Array into another Pseudo Array )
-Pseudo Arrays are difficult to free and are not freed automatically
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

26 Nov 2017, 12:25

- I just want to point out that there are two string solutions. One is pseudo-arrays, e.g. var1, var2, var3, one is multiple items in one variable but delimited.
- One problem with using 'A_' variables is that if you have to end a function early, you have to reset the variable before using 'return', so it's usually better to specify any modes in hardcode.
- What do you mean by 'Pseudo Arrays clutter the scope', are you saying that some variables are created within a function but are made global? Is there not a way to fix this?
- There are times when 'a,b,c' to 3 variables rather than 1 object is advantageous. The idea of doing that in theory, I think is fine. I don't recall anyone mentioning the implementation problems when I last brought up variables v. objects. I feel more sympathetic to removing RegExMatch variable mode and StringSplit (i.e. StrSplit variable mode), when the implementation problems are considered. I think at the time, the arguments were more that pseudo-arrays were ugly or unusual (arguments that don't work for me).
- So yes I guess on balance, eliminate pseudo-arrays. But that leaves whether ControlXXX should return LF-delimited strings or arrays by default, and the one-item array question. I'm 50/50 on whether the LF-delimited string or array should be the default, until the one-item array question is addressed. Using arrays could mean the frequent use of [1] and StrJoin, and so having 'output as separator-delimited text' as the default or as an option could be advantageous.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

26 Nov 2017, 13:07

jeeswg, for example,

Code: Select all

f(1)
msgbox % var1	; :(	v1
;msgbox(var1)	; : )	v2
f(a){
	var%a% := 37
}

AHK v2 is meant to remove Pseudo Arrays among other things.
There are (rare) use-cases for dynamically named variables, in particular they are better than ever in v2 ;). But for most cases, I certainly agree with your list.
@ jeeswg, under no circumstances should built-in functions return delimited strings or define any number of named variables, imho :).

Cheers.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

26 Nov 2017, 13:49

jeeswg wrote:- I just want to point out that there are two string solutions. One is pseudo-arrays, e.g. var1, var2, var3, one is multiple items in one variable but delimited.
I did not know what you mean with variable mode since you just went ahead and invented a term that I have never heard before - I just assumed you meant Pseudo-Arrays since they really do relate to variables.
The string solution is impossible though due to the fact that there simply is no general delimiter that could never be used inside any of the strings.
So you would have to resort to methods such as character escaping or other methods such as specifiyng a custom delimiter.
Character escaping will introduce significant overhead when extracting the strings. Specifying a custom delimiter is just asking for bugs and it's not very developer friendly either.
Therefore this is not actually an option.
jeeswg wrote:- What do you mean by 'Pseudo Arrays clutter the scope', are you saying that some variables are created within a function but are made global? Is there not a way to fix this?
What I mean is that they clutter the scope you are in.
jeeswg wrote:- There are times when 'a,b,c' to 3 variables rather than 1 object is advantageous. The idea of doing that in theory, I think is fine. I don't recall anyone mentioning the implementation problems when I last brought up variables v. objects. I feel more sympathetic to removing RegExMatch variable mode and StringSplit (i.e. StrSplit variable mode), when the implementation problems are considered. I think at the time, the arguments were more that pseudo-arrays were ugly or unusual (arguments that don't work for me).
You have yet to prove that there is any kind of advantage towards the existence of Pseudo-Arrays that would warrant their drawbacks and the drawbacks from having 2 ways of doing things.
People, just call it ugly, instead of pointing out what's ugly about it, because towards most people these drawbacks are so apparent, that they don't even feel the need to mention them.
Not taking such an argument seriously will only lead to you not being taken seriously.
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

26 Nov 2017, 19:10

The below quote is regarding for loop parameters in v2 (When the loop breaks or completes, these variables are restored to their former values.), I think the discussion is more appropriate for this thread.
jeeswg wrote:Btw this change in AHK v2, could cause mayhem with my scripts. I could do with an advanced script parser to help identity instances of this.
source
Indeed it is an important change when considering two-way compatabillity and conversion. Imo, it is a case best suited for manual conversion, it will be too hard (or simply not worth the trouble) to make a good automatic conversion. If you are desperate, you can use a while loop instead, something like this

Code: Select all

while (e || e:=(expr)._newEnum()) && (e.next(k,v) || e:="")
could (possibly) replace

Code: Select all

for k, v in (expr)
Cheers.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

27 Nov 2017, 01:15

I think an assignment inside the for loop is probably a better alternative.
Recommends AHK Studio
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

27 Nov 2017, 03:41

nnnik wrote:I think an assignment inside the for loop is probably a better alternative.
Yes, I agree, but where? That is the challenge with this conversion. You have to assess if it is needed, and how best to. Eg,

Code: Select all

for k, v in expr {
could be

Code: Select all

for _k, _v in expr {
	k:=_k, v:=_v
but that could imply an immense amount of unnecessary string copies. In some cases you will only need to make 1 assigment before the loop breaks. If I were to blindly convert my for loops, I'd probably go with k:=_k, v:=_v at the beginning of each iteration, it is probably often best :think: .
I would also like to retract my above while + e suggestion, since the enumerator is not being released if the loop break early :facepalm: .

Cheers.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

12 Dec 2017, 18:19

TRANSMISSION ACCOMPLISHED

- I converted all of my main scripts, which run together as one script, around 53000 lines, and got it to run in AHK v2. I haven't moved over yet, because I still need to convert the function libraries. I saved them for later, so I could test my finalised converter script on them.
- I have some interesting things to report back with, but essentially, all the main issues have already been discussed here. There's a modest amount of material to cover, but it'll take me a while to iron it out.

Two main issues I can see with conversion:
- Identifying lines that contain "", that need to be converted to `" or Chr(34) or vDQ. This would require some advanced parsing. Although, """ and """", these can be checked for quite easily.
- A way to list every error in a script, and not one at a time via a MsgBox. Having a list of errors would be a workaround to the point above about double quotes. Perhaps there is already a way to do this, I'll check. Cheers.
- [EDIT:] Re. listing errors, /ErrorStdOut and /iLib are the key.
AutoHotkey Scripts and Macros
https://lexikos.github.io/v2/docs/Scripts.htm#cmd
#ErrorStdOut
https://lexikos.github.io/v2/docs/comma ... StdOut.htm

- [EDIT:] Re. two-way compatibility, the only obstacle has been Loop lines. I don't know if, say, a directive for AHK v1 would be possible, that would make Loop lines act like in AHK v2.
- The other issue is using Chr(34) for double quotes (or \x22 in RegEx), which, though it works to give two-way compatibility, is not ideal.
- Just to be clear, by two-way compatibility, I mean scripts/function libraries that work on both AHK v1.1* and AHK v2 (*AHK v1.1 with the 'AHK v2 functions for AHK v1' library).

- [EDIT:] A general AHK issue has been Deref, there was a Deref function in AHK v2, which is currently not available in AHK v2, that I had hoped would be backported to AHK v1. In AHK v1 the equivalent is Transform's Deref subcommand. I have a subroutine which reads paths from an ini file, and a subroutine which launches paths in the selected text. The subroutines dereference a vast number of known variables defined in the script.
- This is/was useful for debugging because I could select a path containing a variable, and then the script would apply Deref and the folder would open. Deref is awkward because of local/global variable, scope issues, you can't simply create a custom function that replicates it. (I've been able to backport virtually everything else myself using custom functions.)
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

13 Dec 2017, 19:34

CHECKING SCRIPTS FOR ERRORS

- In theory, it would be useful to have a script that could list all of the errors in a script, not just the first one, via the command line. (Perhaps this is already possible but I couldn't see how to do this.)
- A workaround could be to retrieve the text from, and dismiss, the multiple error messages that occur when you try to run a script. However, the risk here is that if the script is able to launch, there could be unpredictable behaviour, even if the first line of the script is ExitApp. (Also, there may be no errors in a script, or minor errors which don't prevent the script from launching.)
- Anyhow, I have been able to check each individual line for errors, and this addresses the vast majority of the errors. Two command line switches are used, /ErrorStdOut to output an error message to a variable, and /iLib to suppress a script, i.e. to stop it from running.

- Here is an AHK v1 script, that can be used to check individual lines of code for errors, for both AHK v1 and AHK v2:

Code: Select all

q:: ;AutoHotkey scripts - check individual lines for errors
vScript = ;continuation section
(` %
var = value
var := value
var := """"
var := "`""
MsgBox, % "hello world"
MsgBox("hello world")
)
vPathAhk2U32 := A_Desktop "\AutoHotkey_2.0-a081-cad307c\AutoHotkeyU32.exe"
vPathAhk2U64 := A_Desktop "\AutoHotkey_2.0-a081-cad307c\AutoHotkeyU64.exe"
;vPathAhk2U32 := A_AhkPath
vOutput := ""
Loop, Parse, vScript, `n, `r
{
	vScriptLine := A_LoopField
	oShell := ComObjCreate("WScript.Shell")
	oExec := oShell.Exec(Chr(34) vPathAhk2U32 Chr(34) " /ErrorStdOut /iLib * *")
	;MsgBox, % vScriptLine
	oExec.StdIn.Write(vScriptLine)
	oExec.StdIn.Close()
	vStdErr := oExec.StdErr.ReadAll()
	;MsgBox, % vStdErr
	vOutput .= vScriptLine "`r`n" vStdErr "`r`n"
	oShell := oExec := ""
}
Clipboard := vOutput
MsgBox, % vOutput
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: conversion logic, v1 = -> v1 := -> v2, two-way compatibility

27 Dec 2017, 17:53

BINARY / CLIPBOARD DATA

FileRead/FileAppend/the Clipboard variable handle binary and clipboard data differently in AHK v2. Hence, if you're wanting any two-way compatible approaches regarding this, here are some possibilities. A key innovation in AHK v2 has been improved support for storing binary data in standard variables, e.g. to pass binary data out of functions, in AHK v1, required the use of ByRef variables.

I had been curious about removing clipboard formats from the clipboard, and this led me to an understanding of the ClipboardAll variable.
clipboard: remove individual clipboard formats + save to clp file - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=6&t=39522

There is a good explanation here:
Clipboard and ClipboardAll
https://autohotkey.com/docs/misc/Clipboard.htm
A saved clipboard file internally consists of a four-byte format type, followed by a four-byte data-block size, followed by the data-block for that format. If the clipboard contained more than one format (which is almost always the case), these three items are repeated until all the formats are included. The file ends with a four-byte format type of 0.
FILE READ/WRITE BINARY DATA

[for JEE_FileReadBin, see:]
conversion logic, v1 = -> v1 := -> v2, two-way compatibility - Page 5 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=37&t=27069&p=169780#p169780

Code: Select all

JEE_FileWriteBin(ByRef vData, vSize, vPath)
{
	if !oFile := FileOpen(vPath, "w") ;empties file
		return
	oFile.RawWrite(&vData, vSize) ;appends data, advances pointer
	oFile.Close()
}
FILE READ/WRITE CLIPBOARD CONTENTS

Clipboard and ClipboardAll
https://autohotkey.com/docs/misc/Clipboard.htm#ClipboardAll
Clipboard and ClipboardAll
https://lexikos.github.io/v2/docs/misc/Clipboard.htm#ClipboardAll

Note: this line should work consistently in the next AHK v2 release:
Clipboard := %vFunc%(%vFunc2%(vPath, "RAW"))
See:
[v2] ClipboardAll(FileRead()) causing crashing - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=14&t=41985

Code: Select all

JEE_ClipboardFromFile(vPath)
{
	static vFunc := "ClipboardAll", vFunc2 := "FileRead"
	if !(SubStr(A_AhkVersion, 1, 2) = "1.")
		Clipboard := %vFunc%(%vFunc2%(vPath, "RAW"))
	else
	{
		if !oFile := FileOpen(vPath, "r")
			return
		hWnd := A_ScriptHwnd ? A_ScriptHwnd : WinExist("ahk_pid " DllCall("kernel32\GetCurrentProcessId", "UInt"))
		DllCall("user32\OpenClipboard", "Ptr",hWnd)
		DllCall("user32\EmptyClipboard")
		oFile.Pos := 0
		while (vFormat := oFile.ReadUInt())
		{
			;GMEM_ZEROINIT := 0x40, GMEM_MOVEABLE := 0x2
			vSize := oFile.ReadUInt()
			hData := DllCall("kernel32\GlobalAlloc", "UInt",0x42, "UPtr",vSize, "Ptr")
			pData := DllCall("kernel32\GlobalLock", "Ptr",hData, "Ptr")
			oFile.RawRead(pData+0, vSize)
			DllCall("user32\SetClipboardData", "UInt",vFormat, "Ptr",hData, "Ptr")
			DllCall("kernel32\GlobalUnlock", "Ptr",hData)
		}
		DllCall("user32\CloseClipboard")
		oFile.Close()
	}
}

JEE_ClipboardToFile(vPath)
{
	static vFunc := "ClipboardAll"
	if !oFile := FileOpen(vPath, "w") ;empties file
		return
	if !(SubStr(A_AhkVersion, 1, 2) = "1.")
		oFile.RawWrite(%vFunc%().Data)
	else
	{
		ClipSaved := ClipboardAll
		vSize := StrLen(ClipSaved) << !!A_IsUnicode
		oFile.RawWrite(&ClipSaved, vSize)
	}
	oFile.Close()
}
Last edited by jeeswg on 31 Jul 2019, 08:27, edited 1 time in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: No registered users and 42 guests