NumGet and NumPut Syntax

Discuss the future of the AutoHotkey language
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

NumGet and NumPut Syntax

31 Aug 2017, 20:07

[Update by Lexikos: As of v2.0-a111, NumPut and NumGet do not support the "VarOrAddress" concept, but Offset is still used with Buffer objects, for the same reasons.]


Hello all, I would like to propose a syntax change for NumGet and NumPut. Currently the syntax is Number := NumGet(VarOrAddress [, Offset := 0][, Type := "UPtr"]) and NumPut Number, VarOrAddress [, Offset := 0][, Type := "UPtr"].

Basically:
  • Remove the 'Offset' parameter. This parameter is totally unnecessary, just use 'Address + Offset'.
  • Change 'VarOrAddress' to accept only 'Address'. I think this creates a huge confusion in trying to interpret the code, besides being one of the things that makes, in my opinion, a bad language.


Pros:
  • This would increase performance, since AutoHotkey would not have to do (I think) such a check.
  • It makes the language clearer and easier to interpret, and you do not have to guess if you are passing the memory address of the variable or the address that contains the variable.
  • Reduces unnecessary parameters and source code size.
  • Makes it to be consistent with StrGet/StrPut.


Cons:
  • ... ... ?
What do you think? :)

I would like to add a question, which has nothing to do with the main theme (but anyway...): Why was "UInt64" never implemented?
Last edited by lexikos on 21 Jun 2020, 01:39, edited 1 time in total.
Reason: update
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: NumGet and NumPut Sintax

01 Sep 2017, 00:02

Hello.
I sort of agree on the offset parameter, but I do use it and doesn't really mind. I couldn't agree more with the rest of this post, in particular with this,
Flipeador wrote:
  • Change 'VarOrAddress' to accept only 'Address'. I think this creates a huge confusion in trying to interpret the code, besides being one of the things that makes, in my opinion, a bad language.
This feature is a perfect example of good intentions going wrong.

Thanks for this suggestion,
Cheers :thumbup:

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

Re: NumGet and NumPut Sintax

01 Sep 2017, 01:44

@Flipeador: Yes, I had been thinking about this too, it would be a good idea. I often use the address for DllCall and in custom functions that I've written, and I find NumGet/NumPut as they are now inelegant and awkward to use, even a potential source of bugs. This is the sort of change that is consistent with AHK v2, and the sort of big change that should ideally only occur during a major update.

The con(s) would be all the conversion of NumGet and NumPut. I'm quite relaxed about changes made to commands, because I will convert all of them to functions, and there is no chance of confusion. I am always more reluctant to change the definition of functions because of the possibility for confusion. However my instinct says to make the change.

If someone had a lot of AHK v1 code, and they wanted to quickly convert it to work in AHK v2 (assuming these changes were made), then perhaps these functions would make it possible:

Code: Select all

;unofficial proposal for changes to NumGet and NumPut

;possible AHK v1 functions for AHK v2 proposal:
NumGet1(ByRef VarOrAddress, Offset:=0, Type:="UPtr")
{
	if IsByRef(VarOrAddress)
		VarOrAddress := &VarOrAddress
	return NumGet(VarOrAddress+Offset, Type)
}
NumPut1(Number, ByRef VarOrAddress, Offset:=0, Type:="UPtr")
{
	if IsByRef(VarOrAddress)
		VarOrAddress := &VarOrAddress
	NumPut(Number, VarOrAddress+Offset, Type)
}
Contrariwise I would welcome a directive in AHK v1 to allow you to use NumGet and NumPut as you would in AHK v2 (if this became the new behaviour). [EDIT:] It would be one directive that for all lines between when it is set on and off, applicable functions behave like they do in AHK v2, or, for more granular control, only specified functions in a space-separated list would work like in AHK v2.

Here are functions for that would give you the proposed behaviour right now in AHK v1 and in AHK v2.

Code: Select all

;possible AHK v2 proposal functions for AHK v1:
NumGet2(Address, Type:="UPtr")
{
	return NumGet(Address+0, Offset, Type)
}
NumPut2(Number, Address, Type:="UPtr")
{
	NumPut(Number, Address+0, Offset, Type)
}
Helgef wrote:This feature is a perfect example of good intentions going wrong.
Yes I have felt that a lot when going over AHK, thinking about changes, the rationale is good, but over time you work out what the better approach is.

@Flipeador: Is that true about UInt64, I had thought that it was implemented but that it acts like Int64, which is fine for writing to structs, but which would affect reading. The issue being that AHK can only handle numbers of a certain size. I don't know the exact details.
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
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: NumGet and NumPut Sintax

01 Sep 2017, 08:54

It's good to read positive responses about this :D . As Helgef said, good intentions to facilitate the 'use' to the user, but in the end they end up being bad 'practices' of programming and that lead to a great confusion of how a program actually works. In many cases (not just NumPut/NumGet) causing the user to move away from this type of functions, or in the worst case, from AHK.
I understand that AHK was developed to be friendly and easy to understand for new users, but... what kind of users?, do we really need it?, a good documentation is enough.
Things like these reduce performance, increase the source code 'thanks to' users who do not want to read the documentation or learn, and take away the seriousness of the language. Reasons why I stopped using version 1.
:wave:
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: NumGet and NumPut Sintax

01 Sep 2017, 08:54

Could be handy for short things, but I'm not a fan of this.. especially when it is something like this:

Code: Select all

StrGet(NumGet(buf + 0, (A_Index - 1) * A_PtrSize, "uptr"), "utf-16")
I would stay with both and if someone dont like the first one, they can use the other way...

Code: Select all

NumGet(addr, offset, type)
NumGet(addr + offset, type)
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: NumGet and NumPut Sintax

01 Sep 2017, 08:59

jNizM wrote:Could be handy for short things, but I'm not a fan of this.. especially when it is something like this:
I like this way:

Code: Select all

StrGet(NumGet(pBuf + (A_Index - 1) * A_PtrSize), "UTF-16")
Edit* Note that this is currently valid.
Edit2*
jNizM wrote:I would stay with both and if someone dont like the first one, they can use the other way...
I think it's more about eliminating unnecessary parameters, other problems that tend to confuse, and performance issues.
Visually, it does not look bad (for me). It is simpler and easier to type (fewer commas).
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: NumGet and NumPut Sintax

01 Sep 2017, 11:15

Because of
v2-changes wrote:Address-of: Since pure numbers and strings are now distinct types, &(var := 123) now returns the address of an int64 instead of the address of a string. For consistency, VarSetCapacity returns 6 (the size of int64 minus a null terminator).
...
NumPut/NumGet: If a variable containing a pure number is passed to the VarOrAddress parameter, the variable's value is used rather than the address of the variable itself.
I support the suggestion to change the VarOrAddress parameter to Address and to remove the Offset parameter. It would be consistent with the Address parameter of StrGet/Put().
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: NumGet and NumPut Sintax

01 Sep 2017, 11:41

jNizM wrote:I would stay with both and if someone dont like the first one, they can use the other way...]
I could live with either one or both, but for reasons mentioned by Flipeador, my preferences would be ordered like this: no offset param > offset param > optional.
just me wrote:It would be consistent with the Address parameter of StrGet/Put().
I'm not against consistency, but imo, documentation and performance is more important than consistency. I think the consistency argument is overrated, I don't mean to be rude (and possibly I have used it myself :D )
jeeswg wrote:The con(s) would be all the conversion of NumGet and NumPut.
To me, this is too short term to be relevant. I do not think v2 development should consider compatability (either with v1 or current v2 alpha) or ease of transition. The only goal should be improvements, and it is already better imo.

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

Re: NumGet and NumPut Syntax

01 Sep 2017, 12:17

@Helgef: I think that the labour involved in converting old code, should always be an important factor when making decisions, although not necessarily the deciding factor.

I did consider that allowing both ways in AHK v1 could be a good idea:

Code: Select all

;old style:
NumGet(vData, 0, "UInt")
NumPut(0, vData, 0, "UInt")

;new style:
NumGet(&vData, "UInt")
NumPut(0, &vData, "UInt")
- A versatile function in AHK v1:
- NumGet: if param 2 is alpha, it's the new style.
- NumPut: if param 3 is alpha, it's the new style.

- With AHK v2 only accepting the new style.
- But with custom functions such as my NumGet1 and NumPut1 functions available if desired. For lazy quick-and-dirty conversion.

Btw I think that the current proposal for AHK v2, to check the variable contents for a pure number, actually makes things *more* confusing. 'Smart' behaviour is often not the smart thing do. Gosh, the more I think of it, the more this strikes as me as the kind of quirky AHK v1 inconsistent behaviour we're trying to eliminate. Imagine telling someone new to AutoHotkey of all the special things you have to consider whenever you use NumGet or NumPut.
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
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: NumGet and NumPut Syntax

01 Sep 2017, 12:22

I did consider that allowing both ways in AHK v1 could be a good idea
This works in AHK v1:

Code: Select all

VarSetCapacity(Buffer, 4)
NumPut(666, &Buffer, "Int")
MsgBox % NumGet(&Buffer, "Int")
Edit* I think AHKv1 documentation should be slightly edited, trying to stay close to AHKv2, obviously we can not make changes to AHKv1, but if we can warn of not using, for example, '=' as an assignment operator (intolerable practice), among other things , then it would be easier for new users to get into AHKv2.
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: NumGet and NumPut Syntax

01 Sep 2017, 14:18

Having now double-checked the documentation. Yes, much of what has been talked about does already exist, in terms of omitting the offset parameter. Personally I don't have a problem with keeping this as an option: the user can include/exclude the offset parameter.

So ultimately the idea would be to make the first parameter be a bit stricter and simpler. It's good to see that this optional parameter approach was already implemented, it is the sort of thing I would imagine that Lexikos et al might do. Basically conversion-wise, making the first parameter stricter would mean adding in quite a lot of ampersands, but I wouldn't mind doing the conversion.

I see mention of UInt64 under DllCall, but not under NumGet/NumPut, although I do see mention of UPtr. I would think that it should be included there, even if it returns an Int64.

@Flipeador: Yes, I've mentioned before that I think the documentation should state what the preferred function or syntax is, in various places e.g. InStr v. StringGetPos. Also, I think that a sort of #Warn mode could be made for AHK v1, that forces you to program in a more future compatible way. Actually, instead I think in general, scripts that check your script, and report back errors, or things that don't match your preferred coding style, or for example that list functions with undeclared variables, would be a good idea, versus hundreds of MsgBoxes to notify you of errors when you load a script.

I'm going to code like this now, I think it gives the best most compatible results across AHK v1.1 and v2:

Code: Select all

NumGet(&vData, vType)
NumGet(&vData+vOffset, vType)
NumGet(pData+0, vType)
NumGet(pData+vOffset, vType)
Funnily enough this issue affected me quite directly when I was writing a custom function, I chose to make it ByRef, so you could omit the &, however, later on I wanted to write to an offset of a variable, so specifying an address and requiring an & was the better option.
Last edited by jeeswg on 01 Sep 2017, 14:42, 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
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: NumGet and NumPut Syntax

01 Sep 2017, 14:36

jeeswg wrote:So ultimately the idea would be to make the first parameter be a bit stricter and simpler.
I want to make it clear that this is not about personal programming styles or anything like that.
Edit* I wouldn't call it strict and simple, rather, suitable.
My main proposal is to improve performance and avoid parameters that tend to cause confusion and have unnecessary options.
I see no need to keep the 'Offset' parameter.
jeeswg wrote:I think the documentation should state what the preferred function or syntax is
For example, I would not speak of 'preferred syntax' in using '=' as an assignment operator. This is crazy, which should be removed long ago. Among many other things.

Edit*
jeeswg wrote:I'm going to code like this now, I think it gives the best most compatible results across AHK v1.1 and v2:
The problem is...
NumPut wrote:VarOrAddress: A memory address or variable. If VarOrAddress is a variable such as MyVar, the address of the variable's string buffer is used. This is usually equivalent to passing &MyVar, but omitting the "&" performs better and ensures that the target address + offset is valid.
just me
Posts: 9424
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: NumGet and NumPut Syntax

01 Sep 2017, 16:24

Flipeador wrote:The problem is...
It might be related to
Operators in Expressions wrote:Address (&): &MyVar retrieves the address of MyVar's contents in memory, which is typically used with DllCall structures. &MyVar also disables the caching of binary numbers in that variable, which can slow down its performance if it is ever used for math or numeric comparisons. Caching is re-enabled for a variable whenever its address changes (e.g. via VarSetCapacity()).
and (hopefully) doesn't matter so much in v2. As far as I understand, pure numbers and strings will share the same buffer.
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: NumGet and NumPut Syntax

01 Sep 2017, 16:43

just me wrote:It might be related to [...]
Well, this is not really that important (my mistake) and is not what I mentioned in the main topic. Although it is interesting and I would like to know more about this. :thumbup:
I have already given the pros, and I see no reason to keep this syntax. Let's wait for lexikos or someone who has some good against. :)
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: NumGet and NumPut Syntax

01 Sep 2017, 20:47

I checked the help file, there is one other reference to VarOrAddress, so both uses should either be kept or discarded:

Code: Select all

File.RawRead(VarOrAddress, Bytes)
File.RawWrite(VarOrAddress, Bytes)
Also I think it's worth mentioning here, although only half-relevant: in functions, AFAIK, to return a binary variable from a custom function, you have to refer to the binary variable ByRef, as one of the function parameters. If instead you only return a pointer to the data, that data can then be overwritten when the function returns.

The offset parameter was the bigger problem for me, but this appears to have already been dealt with (although we could of course force the fewer parameter syntax). So for me now, the main issue is that of changing the var/address parameter, the rationale being consistency/simplicity, and if the gains are significant, performance.
Last edited by jeeswg on 01 Sep 2017, 22:09, 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
User avatar
Flipeador
Posts: 1204
Joined: 15 Nov 2014, 21:31
Location: Argentina
Contact:

Re: NumGet and NumPut Syntax

01 Sep 2017, 21:56

jeeswg wrote:Also I think it's worth mentioning here [...]
I do not know what this has to do with this topic. :eh:
jeeswg wrote:I checked the help file, there is one other reference to VarOrAddress, so both uses should either be kept or discarded:
I think it's a bit different, NumGet/Put is used slightly differently and are given much more use. In FileObject, perhaps keeping VarOrAddress saves us a bit of code (File.RawRead(undeclaredvar, File.Length())), bypassing VarSetCapacity, although I do not know to what extent this is better or worse.
At least it would be a breakthrough, making the code more readable and serious, at least in 'NumGet/Put'.
Another reason to remove the 'Offset' parameter from NumGet/Put, are the only functions that have it.
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: NumGet and NumPut Syntax

02 Sep 2017, 03:10

I like the File Object's syntax and would enjoy using it for binary data instead of numget/numput
Recommends AHK Studio
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: NumGet and NumPut Syntax

03 Sep 2017, 15:19

Code: Select all

;This:
vAddr := NumGet(&DIBSECTION, A_PtrSize=8?24:20, "Ptr") ;bmBits
vSize := NumGet(&DIBSECTION, A_PtrSize=8?52:44, "UInt") ;biSizeImage
;becomes this:
vAddr := NumGet(&DIBSECTION+(A_PtrSize=8?24:20), "Ptr") ;bmBits
vSize := NumGet(&DIBSECTION+(A_PtrSize=8?52:44), "UInt") ;biSizeImage

;This:
DllCall("ole32\CoTaskMemFree", Ptr,NumGet(&ArrayITEMIDLIST, (A_Index-1)*A_PtrSize, "Ptr"))
;becomes this:
DllCall("ole32\CoTaskMemFree", Ptr,NumGet(&ArrayITEMIDLIST+((A_Index-1)*A_PtrSize), "Ptr"))
These changes might not look so bad by themselves, but when you are forced to introduce further brackets into complex lines of code that already contain a lot of brackets, it can make things very unclear and unreadable. Thus actually the flexible syntax as it is, has advantages.

It's a little bit nitpicky in my opinion but possibly worth it to force Address over VarOrAddress, although the use of & or +0 can add clarity/certainty here when using the existing syntax. It is not a massive cost for me to add these in manually.

However, if there are performance gains to be had, perhaps it is worth creating new very simple unambiguous NumGet/NumPut alternative functions, or possibly MemWrite/MemRead/MemMove (i.e. copy)/MemSearch (names can be changed) functions. I have also suggested in the past adding support for 'HEX'/'HEX little endian' to StrGet and StrPut.

It might also be worth mentioning, when things like this are under discussion, native support or workarounds for UInt64 and big integers.
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: NumGet and NumPut Syntax

26 Nov 2017, 01:44

Remove the 'Offset' parameter. This parameter is totally unnecessary, just use 'Address + Offset'.
It is unnecessary if the author knows what s/he is doing and never makes mistakes. In other words, it is rarely unnecessary. ;)

The primary purpose of the Var,Offset mode is to provide automatic bound-checking. With Address+Offset, if the variable capacity is insufficient (e.g. due to forgetting VarSetCapacity or making a mistake in the capacity calculation), the error will usually go unnoticed at the point it is introduced. NumGet may return an arbitrary value unrelated to the original purpose, or NumPut may corrupt some other variable or (more importantly) internal state, causing subtle/hard-to-debug bugs.

Of course, even with these checks it is easy to introduce subtle or hard-to-debug bugs with NumPut.

Return to “AutoHotkey Development”

Who is online

Users browsing this forum: No registered users and 43 guests