Traps and pitfalls for polyglot developers

From Cuis CookBook
Jump to navigation Jump to search

As a person who know more than one programming language you will certainly fall more then once on these.

  • In vivo dev. Most of the time you will be modifying a running program. This is the extreme opposite of what you do in C and Perl. It is possible to achieve something similar if you run at least 2 threads in Ruby and Python. Still, in Smalltalk this is the rule, not the exception. This spurs from the fact that Smalltalk was born to be an OS, a developer platform, not a programming language.
  • My language is my world. Take this Wittengstein quote very seriously. Smalltalk is similar to Lisp. It is a world in itself where Strings, Numbers, Windows etc. are fully recognized citizens. Your task is to extend this world in such a way that new beings will be recognized, and that is totally on your application. You can define Point2D, Line2D, etc. and you will end up building a 2D Cad program. You define User, Account, Balance, etc. and you may end up writing a bank application.
  • In your world you are God. Like Ruby and Lisp and differently from Python, if you want to extend or modify the predefined behavior of, say, the String object, you are allowed to do it: fast and easy. You can do the most crazy things to the base system, redefine what = means for Strings ? You can! But beware, the base system can stop working if you act unwisely.
  • Be the Evaluator. In the languages belonging to the C tradition, as Python and at the peak in Perl, you usually write some code according to some template (i.e. you peek at a snippet from a book or a Web page) then you adapt it, when it looks good, you try it out and hope the interpreter/compiler will not complain and understand what you mean. Forget about it! Smalltalk it is not like that. As in Lisp, when you type in your code you know exactly how the Smalltalk core is going to read it, the rules are trivial.
  • 2 + 3 * 4 here is 20 not 14. Parsing rules here are simpler than algebra, same kind of messages are executed strictly left to right. + and * are what we call binary messages, they have no special treatment respect to other bianry messages as @ or ,, & etc.
  • The golden rule of parsing. You have a Smalltalk statement and it is all about sending messages to objects. Some messages get executed before the other according to very simple rules.
    • There are 3 kind of messages: unary, binary, keyword.
    • first are executed unary messages,
    • then binary messages,
    • finally keyword messages.
    • Messages of the same kind are executed strictly left to right.
    • You can change the evaluation order putting (...) around a part of code. What is inside a (...) gets executed with precedence higher than unary messages.
  • Every statement must end with . , it is compulsory as ; in C.
  • = is a message for equality testig, NOT assignment. for assignment we use _.
  • == is a message for identity testing not equality. That is it does not check if two objects are equal, it checks if they are the same.
  • functions. You may be used to work in an imperative way so the second thing you will try to do is define your own function double to double a number. Stop it. Smalltalk does not work like that. You need to create an object who understands the message double:.
  • Whitespaces are insignificant. You can put SPACE, TAB, NEWLINE wherever you wish, this does not change your code meaning, only its readability.
  • There is only one syntax for comments: " .... ". Nested comments are not recognized.
  • If you need to disable big chunks of code don't comment it, use disableCode:.
  • There is only one syntax for strings literals: ' .... '.
    • There aren't special characters in Smalltalk strings, \n and the like of C tradition have no special meaning.
    • You can go newline when you are typing in a string.
    • If you need to type a ' character inside a string write it like this ''.
  • Short circuits. and: and the like, do short circuit but the way to achieve it is this A and: [B].
  • There is no switch or case statement. See LaLonde[1990] vol.1, pg.207 for an implementation.
  • Wanna know all the ways you can type in objects? Don't try&pray, see Help -> Terse Guide -> Literals.
  • Case matters. Example, a Class vairable first letter must be upcase.
  • Smalltalk is not Emacs nor Vim. It is very practical if you have available a large screen. I find useful to have always 3 Browsers open and 1 Workspace. With a 15'' MacBook I am at the limit of usability but still I can work well.
  • Smalltalk has its own Scheduler and Processes because it was created to run without an operating system.
  • If you define your own equality concept on any Class, redefining method =, then you need to define also a congruent hash function. See "Smalltalk by example pg.56" for more info..
  • In general there is no commutativity of operators, that is a * b is in general different from b * a and the reason for this is that the first message STAR is sent to object 'a', the second message STAR sent to obejct 'b'. Nobody ensures the two object classes have the same implementation for the method START, if they have an implementation at all. For example, try this:
dur _ Duration seconds: 2.
dur * 2 . 
2 * dur. 

Fail Examples

  • assignment It seems and an assignment, but ... look it twice.
oc = OrderedCollection new. 
oc add: 1. 
  • 1 char makes the bug. Once I wrote DateAndTime new instead of DateAndTime now, it took me a while to find it. Observe this case is nasty because: 1) both message names do exist 2) they both produce the same kind of output.
  • forget an accessor bringing a method call loop, system hangs. I defined a Class FooBar which had an instance variable name. For some reason I forgot to write the read accessor for that variable. Then I defined a custom print representation for FooBar as
printOn: aStream
        aStream nextPutAll: self class name;
                nextPut: $-; nextPutAll: self name.  

Then I tried to run FooBar new => CRASH. It took me a few hours to understand it but the explanation is, when I call printOn you see I call self name. But since I forgot to define the method FooBar#name, what was called is Objetc#name and that, after a few intermediate calls lands into calling: printOn ! (Exercise. use the Browser and check this is true) So, we can never exit the printOn method.