Post on 15-Jan-2015
description
TI1220 2012-2013Concepts of Programming Languages
Eelco Visser / TU Delft
Lecture 4: Data Types
OutlineType systemsStructures in CDynamic dispatch in JavaPrototype inheritance in JavaScriptFunctional objects in Scala
Type Systems
Bool x, y;x && yx || y
!x
type
data type: a collection of data values and a set of predefined operations on those values
operations
type checking: the activity of ensuring that the operands of an operation are of compatible types.
A compatible type is one that either is legal for the operator or is allowed under language rules to be implicitly converted (coerced) to a legal type
type error: the application of an operator to an operand of an inappropriate type.
static type checking: all type bindings are defined statically, allowing type checking to be done at statically
dynamic type checking: dynamic binding of types to variables requires
checking types at run-time
a programming language is strongly typed if type errors are always detected
(statically or dynamically)
Boolean NumberIntegerFloatCharacterString...
Primitive Datatypes
Read Sebasta Chapter 6
record: an aggregate of elements in which the individual elements are identified by
names and accessed through offsets from the beginning of the structure
The fundamental difference between a record and an array is that record elements, or fields, are not referenced by indices, but by identifiers.
Structures in C
A structure is a collection of one or more variables, possibly of different types, grouped together under a single name for convenient handling. (Structures are called ``records'' in some languages, notably Pascal.)
struct point { int x; int y;};
member
structure tag
Structures in C
struct point { int x; int y;};struct rect { struct point pt1; struct point pt2;};struct point makepoint(int x, int y) { struct point temp; temp.x = x; temp.y = y; return temp;}struct point addpoint(struct point p1, struct point p2) { p1.x += p2.x; p1.y += p2.y; return p1;}
struct point origin, *pp;pp = &origin;
printf("origin is (%d,%d)\n", (*pp).x, (*pp).y);printf("origin is (%d,%d)\n", pp->x, pp->y);
struct rect r, *rp = &r;
r.pt1.xrp->pt1.x(r.pt1).x(rp->pt1).x
Pointers to Structures
struct key { char *word; int count;};struct key keytab[NKEYS];
struct key { char *word; int count;} keytab[] = { "auto", 0, "break", 0, "case", 0, "char", 0, "const", 0, "continue", 0, "default", 0, /* ... */ "unsigned", 0, "void", 0, "volatile", 0, "while", 0 };
Arrays of Structure
/* binsearch: find word in tab[0]...tab[n-1] */
int binsearch(char *word, struct key tab[], int n) { int cond; int low, high, mid; low = 0; high = n - 1; while (low <= high) { mid = (low + high) / 2; if ((cond = strcmp(word, tab[mid].word)) < 0) high = mid - 1; else if (cond > 0) low = mid + 1; else return mid; } return -1;}
Binary Search
struct tnode { /* the tree node: */ char *word; /* points to the text */ int count; /* number of occurrences */ struct tnode *left; /* left child */ struct tnode *right; /* right child */};
struct tnode *talloc(void) { return (struct tnode *) malloc(sizeof(struct tnode));}
Pointers to Structures
struct tnode *addtree(struct tnode *p, char *w) { int cond; if (p == NULL) { /* a new word has arrived */ p = talloc(); /* make a new node */ p->word = strdup(w); p->count = 1; p->left = p->right = NULL; } else if ((cond = strcmp(w, p->word)) == 0) p->count++; /* repeated word */ else if (cond < 0) /* less than into left subtree */ p->left = addtree(p->left, w); else /* greater than into right subtree */ p->right = addtree(p->right, w); return p;}
Tree Insert
Dynamic Dispatch in Javatranslated to C
objects are records with functions as values of members
class Base { Integer x; public Base(Integer v) { x = v; } public void print() { System.out.println("Base: " + x); }}class Child extends Base { Integer y; public Child(Integer v1, Integer v2) { super(v1); y = v2; } public void print() { System.out.println("Child: (" + x + "," + y + ")"); }}
class BaseTest { public static void main(String[] args) { Base base1 = new Base(45); Base base2 = new Child(567, 245); base1.print(); base2.print(); }}
Dynamic Dispatch in Java
typedef struct Base { int x;} Base;
typedef struct Child { int x; // inherited from Base int y;} Child;
class Base { Integer x; public Base(Integer v) { x = v; } public void print() { System.out.println("Base: " + x); }}class Child extends Base { Integer y; public Child(Integer v1, Integer v2) { super(v1); y = v2; } public void print() { System.out.println("Child: (" + x + "," + y + ")"); }}
Representing Objects
typedef struct Base { int x;} Base;
void Base_print(Base* obj) { printf("Base: (%d)\n", obj->x);}
typedef struct Child { int x; // inherited from Base int y;} Child;
void Child_print(Child* obj) { printf("Child: (%d,%d)\n", obj->x, obj->y);}
Defining Methods
Base* newBase(int v) { Base* obj = (Base*)malloc(sizeof(Base)); obj->x = v; return obj;}
Child* newChild(int v1, int v2) { Child* obj = (Child*)malloc(sizeof(Child)); obj->x = v1; obj->y = v2; return obj;}
Constructing Objects
int main() { Base* base = newBase(45); Base* child = (Base*)newChild(567, 245); print(base); print(child);}void print(Base* obj) { if(<obj is a Child>) { Child_print(obj); } else { Base_print(obj); }}
requires reflection
not extensible
class BaseTest { public static void main(String[] args) { Base base1 = new Base(45); Base base2 = new Child(567, 245); base1.print(); base2.print(); }}
Dynamic Dispatch
typedef struct Base { void* (**vtable)(); int x;} Base;
void (*Base_Vtable[])() = { &Base_print };
Base* newBase(int v) { Base* obj = (Base*)malloc(sizeof(Base)); obj->vtable = Base_Vtable; obj->x = v; return obj;}
void print(Base* obj) { obj->vtable[0](obj);}
dynamic dispatch
Virtual Method Table
typedef struct Child { void* (**vtable)(); int x; // inherited from Base int y;} Child;
void Child_print(Child const* obj) { printf("Child: (%d,%d)\n", obj->x, obj->y);}
void (*Child_Vtable[])() = { &Child_print };
Child* newChild(int v1, int v2) { Child* obj = (Child*)malloc(sizeof(Child)); obj->vtable = Child_Vtable; obj->x = v1; obj->y = v2; return obj;}
Subclass
Prototype Inheritancein JavaScript
objects in JavaScript are dynamically composed without class blueprints
var empty = {}; // An object with no propertiesvar point = { x:0, y:0 }; // Two properties
var point2 = { x:point.x, y:point.y+1 }; // More complex values
var book = { "main title" : "JavaScript", // Property names include spaces, 'sub-title' : "The Definitive Guide", // and hyphens, so use string literals "for" : "all audiences", // for is a reserved word, so quote author : { // The value of this property is itself an object firstname : "David", surname : "Flanagan" // Note that these property names are unquoted. }};
Object Literals
var author = book.author; // Get the "author" property of the book.
var name = author.surname // Get the "surname" property of the author.
var title = book["main title"] // Get the "main title" property of the book.
book.edition = 6; // Create an "edition" property of book.
book["main title"] = "ECMAScript"; // Set the "main title" property.
Querying and Setting Properties
var o = {x:1, y:2, z:3}; // Three enumerable own properties
o.propertyIsEnumerable("toString") // => false: not enumerable
for(p in o) // Loop through the properties console.log(p); // Prints x, y, and z, but not toString
for (p in o) { if (!o.hasOwnProperty(p)) continue; // Skip inherited properties}
for (p in o) { if (typeof o[p] === "function") continue; // Skip methods}
Enumerating Properties
/* * Copy the enumerable properties of p to o, and return o. If o and p have a * property by the same name, o's property is overwritten. This function does * not handle getters and setters or copy attributes. */
function extend(o, p) { for (prop in p) { // For all props in p. o[prop] = p[prop]; // Add the property to o. } return o;}
/* * Copy the enumerable properties of p to o, and return o. If o and p have a * property by the same name, o's property is left alone. This function does not * handle getters and setters or copy attributes. */
function merge(o, p) { for (prop in p) { // For all props in p. if (o.hasOwnProperty(prop)) continue; // Except those already in o. o[prop] = p[prop]; // Add the property to o. } return o;}
/* * Remove properties from o if there is not a property with the same name in p. * Return o. */function restrict(o, p) { for (prop in o) { // For all props in o if (!(prop in p)) delete o[prop]; // Delete if not in p } return o;}/* * For each property of p, delete the property with the same name from o. * Return o. */function subtract(o, p) { for (prop in p) { // For all props in p delete o[prop]; // Delete from o (deleting a nonexistent prop is harmless) } return o;}
/* * Return a new object that holds the properties of both o and p. If o and p * have properties by the same name, the values from o are used. */function union(o, p) { return merge(extend({}, o), p);}/* * Return a new object that holds only the properties of o that also appear in * p. This is something like the intersection of o and p, but the values of the * properties in p are discarded */function intersection(o, p) { return restrict(extend({}, o), p);}
/* * Return an array that holds the names of the enumerable own properties of o. */function keys(o) { if (typeof o !== "object") throw TypeError(); // Object argument required var result = []; // The array we will return for (var prop in o) { // For all enumerable properties if (o.hasOwnProperty(prop)) // If it is an own property result.push(prop); // add it to the array. } return result; // Return the array.
objects in JavaScript inherit from a prototype object
var o1 = Object.create({x:1, y:2}); // o1 inherits properties x and y.
var o2 = Object.create(null); // o2 inherits no props or methods.
var o3 = Object.create(Object.prototype); // o3 is like {} or new Object().
Object.create()
var p = {x:1}; // Define a prototype object.
var o = Object.create(p); // Create an object with that prototype.
p.isPrototypeOf(o) // => true: o inherits from p
Object.prototype.isPrototypeOf(o) // => true: p inherits from Object.prototype
The prototype Attribute
var o = {} // o inherits object methods from Object.prototypeo.x = 1; // and has an own property x.var p = Object.create(o); // p inherits properties from o and Object.prototypep.y = 2; // and has an own property y.var q = Object.create(p); // q inherits properties from p, o, and Object.prototypeq.z = 3; // and has an own property z.var s = q.toString(); // toString is inherited from Object.prototypeq.x + q.y // => 3: x and y are inherited from o and p
Inheritance
Inheritance
var unitcircle = { r:1 }; // An object to inherit from
var c = Object.create(unitcircle); // c inherits the property r
c.x = 1; c.y = 1; // c defines two properties of its own
c.r = 2; // c overrides its inherited property
unitcircle.r; // => 1: the prototype object is not affected
Inheritance
How to organize code reuse?
function range(from, to) { var r = Object.create(range.methods); r.from = from; r.to = to; return r;}range.methods = { includes : function(x) { return this.from <= x && x <= this.to; }, foreach : function(f) { for ( var x = Math.ceil(this.from); x <= this.to; x++) f(x); }, toString : function() { return "(" + this.from + "..." + this.to + ")"; }};var r = range(1, 3); // Create a range objectr.includes(2); // => true: 2 is in the ranger.foreach(console.log); // Prints 1 2 3console.log(r); // Prints (1...3)
Classes and Prototypes
function Range(from, to) { this.from = from; this.to = to;}Range.prototype = { includes : function(x) { return this.from <= x && x <= this.to; }, foreach : function(f) { for ( var x = Math.ceil(this.from); x <= this.to; x++) f(x); }, toString : function() { return "(" + this.from + "..." + this.to + ")"; }};var r = new Range(1, 3); // Create a range objectr.includes(2); // => true: 2 is in the ranger.foreach(console.log); // Prints 1 2 3console.log(r); // Prints (1...3)
Classes and Constructors
Constructors and Class Identity
r instanceof Range // returns true if r inherits // from Range.prototype
var F = function() {}; // This is a function object.var p = F.prototype; // This is the prototype object associated with it.var c = p.constructor; // This is the function associated with the prototype.c === F // => true: F.prototype.constructor==F for any functionvar o = new F(); // Create an object o of class Fo.constructor === F // => true: the constructor property specifies the class
Constructor Property
function Range(from, to) { this.from = from; this.to = to;} Range.prototype.includes = function(x) { return this.from <= x && x <= this.to;};Range.prototype.foreach = function(f) { for ( var x = Math.ceil(this.from); x <= this.to; x++) f(x);};Range.prototype.toString = function() { return "(" + this.from + "..." + this.to + ")";};
Extend Prototype
Java Style Classes in JavaScript
Java class
• instance fields
• instance methods
• class fields
• class methods
JavaScript
• constructor object
• prototype object
• instance object
Reading & Programming in Week 4
Reading
Sebesta Chapter 9: Subprograms
Programming in Scala Chapter 15: Case Classes and Pattern Matching
Week 5: Functional Programming
WebLab: C, JavaScript, Scala tutorials