Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Slot Composition
Marcus Denker
Part 1: Introduction
Everything is an Object
Everything?
What about Variables?
Object subclass: #Point
instanceVariableNames: 'x y'
classVariableNames: ''
package: 'Kernel-BasicObjects'
Instance Variables
Class Variable
They are not objects!
Object subclass: #Point
instanceVariableNames: 'x y'
classVariableNames: ''
package: 'Kernel-BasicObjects'
This is just a ...
Instance Variables
Class Variables
They are not objects!
Not just definition, the
whole reflective API is
string / offset based!
Point instVarNames
5@6 instVarAt: 1
5@6 instVarAt: 1 put: 2
5@6 instVarNamed: #x put: 2
We can do better!
We did do better!
Slots and ClassVariables
in Pharo
Slots in 2 minutes
Slots: First Class Ivars
• Every instance variable definition is described an instance
of Slot (or subclass)

• Compiler de...
Slots: First Class Ivars
Object subclass: #Point
slots: { #x. #y }
classVariables: { }
package: 'Kernel-BasicObjects'
• Fo...
Slots: API
pointXSlot := Point slotNamed: #x.
#we can read
pointXSlot read: (4@5).
pointXSlot write: 7 to: (4@5).
pointXSl...
Slots: make your own
Slot subclass: #ExampleSlotWithState
slots: { #value }
classVariables: { }
package: ‘Slot-Examples-Ba...
Slots: First Class Ivars
Object subclass: #MyClass
slots: { #ivar => ExampleSlotWithState }
classVariables: { }
package: '...
Slots: more…
• bytecode: override #emitStore: and #emitValue:

• class builder calls #installingIn: on class creation

• I...
Examples
• PropertySlot

• BooleanSlot

• UnlimitedInstanceVariableSlot

• HistorySlot

• ProcessLocalSlot

• ComputedSlot...
Start to be used
• In Pharo:

• Spec: Observable Slot

• Others:

• Famix: relations, meta data (tag)

• Typed Slots Proje...
Part 2: The Composition
Problem
Let’s take just two
• SpObservableSlot

• Slot with a default value (InitializedSlot or LazySlot)
Let’s take just two
Object subclass: #MyClass2
slots: { #ivar => LazySlot default: 5 }
classVariables: { }
package: ‘Kerne...
I want a SpObservableSlot
with default value!
What to do now?
I could implement
LazyObservableSlot
Combinatorial Explosion
• PropertySlot

• BooleanSlot

• UnlimitedInstanceVariableSlot

• HistorySlot

• ProcessLocalSlot
...
SpObservableSlot + LazySlot default: 5
Let’s take just two
Object subclass: #MyClass2
slots: { #iv => SpObservableSlot + LazySlot default: 5 }
classVariables: { ...
It is not that simple
• We want to compose *instances*, not classes! 

• We want to combine behaviour: e.g. three slots wa...
Kind of Slots
• Storage (“Implementation”)

• Decorators

• Wrappers
Storage
• Define how to store data. 

• Examples: PropertySlots, InstanceVariableSlot,
ComputedSlot

• It only makes sense ...
Decorators
• Before / After read and write

• Initialize instances: slot gets notified on #new

• class builder hook on cla...
Wrappers
• Wrap and write, unwrap on read

• Example: Weak Slot: Wrap into a Weak Array

• We have some of them, as they a...
Wrappers: Problems
• Turns Write into a read on the outer slot.

• Can not compose easily (order!)

• Weak + WriteOnce: th...
Wrappers
• Most (all?) wrappers can be implemented as decorators +
additional hidden state.

• Let’s support one wrapper f...
Solution
• ComposedSlot: a Slot composed of 

• One Storage Slot. InstanceVariableSlot is default

• 0..n Decorators: 

• ...
InstanceVariable +
InitializedSlot default: 5
InitializedSlot default: 5
Reflective Read
read: anObject
| value |
self decorators do: [ :decorator |
decorator beforeRead: anObject ].
value := self...
Status
• Work in progress implementation

• Currently re-implement all existing Slots to be
composable
Future Work
• Integrate with Pharo

• Use in Spec: SpObservable + Initialized, for example

• Unify variable definition for...
Questions?
InstanceVariable +
InitializedSlot default: 5
Upcoming SlideShare
Loading in …5
×

Slot Composition

8 views

Published on

Slot Composition, talk from ESUG19, August 27, 2019

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Slot Composition

  1. 1. Slot Composition Marcus Denker
  2. 2. Part 1: Introduction
  3. 3. Everything is an Object
  4. 4. Everything?
  5. 5. What about Variables?
  6. 6. Object subclass: #Point instanceVariableNames: 'x y' classVariableNames: '' package: 'Kernel-BasicObjects'
  7. 7. Instance Variables Class Variable They are not objects!
  8. 8. Object subclass: #Point instanceVariableNames: 'x y' classVariableNames: '' package: 'Kernel-BasicObjects' This is just a String!
  9. 9. Instance Variables Class Variables They are not objects!
  10. 10. Not just definition, the whole reflective API is string / offset based!
  11. 11. Point instVarNames 5@6 instVarAt: 1 5@6 instVarAt: 1 put: 2 5@6 instVarNamed: #x put: 2
  12. 12. We can do better!
  13. 13. We did do better!
  14. 14. Slots and ClassVariables in Pharo
  15. 15. Slots in 2 minutes
  16. 16. Slots: First Class Ivars • Every instance variable definition is described an instance of Slot (or subclass) • Compiler delegates code generation to Slot class • You can easily make your own! • A set of interesting Slots are emerging
  17. 17. Slots: First Class Ivars Object subclass: #Point slots: { #x. #y } classVariables: { } package: 'Kernel-BasicObjects' • For InstanceVariableSlot: we write just the #name • Bytecode exactly the same as ST80 Instance Variables
  18. 18. Slots: API pointXSlot := Point slotNamed: #x. #we can read pointXSlot read: (4@5). pointXSlot write: 7 to: (4@5). pointXSlot usingMethods. pointXSlot astNodes. pointXSlot assignmentNodes.
  19. 19. Slots: make your own Slot subclass: #ExampleSlotWithState slots: { #value } classVariables: { } package: ‘Slot-Examples-Base' read: anObject ^ value write: aValue to: anObject value := aValue
  20. 20. Slots: First Class Ivars Object subclass: #MyClass slots: { #ivar => ExampleSlotWithState } classVariables: { } package: 'Kernel-BasicObjects' • we can compile normal read and assignment • state ends up in the slot (inspect the slot!)
  21. 21. Slots: more… • bytecode: override #emitStore: and #emitValue: • class builder calls #installingIn: on class creation • Initialize instances: if #wantsInitalization is true, #new sends #initialize: to all slots with the new instance as parameter • Slots can be invisible (just implement #isVisible)
  22. 22. Examples • PropertySlot • BooleanSlot • UnlimitedInstanceVariableSlot • HistorySlot • ProcessLocalSlot • ComputedSlot • RelationSlot • LazySlot • InitializedSlot • ComputedSlot • SpObservableSlot • WriteOnceSlot
  23. 23. Start to be used • In Pharo: • Spec: Observable Slot • Others: • Famix: relations, meta data (tag) • Typed Slots Project
  24. 24. Part 2: The Composition Problem
  25. 25. Let’s take just two • SpObservableSlot • Slot with a default value (InitializedSlot or LazySlot)
  26. 26. Let’s take just two Object subclass: #MyClass2 slots: { #ivar => LazySlot default: 5 } classVariables: { } package: ‘Kernel-BasicObjects' Object subclass: #MyClass2 slots: { #ivar => SpObservableSlot} classVariables: { } package: ‘Kernel-BasicObjects'
  27. 27. I want a SpObservableSlot with default value!
  28. 28. What to do now?
  29. 29. I could implement LazyObservableSlot
  30. 30. Combinatorial Explosion • PropertySlot • BooleanSlot • UnlimitedInstanceVariableSlot • HistorySlot • ProcessLocalSlot • ComputedSlot • RelationSlot • LazySlot • InitializedSlot • ComputedSlot • SpObservableSlot • WriteOnceSlot
  31. 31. SpObservableSlot + LazySlot default: 5
  32. 32. Let’s take just two Object subclass: #MyClass2 slots: { #iv => SpObservableSlot + LazySlot default: 5 } classVariables: { } package: ‘Examples'
  33. 33. It is not that simple • We want to compose *instances*, not classes! • We want to combine behaviour: e.g. three slots want to change what happens after a read • Inheritance or Traits do not solve the problem
  34. 34. Kind of Slots • Storage (“Implementation”) • Decorators • Wrappers
  35. 35. Storage • Define how to store data. • Examples: PropertySlots, InstanceVariableSlot, ComputedSlot • It only makes sense to have one
  36. 36. Decorators • Before / After read and write • Initialize instances: slot gets notified on #new • class builder hook on class creation • Meta Data (e.g. tagged slot) • We can combine as many decorators as we want!
  37. 37. Wrappers • Wrap and write, unwrap on read • Example: Weak Slot: Wrap into a Weak Array • We have some of them, as they are simple to write: • Weak, ProcessLocal, History, WriteOnce
  38. 38. Wrappers: Problems • Turns Write into a read on the outer slot. • Can not compose easily (order!) • Weak + WriteOnce: the history collection is weak! • WriteOnce + Weak: Write goes to weak array
  39. 39. Wrappers • Most (all?) wrappers can be implemented as decorators + additional hidden state. • Let’s support one wrapper for now
  40. 40. Solution • ComposedSlot: a Slot composed of • One Storage Slot. InstanceVariableSlot is default • 0..n Decorators: • one Wrapper
  41. 41. InstanceVariable + InitializedSlot default: 5
  42. 42. InitializedSlot default: 5
  43. 43. Reflective Read read: anObject | value | self decorators do: [ :decorator | decorator beforeRead: anObject ]. value := self wrapperOrImplementor read: anObject. self decorators reversDo: [ :decorator | decorator afterRead: anObject ]. ^value.
  44. 44. Status • Work in progress implementation • Currently re-implement all existing Slots to be composable
  45. 45. Future Work • Integrate with Pharo • Use in Spec: SpObservable + Initialized, for example • Unify variable definition for Class Variables and Slots
  46. 46. Questions? InstanceVariable + InitializedSlot default: 5

×