210 likes | 221 Views
95.3002. Smalltalk on a Dime. Little Things. Java (or C++). Smalltalk. separator. 1+2; 1+3;. statement terminator/separator. 1+2. 1+3. terminator. 1+2. 1+3. Declaration. | a b |. No types. int a; boolean b;. //Hello /*Hello*/. "Hello". comments. characters. $a. 'a'.
E N D
95.3002 Smalltalk on a Dime
Little Things Java (or C++) Smalltalk separator 1+2; 1+3; statement terminator/separator 1+2. 1+3 terminator 1+2. 1+3. Declaration | a b | No types int a; boolean b; //Hello /*Hello*/ "Hello" comments characters $a 'a' 'I''ll go' strings "I\'ll go" Escape character as in C++ 2 single quotes concatenation "ab" + "cd" 'ab' , 'cd' collection1 , collection2 return statement return 10; ^10. a := b. assignment a = b; a +- b; No “operate and assign” operators
Little Things Java (or C++) Smalltalk (new String ("a")).intern () symbol (unique string) #a OR #'a' 'a' asSymbol Java #a asString Objects.equals (a, b) a = b equality (new String ("a")) = (new String ("a")) true 'a' copy = 'a' copy true #a = #a true #a = 'a' false a == b identity a == b 'a' copy = 'a' copy true (new String ("a")) == (new String ("a")) false 'a' copy == 'a' copy false (new String ("a")).intern () == (new String ("a")).intern () #a copy == #a true true Symbols can’t be copied
Little Things Smalltalk Java Boolean a = Boolean.True Boxes (objects) Does not exist a.booleanValue () true Integer a = Integer (2016) Does not exist a.intValue () 2016 a := 2016. Integers/booleans int a = 2016; a := true. boolean a = true; Ints and booleans are NOT objects(so you can’t store them in Object collections) Everything is an object
Little Things Java (or C++) Smalltalk a block C++ int plus (int a) {return a+1;} functions plus := [:a| a+1]. add := plus. Blocks are unnamed functions x.getA ().getB ().getC () method invocation x getAgetBgetC Dot is superfluous Parentheses too are superfluous Control Structures { } [ ] while (e) {x = 2*x;} [e] whileTrue: [x := 2*x] for (long v = 1; v < 11; v++) {…} 1 to: 10 do: [:v | …]
A Bit More About Blocks Smalltalk C++ a block C++ int plus (int a) {return a+1;} int (*add) (int a); add = plus; functions plus := [:a| a+1]. add := plus. Blocks are unnamed functions plus (10) => 11 (*add) (10) => 11 function/block invocation plus value: 10 => 11add value: 10 => 11 usage #(10 20) collect: add Can be passed as parameter (rare to see it) => #(11 21) #(10 20) collect: [:a | a – 1] Can, and usually do, inline => #(9 19) Can implement your own control structures (2 slides further)
Expression Syntax (This is everything) Method Name Highest Priority First unary a factorial factorial binary a + 1 + keyword a between: 1 and: 10 between:and: selectors receiver message a factorial between: a - b and: c negated + 1 No operator precedence; A+B*C Smalltalkers will write (A+B)*C instead Highest priority Medium priority Lowest priority (a factorial between: a - b and: c negated + 1) ifTrue: [a := b] Parentheses needed if more than 1 keyword message
Little Things Period versus semicolon in Smalltalk Sending Multiple Messages to the SAME Receiver a scan; parse; output. equivalent to a scan. a parse. a output. Motivated by english: “I can; therefore I do.” Java (or C++) Smalltalk Blocks is short for ‘CODE BLOCK’ Blocks instead of Scopes a block C++ while (a > b) { a = a+1;} blocks instead of scopes [a > b] whileTrue: [ a := a+1.] where blocks are objects
Little Things File prompters FileDialogpromptTitle: 'Grammar' Full path name or nil if cancelled Input files e.g., 'C:work\data.txt' File pathNameReadOnly: fileName Input File Stream Output File Stream File newFile: aString Input stream of characters ReadStream on: aString Input stream of objects in the collection ReadStream on: aCollection Streams aStream contents A string or a collection of objects aStream peek Next character or object (still there after) aStream next Next character or object removed aStreamatEnd true (nothing to peek at), false (there is) aStream close Needed for file streams
Little Things Printing Your Own Objects e.g., Banana printOn: aStreamaStream << ‘a Banana type '; << self type printOn: aStream << is defined in WriteStream << anObject anObject isCharacter ifTrue: [^self nextPut: anObject]. anObject isString ifTrue: [^self nextPutAll: anObject]. anObject printOn: self printString aString Uses your printOn: indirectly storeString aString Code that will recreate your object Fairly high level looping Iterate through the successive objects one by one #(hi 32 (5 6) 'hello') do: [:object | …]
Class Person • Class Person with name, friends • initialize name := #unknown. friends := OrderedCollection new. • friends • ^friends • add: friend • friends add: friend • friendsDo: aBlock • friends do: aBlock • friendsChainDo: aBlock • | all | • all := OrderedCollection new. all addAll: friends. • all do: [:person | aBlock value: person. all addAllIfIdenticalAbsent: person friends]. USAGE aPerson friendsDo: [:friend| Transcript cr; << friend] aPerson friendsChainDo: [:friend | Transcript cr; << friend] New control structures Collections can grow while you loop over them...
Big Things Since variables are not typed (but objects are), collections can contain ANYTHING #(2016 $a 'hello' #you and #between:and: #(1 2 3.0e0)) an integer a character a string symbols an array The Library is MODIFIABLE Add method #+ in String to perform concatenation The Compiler Can Be Invoked By Sending Messages Classes can be created with code
Collections: Creating and Initializing array := (Array new: 2) at: 1 put: 'hi'; at: 2 put: 'you'; yourself. orderedCollection := OrderedCollection new add: 'hi'; add: ‘you'; yourself. dictionary := Dictionary new at: 1 put: 'hi'; at: 'two' put: 'you'; yourself. Returns the receiver (the dictionary in this case). Without it, you get back 'you'.
Low Level Control Structures Block (because of square brackets) [expression] whileTrue: [body] expression ifTrue: [body] Blocks with no parameters 1 to: 10 do: [:index | body] 10 to: 1 by: -1 do: [:index | body] (1 to: 10) do: [:index | body] Blocks with 1 parameter (the loop variable) This is an interval object, useful for collecting
Higher Level Control Structures #(10 20 30) do: [:item | Transcript space; << item] aDictionarydo: [:value | …] aDictionarykeysDo: [:key | …] aDictionarykeysAndValuesDo: [:key :value | …]
A Bit More About Collections #(10 20 30) collect: [:x | x+1] #(11 21 31) #(1 2 3) select: [:x | x odd] #(1 3) #(1 2 3) collect: [:x | x+10] when:[:x | x odd] #(11 13) • people asSortedCollection: [:x :y | • "Return true if x and y in order, false if not" • x parents size > y parents size or: [ • x parents size = y parents size and: [ • x children size >= y children size]]] • Above sorts by decreasing parent size and when equal, by decreasing children size equivalent to C++’s || and &&
There’s also groupsDo: which other Smalltalk’s Don’t have Plural version (many groups) groupsDo: aBlock " #((1) (10) (100)) groupsDo: [:a | Transcript cr; << a]. #((1 2) (10 20) (100 200)) groupsDo: [:a :b | Transcript cr; << a; << ' '; << b]. #((1 2 3) (10 20 30) (100 200 300)) groupsDo: [:a :b :c | Transcript cr; << a; << ' '; << b; << ' '; << c]. #((1 2 3 4) (10 20 30 40) (100 200 300 400)) groupsDo: [:a :b :c :d | Transcript cr; << a; << ' '; << b; << ' '; << c; << ' '; << d]. " self do: [:collection | aBlock evaluateWithArguments: collection] This is the complete implementation The alternative is to use “… do: [:element | …” but then you have to say a := element first. b := element second. c := element third
And also groupDo: which other Smalltalk’s Don’t have Singular version (one group) groupDo: aBlock " #(1) groupDo: [:a | Transcript cr; << a]. #(1 2) groupDo: [:a :b | Transcript cr; << a; << ' '; << b]. #(1 2 3) groupDo: [:a :b :c | Transcript cr; << a; << ' '; << b; << ' '; << c]. #(1 2 3 4) groupDo: [:a :b :c :d | Transcript cr; << a; << ' '; << b; << ' '; << c; << ' '; << d]. " aBlock evaluateWithArguments: self asArray This is the complete implementation The alternative is to use the “array” directly but then you have to say a := array first. b := array second. c := array third
A Bit More About Collections anOrderedCollectionaddIfAbsent: anObject aDictionary at: key error if key is missing anOrderedCollectionaddIfIdenticalAbsent: anObject anOrderedCollectionincludes: anObject anOrderedCollectionincludesIdentical: anObject anOrderedCollectionincludesAll: aCollection anOrderedCollectionincludesAllIdentical: aCollection aDictionaryat: key ifAbsent: [“any value”]. aDictionaryat: key ifAbsentPut: [“any value”] value
Short Accessors aCollectionfirst aCollectionat: 1 aCollectionsecond aCollectionat: 2 aCollectionthird aCollectionat: 3 aCollectionsecondLast aCollectionat: aCollectionsize - 1 aCollectionlast aCollectionat: aCollectionsize aCollectionrest aCollectioncopyFrom: 2 aCollectionallButLast aCollectioncopyFrom: 1 to: aCollectionsize - 1
Useful Knowledge • (Smalltalk at: #OrderedCollection) gives you back the OrderedCollection class. • Execute a method in a variable The symbol could originally have been in a file that you read in (as a string you converted to a symbol) • Comparing ordered collections O1 and O2 for containing the identical objects… (O1includesAllIdentical: O2) and: [(O2includesAllIdentical: O1)] No nice C++ short circuit Booleans such as A && (B || C) aBananaperform: variable aBananaperform: variable with: 25 aBananaperform: variablewithArguments: anArray