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

Discuss the future of the AutoHotkey language
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

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

21 Mar 2017, 21:38

Feel free to contribute to the existing v2 script converter if you want. I don't mind adding an option to make two-way compatible scripts but there are cases where its just not possible

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

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

22 Mar 2017, 02:19

StrRight should under no case be added to v due to mentioned reasoning. Also I feel that if v puts off many necessary changes ( e.g. creating a new GUI API, a better include System and Base classes for accessessing a certain Variable type ) for the sake of Backqards compatability we might have to deal with a fast Migration to AutoHotkey v3 immediately aftereards.
Recommends AHK Studio
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

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

22 Mar 2017, 03:59

There are several String commands which were redundant even before expressions and SubStr were added. That's probably because they all came from AutoIt v2, which had no expressions, so calculating the index for StringMid would take an extra line or two. But even so, having several different string functions which overlap with SubStr could make it easier to both write and read scripts. The author doesn't have to think about the correct way to calculate the index and length, and the reader doesn't have to interpret the expression to determine which part of the string it's getting.

I don't intend to make any change solely for the purpose of cross-compatibility, but it can be a bonus if there are other good reasons for a change.
jeeswg wrote:If there is a better hack ...
I don't know about hacks, but there's a clean solution: use a separate compatibility library for each version.
if IsFunc(Func := "FileSelect")
Return %Func%( ...
You're resolving the name twice. I suppose this would be faster:

Code: Select all

static FileSelect := Func("FileSelect")  ; Retrieve a reference to FileSelect if available (on startup)
if FileSelect
    return %FileSelect%( ...  ; Call by reference
nnnik wrote:creating a new GUI API
I've more or less decided to use fincs' GUI API, perhaps with minor changes.

For cross-compatibility, someone would need to write a script to bring the API to v1, or bring the v1 API to v2 (by wrapping the new API).
a better include System
A what? If you mean something akin to namespaces, modules or lexically scoped variables (i.e. anything to keep "global" variables contained to a particular include), I don't think that's within my energy budget.
Base classes for accessessing a certain Variable type
(I think you mean data type.) I don't think I'm very likely to implement that, especially if I can pave the way for it to be done after v2.0 (without breaking anything).
we might have to deal with a fast Migration to AutoHotkey v3 immediately aftereards.
Believe me when I say that would be a good thing. Do you realise how long v2 has been around in its incomplete state? You don't know just how close I've come to abandoning AutoHotkey. I will be making compromises to get v2 out of alpha, deferring some changes to a hypothetical future release (hypothetical because it might not happen).
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

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

22 Mar 2017, 04:20

[EDIT:] I resolved these queries in these two posts:
object classes: redefine __Set() temporarily / general queries - Page 2 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 70#p194970
object classes: redefine __Set() temporarily / general queries - Page 2 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 68#p195068

==================================================

If anybody is willing or able to explain ObjAddRef/ObjRelease to a wider audience, my collected queries are as follows.

To be honest, I don't think very many people at all properly understand this, but at least I'm prepared to be honest about it, and not try to deceive myself or others.
Most v1 scripts which use ComObjEnwrap(pdsp) (within the first few pages of Google results) used it incorrectly; i.e. they did not release their own copy of the pointer.
From:
v2-changes
https://autohotkey.com/v2/v2-changes.htm

If the question list seems a bit extensive, well this is the kind of experimentation I normally do to try and understand something.

I apologise for asking so many questions, but I will try and add this to my objects tutorial, if I'm able to get a grasp of it subsequently.

==================================================

Based on AutoHotkey.chm for v1.1.25.01.

contain references to ObjAddRef:
https://autohotkey.com/docs/commands/ComObjValue.htm

contain references to ObjAddRef *and* ObjRelease:
https://autohotkey.com/docs/AHKL_ChangeLog.htm
https://autohotkey.com/docs/commands/ComObjActive.htm
https://autohotkey.com/docs/commands/ComObjConnect.htm
https://autohotkey.com/docs/commands/ComObjCreate.htm
https://autohotkey.com/docs/commands/ComObjQuery.htm
https://autohotkey.com/docs/commands/DllCall.htm
https://autohotkey.com/docs/commands/ObjAddRef.htm
https://autohotkey.com/docs/Objects.htm

==================================================

The capabilities of the Object() function are not clearly listed in one place, here are some collected references to it:

obj := Object()
Array := Object()
"".base := Object()
"".base.base := Object()
Banana := Object("Shape", "Elongated", "Color", "Yellow", "Taste", "Delicious", "Price", 3)
colours := Object("red", 0xFF0000, "blue", 0x0000FF, "green", 0x00FF00)

var := Object(key, value)

address := Object(object)
ptr1 := Object(obj)

object := Object(address)

==================================================

- How do you get the Ref count without changing it?
- Can you just do ObjAddRef followed by ObjRelease?
- But then the logic seems to say it's sticky, almost as though any variable that contains the address to an object, either first-hand/second-hand/third-hand etc., needs an ObjAddRef.
- Is there a direct method to retrieve the actual value.
- Are there terms to distinguish between the 'real' count, and the 'log' count gotten/set by ObjAddRef/ObjRelease?

==================================================

ObjRelease(&obj) v. obj := ""

This code crashes the script, but doesn't it simply delete the object cf. obj := "".

Code: Select all

;q:: ;don't run this code
obj := {}
obj["red"] := 0xFF0000
ObjRelease(&obj)
MsgBox
Reload ;script crashes
return
So you can't use ObjRelease(&obj) there to replace obj := ""?

==================================================

The definition of Object(Param).
Object(obj) v. custom function ObjectToPointer(obj).
Object() creates a new object v. ObjectToPointer().

Supposedly these are equivalent:

Code: Select all

ptr1 := Object(obj)
ptr2 := ObjectToPointer(obj)

ObjectToPointer(obj) {
    if !IsObject(obj)
        return ""
    ptr := &obj
    ObjAddRef(ptr)
    return ptr
}
But you can do obj := Object() to create an object. So for ObjectToPointer(obj) to be equivalent to Object, should it be as follows ('return' line changed):

Code: Select all

ObjectToPointer(obj) {
    if !IsObject(obj)
        return {}
    ptr := &obj
    ObjAddRef(ptr)
    return ptr
}
[EDIT:] The Object and unmodified ObjectToPointer functions *are* equivalent, but with one stipulation, they are only equivalent when Object is used with exactly 1 parameter.

==================================================

What are the logical problems here, can you keep doing ObjAddRef(&obj) and ObjRelease(&obj) to the same &obj?

Code: Select all

q::
obj := {}
obj["red"] := 0xFF0000

Loop, 5
	MsgBox % ObjAddRef(&obj)
Loop, 5
	MsgBox % ObjRelease(&obj)
;MsgBox % ObjRelease(&obj) ;include this line (do ObjRelease a 6th time) and a crash will occur on Reload
Reload
return
==================================================

Apparently these two lines are equivalent:
address := &object, ObjAddRef(address)
address := Object(object)

In the first, we have to update our 'log' count manually.
The second version updates our 'log' count manually.
But what is the 'real' count, or the count we *should* have. Does it have a name? Is it somehow retrievable if we've miscounted.

Is there a way of getting an object's address, without needing to increase the reference count.
Can we get the address, which means we need to add a reference, store the value somehow, and immediately discard that reference?

Code: Select all

address := &object ;the 'real' reference count goes up one?
ObjAddRef(address) ;our 'log' reference count goes up one?
x := address ;does the 'real' count go up here, do we need to increment the 'log'
y := x ;again, does the 'real' count go up here, do we need to increment the 'log'
Is it possible to check if an object is present/begins at a particular address?
Does this affect the reference count?
object := Object(address)

What about this:
obj2 := obj

I suppose in simplest terms reference counting is:

Code: Select all

address := &object
ObjAddRef(address)
address := ""
ObjRelease(address)

ptr := &object
ObjAddRef(ptr)
ptr := ""
ObjRelease(ptr)
If address := &object requires ObjAddRef,
and obj := {} does ObjAddRef for you, what else requires ObjAddRef?
I suppose obj := "" requires ObjRelease(), but only if we've referenced it at some point after it was created.

==================================================
Last edited by jeeswg on 18 Jan 2018, 09:24, edited 3 times 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
guest3456
Posts: 3454
Joined: 09 Oct 2013, 10:31

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

22 Mar 2017, 11:16

lexikos wrote:
we might have to deal with a fast Migration to AutoHotkey v3 immediately aftereards.
Believe me when I say that would be a good thing. Do you realise how long v2 has been around in its incomplete state? You don't know just how close I've come to abandoning AutoHotkey. I will be making compromises to get v2 out of alpha, deferring some changes to a hypothetical future release (hypothetical because it might not happen).
:sadface:

It must be hard being the sole maintainer and having the brunt of all the work fall on you. Its only natural. Chris eventually departed. Sounds like you're near your end too. Will anyone be the next successor? HotKeyIt perhaps? Maybe you can start collaborating sooner?

lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

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

22 Mar 2017, 16:43

jeeswg wrote:... this is the kind of experimentation I normally do to try and understand something.
Don't. Trial and error won't teach you the required concepts; it may teach you how to create code which appears to work, but is actually unsafe. Also, I think you missed this:
Script authors should not invoke this mechanism explicitly, except when dealing directly with unmanaged pointers to objects.
Reference counting is a common technique in various languages. I suggest you read up on it before any further experimentation.
Guest

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

22 Mar 2017, 19:49

lexikos wrote:
we might have to deal with a fast Migration to AutoHotkey v3 immediately aftereards.
Believe me when I say that would be a good thing. Do you realise how long v2 has been around in its incomplete state? You don't know just how close I've come to abandoning AutoHotkey. I will be making compromises to get v2 out of alpha, deferring some changes to a hypothetical future release (hypothetical because it might not happen).
So just pass the Torch to HotKeyIt, He will certainly make AutoHotKey better (he's version is already a lot better than yours)

Do not make AutoHotKey to lag anymore time because of your tiredness.
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

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

22 Mar 2017, 21:03

Do not make AutoHotKey to lag anymore time because of your tiredness.
I 'partially' agree with this.
pass the Torch to HotKeyIt, He will certainly make AutoHotKey better (he's version is already a lot better than yours)
I disagree with this. I have nothing against HotKeyIt, but I do not like its 'programming' way, I think that 99% of the functions that it has added are totally unnecessary, it's a mess.
No offense, I'll probably never use HotKeyIt's version.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

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

23 Mar 2017, 03:13

lexikos wrote:But even so, having several different string functions which overlap with SubStr could make it easier to both write and read scripts. The author doesn't have to think about the correct way to calculate the index and length, and the reader doesn't have to interpret the expression to determine which part of the string it's getting.
That's incredibly encouraging to hear you saying something like this, could have been me saying that.
lexikos wrote:I don't know about hacks, but there's a clean solution: use a separate compatibility library for each version.
Yes, I think that's the best option too. The issue boils down to: is it possible to have a custom function refer to a built-in function with the same name.
lexikos wrote:You don't know just how close I've come to abandoning AutoHotkey.
We love AutoHotkey, however long things take, we're all behind it.

==================================================

@nnnik. Re. #Include. I think the best solution is something like (although I wouldn't mind a different name) #IncludeIfParamContains(Path, ParamNum, Needle), so it checks if Parameter N contains the needle, and if it does, then the script is included. I believe this solves all my conceivable problems regarding 'conditional #Include'. A script sets the parameter before launching.

Re. GUI, let's say I've already created a GUI window via DllCall, e.g. with a custom class name and no icon. Can the Gui command 'take over' that window as though it was created by the Gui command in the normal way.

Also, with InputBox, is it possible to binary edit the dialog resource in the AutoHotkey exe file, to give it a larger (or different) font, in my efforts so far, the InputBox became bigger, but the font remained the same.
MsgBox/InputBox gets hidden under another window (+ InputBox custom font) - Page 2 - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 37#p138537

==================================================

The string functions that I would have in AHK v2 (or also AHK v1):
- StrTrimLeft/StrTrimRight/StrLeft/StrRight(vText, vNum) [function versions of String(Trim)Left/Right]
- StrIn/StrContains/StrStarts/StrEnds(vText, vNeedles, vDelim:=",", vCaseSen:=0, ByRef vMatch:="") [function versions of 'if var in/contains']
- StrRept(vText, vNum)
- StrCountOcc(vText, vNeedle, vCaseSen:=0) [or 'StrCount']

I might consider the following, although I would be happy to do these as my own custom functions, as the usage is rarer:
StrLeft(vText, vNum, vParam3) ;get the first vNum characters, then the last vParam3 of those
StrRight(vText, vNum, vParam3) ;get the last vNum characters, then the first vParam3 of those

I have hundreds of string functions, so please believe me that I've been very sparing in considering what functions I would suggest for AHK v1/v2.

Some advantages:
- StrStarts/StrEnds are much faster than RegExMatch and don't have issues with escaping characters
- turning InStr into StrContains, to add another item, is far easier than changing it to 'if var contains'
- in general StrIn/Contains/Starts/Ends and InStr are far more interchangeable than what is available currently
- without StrRept, you have to 'stop what you're doing' and use a loop, before continuing with the code
- using StrCountOcc is far more readable, than its equivalent involving StrReplace
- string functions are fundamental and can be asked to handle hundreds of megabytes of data, I do this several times a week, optimisation as a built-in function/command is desirable
- I often waste time thinking: I can do SubStr either future-proof and ugly, or looking reasonable but requiring subsequent conversion, can I get away with RTrim here, RegExReplace might work here but it's slow and might confuse the user and seems overkill plus what if the string contains special characters, I could use Format, will this method be slow on big text ...
- if InStr/SubStr were changed in AHK v2 to make then more intuitive, then intuitiveness is a reasonable argument in relation to other string functions
- people see the 'String' commands as holdovers from AutoIt, without realising their potential as demonstrated by the 'StrReplace' and 'StrSplit' revamps
- easier to convert code from other languages that use functions similar to StrLeft/Right and StrRept
- easier to share code on forums without defining commonly-needed string functions at the bottom
- with StrEnds v. multiple InStr, you don't have to work out the string length each time
- once you've conceived of these functions, you will come across situations where you wish they were already built-in functions
- code is more readable and understandable, and easier to maintain

[EDIT:]
- there are times when you want to write stand-alone functions, that make no reference to other functions, and so must use ugly and lengthy techniques like InStr a dozen times, rather than RegExMatch which is shorter but slows down the script, in such cases the nature of the available string functions becomes more important
- there are potential disadvantages in using custom functions to perform core duties, versus built-in functions
- 'if var contains/in' has limitations relating to using 'if' with '&&' and '||' and other conditions in adjacent lines, and can thus mislead the person reading/maintaining the script regarding control flow, also, it affects indentation

E.g. code for StrStarts, StrRept, StrCountOcc:

Code: Select all

;e.g. JEE_StrStarts(vText, "red,yellow,green,blue")
;e.g. JEE_StrStarts(vText, "red,yellow,green,blue", ",") ;same as line above
;e.g. JEE_StrStarts(vText, "red|yellow|green|blue", "|")
;e.g. JEE_StrStarts(vText, "Return,", "") ;treat as one string, in a similar way to InStr
;e.g. JEE_StrStarts(vText, "Return,,", ",,") ;'if var contains'-style double comma handling
JEE_StrStarts(ByRef vText, ByRef vNeedles, vDelim=",", vCaseSen=0, ByRef vMatch="")
{
vSCS := A_StringCaseSense
StringCaseSense, % vCaseSen ? "On" : "Off"

if (vDelim = "")
{
	StringCaseSense, % vSCS
	Return !!(SubStr(vText, 1, StrLen(vNeedles)) = "" vNeedles)
}

if (vDelim = ",,")
{
	vDelim := JEE_StrGetUnusedChar1Var(vText)
	vText := StrReplace(vText, ",", vDelim)
	vText := StrReplace(vText, vDelim vDelim, ",")
}

Loop, Parse, vNeedles, % vDelim
	if !(SubStr(vText, 1, StrLen(A_LoopField)) <> "" A_LoopField) ;if not different (i.e. if same) (handles case sensitive/insensitive)
	{
		vMatch := A_LoopField
		StringCaseSense, % vSCS
		Return 1
	}

StringCaseSense, % vSCS
Return 0
}

;==================================================

JEE_StrRept(vText, vNum)
{
if (vNum <= 0)
	Return ""
VarSetCapacity(vOutput, StrLen(vText)*vNum*(A_IsUnicode+1))
Loop, % vNum
	vOutput .= vText
Return vOutput
}

;==================================================

JEE_StrCountOcc(ByRef vText, vNeedle, vCaseSen=0)
{
if (vNeedle = "")
	Return "" ;StrReplace's count returns 0, but perhaps this should return blank
vSCS := A_StringCaseSense
StringCaseSense, % vCaseSen ? "On" : "Off"
StrReplace(vText, vNeedle, "", vCount)
;StrReplace(vText, vNeedle, vNeedle, vCount) ;seemed to be slower than the line above
;note: using InStr and Loop together seemed very slow
StringCaseSense, % vSCS
Return vCount
}
==================================================

Re. 'StrRight' and 'StrEnds'. I recently collected some examples regarding the ends of strings:

Code: Select all

if (SubStr(vText, StrLen(vText)-StrLen(vSuffix1)) = vSuffix1)
|| (SubStr(vText, StrLen(vText)-StrLen(vSuffix2)) = vSuffix2)
|| (SubStr(vText, StrLen(vText)-StrLen(vSuffix3)) = vSuffix3)

;AHK v1 only
if (SubStr(vText, 1-StrLen(vSuffix1)) = vSuffix1)
|| (SubStr(vText, 1-StrLen(vSuffix2)) = vSuffix2)
|| (SubStr(vText, 1-StrLen(vSuffix3)) = vSuffix3)

;AHK v2 only
if (SubStr(vText, -StrLen(vSuffix1)) = vSuffix1)
|| (SubStr(vText, -StrLen(vSuffix2)) = vSuffix2)
|| (SubStr(vText, -StrLen(vSuffix3)) = vSuffix3)

vIsV1 := !!SubStr(1,0)
if (SubStr(vText, vIsV1-StrLen(vSuffix1)) = vSuffix1)
|| (SubStr(vText, vIsV1-StrLen(vSuffix2)) = vSuffix2)
|| (SubStr(vText, vIsV1-StrLen(vSuffix3)) = vSuffix3)

if (StrRight(vText, StrLen(vSuffix1)) = vSuffix1)
|| (StrRight(vText, StrLen(vSuffix2)) = vSuffix2)
|| (StrRight(vText, StrLen(vSuffix3)) = vSuffix3)

;introducing StrEnds:
;3rd parameter: ',' for lists, ',,' for 'if var contains' style commas,
;blank for treat commas literally, another character for an alternative delimiter

;if it is not known whether vSuffix1/2/3 contains commas or not
if StrEnds(vText, vSuffix1, "")
|| StrEnds(vText, vSuffix2, "")
|| StrEnds(vText, vSuffix3, "")

;assuming there are no problem characters or pipes
;and bearing in mind that RegExMatch can be slow
if RegExMatch(vText, "(" vSuffix1 "|" vSuffix2 "|" vSuffix3 ")$")

;if vSuffix1/2/3 are known not to contain commas
if StrEnds(vText, vSuffix1 "," vSuffix2 "," vSuffix3)

;if vSuffix1/2/3 are known not to contain pipes
if StrEnds(vText, vSuffix1 "|" vSuffix2 "|" vSuffix3, "|")
This function to add indentation to code, has examples where I would have used StrRept and StrEnds, but commented them out, to avoid references to custom functions:
text/list/table functions (latest: add indentation, get nth(-to-last) line of specified length, html to/from text) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic ... 63#p134363

Code: Select all

	;if !vType && StrStarts(vTemp, vList)
	vList := StrReplace(vList, ",", "|")
	if !vType && RegExMatch(vTemp, "i)^(" vList ")")

	;vOutput .= StrRept("`t", vCount+vAdjNow) vTemp "`r`n"
	Loop, % vCount+vAdjNow
		vOutput .= "`t"
	vOutput .= vTemp "`r`n"
==================================================
Last edited by jeeswg on 23 Mar 2017, 08:31, edited 4 times 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
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

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

23 Mar 2017, 04:14

lexikos wrote:But even so, having several different string functions which overlap with SubStr could make it easier to both write and read scripts. The author doesn't have to think about the correct way to calculate the index and length, and the reader doesn't have to interpret the expression to determine which part of the string it's getting.
If they are forced to use SubStr() frequently it shouldn't be a problem.

Many of the syntax changes needed for v2 can already be implemented in v1. For the rest a mark could be added in the source to simplify the final conversion. But as long as v2 is open for feature requests like additional Str... functions, many writers won't do it.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

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

23 Mar 2017, 07:28

lexikos wrote:
nnnik wrote:creating a new GUI API
I've more or less decided to use fincs' GUI API, perhaps with minor changes.

For cross-compatibility, someone would need to write a script to bring the API to v1, or bring the v1 API to v2 (by wrapping the new API).
a better include System
A what? If you mean something akin to namespaces, modules or lexically scoped variables (i.e. anything to keep "global" variables contained to a particular include), I don't think that's within my energy budget.
Base classes for accessessing a certain Variable type
(I think you mean data type.) I don't think I'm very likely to implement that, especially if I can pave the way for it to be done after v2.0 (without breaking anything).
we might have to deal with a fast Migration to AutoHotkey v3 immediately aftereards.
Believe me when I say that would be a good thing. Do you realise how long v2 has been around in its incomplete state? You don't know just how close I've come to abandoning AutoHotkey. I will be making compromises to get v2 out of alpha, deferring some changes to a hypothetical future release (hypothetical because it might not happen).
I think that the changes you did for AutoHotkey objects are the thing that keeps me here in AutoHotkey. You have made great changes and I think that we may have hit something worth discussing here. However it will break the scope of this discuassion. Currently I'm not in a state to reply to your answers to my post however I think you got most of what I wanted to write here. I do think that jeeswg has hit a nerve of many AutoHotkey users here. I will reply as soon as possible.
Recommends AHK Studio
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

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

23 Mar 2017, 18:51

jeeswg wrote:The issue boils down to: is it possible to have a custom function refer to a built-in function with the same name.
No, it doesn't: and no, it isn't. There is no reason that the compatibility libraries would need to override built-in functions. The script would be utilising the library, not trying to pretend that it's really on one specific AutoHotkey version.
Re. GUI, let's say I've already created a GUI window via DllCall, e.g. with a custom class name and no icon. Can the Gui command 'take over' that window as though it was created by the Gui command in the normal way.
No.
just me wrote:If they are forced to use SubStr() frequently it shouldn't be a problem.
One thing can be easier than another without either one being a problem. Anyway, your argument is somewhat limited to users who would use the function frequently enough in every "mode" to memorise the patterns.
But as long as v2 is open for feature requests like additional Str... functions, many writers won't do it.
Won't do what? Making the "syntax changes needed for v2" in v1, marking their code with conversion notes, or something else?

Whatever it is, many writers won't do it regardless of whether v2 is open for feature requests. People generally aren't that observant. There have been quite a few feature requests in v2 topics that didn't even have any relevance to v2. An observant person might notice that although AutoHotkey is open to feature requests, they very rarely get implemented.
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

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

24 Mar 2017, 06:30

lexikos wrote:Won't do what? Making the "syntax changes needed for v2" in v1, marking their code with conversion notes, or something else?
Solange sich niemand sicher sein kann, wie die Syntax letztendlich aussehen wird - ich erinnere mich da an einige Raus-und-wieder-Rein-Aktionen wie z.B. MinIndex()/MaxIndex() - ist es nur von sehr begrenztem Nutzen, die scheinbar schon heute möglichen Anpassungen von v1 nach v2 vorzuziehen. Ich habe das eine zeitlang versucht, es dann aber wieder aufgegeben. Ist das verständlicher?
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

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

25 Mar 2017, 01:45

No, that does not help me to understand your original statement.

The changing syntax is a far bigger deterrent to regular use of v2 than the possibility of adding a few functions.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

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

25 Mar 2017, 04:01

just me wrote:
lexikos wrote:Won't do what? Making the "syntax changes needed for v2" in v1, marking their code with conversion notes, or something else?
Solange sich niemand sicher sein kann, wie die Syntax letztendlich aussehen wird - ich erinnere mich da an einige Raus-und-wieder-Rein-Aktionen wie z.B. MinIndex()/MaxIndex() - ist es nur von sehr begrenztem Nutzen, die scheinbar schon heute möglichen Anpassungen von v1 nach v2 vorzuziehen. Ich habe das eine zeitlang versucht, es dann aber wieder aufgegeben. Ist das verständlicher?
"As long as we can't be sure how the final syntax looks it is pointless to mark anything for translation"
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

27 Mar 2017, 18:09

I thought that perhaps LTrimN, RTrimN, might be possible names instead of StrTrimLeft/StrTrimRight. I.e. 'N' for numeric/number, trim a specific number of characters.

@nnnik. Re. #Include. Perhaps #Include C:\%A_Args1% or #Include C:\%A_Arg1% would be useful.

@just me. Now is the best time to make feature requests, whether they are implemented or not. All the power users, indeed anyone who can do a good job of it, should provide wish lists. This is because all the AHK code is being reviewed now, and as it is rewritten, things can be done now, that will allow changes to be made, if not now, in future. I always like to know as many feature requests as possible in advance for projects, as it can make the code I write easier to amend later.

String functions *are* being changed currently, InStr/SubStr/RegExMatch/RegExReplace position parameter, String(Trim)Left/Right due to be removed, both of these things mean there is no sensible forwards-compatible way to get the last n characters from a string, which is a big problem. 'if var in' and 'if var contains' are being removed at present, however they are awkward in numerous respects, including requiring using the word 'not', whatever is done, function versions of these would be useful.

Some of us produce a lot of code and libraries in AutoHotkey, I don't think strings are a minor issue, also whatever happened to the beginner-friendly ethos of AutoHotkey versus giving a lecture to someone who is worried about AutoHotkey v2 and wants to be able to get the last n characters from a string in a forwards-compatible manner.

Now is the time to mention something like `s for space cf. `t for tab. There are issues to do with leading/multiple/trailing spaces, e.g. the awkward hotstrings workaround (space backtick), and `s is already present in some contexts in AutoHotkey, this could be a useful general solution, to clean up the syntax. Also, code involving `" has recently been worked on.

Note: let MS Excel be a guide for potential useful string functions.
It has 'Proper' (title case, e.g. AHK could have 'StrTitle'), 'Left', 'Right' and 'Rept'.
Excel Text Functions
http://www.excelfunctions.net/Excel-Text-Functions.html
Excel Math Functions
http://www.excelfunctions.net/Excel-Math-Functions.html
As long as we can't be sure how the final syntax looks it is pointless to mark anything for translation
I think it's essentially finished, we know the final outcome. Worst-case scenario, you unconvert something that you converted, but I doubt that would happen very often, if at all. One possible exception is GUI where proposals are being debated right now, however, that API may be available in AHK v1 anyhow.

Btw has anything been said about #MaxMem, apparently FileRead doesn't obey it, but without it, what's to stop a variable reaching 1 gigabyte?

==================================================

The best two-way compatible double quotes solution thus far.

%Q% and vDQ can be easily found and replaced by the user if desired, at a future date.

Code: Select all

q::
global Q := Chr(34), vDQ := Chr(34)
MsgBox % Deref("%Q%%A_ScriptDir%%Q% %Q%%A_ScriptFullPath%%Q%")
MsgBox % vDQ A_ScriptDir vDQ " " vDQ A_ScriptFullPath vDQ
return

;AHK v1
MsgBox % Deref("""%A_ScriptDir%"" ""%A_ScriptFullPath%""")
MsgBox % """" A_ScriptDir """ """ A_ScriptFullPath """"

;AHK v2
MsgBox % "`"%A_ScriptDir%`" `"%A_ScriptFullPath%`""
MsgBox % "`"" A_ScriptDir "`" `"" A_ScriptFullPath "`""
[EDIT:]

Code: Select all

q::
global DQ := Chr(34)
MsgBox % Deref("%DQ%%A_ScriptDir%%DQ% %DQ%%A_ScriptFullPath%%DQ%")
MsgBox % DQ A_ScriptDir DQ " " DQ A_ScriptFullPath DQ
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

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

27 Mar 2017, 22:44

jeeswg wrote:This is because all the AHK code is being reviewed now, and as it is rewritten, [...]
By whom? Not me. I have reviewed some of the code over the last six years. If "it's essentially finished" as you said, there's no reason that I would review or rewrite all of the code.
there is no sensible forwards-compatible way to get the last n characters from a string
It is perfectly sensible and forwards-compatible to calculate the start index for SubStr based on the length. It makes even more sense than passing a negative number.
without [#MaxMem], what's to stop a variable reaching 1 gigabyte?
Don't try to put 1 gigabyte of data into a variable, and it won't reach 1 gigabyte.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

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

28 Mar 2017, 00:59

it's essentially finished
I was referring to the syntax choices and command parameters. The more definite they are, the more worthwhile it is to start conversion. Quite fundamental areas of code appear to be being discussed at the moment. Even from my perspective of converting, I feel like I've become reacquainted with all the old and new AHK issues I've ever faced including IniRead and space.

Re. SubStr:

Code: Select all

if (SubStr(vText, StrLen(vText)-4+1) = ".com")
if (SubStr(vText, StrLen(vText)-3) = ".com")
if (SubStr(vText, StrLen(vText)-StrLen(vSuffix)+1) = vSuffix)
if (StrRight(vText, 4) = ".com")
if (StrRight(vText, StrLen(vSuffix)) = vSuffix)
And also above: Re. 'StrRight' and 'StrEnds'.

Re. #MaxMem:
- The code might not be your own. Or you are new to AutoHotkey.
- A long loop could get large quite quickly, especially if you accidentally append the entire string to itself.
- I could easily add an extra zero, in a loop used for benchmark tests. I quite often go up to #MaxMem for those. I had to be quite careful recently re. repeating something 10 times shorter than something else, 10 times more etc.
- Or concatenating text from text files, but a new large file is there in the folder, or *.* was used instead of *.txt. Or choosing the wrong folder, or accidentally including recurse. Or using the wrong path/dir variable or contents from a previous occasion.
- Plus, 500 MB of ANSI/UTF-8 (UTF-8 that is mainly ASCII) becomes 1 GB of variable space. And the system may be old or already under heavy strain.
Last edited by jeeswg on 28 Mar 2017, 06:25, 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
lexikos
Posts: 9553
Joined: 30 Sep 2013, 04:07
Contact:

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

28 Mar 2017, 04:08

Re. #MaxMem:

I don't doubt it happens; I doubt the frequency and magnitude of the "problem". I doubt that you would be asking for this feature if AutoHotkey never had it, and I doubt that many users will miss it.

I've opened a few large (not even close to 500MB) log files in Notepad, and as a result I learned not to do that.

In my experience, the one thing most likely to create a very large variable is FileRead, which has its own limit.

#MaxMem is ineffective on large arrays, large pseudo-arrays, large files filling up the disk, and a host of other problems that can be caused by errors a script author might make.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

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

28 Mar 2017, 14:52

Some notes on keeping StringSplit in AHK v2, and a few other tidbits.

@lexikos. Thanks re. the interesting information about cases where #MaxMem fails. Anything to keep a script secure is a plus, i.e. not affecting the system or files in an adverse way. I never use FileDelete in my scripts, only FileRecycle for example.

I wrote 'notepad go-between' to open text files with Notepad if under 6MB and Notepad2 otherwise. I compiled it as an exe, but once in a blue moon the virus checker complains and it doesn't work, so I might just point it in the registry to an AHK exe with the script path and txt path as parameters.

==================================================

I was preparing to convert StringSplit to StrSplit, but I often find it preferable e.g. vMyVar1 v. oMyArray[1], and especially vMyVar0 v. oMyArray.MaxIndex(). In some ways it's just a better function and so is worth keeping, the exception is when you have dozens/hundreds of variables.

Btw the function has to pass the output variable name as a string rather than as a ByRef variable, I don't know if there's a workaround for this.

Code: Select all

;two-way compatible: StringSplit
;MsgBox % A_AhkVersion
vText := "a`tb`tc"

JEE_StringSplit("vOutput", vText, "`t")
MsgBox % vOutput0 " " vOutput1 " " vOutput2 " " vOutput3

oOutput := StrSplit(vText, "`t")
MsgBox % oOutput.MaxIndex() " " oOutput[1] " " oOutput[2] " " oOutput[3]

return
;==================================================

JEE_StringSplit(vOutput, ByRef vText, vDelims:="", vOmitChars:="")
{
	global
	%vOutput%0 := 0
	Loop, Parse, % vText, % vDelims, % vOmitChars
		%vOutput%%A_Index% := A_LoopField, %vOutput%0 += 1
	return
}
A function which works in a similar way to SplitPath:
If someone has written a similar function, please post a link.

Code: Select all

;two-way compatible: split to named vars
q:: ;split text to named variables (rather than numbered variables)
vText := "key=value1|value2|value3"
vCount := JEE_StrSplitToVars(vText, "=|", "", vKey, vValue1, vValue2, vValue3)
MsgBox % vCount " | " vKey " " vValue1 " " vValue2 " " vValue3

vText := "03:02:01 04/05/2006" ;DMY
vCount := JEE_StrSplitToVars(vText, ": /", "", vHour,vMin,vSec,vDay,vMonth,vYear)
MsgBox % vCount " | " vYear " " vMonth " " vDay " " vHour " " vMin " " vSec
return

JEE_StrSplitToVars(ByRef vText, vDelims:="", vOmitChars:="", ByRef v1:="", ByRef v2:="", ByRef v3:="", ByRef v4:="", ByRef v5:="", ByRef v6:="", ByRef v7:="", ByRef v8:="", ByRef v9:="", ByRef v10:="", ByRef v11:="", ByRef v12:="")
{
	vCount := 0
	Loop, Parse, % vText, % vDelims, % vOmitChars
	{
		if (A_Index <= 12)
			v%A_Index% := A_LoopField
		vCount++
	}
	return vCount
}
Btw is it possible to use ByRef variables in a variadic function?

Code: Select all

;doesn't work
a := b := c := "_"
MyVFunc(a,b,c)
MsgBox % a b c
return

MyVFunc(ByRef params*)
{
	params[2] := "B"
}
==================================================

One way to #Include directives in AHK v1 only. Call a function that is new to AHK v2. E.g. DirExist(), in AHK v2 the function exists, so nothing happens, in AHK v1 it will look for DirExist.ahk, in that file you can slip in some directives e.g. #NoEnv and #MaxMem.

Btw is there a safe way to avoid variables being changed in an AHK v1 script that doesn't have #NoEnv.

Code: Select all

;two-way compatible: tests with AHK v1-only directives
MsgBox % A_AhkVersion " | " DirExist(A_Desktop) " | " DirExist(A_Desktop A_Now)
MsgBox % "windir: " windir ;blank if #NoEnv

Loop, % (1024**2) -524289
	vOutput .= "a"
MsgBox % VarSetCapacity(vOutput)
vOutput .= "a" ;just one more! ;crashes AHK v1 U32/U64 if #MaxMem 1
return

;==================================================

;code in other script (DirExist.ahk)
/*
#NoEnv
#MaxMem 1

DirExist(FilePattern)
{
    local AttributeString := FileExist(FilePattern)
    return InStr(AttributeString, "D") ? AttributeString : ""
}
*/
==================================================

Use AHK v1-only commands when running a script with AHK v1, but without crashing the same script when running with AHK v2:

Code: Select all

;two-way compatible: AutoTrim and SetBatchLines

MsgBox % A_AhkVersion
JEE_AutoTrim("Off")
return

;==================================================

JEE_AutoTrim(vMode)
{
	AutoTrim, % vMode
}
AutoTrim(vMode) ;do nothing, a dummy function
{
}

JEE_SetBatchLines(vParam)
{
	SetBatchLines, % vParam
}
SetBatchLines(vParam) ;do nothing, a dummy function
{
}
==================================================

Something I'd come up with a little while ago, to check if AHK v1 or AHK v2 is running:
It allows you to know how the function will behave (AHK v1 or AHK v2 style) before you use it.

Code: Select all

;two-way compatible: check if AHK v1/v2
;e.g. IsV1 := !!SubStr(1,0)
vOutput := A_AhkVersion " "
vOutput .= !!SubStr(1,0)
vOutput .= SubStr(10,-1,1)
vOutput .= InStr(1,1,1,0)
vOutput .= InStr(1,1,0,0)
;vOutput .= RegExMatch(1,1,0,0) ;PCRE execution error (position can't be 0?)
vOutput .= RegExMatch(10,1,0,-1)
vOutput .= !RegExReplace(11,1,0,0,-1,-1)
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

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: No registered users and 32 guests