Lisp type system, lang-lisp
Posted: Fri Mar 13, 2009 3:20 pm
As i have already stated i am working on a language i call lang-lisp(thusfar). I am starting this thread fishing for some comments. At the heart of the language is types, and the idea that they can be done better. Secondly is the idea that the language should be flexible enough to be able to express peoples idea in a library, firstly because that is the way it should be, and secondly because it relieves a lot of pressure of not having to bother with every idea out there, just whether you can make a library that creates the language feature. (For instance, i read a little about design patterns, and they seem to be ideas which the language doesn't make you able express.)
Of the language Common Lisp, i find the worst flaw it's type system. For instance, +,-,/,* are functions, not methods. You can't extend them with:
These operators seem to arbitrarily be different to then the regular functions.
Note also that the type could not handle the length of the vectors. You either need to let lisp store length explicitly, or make a new object for each length. Then, lisp also has to look up the length. In this case lisp might optimize this, but the user does not have confidence that it will. Furthermore, there are cases where some elements of a struct/class is 'eql' to something, and The object should be treated like that; not checking around what that object is, not dragging the data around.
So how to fix this? Since common lisp does not have these types itself, macros can't do it.(Besides ones that practically create a whole new language.) I suggest functional types; types depending on arguments, which are defined with (basically) one macro which takes arguments as following:
Where elements are: (element-name element-type &rest other-stuff-here) Where for the other stuff i think stuff like :initform, :derive(pass on functions to take this argument instead of the whole struct, class derivation-like) :reader, :writer,: accessor. Maybe :set :get functions that replace ordenary getting and setting.
Types are written with s-expressions, any symbol that is not the first element of a list is a variable in it. Some types have to be defined as atoms, like (int64), (int32), (ptr of-type), (eql 3)
For instance, with this you make a list with the following:
Functions are all overload(able), chosen by using the function that matches with the most specific type. As you might know, that this is ambiguous by itself, you also need a preference. The preference is used when two functions are applicable with equal specificness, you choose the one with the more specific part leftmost, the earlier argument of a type.
Of course, if you have function overloading, you can choose macros the same way, caveit is that the macro might change the result.
I should say more about specificness and how it is defined. Unmodified, A is more general then B if the variables in A can be set in such a way that the results equals B. However, for some things there are modifications, like (any) which is more general then anything else. (number) and other numbers.
Another override i would like is conversion functions, which would make A more general then B if it can be converted as well. However, i have not succeeded at this yet, currently the generality of numbers is 'manual', like (any).
A simple example of a function in lang-lisp:
Here :define-as-needed means that it will create a new function in binary for each type of number it means. if it is (int32) it will produce (int32), (safe-int32) or maybe (safe (int32)) could be used if you want to prevent overflows.(So types can take over the role of optimisation of code upto an extent as well) I am still unsure about numbers in general, maybe i need to use intervals in types of numbers. (That way the user can also give more info on the functions; to which intervals they map; for instance [a,b] maps to [0, max(abs(a),abs(b))^2])
All in all, i have to admit that i still need to figure this out more. I think typed lambda calculus might help, i think i will try learn about it. Also making some proofs of stuff in the hopes of clarifying things for myself and just for being a fancypants.
So i would like to hear some responses on the idea of types, and what it would take for a language to be efficient and able to change to many forms by adding libraries.
PS been a little slow on my lang-lisp project lately because i was messing with a loop/iterate -like macro. I should kill the ideas i had on how to do the macro with fire, i might try make a post about that on my conclusion. (And macros with ideas regarding a loop-like macro.)
Of the language Common Lisp, i find the worst flaw it's type system. For instance, +,-,/,* are functions, not methods. You can't extend them with:
Code: Select all
(defmethod + ((a vector) (b vector))
(let ((len (min (length a) (length b)))
(out (make-array (list len))))
(do ((i 0 (+ i 1))) ((>= i len) out) (setf (aref out i) (+ (aref a i) (aref b i))))
Note also that the type could not handle the length of the vectors. You either need to let lisp store length explicitly, or make a new object for each length. Then, lisp also has to look up the length. In this case lisp might optimize this, but the user does not have confidence that it will. Furthermore, there are cases where some elements of a struct/class is 'eql' to something, and The object should be treated like that; not checking around what that object is, not dragging the data around.
So how to fix this? Since common lisp does not have these types itself, macros can't do it.(Besides ones that practically create a whole new language.) I suggest functional types; types depending on arguments, which are defined with (basically) one macro which takes arguments as following:
Code: Select all
(struct name (&rest arguments) &rest elements)
Types are written with s-expressions, any symbol that is not the first element of a list is a variable in it. Some types have to be defined as atoms, like (int64), (int32), (ptr of-type), (eql 3)
For instance, with this you make a list with the following:
Code: Select all
(struct listnode (item-tp)
(item item-tp)
(next (ptr(list-node item-tp))))
Of course, if you have function overloading, you can choose macros the same way, caveit is that the macro might change the result.
I should say more about specificness and how it is defined. Unmodified, A is more general then B if the variables in A can be set in such a way that the results equals B. However, for some things there are modifications, like (any) which is more general then anything else. (number) and other numbers.
Another override i would like is conversion functions, which would make A more general then B if it can be converted as well. However, i have not succeeded at this yet, currently the generality of numbers is 'manual', like (any).
A simple example of a function in lang-lisp:
Code: Select all
(defun sqr :define-as-needed ((x (number))) (* x x))
All in all, i have to admit that i still need to figure this out more. I think typed lambda calculus might help, i think i will try learn about it. Also making some proofs of stuff in the hopes of clarifying things for myself and just for being a fancypants.
So i would like to hear some responses on the idea of types, and what it would take for a language to be efficient and able to change to many forms by adding libraries.
PS been a little slow on my lang-lisp project lately because i was messing with a loop/iterate -like macro. I should kill the ideas i had on how to do the macro with fire, i might try make a post about that on my conclusion. (And macros with ideas regarding a loop-like macro.)