On the Uniqueness of Spin
SRLM
Posts: 5,045
I'm in the process of learning the Spin Language, and some things have struck me as odd. Mostly, it's the weird formatting that was choosen and the odd operators that are used, such as <#=, |, :, dira/outa, :=, ~, ~~, >>=. Also, the almost complete lack of closure operators (like {},[noparse]/noparse, and ()) is very confusing, especially for the fact that some things have them (like waitcnt) and others don't (like methods). From a background in traditional computer language (Java), I find the Spin syntax to be very different. Any reason why Parallax choose such? I read somewhere that the language was custom built, but why deviate so far from the norm?
Comments
Anyway, it's quite easy to understand and totally **FREE**, so what's to complain about?!
Be careful of the term "traditional computer language". Java is relatively recent as these things go. C and Pascal are the roots of current programming languages in that their development goes back to the '60s and '70s and they're still in widespread use today. Smalltalk is not in widespread use, but is still used significantly, has current, very sophisticated implementations on a variety of platforms and is the primary example of object oriented languages.
I had some problems at the beginning coming from pascal/delphi
I was used to type ";" at the end of each line of code. But I learned quick to leave it out.
The reasons are simply effectiveness and readability !
It is simply faster to indent two columms instead of taking two hands to type charcters like "{" "}"
whereever it is possible to leave out things without making it unclear what is meant characters are leaved out
Methods HAVE brackets if the have parameters. If they don't have parameters why wasting time to type "()" ???
Using indenting instead of opening/closing brackets forces everybody to format the code in a standardized and readable stile
I have never seen any other computer-language that is so effective to write
best regards
Stefan
More code on the screen at once == more efficient debugging.
-Phil
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
'Still some PropSTICK Kit bare PCBs left!
It's interesting to note that even in the quirky example·presented, the braced code is still not as wide as the indented code.
In a long program, these opportunites are more the exception than the rule, however.
Well, yeah, if you going to add fluff like "(replace this text with your code)" to it to make it wider!
-Phil
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
'Still some PropSTICK Kit bare PCBs left!
I learnt Fortran in 1970.
Took a little to get used to no endif's etc, but I always liked indented code anyway.
With the new compilers on the scene, it should be possible to persuade the writers for options (it has already been discussed). But, I don't take anything away from Chip for creating such marvellous stuff. :-)
Post Edited (Cluso99) : 10/16/2008 7:18:39 AM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chip Gracey
Parallax, Inc.
I think it would be initially initially to teach indented spin to beginners than using the endif's etc. I believe it is more readable. For those of us who are used to the endif type language, it's probably harder for us. Can't have it both ways without a compiler option. What are your thoughts?
As for the mathematics of ==, =< etc... Some of the time I just have to check but this is probably isn't helped by the fact I have done more VB that C, and far more various assemblers than anything.
(tougue in cheek) - anyway why are you here - you should be finishing our PropII (remember, no rest for the wicked·· )
For the record: checked out the Xmos assembler briefly - I don't like the assembler · The Prop's is so easy and regular - a couple of minor traps but the new compilers are addressing most of these with warnings.
Post Edited (Cluso99) : 10/16/2008 10:57:58 AM GMT
Java does not even run on traditional computers.
I have a lot of personal biases regarding programming languages, as do many people I guess, things like formatting, funny looking operators, operator precedence, lazy evaluation, type checking, etc etc. But in general I think spin pretty much hits the mark for it's intended use and audience.
Together with the Propeller Tool and the way the Prop works it's very easy for the novice to get something working quickly without having to learn a lot of junk about header files, linkers, locators, libraries and so on. At the same time being powerful enough to handle some serious tasks unlike old Basic dialects.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
I don't like =< and => as comparisons but I can understand why they are as they are, although I'd personally have sacrificed purity and consistency of design elsewhere to allow <= and >=.
The one major thing I think Chip missed out on, and I don't know why, is the ability to support nested methods and variables.
Some of the tokens for operators are a little bizarre ( || and ^^ ) and strike me as desperation or forced choice as available symbols ran out, but still logically explainable, although why named "and", "or" and "not" rather than multi-symbol tokens ( &&, || etc ) does show some inconsistency.
The most annoying issue I find is that a method parameter name cannot be the same as a VAR variable name. To me that's a compiler design flaw, implementation error or bug in handling name scope not necessarily a language design failure ( although it could be ).
I don't like the way objects have been implemented in Spin; they are not objects in the sense of OOP and in terms of code encapsulation they are too restrictive. Having no #include and the lack of callbacks and function pointers presents major difficulties in source code division and encapsulation.
As to "why deviate from the norm" I think that's three fold; because one can, because there is the freedom to try to do things better than other languages do, and because it better suits a target processor architecture. For Spin there is a very clear relationship between the language, the bytecode and the interpreter. It is hard to tell what drove what but it is a pretty solid and impressive combination.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Chip Gracey
Parallax, Inc.
Post Edited (Chip Gracey (Parallax)) : 10/16/2008 5:12:49 PM GMT
Chip Gracey
Parallax, Inc.
Nested methods as with Pascal's Procedures, a contrived example ...
So each Print would only be in scope and callable for the method it is defined within. Nested variables would be VAR specific to the method but unnecessary as that's what | and a local variables list gives.
Is there any ambiguity ? I'd say simple scope rules apply as per Pascal. The case I was thinking of ...
Within "Print", references to 'ch' would be the local parameter not the global variable. In both cases 'ch' is meaningful to me as 'holds a character' even though one is global, the other is local.
Particular times I've run into a problem is in cutting and pasting from one program or object to another and finding a conflict which wouldn't occur if this was allowed. The awkward thing is it's no good just changing the parameter name or local variable, every use of the variable has to be identified or it wrongly then refers to the global variable of the same name.
Spin definitely lies on its own waaaay out there evolutionary branch, like a platypus compared to regular mammals. (Chip, can we make the platypus be the mascot for Spin?) However, its design philosophy is consistent within itself even as much as it is different than other languages, and it does a few things remarkably well:
1. It packs a lot into a little screen real estate without being "dense". (Yes in C-like languages you can put all the curly brace {} junk on one line to shrink it vertically, but even if it doesn't end up wide horizontally it's still dense in terms of how many symbols get packed in that space. Spin manages to be *compact* without being *dense*.)
2. It integrates very well with assembly.
3. It's good for table driven algorithms. For instance, I can express a table in a DAT section in very compact form, and access it directly in Spin.
4. Uses memory efficiently.
5. Allows you to easily combine components written by other people.
Basically what I think Spin is, is that Parallax took all these years of experience making Basic Stamps and distilled exactly what it is that you want to do with a microcontroller, and wrote a language that makes it easy to do those things, even if the language breaks with mainstream PC language influences. Note, however, that there's some undefinable "feel" to the language that will feel familiar if you've been using Basic Stamp PBasic a long time. So it's not like there is no history at all to it.
In all my years of programming in many languages and in many application domains I've never felt the need for a nested procedure and never come across any code that uses them.
Is there some compelling reason to have them that I have missed all these years?
In an object oriented language were we can have "private" methods can we live without nested procedures?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
1) Spin is more effecient in screen space without extra operators
2) Spin is optimized for uC use
Topic 1) Screen space is a valuable commodity, true, but why should we have to sacrifice readability for visibility? If the code is easy to understand, and uses english terms (not >#=) then there is no real need to save screen space. You understand everything that is happening simplyby reading the phrase out loud. I'm not saying that the Spin operators don't have an English equivalent, it's just that they are less intuitive. As for {}, [noparse]/noparse, and (): these you often have a choice of spacing them wherever your want, and lend sense of finality to the end of a code block. With indenation, you may simply cut and paste something wrongly, and it's a little too far over. In addition, the compiler can easily tell you when you've left out a closing brace, and a good IDE can highlight them for you. But how does it know if you've indented the correct bits of code? That's a logical error, and not a syntax. The more logical errors that can be converted to syntax errors, the easier it is to debug.
Topic 2) Although some things are required for the uC, why can't a compiler optimize? It can cut out the variable names and replace them with the pointers needed. To me, that seems to be the purpose of the compiler: to do all the little housekeeping tasks so that programmers can focus on the higher level problems. These tasks should include optimization of memory and run time speed.
Perhaps I should not have used "traditional programming languages." Instead I probably should have said "Popular" programming languages. Often, it's nice to break from the crowd, but when you use a language, certain things are expected. udn't just things rearrange like feel is best and hope understand ppl it.
Anyway, I don't have any hard feelings against the Propeller, more, it's a new student from a older (popular?) language coming to terms with Spin.
How does a C compiler know if you've put a closing brace in the right spot? Same diff.
Learning a new computer language has many parallels to learning a foreign natural language. There are similarities to what you already know, as well as differences. The differences don't make the foreign language "wrong". After all, native speakers of a "foreign" language may consider English odd, for similar reasons. With any language, once you gain fluency, the weirdness apparent upon first exposure disappears. This is as much true of Spin as it is of any othger language. Expanding one's comfort zone is just part of the learning process.
-Phil
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
'Still some PropSTICK Kit bare PCBs left!
The advantage for having different name spaces for local variables, even constants (like in Pascal) or methods is primarily (as hippy implied) that code is sometimes lifted from other sources and may have variables (usually simple ones like single letters) that accidentally match other identifiers in the program (even global ones). By having local namespaces, there's a formal solution for this potential ambiguity. If you also include nested methods, this makes even more sense since the outer method is its "own world" and anything inside it can't conflict with the rest of the program (unless you forget to declare a local variable and mistakenly reference a global one).
If #include is implemented, this local naming and nested method declarations becomes even more important. One might argue that some of this should be done with objects, but, for some simple cases, particularly where global constants and variables are used, using an object would create more complexity than a simple #include of one or more methods, possibly with internal method, even constant declarations (like Pascal).
One advantage is for what could be called inline-objects ( in the Spin sense of objects ).
Mike perhaps captures it best in terms of "namespace", what I called "scope". Each being its "own world" is a good way of viewing it.
I think it's another of those things which people either see a need for or don't, are familiar with the idea or not. I learned programming with Pascal before C came along so this concept of nesting and scope is second nature to me. I can also live without it, and have done in most other languages I've used.
Still I've never seen this done in working code, only in language tutorials and examples. Chip has got along just fine without ever hearing of them. Many languages, notably C, C++ seem to have dropped nested methods on purpose.
Given an object oriented language is it not sufficient to use private methods instead of nested?. At least the scope of the method is contained to the class now. Even in good old C one can get much of this scoping using just static functions.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
Had C not become dominant but the Algol, Pascal, Modula, Ada, Delphi family taken dominance I think they'd be more commonly seen. Interesting to note that GCC can support nested methods for C.
I can understand why they were dropped; it complicates the compiler and the interpreter or run-time, particularly as code has to deal with where variables local to the method which wraps it are on the stack as that varies on which method call route takes execution into a particular nested routine.
One of the virtues of the current object structure is that you can understand it by looking at a single example... without any comments. You don't have to read anything... it is immediately obvious. This means that you can understand a lot about an application, without any study...
This encourages the inquiring mind to look at Spin... it is like a welcome sign.
I hate full blown oop structures because they requires me to remember and understand relationships between objects... which places demands on me that I simply don't like... some brains take to it like a duck to water... not mine.
Spin objects all look the same to me... they all get called top down, I just need to remember "what is on top of what." And if I forget this... I just need to figure it out again... which takes a few seconds.
Indentation... there are so many bracketed and hyphenated languages around and so many repeat structures syntaxes that it is hard to keep them straight... if you have to flip flop between different languages... Spins indentation is an absolute joy.... you just have to remember the syntax for 1 line... your program flow changes when you change the indentation... what could be easier?
I constantly sit too far back from my monitor... the advantages of indentation over brackets becomes immediately obvious, when you can just barely see what you are looking at[noparse]:)[/noparse]
when it comes to operators... I agree that there is a bit of a learning curve that is uncomfortable... operators are so ingrained in every language that we use them almost without thinking about them... it is where I habitually screw up my code... until I wake up and think about what I am doing. If I haven't programmed in a week or two, I still find myself using the cheat sheets from time to time.
Given the lack of an urgent reason to have nested procedures I don't think Chip should lose any sleep over them. Especially if they are going to over complicate the compiler.
After all this time I didn't know GCC could support nested procedures in C. Perhaps it's because GCC also is used as the back end for numerous other languages e.g. ADA. Time for some experiments.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.