Skip to content
This repository has been archived by the owner on Jan 29, 2024. It is now read-only.

immutability: readonly ref to writable value vs ref to readonly value #321

Open
thecotne opened this issue Dec 12, 2020 · 0 comments
Open
Labels
enhancement New feature or request

Comments

@thecotne
Copy link
Contributor

thecotne commented Dec 12, 2020

i will use

  • writable instead of mutable
  • readonly instead of immutable
  • functionality instead of behaviour

so it's easier to read

examples

// writable binding of writable value
let FEATURES = {
  SORTING: 'Sorting',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
}

// readonly binding of writable value
const FEATURES = {
  SORTING: 'Sorting',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
}

// writable binding of readonly value
let FEATURES = Object.freeze({
  SORTING: 'Sorting',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
})

// readonly binding of readonly value
const FEATURES = Object.freeze({
  SORTING: 'Sorting',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
})

now we need to describe how Object.freeze can magically receive ref to writable value and return ref to readonly value so that user defined functions can have similar functionality

and how this is correct code

const FEATURES = {
  SORTING: 'Sorting',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
}

FEATURES.SORTING = 'cotne'

const FEATURES2: $Immutable<{
  SORTING: 'cotne',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
}> = Object.freeze(FEATURES)

lets go over this code again

// we start with readonly binding of writable value
// and we have 3 refinements on it 
// 1. property SORTING is string literal 'Sorting'
// 2. property FILTERING is string literal 'Filtering'
// 3. property REORDERING is string literal 'Reordering'
const FEATURES = {
  SORTING: 'Sorting',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
}

// here we refine property SORTING to string literal 'cotne'
FEATURES.SORTING = 'cotne'

// Object.freeze receives readonly ref and since it's pure function no other function can alter refinements that where made on that value
// so when it creates new readonly value from readonly ref where all the refinements become frozen and
// we get readonly ref to readonly value
const FEATURES2: $Immutable<{
  SORTING: 'cotne',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
}> = Object.freeze(FEATURES)

more examples

type FEATURES = {
  FILTERING: 'Filtering',
  REORDERING: 'Reordering',
  SORTING: 'Sorting'
}
// this is ok
const FEATURES01: $Immutable<FEATURES> = {
  SORTING: 'Sorting',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
}

// this is ok
const FEATURES02: {  
  'FILTERING': string,
  'REORDERING': string,
  'SORTING': string
} = {
  SORTING: 'Sorting',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
}

// this is not possible
const FEATURES03: $Immutable<FEATURES> = FEATURES02

// this is ok
const FEATURES04: $Immutable<FEATURES> = Object.freeze(FEATURES02)

lets go over it again

type FEATURES = {
  FILTERING: 'Filtering',
  REORDERING: 'Reordering',
  SORTING: 'Sorting'
}
// here we have object literal that is assigned to variable FEATURES01 (readonly binding)
// since object literal returns value not ref we can freeze refinements on the object since we are creating first ever ref and no one else can edit the value
// in other words object literal returns ownership of the value 
// and with ownership we can create ref where we say that value is readonly when it's not but since we own it we say: my value my rules and that's it!
const FEATURES01: $Immutable<FEATURES> = {
  SORTING: 'Sorting',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
}

// here we create readonly binding of writable value
// and we have 3 refinements on it 
// 1. property SORTING is string literal 'Sorting'
// 2. property FILTERING is string literal 'Filtering'
// 3. property REORDERING is string literal 'Reordering'
const FEATURES02: {  
  'FILTERING': string,
  'REORDERING': string,
  'SORTING': string
} = {
  SORTING: 'Sorting',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
}

// here we try to create readonly binding of readonly value
// but we have ref to writable value and since it's ref not value in other words we don't have ownership over this value we can't do it
const FEATURES03: $Immutable<FEATURES> = FEATURES02

// here we try to create readonly binding of readonly value (second time)
// we pass writable value to `Object.freeze` and it will return new readonly value where all the refinements become frozen
const FEATURES04: $Immutable<FEATURES> = Object.freeze(FEATURES02)

one more question

Q: can i get readonly ref to writable value without having ownership or cloning like Object.freeze does?
A: if we introduce some understanding of ownership it is possible

let's say all types are borrowed (not owned) by default

type FEATURES = {
  FILTERING: 'Filtering',
  REORDERING: 'Reordering',
  SORTING: 'Sorting'
}
// this is ok
const FEATURES01: $Owned<$Immutable<FEATURES>> = {
  SORTING: 'Sorting',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
}

// this is ok
const FEATURES02: {  
  'FILTERING': string,
  'REORDERING': string,
  'SORTING': string
} = {
  SORTING: 'Sorting',
  FILTERING: 'Filtering',
  REORDERING: 'Reordering'
}

// this is not possible
const FEATURES03: $Owned<$Immutable<FEATURES>> = FEATURES02

// this is ok
const FEATURES03_1: $Immutable<FEATURES> = FEATURES02

// this is ok
const FEATURES04: $Owned<$Immutable<FEATURES>> = Object.freeze(FEATURES02)

in this new example you can't edit FEATURES03_1 but we know that it's value can be edited after any non-pure function call is made so refinements on it does not stick around like it does for FEATURES01 and FEATURES04


after writing this i think we need ownership and borrowing at some point ...

@JSMonk JSMonk added the enhancement New feature or request label Dec 13, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants