The Sapphire Language: getting and setting instance variables
Strangely, I find that one of the nice features about Ruby is the lack of keywords.
In C# I tend to end up writing things like this:
public override static bool xxx (...
And then there’s ’annotations’ that tell the CLR what to do on top of that.
On the other hand, in Ruby, there are fewer keywords, but some of the traditional functions of keywords have been replaced by methods, such as private. Other ‘pseudo-keywords’ are attr_reader and attr_writer. In fact, these are methods of Module and while you can override them you do so at your peril; they function in all respects like keywords.
But I think that ’duck typing’ ought to apply to keywords as well as code - if it looks like a keyword and behaves like a keyword, then it should be a keyword. And recognised as such by the parser.
Ruby attributes are also messy in another way. A ‘writer’ attribute is indicated by an = symbol at the end of a method declaration:
def x=;... end
...while a ’reader’ attribute looks just like a normal function:
def x;... end
In Sapphire, we’re going to do something different and, we believe, more logical. First, all instance variables will have a read and write accessor built-in. That is, you won’t have to declare any special methods to just get and set them.
So if I declare an instance variable @x in a class C, I will automatically be able to do things like this (without having to declare accessors):
a = C.new
a.x = 5
Now suppose you want to have an accessor do something more than get or set a simple value. We’ve define two keywords get and set which work in a very similar fashion to def. Like this:
get x(); @x + 1 end
set x(v); @x = v – 1 end
So get and set replace the attr_read and attr_write and the dangling = at the end of a method name. It’s more work for the parser, but it’s a whole lot clearer and neater.
For more information on Sapphire, see:
The Sapphire Programming Language - The Fundamentals
The Sapphire Programming Language: defining the grammar
I love that the post starts with "...one of the nice features about Ruby is the lack of keywords." and then starts adding keywords. I was intrigued by the original announcement but, Sapphire is shaping up to be C# with Ruby-like syntax.
Nothing wrong with using keywords when appropriate. A great many things in Ruby look like keywords but turn out to be methods. The distinction between methods and keywords will be absolutely clear in Sapphire. As for C# - no, one thing I can say with complete certainly is that neither the grammar nor the behaviour of Sapphire will have much in common with C# (or Java or C/C++). While every language developer is, of necessity, influenced by languages that have gone before, C# is not one of the languages that have had any significant influence on Sapphire. A few other languages have - some of which we’ve already mentioned, others of which we’ll mention over time. But I promise you that C# won’t figure large among them ;-)
The get and set keywords and their associated functionality are straight out of C#.
The minimalist Ruby approach is far cleaner and flexible IMHO. I would love to see the vastly cleaned up Ruby I envisioned when I first read of Sapphire. Adding keywords and a new way of defining methods is not cleaning up the language, it’s adding more cruft.
I also think the automatic exposing of class internals is a bad idea but, that’s less significant than littering the language with things that are already well served with the existing implementation.
I think there is a misunderstanding here. Class internals will be protected more tightly in Sapphire than in Ruby. There will also be less syntax for accessors. Instance variables that provide accessors will only need to be declared in the public area of the class. This will automatically create simple accessors without any explicit methods or keywords needed to do this. Instance variables can also be declared in a private area of a class in which case no acessors will be available. There will also be a mechanism for declaring ’null’ accessors so that either the get or set method will be unavailable. Believe me, if you want minimalism, this is about as minimal as you can get! The defaults have almost no syntax...
The get and set keywords are used to implement accessor methods when you wish to do it ’long hand’ (as you also can in Ruby). The set method dispenses with the requirement to append a = to the method name. Our approach is that anything that looks and behaves like a keyword should be a keyword - not a method of Module. But that whenever possible, these should be kept to an absolute minimum.
There are 41 keywords in Ruby. Also there are about 6 (more depending on how you count them) or so ’psuedo-keywords’ like private, public, attr_read, etc. which are keywords in all but name. While you CAN override them, I’ve never seen any real code do so. But there’s an awful lot of real code out there :)
Sapphire currently has 35 keywords (including get/set) so we have a good bit less than Ruby.
In my view, if something behaves like a keyword, it should be a keyword. No ands, ifs or buts. I suspect that the reason Matz didn’t put private, etc, in as keywords is that the Ruby yacc grammar is a real pig to debug and it was easier to define them as methods. The effect is the same in the end.
My objection to C# keywords is a) there are way too many and b) I really, really dislike having to put upto 5 keywords in front of a method name. Get/set I have no problem with as the syntax is at least clear. Also, accessors are methods - so why not make this fact explicit and obvious?
In other words... you’re making public the state of an object for both, reading and writing!
Having to define accessors for instance variables is a feature, not a problem. it complies to the principle of encapsulation [http://en.wikipedia.org/wiki/Inform...].
I think what you want is Lua [http://en.wikipedia.org/wiki/Lua_(p...)] It already does some things that you want (no encapsulation and first class methods for example).
Actually, it doesn’t break encapsulation - it just makes instance variable accessors public by default. It’s just that the get/set methods are defined by default to be public. This is the current behaviour, but you can change this. We’ve defined a technique of altering this behaviour using interfaces (picked up from Object Oriented Encapulation or OOE) which I’ll describe next week.
I haven’t had a look at Lua (yet) - thanks for the pointer.