On occasion I try to think up good reasons to not declare instance variables. Yesterday while playing with Javascript and Lisp I realised one of the major reasons why you shouldn't have to declare instance variables in Smalltalk.
Consider the syntax of making objects, examples: 'string', 123, 456.7, #symbol, #(), #[], []
Now, what's the most commonly used 'type' in Smalltalk? .. Object of course. We use Object all the time. But there's no Syntax for building an Object. How strange. You can do this really easily in Lisp just by using the ' (quote) character. You can do it in javascript just by using { slotname: value, ... }.
So why can't we do this in Smalltalk? Don't we try to encompass really core ideas - data and code are the same right? The reason is simple enough. In Smalltalk you have to declare your instance variables, therefore there can be no generic syntax for building an object. Whatever syntax you come up with will be dependent on the definitions of classes in the system - which are dynamic.
Let's say we have class User, with instance variables name and age. We could have a syntax in Smalltalk like this:
{name: 'Michael', age: 26 }
That is basically how Javascript works and sort of how Lisp works too, but unfortunately we didn't say we wanted a User any where. That's where the power of prototype based languages come in. You can make a generic Object with those slots and then give it behaviour afterward. Pretty cool - but let's go back to reality with Smalltalk for a second.
There are a couple of ways to get around this problem. In VisualAge there are compile time constants, eg:
##( User new name: 'Michael'; age: 26; yourself )
However, there are some pretty weird semantics that go with that as you can well imagine. In VisualWorks there is the OnceUponATime library that Travis wrote which would let you do:
[User new name: 'Michael'; age: 26; yourself] once
These are pretty cool, we've extended the environment without changing the syntax or the language.. however, it doesn't really rate against the simplicity of javascript and lisp here.. Let's try and invent a syntax.
The {} syntax is actually taken by Squeak (and available in VisualWorks too btw) to build Arrays programmatically, eg:
{1. 'test'. #test. self doSomething }
That is equivalent to:
Array with: 1 with: 'test' with: #test with: self doSomething
But clearly it takes a lot less typing. Regardless, that means we cannot use {} .. we can't use () or [] and we can't use #{}, #() or #[]. But we still need to state what class we want to use - there's a syntax for specifying classes in Smalltalk and it looks like this:
MyClass
or
MyNamespace.MyClass
We could hijack this syntax, perhaps something like:
MyNamespace.User { self name: 'Michael'. self age: 26 }
If we do that, we're combining two ideas. First: It looks like a message send, we're sending an "initializer" message "{ ... }" and we're saying {} means "execute now to build something that the method will reference". So we're combining the {} array building syntax with the class identifier syntax with the message sending paradigm.
The caveat? .. we're introducing new syntax in to the system. The upside is, we're running real code like a compile time constant - yet it has more meaning than a compile time constant.
I'm not so thrilled about putting 'self' in there though, but anything else requires a _real_ syntax adjustment because we'd be writing something like this:
MyNamespace.User { name: 'Michael'; age: '26' }
I went for ; this time because it looks like a 'cascade'. So in that respect you could say the {} syntax after a class name is like "sending a set of cascaded messages with a receiver of the class". This is a pretty good fit for Smalltalk in many ways.
I'm not game to put the effort in to trying to add this syntax to Smalltalk just yet.. but I'm curious as to what other people think of the idea? Please post your feed back or email me.