What type of object is this?

BlitzMax Forums/BlitzMax Beginners Area/What type of object is this?

DH(Posted 2005) [#1]
for example:
local MyObject:String
Local MyObject2:Int


Is there a way to queery the object type? To find out (in code) if the object is a string, integer, or float?


Perturbatio(Posted 2005) [#2]
there isn't a reliable way to simply say:
If Int(MyObject) then print "Is an int"
If String(MyObject) then print "Is a string"

because if you put a number at the beginning of the string, both cases will be true since the number can be converted to an int.


ImaginaryHuman(Posted 2005) [#3]
Can you use sizeof() to indicate? Int's should be 4 bytes, strings are in almost all cases likely to not be 4 ???


Cajun17(Posted 2005) [#4]
String is an object and since all objects are stroed by refrence they will show a size of 4 as well.


Scienthsine(Posted 2005) [#5]
Ohh come on... atleast test what you say :/

Sizeof() will work, it returns the amount of memory allocated for that variable. It works on strings, objects, etc...


Koriolis(Posted 2005) [#6]
@Pertubatio : this example doesn't make sense anyway as the int is *not* an object while the String is. And thus you can't by example pass in int to a function that expects a string. It appears you can because an implicit int -> string conversion is performed for you, but then the function really get passed a string and not an integer. So let's say MyObject is that parameter, obviously the test "If String(MyObject)" will always succeed.
In short a function that expects as a parameter an object (like a string) cannot get passed a "value" type like an integer or a float, and conversely a function that expects as a parameter a value type cannot get passed an objects. So such a acase will never arise at runtime, and then trying to discriminate at runtime between both categories of types makes no sense.

On the other hand, a function that expects an object of a given type A can very well get passed an object of another type B (provided B inherits A). So in this case checking the type at runtime does make sense.

In short testing at runtime an object's type makes sense only if we're *really* talking about objects. Like by example String , TList, TLink, Object, but *not* int.
And then yes, doing a test like
If String(MyObject) then print "Is a string"
is perfectly reliable.

The key point here is that when you do
Local someString$
Local someInt%
...
If Int(someString) then print "Is an int"
If String(someInt) then print "Is a string"
the compiler does built-in int<->string conversion (like converting 12 from and to "12"), that is a conversion that is entirely specific to the int<->string conversion. But when you do
Local someObject1:SomeType1
...
If SomeType2(someObject1) then print "Is an object of type SomeType2"
the compiler does a very different thing : converting the "reference to SomeType1" someObject1 to a "reference to SomeType2". That is, a very different thing even though the syntax looks the same.


Dreamora(Posted 2005) [#7]
The only test for this kind of stuff is:

1. First test for string, so you look if there is a non numeric in string (input)

2. Test for Float: find a "," in string (input)

3. if both is not the case, it is int.

(if - elseif - else - endif :))


Koriolis(Posted 2005) [#8]
Did you read my post Dreamora?
Here you're advising to parse a string to see if it's a string a float or an integer ^-^
There's some reasoning problem here...


Yan(Posted 2005) [#9]
Wildly of topic I know, but did anyone else find themselves reading this threads title with a crap Lloyd Grossman accent?


Dreamora(Posted 2005) [#10]
No there is no problem with this Koriolis.
See the 3 steps and try them out in the simple 6 line source and you will see that it works.

Problem is that you assume that string (input) only works on objects which isn't true as it is explicitely meant to convert numerics into strings or better objects so it would give true in any case and wouldn't be reliable for this check.

thats why I made the "check for type characteristics" ... string have non numeric an float has a "," followed by more numbers.


Perturbatio(Posted 2005) [#11]
thats why I made the "check for type characteristics" ... string have non numeric an float has a "," followed by more numbers.


A float has a decimal seperator "." unless of course you're weird and foreign ;)


Koriolis(Posted 2005) [#12]
No there is no problem with this Koriolis.
See the 3 steps and try them out in the simple 6 line source and you will see that it works.

It simply depends on what you mean by "works".
Problem is that you assume
I *assume* nothing in programming. And again reading my post would have helped you not to write this wrong statement. I explicitely explained at the end of my last post that although the similar syntax there are here 2 distinct categories of conversion happening here, one of them being the string <-> int conversion like in "string(123").

Let's recap.
First (please, please, read my post this time) in reality you would either *always* have a string, an int or a float, you cannot be in a situation where you get passed (via a parameter, a type field or whatever) something that could be once an integer, once a float and once a string. This is *not*, red my lips, *not* possible.
In the best situation let's say your variable is declared as a string, then in this case, ahem, it's a string. So if the var was assigned an int or a float (via argument passing if it's an argument, or explicit assignment if it's a local var, global var or type field), then a int -> string or float -> string conversion happened in the first place. Reconverting to string ("string(input)") makes no sense.
Example:
Function f(s$)
    ...
End Function
Local param% = 1
f(param)

in f you do know that s IS a string, it will always be. It doesn't matter if param was an integer.

Second point, let's say that's no problem for you that the var you access is really a string, but you want to know what the *value that was assigned to it" originally was (like what "param"'s type in my previous example. But then
Pertubation has been clear enough on the problem.
In my example whe you do f(1) it is *exactly* as if I'd done f("1"), and "1" is a perfectly legitimate string parameter. Your solution would only be applicable if you do know in advance that when the user calls f with a string a value, it will never start by the string representation of some numeraical value. It's not that often that you can enforce this.
And anyway that's not what was requested by the original poster. As I understand it He asked how to determine the "real" type of the variable (which again cannot be once a string, an int or a float).



As a side note I think this an interesting discussion as there might be a non negligeable amount of people here that do not realize that
(1) integers and floats are not objects in BlitzMax (like in most of the other languages), (2) BMX uses static typing (see Wikipedia's type checking page), not dynamic typing (good thing I'd say), and all the concreate implications it has.


Dreamora(Posted 2005) [#13]
Why must the string not start with numerical?
You check the string to see if there is a non-numerical in and it is granted that it is a string. Sure in worse cases it could still be a string that represents a numeric.


The poster wanted to know how to find out if it is an int, string or float and the only way to do that, thanks to BMs C++ like "numerics are no objects" OO break, is to see whats inside ...


btw: Read the first posting. There was nothing with PASSED. He wanted to know how to check for a given type and I'm only answering that question. I did not answer any stuff in between, only tried to do what the XY postings before mine didn't: show a possible solution.

I know that an can't switch between string and int/float as the later are no real objects :(


@Perturbatio: you're right :-) Thats a different language that uses "," as seperator.


Koriolis(Posted 2005) [#14]
Why must the string not start with numerical?
It's precisely because it can that there is a problem. But I'm not sure explaining it again would convince you so I'll just give up.

btw: Read the first posting. There was nothing with PASSED.
I read it thanks, and I'd appreciate you to do the same with my posts.
Why testing the type of an object? Because you are not the one that created it. Typically (like say 95% of the time) this is an object that was passed to you as a parameter.

He wanted to know how to check for a given type and I'm only answering that question
and I'm only saying this this doesn't look like a decent solution to me, and that in any case it's important to understand that in reality you'll always be manipulating a string in the situation you exposed.

I'll guess you get my point now.


Dreamora(Posted 2005) [#15]
I know that I will manipulate a string this way.
But for BM this is the only solution as

1. Numerics are no types (as you know too)
2. Numerics are automatically casted making type () casttests useless for testing purpose
3. There is no other way to examine the "type of content" without using string and checking for characteristic content ... which is why I search for non-numeric for a string (if there is even only 1 non-numeric in the string I can't have been numeric before casting), search for "," for a float (as it will be in even if the number was the same as an Integer) and if both isn't the case, I know that it is an integer.

I know that this isn't the ultimative great solution, but the only solution that I can think of as long as you are not planning to bit examine the stuff.

the only trivial numeric check is the one for double due to sizeof differences with int / float.


btw: the good point of this solution is, that you can use the input:object declaration even for numerics if you cast them to string, you just have to "analyze" them for backparsing afterwards. This is a quite large + of this solution I think (otherwise you have to use Bank, Memory or 2 different function/method declarations for this kind of stuff, at least as long Mark is keeping this inconsistency in the system with non-type numerics which I think was just for simplicity with ASM / C++ stuff. I've been thinking about I could make Numerics as real types as it can sometimes be quite frustrating when you are normally used to Eiffel which only has types and full OO no procedural anymore)


Koriolis(Posted 2005) [#16]
1. yep
2. yep
3. this is indeed no a great solution to say the least.

the only trivial numeric check is the one for double due to sizeof differences with int / float.
Here you're again testing for a type that is very well known at compile time (the sizeof an integer or a float, or double won't magically change during runtime, because the type itself certainly won't change), in short it has no use.
framework brl.basic
Import brl.standardio

Local f% = 123.456
Local d! = 123.456

Local v! ' or v%

v = f
Print SizeOf(v)

v = d
Print SizeOf(v)
It's clear that sizeof v will always be the same no matter the type of the value that was assigned to it. For even more fun use a string var (v$).

I've been thinking about I could make Numerics as real types as it can sometimes be quite frustrating when you are normally used to Eiffel which only has types and full OO no procedural anymore)
It's indeed easy to make some TInt, TDouble etc wrapper type, and will allow to put numerics in lists TList by example. This is exactly what Java does, even if it isn't perfect.
At least if your var is reference to an object (excepting string) you know an integer or a float can't be cast to an object so you would have no problem : handling the case where the var is a numeric would only mean handling these wrappers.


DH(Posted 2005) [#17]
Alright gentlemen, although I appreciate your answers I have found that what I wanted to do cant be done, not only because of the limitations with objects(ints not being objects), but with the way functions pass parameters.

What my goal was, with my scripting engine, was to have the user pass a variable and the engine record it as a pointer so that the script engine may write to it and yet the user's engine still use the variable. I wanted to accept an object (IE string, int, etc), find out what it was and assign a pointer to it that the scripting engine used as a variable. Since I can't pass an arbitrary object to a function/method (have to define what it is anyhow), then I must split up the user defining variables as DefineInt, DefineFloat, and DefineString... So I already know what it is anyhow...

But again, thanks for the help.