Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Choose naming and syntax for built-in Extract/InsertInteger


  • Please log in to reply
100 replies to this topic

Poll: Pass "VarOrAddress, Offset" (20% faster and possibly less error-prone) vs. "&Var + Offset" (fewer parameters and more pure)? (13 member(s) have cast votes)

Pass "VarOrAddress, Offset" (20% faster and possibly less error-prone) vs. "&Var + Offset" (fewer parameters and more pure)?

  1. I strongly prefer passing the single parameter: &Var + Offset (0 votes [0.00%])

    Percentage of vote: 0.00%

  2. I slightly prefer passing the single parameter: &Var + Offset (3 votes [23.08%])

    Percentage of vote: 23.08%

  3. I strongly prefer passing two parameters: VarOrAddress, Offset (4 votes [30.77%])

    Percentage of vote: 30.77%

  4. I slightly prefer passing two parameters: VarOrAddress, Offset (3 votes [23.08%])

    Percentage of vote: 23.08%

  5. No preference. (3 votes [23.08%])

    Percentage of vote: 23.08%

Vote Guests cannot vote
foom
  • Members
  • 386 posts
  • Last active: Jul 04 2007 04:53 PM
  • Joined: 19 Apr 2006
Yep address in memory is indeed a better description.

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
I don't think (Var) will work because the parentheses don't alter its nature as a variable. Also, lazy evaluation isn't implemented except if you count short-circuit boolean and ternary. Maybe it will get added someday.

Here is the draft documentation:

NumGet(VarOrAddress [, Offset = 0, Type = "UInt"]): Returns the binary number stored at the specified address+offset. For VarOrAddress, passing MyVar is equivalent to passing &MyVar. However, omitting the "&" performs better and ensures that the target address is valid (invalid addresses return ""). By contrast, any numeric VarOrAddress is treated as a raw address; consequently, specifying MyVar+0 forces the number in MyVar to be used instead of the address of MyVar itself. For Type, specify UInt, Int, Int64, Short, UShort, Char, UChar, Double, or Float (though unlike DllCall, these must be enclosed in quotes when used as literal strings); for details see DllCall Types.

NumPut(Number, VarOrAddress [, Offset = 0, Type = "UInt"]): Stores Number in binary format at the specified address+offset and returns the address to the right of the item just written. For VarOrAddress, passing MyVar is equivalent to passing &MyVar. However, omitting the "&" performs better and ensures that the target address is valid (invalid addresses return ""). By contrast, any numeric VarOrAddress is treated as a raw address; consequently, specifying MyVar+0 forces the number in MyVar to be used instead of the address of MyVar itself. For Type, specify UInt, Int, Int64, Short, UShort, Char, UChar, Double, or Float (though unlike DllCall, these must be enclosed in quotes when used as literal strings); for details see DllCall Types.

Comments are welcome.

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
In the "NumPut" description the term "and ensures that the target address is valid (invalid addresses return "") " does not seem to fit. Here an invalid address should result in setting ErrorLevel or a nonzero return value.

For lazy function parameter evaluation: general use will brake many scripts. It became a habit of many scripters to use function calls (with side effects) in function parameters, especially in dllcall parameters. Accordingly, the function definition should have an explicit optional "Lazy" directive, maybe for each parameter. (Either nothing, or ByRef, or Lazy.)

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004

In the "NumPut" description the term "and ensures that the target address is valid (invalid addresses return "") " does not seem to fit. Here an invalid address should result in setting ErrorLevel or a nonzero return value.

I prefer to avoid setting ErrorLevel. Also, I don't see why the empty string is an inappropriate return value in this case because if the function succeeds, it returns a non-zero value (i.e. the address to the right of the item just written). If it fails, shouldn't it return 0 or ""? And of the two, "" is more consistent with the return value of NumGet().

For lazy function parameter evaluation: general use will brake many scripts. It became a habit of many scripters to use function calls (with side effects) in function parameters, especially in dllcall parameters. Accordingly, the function definition should have an explicit optional "Lazy" directive, maybe for each parameter. (Either nothing, or ByRef, or Lazy.)

Good point. Thanks.

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005

"" is more consistent with the return value of NumGet()

Good point.

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005
Dear Mr.Chris, :)

I tried the beta version of AHK v1.0.47 and much happier with the in-built functionality. Many thanks.

I request VarSetCapacity() to be renamed to / or given an additional name: VarSet() / VarSize()

VarSet( Spaces, 10, 32 )

Thanks. :)

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
It probably won't get renamed unless you can think of a compelling reason to do so. It currently seems like a good compromise between readability and conciseness.

SKAN
  • Administrators
  • 9115 posts
  • Last active:
  • Joined: 26 Dec 2005

unless you can think of a compelling reason to do so.


Since ExtractInteger() & InsertInteger() have been built-in with shortened names, VarSetCapacity() is the longest function name now used in AHK :).

VarSetCapacity() is not a function a typical newbie will look for, and so I thought I should request this.

DllCall()
NumGet()
NumPut()
VarSet()

It currently seems like a good compromise between readability and conciseness.


I have always felt URLDownloadToFile & VarSetCapacity() are unnaturally long, though I am not able to guess how other users are feeling.

Anyways! I do feel happy about forthcoming enhancements. This was just a humble suggestion.

Thanks :)

PhiLho
  • Moderators
  • 6850 posts
  • Last active: Jan 02 2012 10:09 PM
  • Joined: 27 Dec 2005
I must admit this function is boring to type... :)
InitVar() might be nice, even if partially describing what it does.
Perhaps in v.2?
Posted Image vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")

Laszlo
  • Moderators
  • 4713 posts
  • Last active: Mar 31 2012 03:17 AM
  • Joined: 14 Feb 2005
Returning to Struct support: the new AHK v1.0.47+ features allow to build fully functional, fast Struct handling with some 15 instructions, so most of the time there is no need to include a long script.
Rect = Rect                            ; to save some quotes
Struct(Rect, "UInt","x", "Char","y", "Int64","w", "Double","h") ; creates global array with struct info
VarSetCapacity(MyRect,Rect_StructSIZE) ; ~ declare MyRect as a Rect structure

StructSet(MyRect, Rect, "x", 65), StructSet(MyRect, Rect, "y", 66)
StructSet(MyRect, Rect, "w", 67), StructSet(MyRect, Rect, "h", 68)

MsgBox % StructGet(MyRect, Rect, "x") " " StructGet(MyRect, Rect, "y") " "
       . StructGet(MyRect, Rect, "w") " " Round(StructGet(MyRect, Rect, "h"))


Struct(Struct, type1="",name1="", type2="",name2="", type3="",name3="", type4="",name4="", type5="",name5="") {
   Local t, d           ; store description of Struct in global array: Struct_name_type, ..._offs
   %Struct%_StructSIZE := 0, VarSetCapacity(d,8)
   Loop {
      IfEqual name%A_Index%,,Break
      t := name%A_Index%
      %Struct%_%t%_type := type%A_Index%
      %Struct%_%t%_offs := %Struct%_StructSIZE
      %Struct%_StructSIZE += NumPut(0,d,0,type%A_Index%) - &d ; SizeOf(type%A_Index%)
   }
}

StructSet(ByRef Var, Struct, name, value) {
   Return NumPut(value, Var, %Struct%_%name%_offs, %Struct%_%name%_type)
}

StructGet(ByRef Var, Struct, name) {
   Return NumGet(Var, %Struct%_%name%_offs, %Struct%_%name%_type)
}
The Struct function creates a global description of a structure. For the ultimate speed you can use directly the built in NumPut/NumGet functions, like
NumGet(MyRect,Rect_y_offs,Rect_y_type) ; get MyRect.y
On the other hand, for more convenience, you can allocate extra memory for an instance of a structure and store there a pointer to the description.
Struct("Rect", "UInt","x", "Char","y", "Int64","w", "Double","h") ; creates global array with struct info
StructCreate("MyRect","Rect")           ; declare MyRect as a Rect structure

StructSet("MyRect", "x", 65), StructSet("MyRect", "y", 66)
StructSet("MyRect", "w", 67), StructSet("MyRect", "h", 68)

MsgBox % StructGet("MyRect", "x") . " " . StructGet("MyRect", "y") . " "
       . StructGet("MyRect", "w") . " " . Round(StructGet("MyRect", "h"))


Struct(Struct, type1="",name1="", type2="",name2="", type3="",name3="", type4="",name4="", type5="",name5="") {
   Local t, d           ; store description of Struct in global array: Struct_name_type, ..._offs
   %Struct%_StructSIZE := 0, VarSetCapacity(d,8)
   Loop {
      IfEqual name%A_Index%,,Break
      t := name%A_Index%
      %Struct%_%t%_type := type%A_Index%
      %Struct%_%t%_offs := %Struct%_StructSIZE
      %Struct%_StructSIZE += NumPut(0,d,0,type%A_Index%) - &d ; SizeOf(type%A_Index%)
   }
}

StructCreate(StructVarName, Struct) {
   Global
   %StructVarName%_type := Struct
   VarSetCapacity(StructVarName,%Struct%_StructSIZE)
}

StructSet(StructVarName, FieldName, value) {
   Struct := %StructVarName%_type
   Return NumPut(value, &(%StructVarName%), %Struct%_%FieldName%_offs, %Struct%_%FieldName%_type)
}

StructGet(StructVarName, FieldName) {
   Struct := %StructVarName%_type
   Return NumGet(&(%StructVarName%), %Struct%_%FieldName%_offs, %Struct%_%FieldName%_type)
}
This way one parameter can be saved at accessing the structure fields. With some name assignments a lot of quotes can be saved.

Although, these are fully functional scripts, they are only prototypes. When they get implemented in AHK, the global variables can become hidden and the quotes will not be necessary. With the planned type information for variables, some of the necessary functionality could be automatically there in v2.0.

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Having a built-in struct syntax doesn't seem that compelling to me. I'm not saying it will never get done -- just that the benefit/cost is rather meager when you consider the total code+documentation complexity compared to the actual/tangible benefits.

Another consideration is whether the plan for preprocessor macros (#define) will allow better/faster struct support via the standard library. If so, that might be enough reason not to have it built into the program.

In light of this, struct syntax probably won't get done as part of v2. However, if proper struct support relies on any script-breaking changes, those particular changes could be considered for v2.