Type detection
This draft task needs a purpose, a description and some way to tell whether examples satisfy or do not satisfy it.
- Task
Show a function/procedure that processes a block of text by printing it.
The function takes one parameter (ideally) that describes the text.
Demonstrate by calling the function twice, each time passing in a different type.
This can be done with pattern matching, multi-methods, dynamic type detection, structure(s) with a tag, etc.
The objective is write a [e.g. library] function that processes text from multiple sources (such as a string/char *, socket, file, etc).
If not practical, show how the caller would coerce a type that can be passed to the library function.
AWK
<lang AWK>
- syntax: TAWK -f TYPE_DETECTION.AWK
- uses Thompson Automation's TAWK 5.0c
BEGIN {
arr[0] = 0 print(typeof(arr)) print(typeof(0.)) print(typeof(0)) print(typeof(/0/)) print(typeof("0")) print(typeof(x)) print(typeof(addressof("x"))) print(typeof(fopen("x","r"))) exit(0)
} </lang>
- Output:
array float int regular_expression string uninitialized address fileid
C
The closest C comes to meeting this task, short of building it into the compiler or accessing memory segments via pointers, which is not guaranteed to be portable, is the ctype.h header file. It is part of the C Standard Library and provides 11 methods for detecting the type of a character, out of which the following 7 called in the wrapper function below can be called to be unique. The function accepts a string, but it actually checks the first character. An if ladder is used instead of if-else so that all function calls which return a non-zero value for the character are satisfied and the information is printed. <lang C>
- include<stdio.h>
- include<ctype.h>
void typeDetector(char* str){ if(isalnum(str[0])!=0) printf("\n%c is alphanumeric",str[0]); if(isalpha(str[0])!=0) printf("\n%c is alphabetic",str[0]); if(iscntrl(str[0])!=0) printf("\n%c is a control character",str[0]); if(isdigit(str[0])!=0) printf("\n%c is a digit",str[0]); if(isprint(str[0])!=0) printf("\n%c is printable",str[0]); if(ispunct(str[0])!=0) printf("\n%c is a punctuation character",str[0]); if(isxdigit(str[0])!=0) printf("\n%c is a hexadecimal digit",str[0]); }
int main(int argC, char* argV[]) { int i;
if(argC==1) printf("Usage : %s <followed by ASCII characters>"); else{ for(i=1;i<argC;i++) typeDetector(argV[i]); } return 0; } </lang> Output, shown for multiple inputs, as well as single ones:
C:\rosettaCode>typeDetector.exe s 3 $ f ! as 3 s is alphanumeric s is alphabetic s is printable 3 is alphanumeric 3 is a digit 3 is printable 3 is a hexadecimal digit $ is printable $ is a punctuation character f is alphanumeric f is alphabetic f is printable f is a hexadecimal digit ! is printable ! is a punctuation character a is alphanumeric a is alphabetic a is printable a is a hexadecimal digit 3 is alphanumeric 3 is a digit 3 is printable 3 is a hexadecimal digit C:\rosettaCode>typeDetector.exe a a is alphanumeric a is alphabetic a is printable a is a hexadecimal digit C:\rosettaCode>typeDetector.exe $ $ is printable $ is a punctuation character C:\rosettaCode>typeDetector.exe 3 3 is alphanumeric 3 is a digit 3 is printable 3 is a hexadecimal digit
D
<lang D>import std.stdio;
auto typeString(T)(T _) {
return T.stringof;
}
class C {} struct S {}
void main() {
writeln(typeString(1)); writeln(typeString(1L)); writeln(typeString(1.0f)); writeln(typeString(1.0)); writeln(typeString('c')); writeln(typeString("string")); writeln(typeString(new C())); writeln(typeString(S())); writeln(typeString(null));
}</lang>
- Output:
int long float double char string C S typeof(null)
Factor
Using dynamic dispatch: <lang>USING: arrays formatting io kernel math prettyprint sequences strings ; IN: rosetta-code.type-detection
GENERIC: myprint ( object -- )
M: object myprint drop "I don't know how to print this." print ; M: string myprint "I'm a string: \"%s\"\n" printf ; M: fixnum myprint "I'm a fixnum: " write . ; M: array myprint "I'm an array: { " write
[ pprint bl ] each "}" print ;
"Hello world." myprint { 1 2 3 4 5 } myprint 123 myprint 3.1415 myprint</lang>
- Output:
I'm a string: "Hello world." I'm an array: { 1 2 3 4 5 } I'm a fixnum: 123 I don't know how to print this.
Go
Note that Go doesn't really have a character type. A single quoted character (such as 'd') is by default a rune (or 32 bit integer) literal representing its Unicode code-point. <lang go>package main
import "fmt"
type any = interface{}
func showType(a any) {
switch a.(type) { case rune: fmt.Printf("The type of '%c' is %T\n", a, a) default: fmt.Printf("The type of '%v' is %T\n", a, a) }
}
func main() {
values := []any{5, 7.5, 2 + 3i, 'd', true, "Rosetta"} for _, value := range values { showType(value) }
}</lang>
- Output:
The type of '5' is int The type of '7.5' is float64 The type of '(2+3i)' is complex128 The type of 'd' is int32 The type of 'true' is bool The type of 'Rosetta' is string
J
Presumably this satisfies the task requirements...
<lang J> echo 'one' one
echo 1
1</lang>
Java
<lang Java>public class TypeDetection {
private static void showType(Object a) { if (a instanceof Integer) { System.out.printf("'%s' is an integer\n", a); } else if (a instanceof Double) { System.out.printf("'%s' is a double\n", a); } else if (a instanceof Character) { System.out.printf("'%s' is a character\n", a); } else { System.out.printf("'%s' is some other type\n", a); } }
public static void main(String[] args) { showType(5); showType(7.5); showType('d'); showType(true); }
}</lang>
- Output:
'5' is an integer '7.5' is a double 'd' is a character 'true' is some other type
JavaScript
console.log(typeof('foo')); // Returns string console.log(typeof(12345)); // Returns number
Kotlin
<lang scala>// version 1.0.6 fun showType(a: Any) = when (a) {
is Int -> println("'$a' is an integer") is Double -> println("'$a' is a double") is Char -> println("'$a' is a character") else -> println("'$a' is some other type") }
fun main(args: Array<String>) {
showType(5) showType(7.5) showType('d') showType(true)
}</lang>
- Output:
'5' is an integer '7.5' is a double 'd' is a character 'true' is some other type
Julia
In Julia, the function that returns the type of an object is the
typeof
function, and the function isa
tests
whether an object is of that type.
<lang Julia>
julia> a = 1 1
julia> typeof(a) Int32
julia> b = 1.0 1.0
julia> typeof(b) Float64
julia> 1.0 isa Number true
julia> 1.0 isa Int false
julia> 1 isa Int true
julia> typeof("hello") String
julia> typeof(typeof("hello")) DataType
julia> typeof(Set([1,3,4])) Set{Int64}
julia> 1 isa String false
julia> "1" isa Number false
julia> "1" isa String true
julia> isa(1.0,Float32) false
julia> isa(1.0,Float64) true
</lang>
OASYS Assembler
<lang oasys_oaa>
- The following method checks if a global variable or property is an
- object type. Does not work with locals and arguments.
[&OBJ#,^]
,^<,^<< ; Remember old value ,^<*> ; Create new object ,^<<DES ; Destroy the object ,^<<EX ; Check if variable has been cleared />1RF ; It is clear :>0RF ; It is not clear
</lang>
Perl
The function ref
takes a reference to a variable, via '\', and returns the type. Some of the more common are shown here.
In the cases where the value in question is already a reference ($regex
and $subref
) the '\' is not used.
<lang perl>$scalar = 1;
@array = (1, 2);
%hash = ('a' => 1);
$regex = qr/foo.*bar/;
$reference = \%hash;
sub greet { print "Hello world!" };
$subref = \&greet;
$fmt = "%-11s is type: %s\n"; printf $fmt, '$scalar', ref(\$scalar); printf $fmt, '@array', ref(\@array); printf $fmt, '%hash', ref(\%hash); printf $fmt, '$regex', ref( $regex); printf $fmt, '$reference', ref(\$reference); printf $fmt, '$subref', ref( $subref);</lang>
- Output:
$scalar is type: SCALAR @array is type: ARRAY %hash is type: HASH $regex is type: Regexp $reference is type: REF $subref is type: CODE
Perl 6
Perl 6 is a dynamic language that has gradual, duck typing. It provides introspection methods through its comprehensive MOP (Meta Object Protocol) making it easy to do type detection, subroutine signatures and multi-dispatch. Perl 6 types have two general flavors: content types and container types. Different container types have varying restrictions on what sort of content they can contain and in return provide specialized methods to operate on those contents. Content types give the compiler hints on how to best handle the information, what storage requirements it may have, what operators will work with it, etc.
This is really a very broad and kind of hand-wavey overview of Perl 6 types. For much more indepth coverage see Perl 6 Synopsis S02: Bits and Pieces: Built-In Data Types
<lang perl6>sub type ($t) { say $t.perl, "\tis type: ", $t.WHAT }
- some content types
.&type for 1, 2.0, 3e0, 4i, π, Inf, NaN, 'String';
- some primitive container types
.&type for $, [ ], @, { }, %, (5 .. 7), (8 ... 10), /0/, {;}, sub {}, ( );
- undefined things
.&type for Any, Nil;
- user defined types
class my-type { };
my my-type $object;
$object.&type;</lang>
- Output:
1 is type: (Int) 2.0 is type: (Rat) 3e0 is type: (Num) <0+4i> is type: (Complex) 3.14159265358979e0 is type: (Num) Inf is type: (Num) NaN is type: (Num) "String" is type: (Str) Any is type: (Any) $[] is type: (Array) $[] is type: (Array) {} is type: (Hash) {} is type: (Hash) 5..7 is type: (Range) (8, 9, 10).Seq is type: (Seq) /0/ is type: (Regex) -> ;; $_? is raw { #`(Block|61385680) ... } is type: (Block) sub () { #`(Sub|62948936) ... } is type: (Sub) $() is type: (List) Any is type: (Any) Nil is type: Nil my-type is type: (my-type)
Phix
Phix builtin type tests are: integer(), atom(), string(), sequence(), and object() - the latter returns true unless arg is unassigned. <lang Phix>procedure showtype(object o) string t = iff(atom(o)?iff(integer(o)?"integer":"atom")
:iff(string(o)?"string":"sequence")) ?{t,o}
end procedure
showtype(5) showtype(7.5) showtype("string") showtype({5,7.5,"string"})</lang>
- Output:
{"integer",5} {"atom",7.5} {"string","string"} {"sequence",{5,7.5,"string"}}
PHP
echo gettype('foo'); // Returns string echo gettype(12345); // Returns integer
Specific tester functions
PowerShell
In PowerShell everything is an object and all objects have the GetType() method: <lang PowerShell> [string]$str = "123" $str.GetType() </lang>
- Output:
IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object
<lang PowerShell> [int]$int = $str -as [int] $int.GetType() </lang>
- Output:
IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Int32 System.ValueType
Python
Built-in function type()
>>> type('foo') <class 'str'> >>> type(12345) <class 'int'>
Testing types
>>> type('foo') is str True >>> type(123.0) is not int True >>> type([]) is list True >>> type({}) is dict True
Racket
Hopefully you can see how to extend the code to add all sorts of other types. If I did this, I’d swamp the task page. A good list of types supported/provided by Racket can be found in the Typed Racket reference: http://docs.racket-lang.org/ts-reference/type-ref.html
<lang racket>#lang racket
(require racket/undefined)
(define fooer<%> (interface ())) (define foo% (class* object% (fooer<%>)
(super-new)))
(struct my-tree (l v r))
- -----------------------------------------------------------------------------
(define (n.t f)
(list f (regexp-replace #rx"\\?" (symbol->string (object-name f)) "")))
- listed in the order (as close as) shown in
- http://docs.racket-lang.org/guide/datatypes.html (section numbers next to
- some entries)
(define type-tests.names
`(,@(map n.t (list boolean? immutable? ; 3.1 )) ;; the famous scheme numerical tower ,@(map n.t ; 3.2 (list number? complex? real? rational? integer? exact-integer? exact-nonnegative-integer? exact-positive-integer? inexact-real? fixnum? flonum? double-flonum? single-flonum? zero? positive? negative? odd? even? exact? inexact?)) ,@(map n.t (list char? ; 3.3 --- there are also char-alphabetic? etc -- but they're not ; types as such string? ; 3.4 byte? bytes? ; 3.5 symbol? ; 3.6 keyword? ; 3.7 pair? null? list? ; 3.8 vector? ; 3.9 hash? hash-equal? hash-eqv? hash-eq? hash-weak? ; 3.10 box? ; 3.11 void? ; 3.12 )) ,(list (λ (v) (eq? v undefined)) "undefined") ; 3. 12 ;; now we move to http://docs.racket-lang.org/reference/data.html ;; for section numbering ,@(map n.t (list regexp? pregexp? byte-regexp? byte-pregexp? ; 4.7 stream? sequence? ; 4.14 dict? ; 4.15 set-equal? set-eqv? set-eq? set? set-mutable? set-weak? ; 4.16 continuation? procedure? ; 4.17 )) ;; class/interface testing ,(list (λ (v) (is-a? v object%)) "object%") ,(list (λ (v) (is-a? v foo%)) "foo%") ,(list (λ (v) (is-a? v fooer<%>)) "fooer<%>")
;; more types from reference (sections are top-level, mostly) ,@(map n.t (list syntax? ; 3. my-tree? ; 5. exn? exn:fail? exn:fail:filesystem? ; 10.2 promise? ; 10.3 ))
;; there's all sorts of other types to test! ))
(define (->type-names v)
(let ((rv (for/list ((t.n (in-list type-tests.names)) #:when (with-handlers ((exn? (λ (x) #f))) ((car t.n) v))) (cadr t.n)))) (if (null? rv) (list "UNKNOWN") rv)))
(module+ test
(require xml/xml)
(define test-values (list 3.+4.i 3+4i (- pi) pi 0. 0 -0.5 0.5 -1/3 1/3 -12345678909876543210123456789 12345678909876543210123456788 -132 133 #\t #\null "" "monkeys" "\u03BB" -1 255 256 #"" #"nibble" 'hello '|| '#:woo '() '(1 . 2) '(3) '(5 6)
#() #(1) #("foo" 2 'bar)
(make-hash) (make-hasheq) (make-hasheqv) (hash) (hasheq) (hasheqv) (make-weak-hash) (make-weak-hasheq) (make-weak-hasheqv) (make-immutable-hash) (make-immutable-hasheq) (make-immutable-hasheqv)
(box "x") (void) undefined #rx".*" #px"3?" #rx#"t.m" #px#".i." (in-vector #(1 2 3)) (stream 1 2 3) #hash((a . "apple")) #("apple" "binana") '("apple" "binana") '((a . "apple") (b . "binana")) (set 1 2 3) (seteq 1 2 3) (seteqv 1 2 3) (mutable-set 1 2 3) (mutable-seteq 1 2 3) (mutable-seteqv 1 2 3) (weak-set 1 2 3) (weak-seteq 1 2 3) (weak-seteqv 1 2 3)
+ (λ (x) #t) (call/cc (λ (k) k))
(new object%) (new foo%)
#'(xxy zzy) (my-tree (my-tree #f 1 #f) 2 #f) (with-handlers ((exn? values)) (error 'aargh!)) (with-handlers ((exn? values)) (file->string "/tmp/there-is-no-way-this-file-exists---surely?")) (delay 3) ))
;; tempted to print a cross-reference table, but that would be too wide for RC (maybe) (write-xexpr #:insert-newlines? #f `(table (thead (tr (th "Value [~s]") (th "->type-name"))) "\n" (tbody ,@(map (λ (v) `(tr "\n" (td ,(~s v)) (td ,(string-join (->type-names v) ", ")))) test-values)))))
</lang>
- Output:
The following table is generated:
<thead></thead> <tbody></tbody>Value [~s] | ->type-name |
---|---|
3.0+4.0i | number, complex, inexact |
3+4i | number, complex, exact |
-3.141592653589793 | number, complex, real, rational, inexact-real, flonum, double-flonum, negative, inexact |
3.141592653589793 | number, complex, real, rational, inexact-real, flonum, double-flonum, positive, inexact |
0.0 | number, complex, real, rational, integer, inexact-real, flonum, double-flonum, zero, even, inexact |
0 | number, complex, real, rational, integer, exact-integer, exact-nonnegative-integer, fixnum, zero, even, exact, byte, sequence |
-0.5 | number, complex, real, rational, inexact-real, flonum, double-flonum, negative, inexact |
0.5 | number, complex, real, rational, inexact-real, flonum, double-flonum, positive, inexact |
-1/3 | number, complex, real, rational, negative, exact |
1/3 | number, complex, real, rational, positive, exact |
-12345678909876543210123456789 | number, complex, real, rational, integer, exact-integer, negative, odd, exact |
12345678909876543210123456788 | number, complex, real, rational, integer, exact-integer, exact-nonnegative-integer, exact-positive-integer, positive, even, exact, sequence |
-132 | number, complex, real, rational, integer, exact-integer, fixnum, negative, even, exact |
133 | number, complex, real, rational, integer, exact-integer, exact-nonnegative-integer, exact-positive-integer, fixnum, positive, odd, exact, byte, sequence |
#\t | char |
#\nul | char |
"" | immutable, string, sequence |
"monkeys" | immutable, string, sequence |
"λ" | immutable, string, sequence |
-1 | number, complex, real, rational, integer, exact-integer, fixnum, negative, odd, exact |
255 | number, complex, real, rational, integer, exact-integer, exact-nonnegative-integer, exact-positive-integer, fixnum, positive, odd, exact, byte, sequence |
256 | number, complex, real, rational, integer, exact-integer, exact-nonnegative-integer, exact-positive-integer, fixnum, positive, even, exact, sequence |
#"" | immutable, bytes, sequence |
#"nibble" | immutable, bytes, sequence |
hello | symbol |
|| | symbol |
#:woo | keyword |
() | null, list, stream, sequence, dict |
(1 . 2) | pair |
(3) | pair, list, stream, sequence |
(5 6) | pair, list, stream, sequence |
#() | immutable, vector, sequence, dict |
#(1) | immutable, vector, sequence, dict |
#("foo" 2 (quote bar)) | immutable, vector, sequence, dict |
#hash() | hash, hash-equal, sequence, dict |
#hasheq() | hash, hash-eq, sequence, dict |
#hasheqv() | hash, hash-eqv, sequence, dict |
#hash() | immutable, hash, hash-equal, sequence, dict |
#hasheq() | immutable, hash, hash-eq, sequence, dict |
#hasheqv() | immutable, hash, hash-eqv, sequence, dict |
#<hash> | hash, hash-equal, hash-weak, sequence, dict |
#<hash> | hash, hash-eq, hash-weak, sequence, dict |
#<hash> | hash, hash-eqv, hash-weak, sequence, dict |
#hash() | immutable, hash, hash-equal, sequence, dict |
#hasheq() | immutable, hash, hash-eq, sequence, dict |
#hasheqv() | immutable, hash, hash-eqv, sequence, dict |
#&"x" | box |
#<void> | void |
#<undefined> | undefined |
#rx".*" | regexp |
#px"3?" | regexp, pregexp |
#rx#"t.m" | byte-regexp |
#px#".i." | byte-regexp, byte-pregexp |
#<sequence> | sequence |
#<stream> | stream, sequence |
#hash((a . "apple")) | immutable, hash, hash-equal, sequence, dict |
#("apple" "binana") | immutable, vector, sequence, dict |
("apple" "binana") | pair, list, stream, sequence |
((a . "apple") (b . "binana")) | pair, list, stream, sequence, dict |
#<set: 1 3 2> | stream, sequence, set-equal, set |
#<seteq: 1 2 3> | stream, sequence, set-eq, set |
#<seteqv: 1 2 3> | stream, sequence, set-eqv, set |
#<mutable-set: 1 2 3> | sequence, set-equal, set-mutable |
#<mutable-seteq: 1 2 3> | sequence, set-eq, set-mutable |
#<mutable-seteqv: 1 2 3> | sequence, set-eqv, set-mutable |
#<weak-set: 1 3 2> | sequence, set-equal, set-weak |
#<weak-seteq: 1 2 3> | sequence, set-eq, set-weak |
#<weak-seteqv: 1 2 3> | sequence, set-eqv, set-weak |
#<procedure:+> | procedure |
#<procedure:...pe-detection.rkt:113:13> | procedure |
#<continuation> | continuation, procedure |
#(struct:object) | object% |
#(struct:object:foo% ...) | object%, foo%, fooer<%> |
#<syntax:D:\Users\tim\Dropbox\hacking\rosettacode\type-detection.rkt:117:13 (xxy zzy)> | syntax |
#<my-tree> | my-tree |
#(struct:exn:fail "error: aargh!" #<continuation-mark-set>) | exn, exn:fail |
#(struct:exn:fail:filesystem "file-size: file not found\n path: D:/tmp/there-is-no-way-this-file-exists---surely?" #<continuation-mark-set>) | exn, exn:fail, exn:fail:filesystem |
#<promise:...e/type-detection.rkt:122:11> | promise |
REXX
These are some of the tests that can be performed on REXX variables (values) to determine which type they are.
Although everything (as far as variables are concerning) in the REXX language is a character string, character
strings can be classified by having certain characteristics, or in other words, types.
Characteristics of these types can overlap.
<lang rexx>/*REXX program displays what "type" a variable is (based on the variable's value). */
signal on noValue /*trap for undefined REXX variables. */
y= 1938 ; call showType y /*╔═══════════════════════════════════╗*/
y= 77.1 ; call showType y /*║ All REXX variables are stored as ║*/
y= ; call showType y /*║ character strings, even numbers. ║*/
y= ' ' ; call showType y /*║ If a variable string is numeric, ║*/
y= 'abc' ; call showType y /*║ all comparisons (IF statements) ║*/
y= 'ABC' ; call showType y /*║ that are made with numbers are ║*/
y= 'aBc' ; call showType y /*║ compared numerically. If not ║*/
y= '1515'x ; call showType y /*║ numeric, the string is compared ║*/
y= '10 11'x ; call showType y /*║ char by char after leading and ║*/
y= '00 0001'b ; call showType y /*║ trailing blanks are removed, and ║*/
y= '1'b ; call showType y /*║ shorter strings are padded with ║*/
y= ' + 1938 ' ; call showType y /*║ blanks to match the longer string.║*/
y= ' - 1.2e4' ; call showType y /*╚═══════════════════════════════════╝*/
y= '1' ; call showType y /* */
call showType yyy /*note: the variable YYY is undefined.*/
exit /*stick a fork in it, we're all done. */ /*──────────────────────────────────────────────────────────────────────────────────────*/ noValue: say ' REXX variable ' condition("D") ' is undefined.'; exit /*──────────────────────────────────────────────────────────────────────────────────────*/ showType: procedure; parse arg x 1 xu; upper xu /*get true value & an uppercase version*/
@= ' value is'; say @ x say @ 'of length' length(x) if x == then say @ "null." if x\== & x= then say @ "all blank." if datatype(x, 'N') then say @ "numeric (decimal)." else say @ "a character string (not numeric)." if datatype(x, 'W') then say @ "an integer (a whole number)." if datatype(x, 'N') &, \datatype(x, 'W') then say @ "not an integer." if datatype(x, 'N') &, pos('E', xu)\==0 then say @ "a number in exponential format." if datatype(x, 'A') then say @ "an alphanumeric string." if datatype(x, 'U') then say @ "all uppercase (Latin) letters." if datatype(x, 'L') then say @ "all lowercase (Latin) letters." if \datatype(x, 'L') &, \datatype(x, 'U') &, datatype(x, 'M') then say @ "of mixed case (Latin) letters." if datatype(x, 'B') then say @ "binary." if datatype(x, 'X') then say @ "hexadecimal." if datatype(x, 'S') then say @ "a REXX symbol." say copies('▒', 50) /*a fence that is used as a separator. */ return</lang>
- output when using the internal default data:
value is 1938 value is of length 4 value is numeric (decimal). value is an integer (a whole number). value is an alphanumeric string. value is hexadecimal. value is a REXX symbol. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is 77.1 value is of length 4 value is numeric (decimal). value is not an integer. value is a REXX symbol. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is value is of length 0 value is null. value is a character string (not numeric). value is binary. value is hexadecimal. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is value is of length 3 value is all blank. value is a character string (not numeric). ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is abc value is of length 3 value is a character string (not numeric). value is an alphanumeric string. value is all lowercase (Latin) letters. value is hexadecimal. value is a REXX symbol. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is ABC value is of length 3 value is a character string (not numeric). value is an alphanumeric string. value is all uppercase (Latin) letters. value is hexadecimal. value is a REXX symbol. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is aBc value is of length 3 value is a character string (not numeric). value is an alphanumeric string. value is of mixed case (Latin) letters. value is hexadecimal. value is a REXX symbol. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is §§ value is of length 2 value is a character string (not numeric). ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is ►◄ value is of length 2 value is a character string (not numeric). ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is ☺ value is of length 1 value is a character string (not numeric). ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is ☺ value is of length 1 value is a character string (not numeric). ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is + 1938 value is of length 8 value is numeric (decimal). value is an integer (a whole number). ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is - 1.2e4 value is of length 8 value is numeric (decimal). value is an integer (a whole number). value is a number in exponential format. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ value is 1 value is of length 1 value is numeric (decimal). value is an integer (a whole number). value is an alphanumeric string. value is binary. value is hexadecimal. value is a REXX symbol. ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ REXX variable YYY is undefined.
Ring
<lang ring>
- Project : Type detection
see "5 -> " + type(5) + nl see "7.5 -> " + type(7.5) + nl see "d -> " + type('d') + nl </lang> Output:
5 -> NUMBER 7.5 -> NUMBER d -> STRING
Scala
<lang scala>object TypeDetection extends App { def showType(a: Any) = a match { case a: Int => println(s"'$a' is an integer") case a: Double => println(s"'$a' is a double") case a: Char => println(s"'$a' is a character") case _ => println(s"'$a' is some other type") }
showType(5) showType(7.5) showType('d') showType(true)
println(s"\nSuccessfully completed without errors. [total ${scala.compat.Platform.currentTime - executionStart} ms]")
}</lang>
VBA
VBA has a built-in function TypeName (VarType returns a number), which can also recognize arrays. <lang vb>Public Sub main()
Dim c(1) As Currency Dim d(1) As Double Dim dt(1) As Date Dim a(1) As Integer Dim l(1) As Long Dim s(1) As Single Dim e As Variant Dim o As Object Set o = New Application Debug.Print TypeName(o) Debug.Print TypeName(1 = 1) Debug.Print TypeName(CByte(1)) Set o = New Collection Debug.Print TypeName(o) Debug.Print TypeName(1@) Debug.Print TypeName(c) Debug.Print TypeName(CDate(1)) Debug.Print TypeName(dt) Debug.Print TypeName(CDec(1)) Debug.Print TypeName(1#) Debug.Print TypeName(d) Debug.Print TypeName(e) Debug.Print TypeName(CVErr(1)) Debug.Print TypeName(1) Debug.Print TypeName(a) Debug.Print TypeName(1&) Debug.Print TypeName(l) Set o = Nothing Debug.Print TypeName(o) Debug.Print TypeName([A1]) Debug.Print TypeName(1!) Debug.Print TypeName(s) Debug.Print TypeName(CStr(1)) Debug.Print TypeName(Worksheets(1))
End Sub</lang>
- Output:
Application Boolean Byte Collection Currency Currency() Date Date() Decimal Double Double() Empty Error Integer Integer() Long Long() Nothing Range Single Single() String Worksheet
zkl
<lang zkl>fcn processText(data_or_fileName){ // unknown
if (data_or_fileName.isType(String)) // == .isType("") data_or_fileName=File(data_or_fileName,"rb").read(); //-->Data text:=data_or_fileName.text; //-->String doTheActualTextProcessing(text);
} fcn doTheActualTextProcessing(text){ println(text) }</lang> If an int is passed in, (123).text --> "123", other objects might throw an exception.
How to use: <lang zkl>processText("foo.txt"); processText(Data(Void,"This is some text")); // fake up a class that holds a string: cs:=class{ var text }; cs.text="this is more text"; processText(cs);</lang>
- Output:
this is foo.txt This is some text this is more text