I noticed that (cnvDrawText ...) only takes strings as the 3rd argument. I remedied this by using (cat ...) to force whatever type the variable was into a string.
Then, I encountered the local variable error in (errblock (error) ...) and had a hard time trying to use it. So, after having a fight with two types, I think I need a bit more background on the types and how they behave in TLisp.
The build in function (typeof ...) seems to indicate that the types available in TLisp are:
error
function
int32
list
primitive
string
struct
List of questions:
Is this list complete?
What do these types represent/how do they behave?
Is there an function to explicitly cast types?
Does TLisp automagically convert types? or is the flexibility of -for example- (cat ...) provided by the function's definition?
the error type seems to have some sort of build in 'toString' method, is this interpretation correct? are there other types which have similar behaviour build in?
Probably a bunch of other questions I did not think of yet.
Not sure I can answer this question completely, but let me try.
A few general comments:
A. TLisp, like other dynamic languages, handles datatypes at runtime. This is in contrast to static-typed languages like C++, which expose datatypes in the code itself and require explicit conversion. The result, therefore, is that you can't tell (from the arg-list) what datatypes a particular function accepts.
B. In theory, TLisp function should accept any datatype and do something appropriate accordingly. For example, as you discovered, (cat ...) accepts both integers and strings and does the right thing.
C. In practice, of course, that's not 100% true. (cnvDrawText ...) should accept integers (it should probably accept multiple arguments too). But either from laziness (as in this case) or uncertainty as to appropriate behavior, many functions give runtime errors instead. In these cases, we should write up bugs/requests. For example, it shouldn't be too hard to fix cnvDrawText.
Now let me try to answer your questions:
1. The only missing types on your list are "nil" and "true". But in the future there may be more types.
2. Here is a list of all currently defined types:
error: Error is a special type with unique properties. Most of the time, if a function returns an error type, the execution of the caller is aborted and we return the error all the way up. The exception is (errblock ...) which traps the error.
function: This is a lambda expression, created by (lambda ...).
int32: This is a 32-bit signed integer. Some functions will automatically convert an integer to a string, if necessary. But not all do.
list: This is a list created by (list ...). Note however that empty lists are treated as nil (see below).
nil: Nil is a special type. Empty lists and empty structures are also considered nil. [Inconsistently, however, empty strings are not considered nil.]
primitive: This is a built-in function (i.e., one implemented in C++). For example: (typeof typeof) -> primitive
string: This is a character string.
struct: This is a structure (a key-map) created with (struct ...).
true: This is a special type.
3. There is no general function to cast types. There should be a function like (convertTo {type} {value}) which converts the given value to the given type, but that doesn't exist yet. Instead, there are a couple of function that convert types in limited circumstances:
(int {value}) converts a value (usually a string) to an integer.
(cat {value} ...) converts a sequence of values to a string.
4. Specific functions are responsible for converting types as appropriate. This is because functions may want to do different things depending on the type. For example, (count ...) behaves differently on strings and lists. For lists it returns the number of elements. For strings, it returns the number of characters.
5. The error type is a special type which is generally converted to a string at appropriate times.
Hope that helps, but keep asking questions if necessary.
I always thought that there was a type boolean with possible values True and Nil. This seems incorrect now.
Is True the data type? or is there a boolean data type which can only be True or unset?
Can I interpret Nil as null in c? Or are there enough differences that you recommend finding a Lisp book to figure it out?
george moromisato wrote:Empty lists and empty structures are also considered nil. [Inconsistently, however, empty strings are not considered nil.]
How about empty error and int32?
Specific function are responsible for handling the different data types as you describe. Can I interpret this as function overloading in c++?