Record: Aggregates multiple values of potentially different types.
// Declarationrecord Student isstring first-namestring last-nameint idend record// InstantiationStudent freddy := new Studenttag first-name := "Friedrich"tag last-name := "Engels"tag id := 1895
Important: Note the lack of data hiding. This is for abstraction, not encapsulation.
Tuple; Aggregates values of potentially different types.
In most languages, tuples are immutable.
More on Tuples and Records — Object Oriented languages lack records because they already have objects. Tuples are also unnecessary if you have arrays.
- Simpler languages like C and Rust tend to have records.
- Functional languages tend to have tuples.
List: ADT defined as a sequence of element, usually of the same type.
Appears in the definition of some languages.
- e.g., Functional languages can’t have arrays (arrays need constructive updates, which are forbidden), so they define lists in their language.
1. Linked List: The obvious.
2. Array: You could also implement a linked-list with arrays (e.g., buffered arrays, etc.)
In functional languages, option 1 is the only option.
Note — If you have singly-linked list, prepending is O(1), but appending is O(n).
Union: Data types that are the union multiple other data typrs
Note — These things are useless in OOP languages.
- They are used in C though, because you lack polymorphism.
// Defineunion U isint xString Send union// UsageU a := new Uint b := 42int c := TODO
Variables that hold memory addresses (L-values).
Pointers
char* str = "Hello";
str += 1;
print str;
// "ello"References
String str = "Hello";
// can't do str += 1; In most languages, pointers and references are always active from creation to deallocation.
func f is...D x := new D...// (end without deallocating)end f
Another issue is aliasing, where we can have two references to the same thing and don’t fully deallocate (dangling pointers).Example: Aliasing and Dangling Pointers
// Aliasingp \to 0x0q \to 0x0// Free qfree q// p has no idea it points to junk
Two types are compatabile if we can assign one type to another.
Garbage Collector: Runtime support program that periodically identifiers and deallocates garbage.
Practice — In practice, because GC is undecidable, we simplify the definition to be “garbage is unreachable resources”
- i.e., stuff without pointers to it
Memory leaks happen in the heap — Notice how you only have to do this on the heap, as stuff is never deallocated on the stack.
Generations:
We’ll garbage collect more often from the younger generation than the older generations.
Why — Objects with a limited lifetime usually have a really short lifetime.
- e.g., Variables in a typical function or loop are usually only used for a few milliseconds. If it lasts longer than a few ms, it’s probably going to be alive for very long.
Suppose you have three generations:
We’ll collect Gen 0 really often, and very rarely from Gen 2.
Java has a 3-generational mark and sweep garbage collector.
Two types T and S are equivalent, if whenver one is expected, the other may be used.
Example:
We say type S is compatible with type T if anything of type S can be assignment to type T