Really nice language, with similarities to Smalltalk Language, but Prototype Based, and things from Lisp Language and Java Script.
Still in beta, but pretty functional, it's being developed by Manuel Tomis. I am just helping for testing, examples, &c...
See brain.sourceforge.net for more. I am sure you'll like it :)
-- David De Lis
Don't you mean 'similarities to Self Language'? The syntax seems a little kooky - what was wrong with Self's syntax? -- Richard Emerson
I agree -- the syntax is kooky. I'd like to learn more about the reasons for developing this language. Having spent two years working in a prototypical language (now dead), I'm always eager to learn about others. I'm assuming there are some shortcomings in Self Language that Brain Language is focusing on overcoming. What are they?
On a brief scan of the docs, I saw one point that really troubles me: "If the method or property is found in the prototype then it is the prototype that becomes the receiver object of the message." If the prototype is the receiver, how do you override data members? I'm accustomed to the original object remaining the receiver so that further member lookups begin there. -- Greg Vaughn
What does kooky mean? As far as I know from email interchange with the author (a young CSC student in Chyprus) he looked some books of Smalltalk and Java Script and liked it, so he started to make the Brain Language. I didn't know Self, although I did know a bit about Newtonscript. I'll point Manuel Tomis to this wiki and to the pages given on the Self Language page and see what he thinks. The language is slowly changing and even today I have some proposals for changes to send to him. It would be nice if people interested would get in touch with Manuel Tomis, he will surely appreciate any and all input about Brain Language.
As for my own opinion, I like it because it's really clean, without some extra syntax commonly found in Smalltalk that usually remains void, &c.
Regarding prototypes, you don't have to delegate, you can subtype. That means the new object is a clone of the first one but with added functionality or data... (properties)...
This is an example I am making myself for the examples section:
Person = object subtype property: #name is: ""; -- defaults property: #age is: 0;
method:
#get_name is: {
self!name }; method: #get_age is: { self!age }; method: #set_name: is: { |new_name| self!name = new_name }; method: #set_age: is: { |new_age| self!age = new_age };
.
And then you can subtype or delegate Boy, Girl, Baby, &c... It's extremely clear, (specially written in this C++/Java look&feel... I am still looking the right style for this language.. any suggestions very appreciated :)
If you have to override data members for an object, you should refactor it to be a subtype of its parent and not delegate that functionality to it. I see delegation like in legal matters. If a young boy does something bad, he is delegating the responsibility to his parents (until he is over 18/21 years-old) and thus the father/mother/legal tutor becomes fully receiver of the message (sent by Justice in this example...) I may be off-the-track, though...
Hope this helps... -- David De Lis
Newtonscript was actually the Self derived language I have experience in. I haven't had the chance to read through all the details of the docs, so correct me if I'm wrong about subtyping in Brain Language: a subtype of X is an object with X as it's prototype. Suppose you create a Baby class with your example Person as its prototype, and it does not override the getName method, but it does have it own name property. If you sent a getName message to Baby would it return the name from Person or Baby? My reading of the rule that the prototype becomes the receiver would mean that it would return name from Person, which is not what I would want. -- Greg Vaughn
Actually Babies are down in the chain of my example... :-) That would only happen if Baby delegate its methods to Person. Problem here is how you model the whole thing: a baby IS-A person or a baby IS-LIKE a person? (using Scott Meyers' relationships (we've left HAS-A out))
If a baby IS-A person, then:
Let's suppose:
Animal = object new. -- an animal (''instance'' of object) -- Animal = object subtype. -- this would yield a specialization of object... Person = Animal subtype. -- a person IS-A animal Baby = Person subtype. -- it would have all data and methods from Person.
But if Baby = Animal subtype property: #prototype is: #Person.
In this case, we are stating that a Baby is an animal, the same way a Person is, that a Baby is not a Person, but that it behaves in a similar way... (IS-LIKE). I think I remember Coplien or Meyers have a discussion on C++ inheritance: IS-A is public inheritance, HAS-A is private inheritance and IS-LIKE is protected inheritance... or a permutation of the two last ones... I wonder is that right? Hope this makes things clearer... -- David De Lis
Sorry, but I still don't see it. I guess I should read the Brain Language docs more. It sounds to me from your example that the 'subtype' keyword is not the same as setting a prototype, which was the assumption I made above. Still if
Baby = Animal subtype property:
#prototype is: #Person, property: #name is: "Junior"
and I call Baby.getName() (or whatever the syntax is) will it return "Junior" or whatever name is defined as in Person? -- Greg Vaughn
About the question why I wrote Brain Language. About 2+ something years ago I decided to write a programming language, just for fun :) I started looking around on the net and i had a good look at languages like Java Language, Python Language, Scheme Language, Smalltalk Language, Self Language, Pike Language, Java Script, Haskell Language and a few more. After trying some approaches I finally decided on the general design of Brain Language at the beginning of last year. Brain Language is obviously influenced a lot from Smalltalk Language/Self Language. Basically I liked the ideas behind those languages but there were also some things I didn't like, so I borrowed the general ideas about the syntax and the semantics, but I decided to do the rest the way I wanted to. So what are the differences between Brain Language and Self Language?
First of all there are some obvious syntactic differences ex. identifiers can contain dash, blocks and literals have kind of different (kooky ?:) syntax etc. Local variables in Brain Language are introduced with the var keyword. Besides the usual unary/binary/keyword message syntax, Brain Language has a block evaluation syntax (). This makes evaluating blocks more convenient rather than using block value: ??? value: ??? value: ???, and allows blocks to be used like functions in other languages. You can access properties of objects with object!property syntax rather that the system creating special methods. There are also semantic differences: Brain Language supports Scheme Language style closures, and it does not have a non local exit ^ because it would make no sense given the semantics of blocks in Brain Language. In Brain Language all blocks are equals, that is there is no distinction between methods and blocks. Also Brain Language supports single delegation, instead of multiple delegation, because I thought the complexity wasn't worth it. One of the most important differences is that Brain Language libraries do not have much in common with the Self Language libraries (although again there are methods that have similar names).
Last but not least Self Language and Smalltalk Language usually come with a set of thousands of objects, which live in a persistent image. From what I saw Self Language is worth about 15 megabytes of download. I preferred to make Brain Language run more like a traditional scripting language like Perl Language or Python Language.
Now about the (kooky :) semantics of Brain Language objects. Delegation in Brain Language means something like "I don't understand this, will you do it for me?". So why does the prototype become the self object?
The first reason is that each object is supposed to work on it's own data, and is not supposed to know about the data in objects that it is the prototype of. Let's say that an object A has a property called Data. Let's say that this object is the prototype of another object B which also has a property called Data. Let's assume that a message make-it-so is sent to B, is not found, and is then found in A. I think that A's method make-it-so should work on it's own object's Data rather on B's data.
A second reason for having these semantics is that you can have native objects (like strings/chars/numbers) as prototypes. For (a not very useful) example:
object!prototype = "Hello World". object reverse println.
A third reason is that you can have different objects share the same prototypes properties (something like virtual inheritance in C++)
And finally about the meaning of subtype. In Brain Language there is a concept of types, like for example all strings are considered to be of string type. When you add a method to an object, that method will automatically be added to all objects of the same type. What the subtype message does is that it clones an object and at the same time it makes it to be of a new type. Think of it like creating a new species in the process of evolution :). The object will have all the properties and methods of the original object, but if you add a new method to it, it will be added only to itself and any objects that were cloned from it (that is objects that are the same type with it).
I hope that this information was useful. -- Manuel Tomis
Aha! I did read that rule about the prototype becoming the receiver properly. From my experience with Newton Script, that seems terribly limiting. The fact that I could override data without overriding methods was very helpful. However, if I'm understanding subtypes correctly (I haven't experienced anything like it before), it looks like you can get the same sort of functionality at the memory expense of a clone. That wouldn't have been acceptable in the low-memory environment of the Newton, but it is probably fine on a desktop. The subtype sounds an awful lot like an instance of a class, but I thought this was a prototypical language :-) -- Greg Vaughn
:-) Well, every object in Brain (as Manuel has told me) has two parts: a data space and a methods space (think of boxes). Every object of a given type shares the methods box, while maintaining a private data box. Cloning a new object of that type simply creates a new data box... It's like if we had this:
[data|methods] == [data| *p], p--> [methods]
So ob1 = [data1| *p], ob2 = [data2| *p], etc...
On the other hand, if we subtype from an object, the new object had a methods box of its own, and it's effectively separated from it's parent object.
If may be like inheritance in class-driven languages, but if o2 = o1 subtype, you can after this add methods and properties to both objects. They will share a common ground, but their behavior will be pretty different (so that could mean there's a virtual parent object would be there floating around... but there is not :-)
By the way, it's all down to using the appropriate idioms for the language. You can do it class-like by maintaining an immutable object as a template or you can create a dynamic world were objects just evolve as needed. Extreme Programming would probably be a good methodology for this, as Refactor Mercilessly and Do The Simplest Thing That Could Possibly Work sound pretty much like the above... I don't know many idioms myself (still learning). Manuel has already developed some of them, and I am sure many more are still buried in the language. I hope they'll pop up as the language evolves and our understanding of it grows. -- David De Lis
See original on c2.com