Sie sind auf Seite 1von 77

CS2104: Programming Languages

Concepts
Lecture 2 : Basic Concepts

Key Language Concepts

Lecturer : Chin Wei Ngan


Email : chinwn@comp.nus.edu.sg
Office : COM2 4-32

CS2104

Concepts

Why so Many Programming Languages?


Over 1000 languages in existence, with some 25 in
relatively wide-spread use
Key considerations for PL
Productivity
Robustness
Modularity
Reusability
Maintainability
Correctness
Common Traits
A number of paradigms (styles)
A number of features (components)
CS2104

Concepts

Scala vs C

CS2104

Scala Language

Motivation for Scala Language


interoperable with Java
conciseness (2-10 times shorter)
supports higher-order functions (OOP+FP)

advance static typing and inference


developed by Martin Odersky group @ EPFL
http://www.tutorialspoint.com/scala/index.htm
CS2104

Scala Language

Conciseness
// in Java
class MyClass {
private int index;
private String name;
public MyClass(int index, String name) {
this.index = index;
this.name = name;
}
}

// in Scala:
class MyClass(index: Int, name: String)

CS2104

Scala Language

Multi-Paradigm Approach
Integrates two successful programming styles

functional programming (FP)

object-oriented programming (OOP)

OCaml also adopted a similar approach. The main


difference is that Scala interoperates with Java.

CS2104

Scala Language

Object-Oriented Style Supported


Every value is an object
Types and behavior of objects are described by
classes (including abstract classes)
traits
Class abstraction are extended by
sub-classing
mixin composition
(cleaner replacement for multiple inheritance)

CS2104

Scala Language

Functional Style Supported


Every function is an object
Functions are first-class values

passed as argument

returned as result

can be stored in data structures

Anonymous functions allowed


Pattern-matching via Case Classes

CS2104

Scala Language

Scala
Classes
CS2104

Scala Language

Scala Classes
Factory templates that can be instantiated to objects.
Class Parameters and Explicit Overriding
class Point(xc: Int, yc: Int) {
var x: Int = xc
var y: Int = yc
def move(dx: Int, dy: Int) {
x = x + dx
y = y + dy
}
override def toString(): String
= "(" + x + ", " + y + ")";
}

CS2104

Scala Language

10

Scala Classes
Parameterised by constructor arguments.
Objects are instantiated with new command, e.g.
new Point(3,4);

Uses dynamically-dispatched methods only:


this.move(dx,dy);
this.toString();

CS2104

Scala Language

11

Scala Classes
A class with a single object is declared with the "object"
keyword.
This example captures an executable application with
a main method that can be directly executed.
object Classes {
def main(args: Array[String]) {
val pt = new Point(1, 2)
println(pt)
pt.move(10,10)
println(pt)
}
}

CS2104

Scala Language

12

Basic Concepts
Primitive vs User-Defined Types
Constructs and Binders

Loops vs Methods
Pure vs Impure
Strict vs Lazy Evaluation
Strong vs Weak Typing

CS2104

Concepts

13

Program = Data + Algorithm

Primitive and
User-Defined Types
CS2104

Concepts

14

Primitive Types
Built-In Types of Languages

Directly implemented in hardware (usually).


Simpler types
e.g. boolean, integer, float, char, string, arrays
Important for performance
May include Standard Libraries (extensible)
Language without primitive type
Lambda Calculus
Use just functions!
CS2104

Concepts

15

Primitive Types (C Language)


Built-In Types
int (bounded integer, e.g. int x = 42)
float (single precision floating, e.g. float r = 4.2)
double (double precision floating point)
char (e.g. char Letter; Letter = x; )
arrays (e.g. int arr[10]; )
Modifiers
short, long (e.g. short int, long double)
signed, unsigned
void can be considered a type with a single value
void* denotes pointer with unspecified type

boolean implemented as integer


(0 for false, non-0 for true)
CS2104

Concepts

16

Primitive Types (Scala)


Built-In Types are objects too!
Boolean (e.g. val b = true)
Int (bounded integer, e.g. val x = 42)
Float (double precision floating, e.g. val r = 4.2)
Char (e.g. val letter = x; )
java.lang.String (e.g. val course = cs2104 )
Type annotation expr : type
E.g. val (course:string) = cs2104
Rich libraries, through modules
e.g. List, Array, scala.math.Bigint,
scala.collection.mutable.HashMap,
scalax.collection.immutable.Graph[N,E[X]]
CS2104

Concepts

17

User-Defined Types
User can design their own types

Support more complex data structures


Examples:
Ordinal type
Record type
Pointer type
Tuple type
Union types
Algebraic Data type
Polymorphic/Generic type
Sum vs Product types

CS2104

Concepts

18

Ordinal Types
An ordinal type is a finite enumeration of distinct values
that can be associated with positive integers.
An example in Ada is
type DAYS is (Mon,Tue,Wed,Thu,Fri,Sat,Sun)
if today>Fri then
print Hippie
else
print Oh..

If values can occur in more than one ordinal type, it is


referred to as overloaded literals, but may be difficult to
determine which type such values belong to.
CS2104

Concepts

19

Ordinal Types
Scala enumeration can be done through sealed case objects.
object DaysObj {
sealed trait Days
case object Mon extends Days
case object Tue extends Days
case object Wed extends Days
case object Thu extends Days
case object Fri extends Days
case object Sat extends Days
case object Sun extends Days
val daysOfWeek = Seq(Mon,Tue,Wed,Thu,Fri,Sat,Sun)
}

Sealed trait can only be extended within in a single file.


Benefit : Compiler can emit warning if a match is not
exhaustive
CS2104

Concepts

20

Ordinal Types
Non-exhaustive pattern.
def weekend (x:Days) : Boolean = x match {
case Mon | Tue | Wed => false
case Sat | Sun => true
}

Exhaustive Pattern.
def weekend (x:Days) = x match {
case Mon | Tue | Wed | Thu | Fri => false
case Sat | Sun => true
}

Alternative exhaustive pattern:


def weekend (x:Days) = x match {
case Sat | Sun => true
case _ => false
}
CS2104

Concepts

21

Record Types
Record is a collection of values of possibly different
types. In C, this is implemented as structures
struct [structure_tag] {
(type id)+
} id+ ;

An example:
struct Student {
char name[20];
char matric[10];
int year;
} s1, s2 ;

CS2104

Concepts

22

Record Types (C)


Can access the fields by the dot notation

Examples : s1.year or s2.matric


Access is efficiently done via offset calculation.
Operations on records, e.g. assignment
s1 = s2;

Entire record is copied or passed as parameters.


This occurs for struct type of C.

CS2104

Concepts

23

Record Types (in Scala)


Traditional records can be realised as classes in
Scala
class Student(n:String,m:String,y:Int) {
val name = n;
val matrix = m;
val year = y;
} ;;

Can use class constructor to built an object/record


val s = new Student(xxx,A8888,2016);

Use field access to obtain components of object/record


s.name
CS2104

s.matrix
Concepts

s.year
24

Fancy Record Types (in Scala)


https://github.com/scala-records/scala-records
import records.Rec
scala> val student = Rec("name" -> "Hannah", year" -> 2016)

person: records.Rec{def name: String; def year: Int} =


Rec { name = Hannah, year = 2016 }

Fields are records can be accessed like fields of classes.


if (student.year > 2015)
println(s"${student.name} is a freshman.")

These records are created on the fly


CS2104

Concepts

25

Structure Type (in Scala)


Closely related is structure type which allows partial
specification of fields, including method fields.
Below declares a parameter based on structure type:
def foo(x: { def get: Int }) = 123 + x.get
// foo: (x: AnyRef{def get: Int})Int

It is also possible to construct an AnyRef object with a get


method, as follows:
foo(new { def get = 10 })
// res0: Int = 133

CS2104

Concepts

26

Structure Type (in Scala)


Another example with two methods:
type DuckType = { def walk; def quack }
def doTheThings(duck: DuckType) { duck.quack }

The type alias DuckType can be used for any objects with at
least the walk and quack methods but could have more
methods, such as the class below.
class
def
def
def
}

CS2104

Dog {
walk { println("Dog walk") }
quack { println("Dog quacks") }
run { println("Dog runs") }

Concepts

27

Tuple Types (Scala)


A special case of record type is the tuple type. This
groups a number of components, but uses positional
order rather than field names.
val stud1 = (John,A1234567J,2013);;
stud1 : (java.lang.String,java.lang.String,Int) =

Tuple type is shorthand for:


Tuple3[java.lang.String,java.lang.String,Int]

The components can be accessed by positional fields.


stud1._1
stud1._3
CS2104

Concepts

28

Pointer Type
A pointer type is meant to capture the address of an
object value. There is also a special value nil that is
not a valid address.
An example in C with pointer types are:
int count, init;
int *ptr;

ptr = &init;
count = *ptr;

count

init

ptr

The * operation will dereference a pointer type.

CS2104

Concepts

29

Pointer Type
Pointer types are crucial for recursive data type.

An example in C is:
struct node {
int val;
struct node *next;
} list;

We cannot use below. Why?


struct node {
int val;
struct node next;
} inf_list;

CS2104

Concepts

list

val
next

inf_list

val
next val
next

30

Pointer Types (in Scala)


No need for explicit pointer types in Scala.

By default, each object type is already implemented as a


pointer.
Thus, recursive type is possible but can be infinite since a
list may not terminate with null value.
class Node(v:Int, n:Node) {
val vv: Int = v
val next:Node = n
list
vv
}
next

vv

next

let list:node =
new Node(3,null)
CS2104

Concepts

31

Union Types (in C)


Union type is a type that may store different type of
values at different times/instances.
We can define a union of many members but only
one member can exists at any one time. Format:
union [union_tag] {
(type id)+
} id+ ;

An example where the fields are overlaid.


union Data {
int i;
float f;
char str[20]
};

CS2104

int

float

str

Concepts

32

Sum/Union Type vs Product Type


Union type
Int | Float | String

int

Product type
(Int , Float , String)
int

float

str

float

str
CS2104

Concepts

33

Some Issues with Union Type


Union type
Int | Float | String

int

float

str

Space must be big enough for all possibilities, if


you want to support mutable location
You need to remember what you wrote earlier, unless
you add an integer tag to remember the value.
CS2104

Concepts

34

Tagged Union Type in OCaml


Algebraic data type
type udata = I of int
| F of float
| S of string

With this, we can build objects of different values


but with the same type.
let v1 = I 3;;
let v2 = F 4.5;;
let v3 = S CS2104;;

Above values all have the same type


v1:udata

CS2104

v2:udata

Concepts

v2:udata

35

Tagged Union Type in Scala


Case Classes
abstract class UData
case class I(value: Int) extends UData
case class F(value: Float) extends UData
case class S(value: String) extends Udata

Above values all have the same type


val v1 = I(3);;
val v2 = F(4.5);;
val v3 = S(CS2104);;

Above values all have the same super-type


v1:UData

CS2104

v2:UData

Concepts

v2:UData

36

Pattern-Matching (in Scala)


Generic printer.
def print_data (v:Udata) =
v match {
case I(a) => string_of_int a
case F(v) => string_of_float v
case S(v) => v }

Note pattern-matching is able to obtain type-safe


values.
What is the type of this function?

CS2104

Concepts

37

Product Type
Record and tuples belong to product types.
A pair is the foundation of product type.
A polymorphic version is:
type Pair[A,B] = (A, B)
val v2:Pair[Int,String] = (3,"cs2104");;

Product types are analogous to logical conjunction

CS2104

Concepts

38

Sum Type
Union, ordinals and algebraic data type belongs to
sum types.
Untyped languages essentially sums different types
together, e.g:
type univ = int | float | .. | array | object

However, cannot distinguish between the sum type


and its constituent types.
type Sum[A,B] = A | B

let v1 = [3; "cs2104"];;

CS2104

Concepts

39

Sum Type
Like algebraic data type, sum types are usually
tagged, as follows:
type Sum[A,B] = L(A) | R(B)
val v0 = [3;cs2104] /* error */
val v1 = [L 3; R "cs2104"]

Sum types are analogous to logical disjunction.


Polymorphic sum type in Scala.
sealed abstract class Sum[A,B]
case class Left[A,B](value:A) extends Sum[A,B]
case class Right[A,B](value:A) extends Sum[A,B]

CS2104

Concepts

40

Language Constructs
and Binders
CS2104

Concepts

41

Language Constructs
Language constructs are features used to build
programs
Statements vs Expressions
Statement executed for their effects
Expression computes a result and may have
effects too.
Statement a special case of expression
Examples of Constructs
Blocks, Conditional, Sequences,
Exceptions, Loops, Calls

CS2104

Concepts

42

Language Construct (for C)


Statement

option

terminals

<stmt> ::= if (<exp>) <stmt> [else <stmt>]


| {<stmt>}
| <type> <id>
| <id> = <exp>
non-terminal
| <stmt> ; <stmt>
| loop-stmt | break | continue
| switch (<exp>)
alternatives
{ case <exp>
: <stmt>; ..;
default : <stmt>; }
| return <exp>
| <id>(<exp>*)
| ..
repetition
CS2104

Concepts

43

Language Construct (for C)


Loop Statement
<loop-stmt> ::=
for(<var_init>; <exp>; <var_upd>) <stmt>
| while (<exp>) <stmt>
| do {<stmt>} while (<exp>)

Expression
<exp> ::= <id>
| <id>(<exp>*)
| <exp> ? <exp> : <exp>
| <op> <exp> | <exp> <op>
| <exp> <op> <exp>

CS2104

Concepts

44

Binders
Binders are a special class of constructs which
declare new identifiers and their possible values.
Each binder has some lexical scope where the
identifier is visible.
Values of the binders may be either immutable or
mutable.
Examples of name binders
Local declarations
Method declaration (parameters)
Pattern-Matching
CS2104

Concepts

45

Binders (in C)
Block Declaration

scope of
local variable

{ ;
<type> <id>;

names

Method Declaration

scope of
parameters

CS2104

<type> <id>((<type> <id>)*)


{

Concepts

46

Examples (for C)
Each name may appear only once in each block, but
the name from an inner block can shadow an
identical name from its outer block.
Example : inner i shadowed the outer i name
int main() {
int i;
i=3;
i from
outer block
{ int i;
i=4;
printf("inner i is %d\n",i);
}
printf("outer i is %d\n",i);
}

CS2104

Concepts

i from
inner block

47

Language Construct (for Scala)


Expression-Oriented Constructs
<exp> ::= if (<exp>) <exp> else <exp>
| <id>
| <exp>:<type>
| <exp> <exp>
| (<exp>,..,<exp>)
| throw <exp>
| def <id> () = <exp>
| val <id> = <exp>
| var <id> = <exp>
| <exp> match {(case <pat> => <exp>)+ }
|
def/val declaration and match pattern contains binders

that are immutable (bound values cannot be changed).


var declaration binders that is mutable (can be
changed).
CS2104

Concepts

48

Language Construct (for Scala)


Value Declarations
val x = e1;;
val y = e2;;
val z = e3;;

Variable Declaration (that can be mutated):


var a = e1
a = a + 1

CS2104

Concepts

49

Examples (in Scala)


Expression-oriented methods.
def max (x:Int,y:Int) =
if (x<y) y else x;;

What is the type of max?


max : (int,int) -> int

What is the scope of max?


rest of block

What is the scope of x,y?


RHS of = binding till ;;
CS2104

Concepts

50

Examples (in Scala)


Recursive methods (result type needs to be given):
def fact (n:Int) : Int =
if (n==0) 1 else n * fact (n-1)

What is the type of fact?


fact: int -> int

What is the scope of fact?


expression after = and rest of the block

What is the scope of n?


expression after = only
CS2104

Concepts

51

Pattern-Matching in Scala
Pattern-matching can be organized as an expression.
def height(t:Tree[A]):Int = t match {
case Leaf _
=> 1
case Node(l,r) =>
max(height l, height r) }
val h = height(Node(Leaf 1,Node(Leaf 2,Leaf 3)))

What is the type of height?

height: tree -> int

What is the lexical scope of height?

expressions after = and till end of block

What is the lexical scope of t?


expressions after = only

What is the scope of pattern variables l,r ?


expressions after => only

CS2104

Concepts

52

Exception
Exceptions are used to make code more robust by
signalling error scenarios that might be handled.
For example, in Java, accessing NULL pointer
triggers an exception.

CS2104

Concepts

53

Exception in Java
Exception constructs are statements in Java.
Statement throw e yields an exception

Try-catch block
try {

} catch (ExceptionType name) {

} catch (ExceptionType name) {

CS2104

Concepts

54

Exception in Scala
Exceptions are case-classes in Scala.
case class UnderAgeException(message: String)
extends Exception(message)
def buyCigarettes(customer: Customer): Cigarettes =
if (customer.age < 16)
throw UnderAgeException(s"Customer must be older
than 16 but was ${customer.age}")
else new Cigarettes

CS2104

Concepts

55

Exception in Scala
Try-catch block are expression-oriented in Scala as
opposed to statement-based in Java.
val c =
try {
buyCigarettes(c)
"Yo, here are your cancer sticks! Happy smokin'!"
} catch {
case UnderAgeException(msg) => msg
}

CS2104

Concepts

56

Loops vs Methods

CS2104

Concepts

57

Loops
Loops are efficient computational structure but
requires mutable variables. An example (in C):
int fact(int n) {
int res = 1;
while (n>0) {
res = res * n;
n--;
}
return res;
}

Uses constant stack space but requires variables to


be modified during loop iteration.

CS2104

Concepts

58

Recursive Methods
Can use recursive methods instead:
int fact(int n) {
if (n<=0) return 1;
else return n * fact(n-1);
}

Each recursive call can have a different argument,


and would return the factorial of that argument.
Advantage : No mutable variable!

Overhead : requires stack space to support each


recursive method invocation
CS2104

Concepts

59

Tail-Recursive Methods (Definition)


A method is tail-recursive if the last operation in
recursive branch is the recursive call.
int fact(int n) {
if (n<=0) return 1;
else return n * fact(n-1);
}

Why is this method not tail-recursive?

What is the last operation of the recursive branch?

CS2104

Concepts

60

Tail-Recursive Methods
We can support tail-recursive method with an extra
accumulating parameter.
int fact(int n) {
if (n<=0) return 1;
else return factit(n,1);
}
int factit(int n, int res) {
if (n==0) return res;
else return factit(n-1,n*res);
}

What is the last operation of the recursive branch of


factit method?
CS2104

Concepts

61

Importance of Tail-Recursive Methods


Last call of each method do not require stack frame.
Instead, we can use a tail-call optimization that reuses the stack frame of its parent call.
int factit(int n, int res) {
if (n==0) return res;
else { res=n*res; n=n-1;
return factit(n,res) };
}

int factit(int n, int res) {


L: if (n==0) return res;
else { res=n*res; n=n-1;
goto L };
}
CS2104

Concepts

62

Pure vs Impure
Features

CS2104

Concepts

63

Pure vs Impure
Pure operations (in Ocaml) do not allow variables to
be re-assigned after initial binding. These tend to be
expression-oriented.
let x = 1;;

let x = x + 1;;

(* new x *)

Impure operations (in C) allow values of variable to


change. These tend to be statement-oriented.
int x = 1;
x = x + 1;

CS2104

(* x updated to new value *)

Concepts

64

Impure Method (in C)


Impure method has side-effects.
Consider an example to join ys to the end of a nonempty list xs. This method has side-effect since it
modifies xs.
void append(node xs, node ys)
{
if (xs->next==NULL) xs->next = ys
else append(xs->next,ys);
}

CS2104

Concepts

65

Pure Method (in C)


Pure method do not have any side-effects.
Consider an example to return a new list that
denotes a catenation of xs and ys . This method is
side-effect free since it does not change its inputs
nor any global variables.
node append(node xs, node ys)
{
if (xs==NULL) return ys
else {
node r = append(xs->next,ys);
r = new node(xs->val,r);
return r;
}
}
CS2104

Concepts

66

Pure Methods
Factors to support pure methods (functions).
expression-oriented language.

bound variables cannot be modified


return new data structure rather than modified ones
allow free sharing of immutable data structure
use recursive functions instead of loops.

CS2104

Concepts

67

Evaluation Order

CS2104

Concepts

68

Evaluation Order
Expressions are evaluated in a certain order.
Strict Evaluation
Evaluate eagerly
Evaluate left-to-right order
Lazy Evaluation
Evaluate only when needed
Create suspension (to denote unevaluated value)
Speculative Evaluation
Advanced evaluation (that may be discarded)
Support better parallelism

CS2104

Concepts

69

Strict Evaluation (C Language & Scala)


Strict evaluation is typically done sequentially (topdown) and in a left-to-right order.
Example in C:
v1 = e1;
v2 = e2;
v3 = mn(e4,e5,e6);

Example in Scala
val v1 = e1;;
val v2 = e2;;
val v3 = mn(e4,e5,e6);;

CS2104

Concepts

70

Non-Strict Evaluation (in Scala)


Non-strict evaluation are supported in short-circuit
operators.
def loop () : Nothing = loop ();;
val v = true || loop ();;

Also, conditionals are expressions that are non-strict


on the branches.
val v = if (true) 1
else (loop ())

CS2104

Concepts

71

Strict Method Arguments (Scala)


Arguments of method calls are strict by default.
def fn_if[T](a:Boolean,b:T,c:T)
= if (a) b else c
val v = fn_if(true,1,loop ());;

Above code goes into infinite loop as arguments of


methods are evaluated strictly.

Above method is polymorphic with T as type


variable. An example of a monomorphic (integer)
method is:
def fn_if_int(a:Boolean,b:Int,c:Int)
= if (a) b else c
CS2104

Concepts

72

Lazy Method Arguments (Scala)


Lazy parameters can be specified in Scala, as follows:
def fn_if_lazy[T](a:Boolean,b: => T,c: => T)
= if (a) b else c
val v = fn_if_lazy(true,1,loop ());;

Above code terminates with value 1.


The use of => T is to denote that this is a lazy
closure with a value of type T

CS2104

Concepts

73

Lazy Evaluation (in Haskell and Miranda)


In Haskell, method arguments are evaluated lazily
by default.
fn_if a b c =
if a then b else c;;

v = fn_if true 1 (loop ());;

This code terminates in Haskell, despite the loop,


due to use of lazy evaluation.
Lazy evaluation terminates more often but are more
costly to execute and makes debugging harder.

CS2104

Concepts

74

Speculative Evaluation
Speculation can be used to utilize parallelism.
val v = compute1(..) in
if (v>0) then v
else {val w = compute2(..); w }

Speculate that w may be needed.


val w = fork(compute2(..))
val v = (compute1(..))
if (v>0) {kill w; v}
else w

CS2104

Concepts

75

Strong vs
Weak Typing
CS2104

Concepts

76

Strong vs Weak Typing


Strongly-Typed (e.g OCaml, Scala, Haskell)
Every expression has a type
Advantage more secure code
Disadvantage annotation efforts;
- requires type inference otherwise
Un-Typed (e.g Lisp, Python, Prolog)
Support some universal type
Advantage write faster code
Disadvantage may have errors at runtime.

Weakly-typed (e.g. C)
Some type errors at run-time
Uses casting
e.g. void*
CS2104

Concepts

77

Das könnte Ihnen auch gefallen