nnnik wrote: ↑13 Jan 2019, 14:44
I think the best option here is to force the users to define a data type in all three cases and remove a default type.
Perhaps the main reason it isn't that way is historical. The most common calls are probably Int or Ptr for DllCall and UInt or UPtr/Ptr for NumPut/NumGet, but before x64 builds, they were the same thing. It's easy to get DllCall and NumPut/NumGet wrong, and can be hard to track down the problem when they are, so being explicit is a good thing.
I started working on a buffer object as a very simple replacement for SetCapacity/GetCapacity/GetAddress, and found that I had already made one: the
ClipboardAll object; except:
- Size is read-only, whereas SetCapacity allows a buffer to be resized.
- It isn't accepted by the "var or address" buffer parameter of any built-in function.
So after making
Size read/write, I naturally tested with NumPut, adding a clipboard format to the ClipboardAll object. This was part of the code:
Code: Select all
; Put the format code f, size 4, value 42, and null-terminator (right-to-left)
NumPut(0, NumPut(42, NumPut(4, NumPut(f, c.Ptr, offset, "uint"), "uint"), "uint"), "uint")
My first thought was that this was part of why the File object makes the type part of the method name; like:
Code: Select all
PutUint(0, PutUint(42, PutUint(4, c.Ptr, offset)))
But then it struck me that a simple loop and some minor adjustments is probably all it would take to allow this:
Code: Select all
NumPut("uint", f, "uint", 42, "uint", 0, c.Ptr, offset)
I think something like this was suggested before, in the form of a "make struct" function. Since it would probably be used mostly for structs, perhaps it should pad to default C alignment values by default (with the single-value mode available to override it).
This ordering is a lot better for chaining even without the internal loop, since it puts the type and value together. It is also reminiscent of DllCall, and similar ordering to a type cast or parameter type declaration.
And it reminded me that nnnik suggested the type parameter be made mandatory, although it could be implemented in a way that allows the type to be optional, and even without breaking scripts.
I'm not too sure about how NumGet should look, though. Keep in mind that it would not be intended as a substitute for struct support.
Someone suggested removing the offset parameter. Although I could have used
c.Ptr + offset in this case, the offset parameter provides an important utility in other cases: validation. NumPut knows how big each value is, so if you also let it know how big the buffer is (by passing a variable reference or buffer object), it can prevent you from overrunning the buffer.