Tomáš Petříček, 309 (3rd floor)
petricek@d3s.mff.cuni.cz
https://tomasp.net | @tomaspetricek
https://d3s.mff.cuni.cz/teaching/nprg077
Dynamic lookup - object chooses how to respond
Abstraction - object state can be hidden from user
Subtyping - any compatible object can be used
Inheritance - reuse to implement a new object
Algol-based and scientific Simula
Tools for thought and messaging in Smalltalk
Rigorous Eiffel and "serious" C++
Prototypes and materialized objects in Self
Class-based safe Java and C#
Prototypes in JavaScript and typed TypeScript
Visual programming
Programming by graphically manipulating objects on screen
Direct programming
Objects on screen are objects in the system
// Object consists of zero or more
// slots and optionally code
type Objekt =
{ mutable Code : Objekt option
mutable Slots : Slot list }
// A slot has name and contents;
// Some slots are parents
and Slot =
{ Name : string
Contents : Objekt
IsParent : bool }
Object consists of zero or more slots and optional code!
In Self parent slot names end with *
TinySelf objects can
also be special things
Message send looks at target object first, then searches parents
cheshire name // OK
cheshire book // OK
larry name // OK
larry book // Fail
Message send fail if none or multiple slots found
"""Data object with name"""
(| book = 'Alice in Wonderland' |)
"""Method with some code"""
( self name printLine )
"""Data object with parent
slot and a 'speak' method"""
(| parent* = cat
name = 'Cheshire Cat'
speak = (
self sound printLine
)
|)
"""Data access or method call"""
cheshire name
cheshire speak
Lookup slot with a matching name, then:
Assignment slots and special calls differ...
mutable
fieldsReferenceEquality
attribute to overridetype Person =
{ mutable Name : string
mutable Book : string option }
let setName n p =
p.Name <- n
let setBook b p =
p.Book <- Some b
let x = { Name = "Bill"; k = None }
x |> setName "William"
x |> setBook "Alice in Wonderland"
match x with
| { Book = Some book } ->
printfn "%s likes %s" x.Name book
| _ ->
printfn "%s is sad :-(" x.Name
Helper functions
Make code a bit nicer
Can support |>
pipe
Pattern matching
Same as immutable
Nice data extraction!
Everything is an Objekt
Type definition stays
We change what we put in!
Uniformity has drawbacks Everything type checks!
Simplify object construction
let makeString s =
makeDataObject [
makeParentSlot "parent*"
stringPrototype
makeSlot "value"
(makeSpecial(String s))
makeAssignmentSlot "value"
]
Escape hatch is a must
Smalltalk system calls
Self primitive calls
(primitives primitiveList)
TinySelf special objects
Primitive string values
Native F# methods
// Special TinySelf objects!
type Special =
| String of string
| Native of (Objekt -> Objekt)
// Optionally special object
and Objekt =
{ mutable Code : Objekt option
mutable Special : Special option
mutable Slots : Slot list }
// Code to clone an object
let cloneCode =
{ Slots = []; Code = None
Special = Some(Native(fun arcd ->
lookupSlotValue "self*" arcd
|> cloneObject )) }
// Method with special code object
let cloneMethod =
{ Slots = []; Special = None;
Code = Some cloneCode }
String values
No other way to represent strings!
Native methods
F# function taking "activation record" and returning the result
Used as method code
1) Search target object
2) Search parents and union the results
3) Avoid infinite loops!
A normal send does a lookup to obtain the target slot;
If the slot contains a data object, then the data object is simply returned.
If the slot contains a method, an activation is created and run.
Lookup in activation record to get all our code needs!
Clone of method
It could have data!
Self as parent
Access target's slots!
Arguments as parent
Access arguments!
eval
methodactivation
as argumentObjekt
!'Hello world' print
Send expression
Receiver, message, arguments to be used
String expression
String value to be returned
To make this nicer, put eval code into prototypes...
Implementing slot lookup
Traversing the prototype hierarchy to find slots
Implementing (basic) message sending
Handling of data objects and (native) methods
Cloning and mutating TinySelf objects
Assignment slots and clonable trait
Representing & interpreting TinySelf expressions
Creating expression objects with eval
method
Arguments and sequencing of expressions
Adding more types of expressions to TinySelf
Booleans and 'if' as a message send!
Booleans are just objects with an if
method
Objects as lists and more expressions
Adding more infrastructure before the next step...
Creating web-based visualizers
A small step towards TinyMorphic framework
Dynamic lookup
Find method using lookup
Abstraction
No private slots in TinySelf
Subtyping
Object with required slots
Inheritance
By setting a parent slot
Self-sustainable
Complete basic library
Reflection capabilities
Reflection via mirrors
Mirror objects
Inspect & modify
Done in Nanospeak
A tiny prototype-based object-oriented language
Tomáš Petříček, 309 (3rd floor)
petricek@d3s.mff.cuni.cz
https://tomasp.net | @tomaspetricek
https://d3s.mff.cuni.cz/teaching/nprg077
https://bibliography.selflanguage.org/
https://bibliography.selflanguage.org/_static/self-power.pdf
https://handbook.selflanguage.org/SelfHandbook2017.1.pdf
https://sin-ack.github.io/posts/a-tour-of-self/
https://github.com/sin-ack/zigself/ ??
https://github.com/tpetricek/nanospeak/
http://blog.rfox.eu/en/Programming/Series_about_Self/index.html