Category:Smalltalk: Difference between revisions

 
(10 intermediate revisions by the same user not shown)
Line 357:
 
====Class Variables (Statics)====
These are visible inside a class and shared with all of its subclasses. They have the lifetime of the defining class. The same binding is shared with all subclasses, thus the value is seen in the defining class and all of its subclasses. Typically, these are used for constants. Class variables are defined in the class definition message when the class is instantiated or redefined by setters to the class.
 
====Instance Variables====
These are the slots where the private state of an object is held. Instances have the same structure (layout), but each has its own values. The instance layout is defined in the class definition message when the class is instantiated or redefined by setters to the class.
Line 454 ⟶ 455:
</lang>
Classes can be anonymous, in most systems, you can "Class new new" to create a new anonymous class and an instance of it (but be aware, that the class should contain enough state to properly specify their instance's layout, so usually more info is needed (number and names of instance variables, inheritance etc.). Otherwise some tools (Inspector) may fail to reflect on it.
 
Be reminded that classes are themself objects and therefore instances of some class; in this case a so called <I>Metaclass</I>. They follow the same inheritance and message send semantics as ordinary objects. Thus, you can define class-side methods and redefine them in subclasses. For example, you can redefine the "new" method to implement caches, singletons or any other special feature. Often multiple instance creation methods (with different parameters) are provided by a class.
 
The class also provides reflection protocol, eg. to retrieve all of its instances, to ask for the names of private slots, to ask for the set of supported messages etc.
 
=== Control Structures ===
As mentioned above, these are defined as messages and their implementation is found in the corresponding receiver classes. For illustration, here is how conditional execution ('if-then-else')s is implemented in Smalltalkclass. There are two boolean objects named "true" and "false", which are singletons of corresponding classes named "True" and "False" (both inherit from Boolean, which inherits from Object). It is essential, that these are singletons, and that typical relational operators like "<", ">" etc. return one of those two.
 
<br>Then, in the True class, define:
For illustration, here is how conditional execution ('if-then-else') is implemented in Smalltalk. There are two boolean objects named "true" and "false", which are singletons of corresponding classes named "True" and "False" (both inherit from Boolean, which inherits from Object). It is essential, that these are singletons, and that typical relational operators like "<", ">" etc. return one of those two.
 
<br>Then, in the True class, define:
<lang smalltalk>ifYouAreTrueThenDo: arg1 ifNotThenDo: arg2
^ arg1 value</lang>
Line 466 ⟶ 474:
<lang smalltalk>(a > 0) ifYouAreTrueThenDo:[ 'positive' printCR ] ifNotThenDo:[ 'negative' printCR ]</lang>
actually, because these two return the value of the block they evaluated, it can also be used for its value (in C, the ternary if expression), as in:
<lang smalltalk>(outcome := (a > 0) ifYouAreTrueThenDo:['positive'] ifNotThenDo:['negative'] ) printCR</lang>.
outcome printCR</lang>
Finally, by adding a self-returning "value" method to the Object class, we can also write:
<lang smalltalk>( (a > 0) ifYouAreTrueThenDo:'positive' ifNotThenDo:'negative' ) printCR</lang>
(knowing that the if "ifXX"-methods send <tt>"value"</tt> to the corresponding arg and return that)
 
In this style, all of Smalltalk's control structures, loops, enumeration, stream readers and event- theor exception handling constructs are built. And since every class is open for extension, you can easily add additional convenient control functions (which is one place, where dialects differ, so very often, one has to transport some of those when porting apps from one dialect to another).
 
The following is only a tiny subset - there are virtually hundreds or thousands of uses of blocks for control structures in the system.
Line 483 ⟶ 492:
[ loop code . condition expression ] whileTrue.
[ loop code ] doWhile:[ condition ].
[ loop code ] doUntil:[ condition ].
 
n timesRepeat:[ block to be looped over ] "n being an integer"
Line 498 ⟶ 508:
 
=== Return from a Block ===
it should be noted that a " ˆ " (return) inside a block will return from the enclosing method, NOT only from the block. And that this is an essential semantic property of the return (technically, it may be a long return from a deeply nested call hierarchy, possibly involving unwind actions).
 
This makes it possible to pass a block to eg. collections to enumerate elements up-to and until some condition is met. For example, if we need a helper method, which searches the first element in a dataset to some condition and evaluate an action on it, we can write:
Line 532 ⟶ 542:
 
<lang smalltalk>[ try block to be evaluated ] on:exception do:[:ex | handler code ]</lang>
where '<I>exception</I>' is an Exception class or Signal instance and the '<I>ex</I>' argument provides detail information (where and why) to the hander and also allows control of how to continue afterwards (proceed, return, restart, reject).
<br>The handler basically has the following options:
* ex return - return out of the try block
Line 572 ⟶ 582:
Some implementations support source-to-source compilation to C, JavaScript or Java. These may or may not show some limitations in the support for dynamic changes at execution time. Typically, the full dynamic bytecode is used for development, followed by a compilation phase for deployment/packaging.
 
All Smalltalks use and depend on garbage collection for automatic reclamation of unused objects, and most implementations use modern algorithms such as generation scavenging, incremental background mark&sweepcollectors, weak references and finalization support. Imprecise conservative collectors are typically not used. Reference counting was abandoned in the 70s.
 
As message send performance is critical in Smalltalk, highly tuned cache mechanisms have been invented and are used: inline caches, polymorph inline caches, dynamic recompilation based on receiver and/or argument types etc.
Line 629 ⟶ 639:
ifTrue:[1]
ifFalse:[ self * (self-1) factorial ]</lang>
(here '<I>self</I>' is the Integer receiver object, and " ˆ " returns a value from the message send).
 
To get the factorial value, we'd evaluate in a workspace:<lang>10 factorial</lang>
Line 640 ⟶ 650:
 
a) is somewhat inconvenient if the code example consists of multiple methods, possibly in multiple classes.
<br>b) comes with the additional trouble that fileIn formats are different (chunk file, vs. XML file, vs. Monticello, vs. GNU-ST etc.).
 
For example, for export/import, GNU-ST uses a ''private format'', (which has the advantage of not needing the chunk format's bangs and especially the ugly bang doubling inside code and the empty chunk at the end):
<lang smalltalk>Number extend [
my_factorial [
Anonymous user