type(v) for v1.1

Post your working scripts, libraries and tools
lexikos
Posts: 6207
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

type(v) for v1.1

21 Feb 2014, 01:10

type(v)

Returns the type of a value: "Integer", "String", "Float" or "Object"

Code: Select all

; Object version - depends on current float format including a decimal point.
type(v) {
    if IsObject(v)
        return "Object"
    return v="" || [v].GetCapacity(1) ? "String" : InStr(v,".") ? "Float" : "Integer"
}

Code: Select all

; COM version - reports the wrong type for integers outside 32-bit range.
type(ByRef v) {
	if IsObject(v)
		return "Object"
	a := ComObjArray(0xC, 1)
	a[0] := v
	DllCall("oleaut32\SafeArrayAccessData", "ptr", ComObjValue(a), "ptr*", ap)
	type := NumGet(ap+0, "ushort")
	DllCall("oleaut32\SafeArrayUnaccessData", "ptr", ComObjValue(a))
	return type=3?"Integer" : type=8?"String" : type=5?"Float" : type
}
Note: Requires v1.1. It might work with v2, but I wouldn't recommend it.

Note: Results can be hard to predict due to binary number caching in v1. For instance, y := x + 0 can change the type of x from "String" to "Integer" or "Float".

Note: type(1.0) returns "String" because floating-point literals in v1 actually are strings. type(1.0+0) returns "Float".


Differentiating between object types

type() in v2 returns specific object classes, like FileObject or ComObject. This function doesn't. There are a couple of workarounds:
  • ComObjValue(x) != "" is true if x is a ComObject.
  • ObjGetCapacity(x) != "" is true if x is an Object (associative array).
User avatar
joedf
Posts: 6849
Joined: 29 Sep 2013, 17:08
Facebook: J0EDF
Google: +joedf
GitHub: joedf
Location: Canada, Quebec
Contact:

Re: type(v) for v1.1

22 Feb 2014, 18:16

nice!
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500 @ 3.00 GHz, 16GB DDR4 3200 MHz, NVIDIA GTX 1060 6GB | [About Me] | [ASPDM - StdLib Distribution]
[Populate the AHK MiniCity!] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library] | [About the AHK Foundation]
obeeb
Posts: 140
Joined: 20 Feb 2014, 19:15

Re: type(v) for v1.1

22 Feb 2014, 21:10

Great function.
Another note: It will incorrectly return float for integers bigger than 2147483647 (maximum number for signed 32 bit integers)
lexikos
Posts: 6207
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: type(v) for v1.1

23 Feb 2014, 02:38

Right. Technically, it returns the type which will be used if the value is passed to a COM object.
lexikos
Posts: 6207
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: type(v) for v1.1

10 Mar 2014, 04:10

I've updated the first post with a new version of the function which doesn't have the limitation obeeb mentioned:

Code: Select all

MsgBox % type("")     ; String
MsgBox % type(1)      ; Integer
MsgBox % type(1/1)    ; Float
MsgBox % type("1")    ; String
MsgBox % type(2**42)  ; Integer

type(v) {
    if IsObject(v)
        return "Object"
    return v="" || [v].GetCapacity(1) ? "String" : InStr(v,".") ? "Float" : "Integer"
}
This relies on the following:
  • Unlike a variable, an array element can't contain a string and a pure number simultaneously.
  • A field's "capacity" is the size of string it can hold before it needs to expand. If it doesn't hold a string it has no capacity.
  • SetFormat hasn't been used to remove the decimal point from the floating-point string format. (If var is float has the same limitation, since it always converts the value to a string for analysis.)
v="" || [v].GetCapacity(1) could be replaced with [v].GetCapacity(1) != "" or v="" || [v].GetAddress(1) to the same effect.

Return to “Scripts and Functions”

Who is online

Users browsing this forum: No registered users and 25 guests