The use of ">>" in Pharo/Smalltalk - smalltalk

I am implementing futures in Pharo. I came across this website http://onsmalltalk.com/smalltalk-concurrency-playing-with-futures. I am following this example and trying to replicate it on Pharo. However, I get to this point the last step and I have no idea what ">>" means: This symbol is not also included as part of Smalltalk syntax in http://rigaux.org/language-study/syntax-across-languages-per-language/Smalltalk.html.
BlockClosure>>future
^ SFuture new value: self fixTemps
I can see future is not a variable or a method implemented by BlockClosure. What should I do with this part of the code to make the promises/futures work as indicated at http://onsmalltalk.com/smalltalk-concurrency-playing-with-futures? I cannot add it on the Playground or as a method to my Promise class as it is, or am I missing something?
After adding the future method to BlockClosure, this is the code I try on the PlayGround.
value1 := [200 timesRepeat:[Transcript show: '.']. 6] future.
value2 := [200 timesRepeat:[Transcript show: '+']. 6] future.
Transcript show: 'other work'.
Transcript show: (value1 + value2).
Date today
The transcript displays the below error instead of the expected value of 12.
UndefinedObject>>DoIt (value1 is Undeclared)
UndefinedObject>>DoIt (value2 is Undeclared)

For some reason that it would be nice to learn, there is a traditional notation in Smalltalk to refer to the method with selector, say, m in class C which is C>>m. For example, BlockClosure>>future denotes the method of BlockClosure with selector #future. Interestingly enough, the expression is not an evaluable Smalltalk one, meaning, it is not a Smalltalk expression. It is just a succinct way of saying, "what comes below is the source code of method m in class C". Just that.
In Smalltalk, however, methods are objects too. In fact, they are instances of CompiledMethod. This means that they can be retrieved by sending a message. In this case, the message is methodAt:. The receiver of the message is the class which implements the method and the argument is the selector (respectively, C and #m, or BlockClosure and #future in your example).
Most dialects, therefore, implement a synonym of methodAt: named >>. This is easily done in this way:
>> aSymbol
^self methodAt: aSymbol
This puts the Smalltalk syntax much closer to the traditional notation because now BlockClosure>>future looks like the expression that would send the message >> to BlockClosure with argument future. However, future is not a Symbol unless we prepend it with #, namely #future. So, if we prefix the selector with the # sign, we get the literal Symbol #future, which is a valid Smalltalk object. Now the expression
BlockClosure >> #future
becomes a message, and its result after evaluating it, the CompiledMethod with selector #future in the class BlockClosure.
In sum, BlockClosure>>future is a notation, not a valid Smalltalk expression. However, by tweaking it to be BlockClosure >> #future, it becomes an evaluable expression of the language that returns the method the notation referred to.

Related

Access message documentation in Smalltalk

When you define a class in Smalltalk, you can acces the documentation comment like this:
st> Integer comment
'I am the abstract integer class of the GNU Smalltalk system. My
subclasses'' instances can represent signed integers of various
sizes (a subclass is picked according to the size), with varying
efficiency.'
But maybe, I'm to newbie to Smalltalk, but I cannot find how to access to the method/message documentation. i.e.
Let's consider the following method
SomeClass >> #msg: arg
"This is a comment"
^self doThisTo: arg
It is tempting to implement a service for extracting comments such as:
commentOf: aCompiledMethod
^method sourceCode readStream upTo: $"; upTo: $"
In fact, in the example above, we would get the string 'This is a comment'. The problem, however, is that the double quote character is not always a comment delimiter. Consider for instance the following method
String >> #doubleQuoted
^'"', self , '"'
if we tried to use our method #commentOf: above for extracting comments from this method, we would get
' , self, '
which doesn't make any sense.
This means that our parsing should be less naïve. Therefore, the question that we should ask ourselves is whether it is not better to use the Smalltalk Parser of our environment. I don't know how to do this in gnu-smalltalk, so let me show here (as an example) how could we proceed in Pharo:
aCompiledMethod ast comments
The #ast message answers with the Abstract Syntactic Tree of the the method, also known as the Parse Tree, which exposes the syntactic structure of the method's source code. In particular, it detects all comments in the form of CommentNode objects, and that is why the #comments method simply consists in enumerating all parse nodes while collecting the comments.

Smalltalk: How primitives are implemented?

I know that everything is an object and you send messages to objects in Smalltalk to do almost everything.
Now how can we implement an object (memory representation and basic operations) to represent a primitive data type? For example how + for integers is implemented?
I looked at the source code for Smalltalk and found this in Smallint.st. Can someone explain this piece of code?
+ arg [
"Sum the receiver and arg and answer another Number"
<category: 'built ins'>
<primitive: VMpr_SmallInteger_plus>
^self generality == arg generality
ifFalse: [self retrySumCoercing: arg]
ifTrue: [(LargeInteger fromInteger: self) + (LargeInteger fromInteger: arg)]
]
Here is the link of above code: https://github.com/gnu-smalltalk/smalltalk/blob/62dab58e5231909c7286f1e61e26c9f503b2b3df/kernel/SmallInt.st
Conceptually speaking primitive methods are pieces of behavior (routines) implemented by the Virtual Machine (VM), not by regular Smalltalk code.
When the Smalltalk compiler finds the statement <primitive: ...> it interprets this as an special type of method whose argument (in your case VMpr_SmallInteger_plus) indicates the integer index of the target routine within the VM.
In this sense a primitive is a global routine not bound to the MethodDictionary of any particular class. The primitive logic is intended for a receiver and arguments of certain classes and that's why it must check that the receiver and the arguments (if any) conform its requirements. If not, the primitive fails and in that case the control flows to the Smalltalk code that follows the <primitive: ...> statement. Otherwise the primitive succeeds and the Smalltalk code below is not executed. Note also that the compiler will not allow for any Smalltalk code other than temporary declaration occurring above the <primitive:...> sentence.
In your example, if the argument arg is not of the expected class (presumably a SmallInteger) the routine gives up trying to sum it to the receiver and delegates the resolution of the operation to the Smalltalk code.
If the argument happens to be a SmallInteger, the primitive will compute the result (using the routine held in the VM) and answer with it.
I haven't seen the code of this primitive but it could also happen that the primitive fails if the result of the sum does not fit in a SmallInteger, in which case both the receiver and the argument would be cast to LargeIntegers and the addition would take place in the #+ method of the appropriate class (LargePositiveInteger or LargeNegativeInteger).
The other branch of the Smalltalk code allows for the implementation of a polymorphic sum between a SmallInteger and any other type of object. For instance this part of the Smalltalk code would take place if you evaluate 3 + 4.0 because in this case the argument is a Float. Something similar happens if you evaluate 3 + (4 / 3), etc.

Smalltalk type system

I'm very new to Smalltalk and would like to understand a few things and confirm others (in order to see if I'm getting the idea or not):
1) In Smalltalk variables are untyped?
2) The only "type check" in Smalltalk occurs when a message is sent and the inheritance hierarchy is climbed up in order to bind the message to a method? And in case the class Object is reached it throws a run time error because the method doesn't exist?
3) There are no coercions because there are no types...?
4) Is it possible to overload methods or operators?
5) Is there some kind of Genericity? I mean, parametric polymorphism?
6) Is there some kind of compatibility/equivalence check for arguments when a message is sent? or when a variable is assigned?
Most questions probably have very short answers (If I'm in the right direction).
1) Variables have no declared types. They are all implicitly references to objects. The objects know what kind they are.
2) There is no implicit type check but you can do explicit checks if you like. Check out the methods isMemberOf: and isKindOf:.
3) Correct. There is no concept of coercion.
4) Operators are just messages. Any object can implement any method so, yes it has overloading.
5) Smalltalk is the ultimate in generic. Variables and collections can contain any object. Languages that have "generics" make the variables and collections more specific. Go figure. Polymorphism is based on the class of the receiver. To do multiple polymorphism use double dispatching.
6) There are no implicit checks. You can add your own explicit checks as needed.
Answer 3) you can change the type of an object using messages like #changeClassTo:, #changeClassToThatOf:, and #adoptInstance:. There are, of course caveats on what can be converted to what. See the method comments.
For the sake of completion, an example from the Squeak image:
Integer>>+ aNumber
"Refer to the comment in Number + "
aNumber isInteger ifTrue:
[self negative == aNumber negative
ifTrue: [^ (self digitAdd: aNumber) normalize]
ifFalse: [^ self digitSubtract: aNumber]].
aNumber isFraction ifTrue:
[^Fraction numerator: self * aNumber denominator + aNumber numerator denominator: aNumber denominator].
^ aNumber adaptToInteger: self andSend: #+
This shows:
that classes work as some kind of 'practical typing', effectively differentiating things that can be summed (see below).
a case of explicitly checking for Type/Class. Of course, if the parameter is not an Integer or Fraction, and does_not_understand #adaptToInteger:andSend:, it will raise a DNU (doesNotUnderstand see below).
some kind of 'coercion' going on, but not implicitly. The last line:
^aNumber adaptToInteger: self andSend: #+
asks the argument to the method to do the appropriate thing to add himself to an integer. This can involve asking the original receiver to return, say, a version of himself as a Float.
(doesn't really show, but insinuates) that #+ is defined in more than one class. Operators are defined as regular methods, they're called binary methods. The difference is some Smalltalk dialects limit them up to two chars length, and their precedence.
an example of dispatching on the type of the receiver and the argument. It uses double dispatch (see 3).
an explicit check where it's needed. Object can be seen as having types (classes), but variables are not. They just hold references to any object, as Smalltalk is dynamically typed.
This also shows that much of Smalltalk is implemented in Smalltalk itself, so the image is always a good place to look for this kind of things.
About DNU errors, they are actually a bit more involved:
When the search reaches the top class in the inheritance chain (presumably ProtoObject) and the method is not found, a #doesNotUndertand: message is sent to the object, with the message not understood as parameter) in case it wants to handle the miss. If #doesNotUnderstand: is not implemented, the lookup once again climbs up to Object, where its implementation is to throw an error.
Note: I'm not sure about the equivalence between Classes and Types, so I tried to be careful about that point.

Is it really all about message passing in smalltalk

I'm new to smalltalk and I'm impressed with the fact that there are only just 6 keywords in the language (self, super, true, false, nil & thisContext), and how pure it is in having almost everything as message passing, eg. looping using whileTrue, if/else using ifTrue, etc ... which are way different from what I'm used to in other languages.
Yet, there are cases where I just cannot make sense of how message passing really fit in, these include:
the assignment operator :=
the cascading operator ;
the period operator .
the way to create a set #( ... )
These aren't message passing, right?
As you've discovered, there's still some actual Smalltalk syntax. Block construction, literal strings/symbols/comments, local variable declaration (|...|), and returning (^) are a few things you didn't mention which are also syntax.
Some extensions (e.g. #(...), which typically creates an Array, not a set) are certainly expressible otherwise, for example #(1 2 3) is equivalent to Array with: 1 with: 2 with: 3; they're just there to make the code easier to read and write.
One thing that might help clarify : self, super, true, false, nil & thisContext are data primitives, rather than keywords.
They are the only 6 data primitives. These 6 are also known as pseudo-variables. Absolutely every other thing is an instance of Class Object or its subclasses.
There are very few pre-defined keywords in Smalltalk. They can be written in a very condensed form.
A famous example is Smalltalk Syntax on a Postcard (link)
exampleWithNumber: x
| y |
true & false not & (nil isNil) ifFalse: [self halt].
y := self size + super size.
#($a #a "a" 1 1.0)
do: [ :each |
Transcript show: (each class name);
show: ' '].
^x < y
Here's the comment for this method - which is larger than the method itself:
"A method that illustrates every part of Smalltalk method syntax
except primitives. It has unary, binary, and keyboard messages,
declares arguments and temporaries, accesses a global variable
(but not an instance variable), uses literals (array, character,
symbol, string, integer, float), uses the pseudo variables
true, false, nil, self, and super, and has sequence, assignment,
return and cascade. It has both zero argument and one argument blocks."

Smalltalk exotic features

Smalltalk syntax (and features) can be found pretty exotic (and even disturbing) when you come from a more C-like syntax world. I found myself losing time with some
I would be interested in learning knowing what you found really exotic compared to more classic/mainstream languages and that you think helps to understand the language.
For example, evaluation with logic operators :
(object1 = object2) & (object3 = object4) : this will evaluate the whole expression, even if the left part is false, the rest will be evaluated.
(object1 = object2) and: [object3 = object4] : this will evaluate the left part, and only will evaluate the right part if the first is true.
Everything is an object, and everything above the VM's available for inspection and modification. (Primitives are part of the VM, conceptually at least.) Even your call stack's available (thisContext) - Seaside implemented continuations back in the day by simply swizzling down the call stack into a stream, and restoring it (returning to the continuation) by simply reading out activation frames from that stream!
You can construct a selector from a string and turn it into a Symbol and send it as a message: self perform: 'this', 'That' will do the same thing as self thisThat. (But don't do this, for the same reasons you should avoid eval in both Lisps and PHP: very hard to debug!)
Message passing: it's not method invocation!
#become: is probably a bit of a shock to anyone who hasn't seen it before. (tl;dr a wholesale swapping of two object pointers - all references to B now point to A, and all references to A now point to B)
Primitves
someMethod
<primitive 14122 wtf>
"fail and execute the following"
[self] inlineCopyInject: [:t1 | self].
My first wrestling session with Smalltalk was the metaclass implementation.
Consider this:
What is the class of 'This is a string'? Well, something like String.
What is the class of String? String class. Note: this is a class, but it has no name, it just prints itself as 'String class'.
What is the class of String class? Metaclass. Note: this is a named class.
What is the class of Metaclass? As you might expect (or not) this is Metaclass class. Of which, again as you might expect, the class is Metaclass again.
This is the first circularity. Another one which I found rather esoteric at first (of course, now I eat metaclasses for breakfast) is the next one:
What is the superclass of String? Object (eventually, different implementations of Smalltalk have different class hierarchies of these basic classes).
What is the superclass of Object? nil. Now this is an interesting answer in Smalltalk, because it actually is an object! nil class answers UndefinedObject. Of which the superclass is ... Object.
Navigating through the superclass and instance of relations was a real rollercoster ride for me in those days...
How about selective breakpointing (which I actually use at times):
foo
thisContext sender selector == #bar ifTrue:[ self halt ].
...
will debug itself, but only if called from bar. Useful, if foo is called for from zillion other places and a regular breakpoint hits too often.
I've always been fond of the Smalltalk quine:
quine
^thisContext method getSource
(Pharo version.)