Open dragoncoder047 opened 1 year ago
I welcome your comments on my simple object system.
can't have multiple parents / "mixins" it doesn't support setf'ing slots
Yes, obviously CLOS has these, but I was trying to create the minimum system that would actually be useful for something like my Mini text adventure game.
You went to the length of defining a "generic area function" too but that just seems unnecessary.
How would you implement the example without this?
First off, generic keyword support needs to be added.
Do you mean add keyword support to uLisp, or add keyword support to the simple object system?
What extra would this give you beyond using symbols starting with a colon as markers?
How would you implement the example without this?
Ideally it would be with keywords - you would do (:area object)
if it is just a property, or (object :area)
if it is a method with no arguments (as opposed to (area object)
whose only advantage in terms of readability is it doesn't have a colon).
Do you mean add keyword support to uLisp, or add keyword support to the simple object system?
What extra would this give you beyond using symbols starting with a colon as markers?
Keywords to uLisp as a whole. Any symbol starting with a colon evaluates to itself -- that's all.
The advantage is (besides also being able to do &key
arguments) is that special forms that don't evaluate their arguments won't get confused if someone puts in 'foo
instead of just foo
. That way, since keywords evaluate to themselves, the special form CAN evaluate some of its arguments so the user can use variables.
I just had another idea last night.
Consider this line:
The meaning of this is that builtin symbols evaluate to themselves, that is:
> foo
Error: undefined: foo
> print
print
However, I was kind of expecting the output of what Python and Common Lisp do when printing a function:
>>> print(print)
<built-in function print>
CL-USER> (print #'print)
#<SYSTEM-FUNCTION PRINT>
But within uLisp's execution model, this ends up working. It is because of this if case:
Essentially what ends up happening is that the symbol evaluates to itself, and then the symbol is called as if it was a lambda.
A good start on objects, I think, would be to implement another type, C_FUNCTION
, which is identical to SYMBOL
and would be treated as such by functions that deal with and expect symbols, but when a true SYMBOL
is evaluated, it is changed into a C_FUNCTION
, and when a C_FUNCTION
is printed, it prints <c-function print>
instead of just print
.
What do you think?
I think that would work, but I'm not sure what the benefit would be.
Also, would you still be able to do this?
http://forum.ulisp.com/t/extending-ulisps-built-in-operators/1181
Also, would you still be able to do this?
http://forum.ulisp.com/t/extending-ulisps-built-in-operators/1181
Certainly, since the mechanism would be the same (all the change really does is change how the built-in symbols are printed). The point here is that it seems a bit strange to be calling a symbol as if it was a lambda or function in a language like Lisp.
Another thing this kind of "does" is make it as if each symbol is bound by default in the global environment to a C function, just in a way that takes zero workspace, and also prevents them from being accidentally makunbound
'ed.
Continuing the discussion from https://github.com/technoblogy/ulisp-esp/issues/71#issuecomment-1523873453:
Yes, but a) it only supports single inheritance because it's prototype-based (can't have multiple parents / "mixins") and b) it doesn't support
setf
'ing slots ((setf (value obj 'foo) new-value)
would kind of make sense but it doesn't work so you have to useupdate
). Also, calling a method on an object is more verbose because you have to do((value obj 'key) obj arg1 arg2 ...)
instead of just(obj :key arg1 arg2 ...)
. You went to the length of defining a "generic area function" too but that just seems unnecessary. I'm all for reducing the number of required parenthesis especially in a parenthesis-heavy language like Lisp.Another potential problem with this I can see is having the special key
'parent
being used to point to the prototype of the object, seems like it would be prone to collisions if someone did something where it makes sense to point to a parent, such as nested parsers for something (e.g. JSON).But I do think this is a good starting point: an object can be represented as an assoc list of its slots, and the tail of the assoc list somehow points to the prototype(s).
Okay, my idea here:
First off, generic keyword support needs to be added.
My idea is that a new type (in the type enum) called OBJECT would be defined. The cdr of the actual OBJECT cell would point to a cons pair. The car of that cons pair would point to the slots array, and the cdr would point to an (improper) list of prototypes.
Then two changes need to be made to eval(), right before the
not valid here
error case:(obj :foo 1 2 3)
desugars into((:foo obj) obj 1 2 3)
. Of course this longer syntax would still be possible and would also be the only way to get the equivalent of Javascript'sFunction.call
.Hope that helps.