snow-deprecated
snow-deprecated copied to clipboard
Classes or only objects?
Okai, right now Snow is a little prototype-based, and a little class-based.
In a purely prototype-based language Array would simply be an empty Array which you can clone (aka. create a new object and set the parent/prototype to the original object):
snow> Array
=> @()
snow> Array.clone(1, 2)
=> @(1, 2)
snow> Array.clone().prototype = Array
=> true
In a class-based language (hacked upon a prototype-based thingie) it would look more like this:
snow> Array
=> Array
snow> Array.new()
=> @()
snow> Array.new().prototype = Array.instance_prototype
=> true
This is currently how the current class-support in prelude.sn works.
However, currently Snow uses a mix:
snow> Array.members
=> @(#include?, #map_parallel, #pop, #shift, #*, #inject, #-, #unshift, #push, #each_parallel, #map, #each, #get, #set, #inspect, #<<, #new, #+, #to_string)
snow> Array
=> Assertion failed: (object_cast<Array>(self) && "expected pointer to object of class " "Array"), function array_inspect, file Array.cpp, line 296.
snow> Array.new().prototype = Array
=> true
Array is an Object with a lot of members, but if you try to use them you get a nasty error. It looks like a prototype-based thingie, but it wants to be class-based.
I would prefer the completely prototype-based way, but I do realize that sometimes classes makes sense. However, if we're going to use classes, the core classes should follow the class-system, and not some weird mix…
This is actually a bug, due mostly to laziness on my part. It's on my roadmap to split the base classes into a Class object and an instance prototype, the same way prelude does it.
I will not be able to do it for at least a few weeks (currently trying to squeeze the last of the bugs from the GC).
It should be fairly straight-forward to do, so if anyone feels up to the task, it's hereby up for grabs! :)
As for the purely prototype-based system: I think that Snow should be purely prototype-based (and it currently is), but provide an easy way to do "traditional" Ruby-style OOP, as prelude.sn attempts to achieve. These are not mutually exclusive; if a programmer wants to go purely prototype, there's currently nothing stopping him, and an empty array can indeed be used as a prototype (although not a particularly useful one, since Array needs a C++-side implementation for allocating internal data – the prototype will have the data, while the derived object will not, so the above mentioned ASSERT will be hit).
The reason we'll use the Class-emulation for the base library is that most objects in the base library need special C++ implementations (each instance is actually a C++ object derived from snow::Object, and not a pure Object, like all other object allocated by the user). It could still be done, but C++ provides no easy way to see what type of data a pointer points to, so using a flat hierachy with a single Class instance prototype is much easier.
On top of that: I like OOP. It's not a bad paradigm. But I also like freedom, so I think Snow is perfect because it allows the programmer to go with whatever paradigm fits the problem best.
The default clone could easily transfer the C++-objects to the new object, couldn't it?
But yeah, let's just use the same Class-emulation in prelude.sn and the base library and I'm happy :-)
There is already preliminary support for copy on the C++ side, actually. I'm not sure it's hooked up to the Snow runtime, but all classes deriving from snow::IObject should implement a copy, that returns a deep copy. Not sure if that's the case yet.
Please make a separate feature request if anybody needs it just yet, so it's on the TODO.
Speaking of prelude, is it really necessary? Right now it contains an incomplete class paradigm implementation, and a single pure-Snow method (Array.inject).
I think it'd be pretty badass to have the entire class paradigm implementation in the standard library of the language. It's like Forth, only sane.
I think prelude.sn should be a list of require()s, including the base standard library (class, etc.). Having it in a single file makes the C++ side less dependent on the filesystem layout of the stdlib, and makes maintenance a bit easier, so I think the file itself should remain, but its contents should change dramatically.