Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
From Principles to Practicewith Classin the First Year
Sam Tobin-HochstadtDavid Van Horn
1 2 3 4
1 2 3 4
Principles
1 2 3 4
Principles
Practice
1 2 3 4
Principles
Practice
11 2 3 4
Industrial co-op
Principles
Practice
1
Principles
Practice
Industrial co-op
Principles
Practice
Principles
Practice
Principles
Practice
Principles
Practice
Under consideration for publication in J. Functional Programming 1
EDUCATIONAL PEARL
The Structure and Interpretation of the
Computer Science Curriculum
Matthias Felleisen, Northeastern University, Boston, MA, USA
Robert Bruce Findler, University of Chicago, Chicago, IL, USA
Matthew Flatt, University of Utah, Salt Lake City, UT, USA
Shriram Krishnamurthi, Brown University, Providence, RI, USA
Email: {matthias,robby,mflatt,shriram}@plt-scheme.org
Abstract
Twenty years ago Abelson and Sussman’s Structure and Interpretation of Computer Pro-grams radically changed the intellectual landscape of introductory computing courses. In-stead of teaching some currently fashionable programming language, it employed Schemeand functional programming to teach important ideas. Introductory courses based on thebook showed up around the world and made Scheme and functional programming popular.Unfortunately, these courses quickly disappeared again due to shortcomings of the bookand the whimsies of Scheme. Worse, the experiment left people with a bad impression ofScheme and functional programming in general.
In this pearl, we propose an alternative role for functional programming in the first-yearcurriculum. Specifically, we present a framework for discussing the first-year curriculumand, based on it, the design rationale for our book and course, dubbed How to Design
Programs. The approach emphasizes the systematic design of programs. Experience showsthat it works extremely well as a preparation for a course on object-oriented programming.
1 History and critique
The publication of Abelson and Sussman’s Structure and Interpretation of Com-
puter Programs (sicp) (Abelson et al., 1985) revolutionized the landscape of theintroductory computing curriculum in the 1980s. Most importantly, the book lib-erated the introductory course from the tyranny of syntax. Instead of arranging acourse around the syntax of a currently fashionable programming language, sicp
focused the first course on the study of important ideas in computing: functional ab-straction, data abstraction, streams, data-directed programming, implementationof message-passing objects, interpreters, compilers, and register machines.
Over a short period, many universities in the US and around the world switchedtheir first course to sicp and Scheme. The book became a major bestseller for MITPress.1 Along with sicp, the Scheme programming language (Sussman & Steele Jr.,
1 According to Bob Prior (editor at MIT Press), sicp sold 45,000 copies in its first five years[personal communication, 9 June 2003].
Under consideration for publication in J. Functional Programming 1
EDUCATIONAL PEARL
The Structure and Interpretation of the
Computer Science Curriculum
Matthias Felleisen, Northeastern University, Boston, MA, USA
Robert Bruce Findler, University of Chicago, Chicago, IL, USA
Matthew Flatt, University of Utah, Salt Lake City, UT, USA
Shriram Krishnamurthi, Brown University, Providence, RI, USA
Email: {matthias,robby,mflatt,shriram}@plt-scheme.org
Abstract
Twenty years ago Abelson and Sussman’s Structure and Interpretation of Computer Pro-grams radically changed the intellectual landscape of introductory computing courses. In-stead of teaching some currently fashionable programming language, it employed Schemeand functional programming to teach important ideas. Introductory courses based on thebook showed up around the world and made Scheme and functional programming popular.Unfortunately, these courses quickly disappeared again due to shortcomings of the bookand the whimsies of Scheme. Worse, the experiment left people with a bad impression ofScheme and functional programming in general.
In this pearl, we propose an alternative role for functional programming in the first-yearcurriculum. Specifically, we present a framework for discussing the first-year curriculumand, based on it, the design rationale for our book and course, dubbed How to Design
Programs. The approach emphasizes the systematic design of programs. Experience showsthat it works extremely well as a preparation for a course on object-oriented programming.
1 History and critique
The publication of Abelson and Sussman’s Structure and Interpretation of Com-
puter Programs (sicp) (Abelson et al., 1985) revolutionized the landscape of theintroductory computing curriculum in the 1980s. Most importantly, the book lib-erated the introductory course from the tyranny of syntax. Instead of arranging acourse around the syntax of a currently fashionable programming language, sicp
focused the first course on the study of important ideas in computing: functional ab-straction, data abstraction, streams, data-directed programming, implementationof message-passing objects, interpreters, compilers, and register machines.
Over a short period, many universities in the US and around the world switchedtheir first course to sicp and Scheme. The book became a major bestseller for MITPress.1 Along with sicp, the Scheme programming language (Sussman & Steele Jr.,
1 According to Bob Prior (editor at MIT Press), sicp sold 45,000 copies in its first five years[personal communication, 9 June 2003].
Under consideration for publication in J. Functional Programming 1
EDUCATIONAL PEARL
The Structure and Interpretation of the
Computer Science Curriculum
Matthias Felleisen, Northeastern University, Boston, MA, USA
Robert Bruce Findler, University of Chicago, Chicago, IL, USA
Matthew Flatt, University of Utah, Salt Lake City, UT, USA
Shriram Krishnamurthi, Brown University, Providence, RI, USA
Email: {matthias,robby,mflatt,shriram}@plt-scheme.org
Abstract
Twenty years ago Abelson and Sussman’s Structure and Interpretation of Computer Pro-grams radically changed the intellectual landscape of introductory computing courses. In-stead of teaching some currently fashionable programming language, it employed Schemeand functional programming to teach important ideas. Introductory courses based on thebook showed up around the world and made Scheme and functional programming popular.Unfortunately, these courses quickly disappeared again due to shortcomings of the bookand the whimsies of Scheme. Worse, the experiment left people with a bad impression ofScheme and functional programming in general.
In this pearl, we propose an alternative role for functional programming in the first-yearcurriculum. Specifically, we present a framework for discussing the first-year curriculumand, based on it, the design rationale for our book and course, dubbed How to Design
Programs. The approach emphasizes the systematic design of programs. Experience showsthat it works extremely well as a preparation for a course on object-oriented programming.
1 History and critique
The publication of Abelson and Sussman’s Structure and Interpretation of Com-
puter Programs (sicp) (Abelson et al., 1985) revolutionized the landscape of theintroductory computing curriculum in the 1980s. Most importantly, the book lib-erated the introductory course from the tyranny of syntax. Instead of arranging acourse around the syntax of a currently fashionable programming language, sicp
focused the first course on the study of important ideas in computing: functional ab-straction, data abstraction, streams, data-directed programming, implementationof message-passing objects, interpreters, compilers, and register machines.
Over a short period, many universities in the US and around the world switchedtheir first course to sicp and Scheme. The book became a major bestseller for MITPress.1 Along with sicp, the Scheme programming language (Sussman & Steele Jr.,
1 According to Bob Prior (editor at MIT Press), sicp sold 45,000 copies in its first five years[personal communication, 9 June 2003].
1. Introduce only those language constructs that are necessary to teach programming principles
Under consideration for publication in J. Functional Programming 1
EDUCATIONAL PEARL
The Structure and Interpretation of the
Computer Science Curriculum
Matthias Felleisen, Northeastern University, Boston, MA, USA
Robert Bruce Findler, University of Chicago, Chicago, IL, USA
Matthew Flatt, University of Utah, Salt Lake City, UT, USA
Shriram Krishnamurthi, Brown University, Providence, RI, USA
Email: {matthias,robby,mflatt,shriram}@plt-scheme.org
Abstract
Twenty years ago Abelson and Sussman’s Structure and Interpretation of Computer Pro-grams radically changed the intellectual landscape of introductory computing courses. In-stead of teaching some currently fashionable programming language, it employed Schemeand functional programming to teach important ideas. Introductory courses based on thebook showed up around the world and made Scheme and functional programming popular.Unfortunately, these courses quickly disappeared again due to shortcomings of the bookand the whimsies of Scheme. Worse, the experiment left people with a bad impression ofScheme and functional programming in general.
In this pearl, we propose an alternative role for functional programming in the first-yearcurriculum. Specifically, we present a framework for discussing the first-year curriculumand, based on it, the design rationale for our book and course, dubbed How to Design
Programs. The approach emphasizes the systematic design of programs. Experience showsthat it works extremely well as a preparation for a course on object-oriented programming.
1 History and critique
The publication of Abelson and Sussman’s Structure and Interpretation of Com-
puter Programs (sicp) (Abelson et al., 1985) revolutionized the landscape of theintroductory computing curriculum in the 1980s. Most importantly, the book lib-erated the introductory course from the tyranny of syntax. Instead of arranging acourse around the syntax of a currently fashionable programming language, sicp
focused the first course on the study of important ideas in computing: functional ab-straction, data abstraction, streams, data-directed programming, implementationof message-passing objects, interpreters, compilers, and register machines.
Over a short period, many universities in the US and around the world switchedtheir first course to sicp and Scheme. The book became a major bestseller for MITPress.1 Along with sicp, the Scheme programming language (Sussman & Steele Jr.,
1 According to Bob Prior (editor at MIT Press), sicp sold 45,000 copies in its first five years[personal communication, 9 June 2003].
1. Introduce only those language constructs that are necessary to teach programming principles
2. Choose a language with as few language constructs as possible, and one in which they can be introduced one at a time
regular, minimal syntax
regular, minimal syntax complicated irregular syntax
regular, minimal syntax complicated irregular syntax
untyped
regular, minimal syntax complicated irregular syntax
untyped typed
regular, minimal syntax complicated irregular syntax
untyped typed
pedagogical environment
regular, minimal syntax complicated irregular syntax
untyped typed
pedagogical environment industrial environment
regular, minimal syntax complicated irregular syntax
untyped typed
pedagogical environment industrial environment
mathematical numbers
regular, minimal syntax complicated irregular syntax
untyped typed
pedagogical environment industrial environment
mathematical numbers machine numbers
regular, minimal syntax complicated irregular syntax
untyped typed
pedagogical environment industrial environment
mathematical numbers machine numbers
images as values
regular, minimal syntax complicated irregular syntax
untyped typed
pedagogical environment industrial environment
mathematical numbers machine numbers
images as values ?
regular, minimal syntax complicated irregular syntax
untyped typed
pedagogical environment industrial environment
mathematical numbers machine numbers
images as values ?
interaction
regular, minimal syntax complicated irregular syntax
untyped typed
pedagogical environment industrial environment
mathematical numbers machine numbers
images as values ?
interaction compilation
regular, minimal syntax complicated irregular syntax
untyped typed
pedagogical environment industrial environment
mathematical numbers machine numbers
images as values ?
interaction compilation
regular, minimal syntax complicated irregular syntax
untyped typed
pedagogical environment industrial environment
mathematical numbers machine numbers
images as values ?
interaction compilation
functions and structures
regular, minimal syntax complicated irregular syntax
untyped typed
pedagogical environment industrial environment
mathematical numbers machine numbers
images as values ?
interaction compilation
functions and structures objects
regular, minimal syntax
untyped
pedagogical environment
mathematical numbers
images as values
interaction
functions and structures objects
objects
1. Introduce only those language constructs that are necessary to teach programming principles
2. Choose a language with as few language constructs as possible, and one in which they can be introduced one at a time
objects
1. Introduce only those language constructs that are necessary to teach programming principles
2. Choose a language with as few language constructs as possible, and one in which they can be introduced one at a time
S. Tobin-Hochstadt & D. Van Horn 5
included with each method definition, following the principles of the design recipe studied in the firstsemester. In fact, the check-expect mechanism works exactly as it did before.
Methods can be defined to consume any number of arguments, but they are implicitly parameterizedover this, the object that was sent the message.
3.2 Where did the cond go?
Unions, and recursive unions in particular, are a fundamental kind of data definition that students arewell-versed in from the previous semester. A fundamental early lesson is how to represent (recursive)unions using classes and how to write recursive methods. As an example, figure 1 defines binary trees ofnumbers (an archetypal recursive union data definition) using the BSL language and the Class language.
#lang bsl
;; A Tree is one of:
;; - (make-leaf Number)
;; - (make-node Tree Number Tree)
(define-struct leaf (v))
(define-struct node (left v right))
;; sum : Tree -> Number
;; sums the elements of the given tree
(define (sum a-tree)
(cond [(leaf? a-tree) (leaf-v a-tree)]
[else
(+ (sum (node-left a-tree))
(node-v a-tree)
(sum (node-right a-tree)))]))
(check-expect (sum (make-leaf 7)) 7)
(check-expect
(sum (make-node
(make-leaf 1)
5
(make-node (make-leaf 0)
10
(make-leaf 0))))
16)
#lang class/1
;; A Tree is one of:
;; - (new leaf Number)
;; - (new node Tree Number Tree)
;; and implements
;; sum : -> Number
;; sums the elements of this tree
(define-class leaf
(fields v)
(define (sum) (this . v)))
(define-class node
(fields left v right)
(define (sum)
(+ (this . left . sum)
(this . v)
(this . right .sum))))
(check-expect ((new leaf 7) . sum) 7)
(check-expect
((new node
(new leaf 1)
5
(new node (new leaf 0)
10
(new leaf 0))))
. sum)
16)
Figure 1: Binary tree sum in Beginning Student and in the Class language
The structure of this data definition is analogous to the approach of the previous semester but thisexample brings to light an important difference with the functional approach. The method for computingthe sum of the empty tree is defined in the leaf class, while the method for computing the sum of a node
objects
#lang class/0(define-class posn (fields x y))(new posn 3 4)(send (new posn 3 4) x) ;=> 3(send (new posn 3 4) y) ;=> 4
objects
#lang class/1(define-class posn (fields x y))(new posn 3 4)((new posn 3 4) . x) ;=> 3((new posn 3 4) . y) ;=> 4
objects
#lang class/1(define-class posn (fields x y) ;; Posn -> Number ;; Distance between this posn and that posn (check-expect ((new posn 0 0) . dist (new posn 3 4)) 5) (define (dist that) (sqrt (+ (sqr (- (this . x) (that . x))) (sqr (- (this . y) (that . y)))))) ;; -> Number ;; Distance of this posn from the origin (check-expect ((new posn 0 0) . dist-origin) 0) (check-expect ((new posn 3 4) . dist-origin) 5) (define (dist-origin) (this . dist (new posn 0 0))))
objects
#lang class/1 ;;A Tree is one of:;; - (new leaf Number);; - (new node Tree Number Tree);; and implements;; sum : -> Number;; sums the elements of this tree(define-class leaf (fields v) (define (sum) (this . v)))
(define-class node (fields left v right) (define (sum) (+ (this . left . sum) (this . v) (this . right . sum))))
(check-expect ((new leaf 7) . sum) 7)(check-expect ((new node (new leaf 1) 5 (new node (new leaf 0) 10 (new leaf 0))) . sum) 16)
#lang class/1 ;; A Tree is one of:;; - (make-leaf Number);; - (make-node Tree Number Tree)(define-struct leaf (v))(define-struct node (left v right))
;; sum : Tree -> Number;; sums the elements of the given tree(define (sum a-tree) (cond [(leaf? a-tree) (leaf-v a-tree)] [else (+ (sum (node-left a-tree)) (node-v a-tree) (sum (node-right a-tree)))]))
objects
objects
#lang class/1(require 2htdp/image class/universe)
;; A World is a (new world Number)(define-class world (fields n)
;; on-tick : -> World (define (on-tick) (new world (add1 (this . n))))
;; to-draw : -> Image (define (to-draw) (rotate (modulo (this . n) 360)
))
;; on-key : KeyEvent -> World (define (on-key k) (new world 10)))
(big-bang (new world 0))
#lang class/1(require 2htdp/image 2htdp/universe)
;; A World is a Number(define-struct world (n))
;; tock : World -> World(define (tock w) (make-world (add1 (world-n w))))
;; draw : World -> Image(define (draw w) (rotate (modulo (world-n w) 360)
))
;; : KeyEvent World -> World(define (press k w) (make-world 0))
(big-bang (make-world 0) [on-tick tock] [on-draw draw] [on-key press])
objects
S. Tobin-Hochstadt & D. Van Horn 5
included with each method definition, following the principles of the design recipe studied in the firstsemester. In fact, the check-expect mechanism works exactly as it did before.
Methods can be defined to consume any number of arguments, but they are implicitly parameterizedover this, the object that was sent the message.
3.2 Where did the cond go?
Unions, and recursive unions in particular, are a fundamental kind of data definition that students arewell-versed in from the previous semester. A fundamental early lesson is how to represent (recursive)unions using classes and how to write recursive methods. As an example, figure 1 defines binary trees ofnumbers (an archetypal recursive union data definition) using the BSL language and the Class language.
#lang bsl
;; A Tree is one of:
;; - (make-leaf Number)
;; - (make-node Tree Number Tree)
(define-struct leaf (v))
(define-struct node (left v right))
;; sum : Tree -> Number
;; sums the elements of the given tree
(define (sum a-tree)
(cond [(leaf? a-tree) (leaf-v a-tree)]
[else
(+ (sum (node-left a-tree))
(node-v a-tree)
(sum (node-right a-tree)))]))
(check-expect (sum (make-leaf 7)) 7)
(check-expect
(sum (make-node
(make-leaf 1)
5
(make-node (make-leaf 0)
10
(make-leaf 0))))
16)
#lang class/1
;; A Tree is one of:
;; - (new leaf Number)
;; - (new node Tree Number Tree)
;; and implements
;; sum : -> Number
;; sums the elements of this tree
(define-class leaf
(fields v)
(define (sum) (this . v)))
(define-class node
(fields left v right)
(define (sum)
(+ (this . left . sum)
(this . v)
(this . right .sum))))
(check-expect ((new leaf 7) . sum) 7)
(check-expect
((new node
(new leaf 1)
5
(new node (new leaf 0)
10
(new leaf 0))))
. sum)
16)
Figure 1: Binary tree sum in Beginning Student and in the Class language
The structure of this data definition is analogous to the approach of the previous semester but thisexample brings to light an important difference with the functional approach. The method for computingthe sum of the empty tree is defined in the leaf class, while the method for computing the sum of a node
0. objects
S. Tobin-Hochstadt & D. Van Horn 5
included with each method definition, following the principles of the design recipe studied in the firstsemester. In fact, the check-expect mechanism works exactly as it did before.
Methods can be defined to consume any number of arguments, but they are implicitly parameterizedover this, the object that was sent the message.
3.2 Where did the cond go?
Unions, and recursive unions in particular, are a fundamental kind of data definition that students arewell-versed in from the previous semester. A fundamental early lesson is how to represent (recursive)unions using classes and how to write recursive methods. As an example, figure 1 defines binary trees ofnumbers (an archetypal recursive union data definition) using the BSL language and the Class language.
#lang bsl
;; A Tree is one of:
;; - (make-leaf Number)
;; - (make-node Tree Number Tree)
(define-struct leaf (v))
(define-struct node (left v right))
;; sum : Tree -> Number
;; sums the elements of the given tree
(define (sum a-tree)
(cond [(leaf? a-tree) (leaf-v a-tree)]
[else
(+ (sum (node-left a-tree))
(node-v a-tree)
(sum (node-right a-tree)))]))
(check-expect (sum (make-leaf 7)) 7)
(check-expect
(sum (make-node
(make-leaf 1)
5
(make-node (make-leaf 0)
10
(make-leaf 0))))
16)
#lang class/1
;; A Tree is one of:
;; - (new leaf Number)
;; - (new node Tree Number Tree)
;; and implements
;; sum : -> Number
;; sums the elements of this tree
(define-class leaf
(fields v)
(define (sum) (this . v)))
(define-class node
(fields left v right)
(define (sum)
(+ (this . left . sum)
(this . v)
(this . right .sum))))
(check-expect ((new leaf 7) . sum) 7)
(check-expect
((new node
(new leaf 1)
5
(new node (new leaf 0)
10
(new leaf 0))))
. sum)
16)
Figure 1: Binary tree sum in Beginning Student and in the Class language
The structure of this data definition is analogous to the approach of the previous semester but thisexample brings to light an important difference with the functional approach. The method for computingthe sum of the empty tree is defined in the leaf class, while the method for computing the sum of a node
0. objects
S. Tobin-Hochstadt & D. Van Horn 5
included with each method definition, following the principles of the design recipe studied in the firstsemester. In fact, the check-expect mechanism works exactly as it did before.
Methods can be defined to consume any number of arguments, but they are implicitly parameterizedover this, the object that was sent the message.
3.2 Where did the cond go?
Unions, and recursive unions in particular, are a fundamental kind of data definition that students arewell-versed in from the previous semester. A fundamental early lesson is how to represent (recursive)unions using classes and how to write recursive methods. As an example, figure 1 defines binary trees ofnumbers (an archetypal recursive union data definition) using the BSL language and the Class language.
#lang bsl
;; A Tree is one of:
;; - (make-leaf Number)
;; - (make-node Tree Number Tree)
(define-struct leaf (v))
(define-struct node (left v right))
;; sum : Tree -> Number
;; sums the elements of the given tree
(define (sum a-tree)
(cond [(leaf? a-tree) (leaf-v a-tree)]
[else
(+ (sum (node-left a-tree))
(node-v a-tree)
(sum (node-right a-tree)))]))
(check-expect (sum (make-leaf 7)) 7)
(check-expect
(sum (make-node
(make-leaf 1)
5
(make-node (make-leaf 0)
10
(make-leaf 0))))
16)
#lang class/1
;; A Tree is one of:
;; - (new leaf Number)
;; - (new node Tree Number Tree)
;; and implements
;; sum : -> Number
;; sums the elements of this tree
(define-class leaf
(fields v)
(define (sum) (this . v)))
(define-class node
(fields left v right)
(define (sum)
(+ (this . left . sum)
(this . v)
(this . right .sum))))
(check-expect ((new leaf 7) . sum) 7)
(check-expect
((new node
(new leaf 1)
5
(new node (new leaf 0)
10
(new leaf 0))))
. sum)
16)
Figure 1: Binary tree sum in Beginning Student and in the Class language
The structure of this data definition is analogous to the approach of the previous semester but thisexample brings to light an important difference with the functional approach. The method for computingthe sum of the empty tree is defined in the leaf class, while the method for computing the sum of a node
0. objects
1. shorthand method call
S. Tobin-Hochstadt & D. Van Horn 5
included with each method definition, following the principles of the design recipe studied in the firstsemester. In fact, the check-expect mechanism works exactly as it did before.
Methods can be defined to consume any number of arguments, but they are implicitly parameterizedover this, the object that was sent the message.
3.2 Where did the cond go?
Unions, and recursive unions in particular, are a fundamental kind of data definition that students arewell-versed in from the previous semester. A fundamental early lesson is how to represent (recursive)unions using classes and how to write recursive methods. As an example, figure 1 defines binary trees ofnumbers (an archetypal recursive union data definition) using the BSL language and the Class language.
#lang bsl
;; A Tree is one of:
;; - (make-leaf Number)
;; - (make-node Tree Number Tree)
(define-struct leaf (v))
(define-struct node (left v right))
;; sum : Tree -> Number
;; sums the elements of the given tree
(define (sum a-tree)
(cond [(leaf? a-tree) (leaf-v a-tree)]
[else
(+ (sum (node-left a-tree))
(node-v a-tree)
(sum (node-right a-tree)))]))
(check-expect (sum (make-leaf 7)) 7)
(check-expect
(sum (make-node
(make-leaf 1)
5
(make-node (make-leaf 0)
10
(make-leaf 0))))
16)
#lang class/1
;; A Tree is one of:
;; - (new leaf Number)
;; - (new node Tree Number Tree)
;; and implements
;; sum : -> Number
;; sums the elements of this tree
(define-class leaf
(fields v)
(define (sum) (this . v)))
(define-class node
(fields left v right)
(define (sum)
(+ (this . left . sum)
(this . v)
(this . right .sum))))
(check-expect ((new leaf 7) . sum) 7)
(check-expect
((new node
(new leaf 1)
5
(new node (new leaf 0)
10
(new leaf 0))))
. sum)
16)
Figure 1: Binary tree sum in Beginning Student and in the Class language
The structure of this data definition is analogous to the approach of the previous semester but thisexample brings to light an important difference with the functional approach. The method for computingthe sum of the empty tree is defined in the leaf class, while the method for computing the sum of a node
0. objects
1. shorthand method call
2. inheritance
S. Tobin-Hochstadt & D. Van Horn 5
included with each method definition, following the principles of the design recipe studied in the firstsemester. In fact, the check-expect mechanism works exactly as it did before.
Methods can be defined to consume any number of arguments, but they are implicitly parameterizedover this, the object that was sent the message.
3.2 Where did the cond go?
Unions, and recursive unions in particular, are a fundamental kind of data definition that students arewell-versed in from the previous semester. A fundamental early lesson is how to represent (recursive)unions using classes and how to write recursive methods. As an example, figure 1 defines binary trees ofnumbers (an archetypal recursive union data definition) using the BSL language and the Class language.
#lang bsl
;; A Tree is one of:
;; - (make-leaf Number)
;; - (make-node Tree Number Tree)
(define-struct leaf (v))
(define-struct node (left v right))
;; sum : Tree -> Number
;; sums the elements of the given tree
(define (sum a-tree)
(cond [(leaf? a-tree) (leaf-v a-tree)]
[else
(+ (sum (node-left a-tree))
(node-v a-tree)
(sum (node-right a-tree)))]))
(check-expect (sum (make-leaf 7)) 7)
(check-expect
(sum (make-node
(make-leaf 1)
5
(make-node (make-leaf 0)
10
(make-leaf 0))))
16)
#lang class/1
;; A Tree is one of:
;; - (new leaf Number)
;; - (new node Tree Number Tree)
;; and implements
;; sum : -> Number
;; sums the elements of this tree
(define-class leaf
(fields v)
(define (sum) (this . v)))
(define-class node
(fields left v right)
(define (sum)
(+ (this . left . sum)
(this . v)
(this . right .sum))))
(check-expect ((new leaf 7) . sum) 7)
(check-expect
((new node
(new leaf 1)
5
(new node (new leaf 0)
10
(new leaf 0))))
. sum)
16)
Figure 1: Binary tree sum in Beginning Student and in the Class language
The structure of this data definition is analogous to the approach of the previous semester but thisexample brings to light an important difference with the functional approach. The method for computingthe sum of the empty tree is defined in the leaf class, while the method for computing the sum of a node
0. objects
1. shorthand method call
2. inheritance
3. overriding
S. Tobin-Hochstadt & D. Van Horn 5
included with each method definition, following the principles of the design recipe studied in the firstsemester. In fact, the check-expect mechanism works exactly as it did before.
Methods can be defined to consume any number of arguments, but they are implicitly parameterizedover this, the object that was sent the message.
3.2 Where did the cond go?
Unions, and recursive unions in particular, are a fundamental kind of data definition that students arewell-versed in from the previous semester. A fundamental early lesson is how to represent (recursive)unions using classes and how to write recursive methods. As an example, figure 1 defines binary trees ofnumbers (an archetypal recursive union data definition) using the BSL language and the Class language.
#lang bsl
;; A Tree is one of:
;; - (make-leaf Number)
;; - (make-node Tree Number Tree)
(define-struct leaf (v))
(define-struct node (left v right))
;; sum : Tree -> Number
;; sums the elements of the given tree
(define (sum a-tree)
(cond [(leaf? a-tree) (leaf-v a-tree)]
[else
(+ (sum (node-left a-tree))
(node-v a-tree)
(sum (node-right a-tree)))]))
(check-expect (sum (make-leaf 7)) 7)
(check-expect
(sum (make-node
(make-leaf 1)
5
(make-node (make-leaf 0)
10
(make-leaf 0))))
16)
#lang class/1
;; A Tree is one of:
;; - (new leaf Number)
;; - (new node Tree Number Tree)
;; and implements
;; sum : -> Number
;; sums the elements of this tree
(define-class leaf
(fields v)
(define (sum) (this . v)))
(define-class node
(fields left v right)
(define (sum)
(+ (this . left . sum)
(this . v)
(this . right .sum))))
(check-expect ((new leaf 7) . sum) 7)
(check-expect
((new node
(new leaf 1)
5
(new node (new leaf 0)
10
(new leaf 0))))
. sum)
16)
Figure 1: Binary tree sum in Beginning Student and in the Class language
The structure of this data definition is analogous to the approach of the previous semester but thisexample brings to light an important difference with the functional approach. The method for computingthe sum of the empty tree is defined in the leaf class, while the method for computing the sum of a node
0. objects
1. shorthand method call
2. inheritance
3. overriding
4. first-class classes
S. Tobin-Hochstadt & D. Van Horn 5
included with each method definition, following the principles of the design recipe studied in the firstsemester. In fact, the check-expect mechanism works exactly as it did before.
Methods can be defined to consume any number of arguments, but they are implicitly parameterizedover this, the object that was sent the message.
3.2 Where did the cond go?
Unions, and recursive unions in particular, are a fundamental kind of data definition that students arewell-versed in from the previous semester. A fundamental early lesson is how to represent (recursive)unions using classes and how to write recursive methods. As an example, figure 1 defines binary trees ofnumbers (an archetypal recursive union data definition) using the BSL language and the Class language.
#lang bsl
;; A Tree is one of:
;; - (make-leaf Number)
;; - (make-node Tree Number Tree)
(define-struct leaf (v))
(define-struct node (left v right))
;; sum : Tree -> Number
;; sums the elements of the given tree
(define (sum a-tree)
(cond [(leaf? a-tree) (leaf-v a-tree)]
[else
(+ (sum (node-left a-tree))
(node-v a-tree)
(sum (node-right a-tree)))]))
(check-expect (sum (make-leaf 7)) 7)
(check-expect
(sum (make-node
(make-leaf 1)
5
(make-node (make-leaf 0)
10
(make-leaf 0))))
16)
#lang class/1
;; A Tree is one of:
;; - (new leaf Number)
;; - (new node Tree Number Tree)
;; and implements
;; sum : -> Number
;; sums the elements of this tree
(define-class leaf
(fields v)
(define (sum) (this . v)))
(define-class node
(fields left v right)
(define (sum)
(+ (this . left . sum)
(this . v)
(this . right .sum))))
(check-expect ((new leaf 7) . sum) 7)
(check-expect
((new node
(new leaf 1)
5
(new node (new leaf 0)
10
(new leaf 0))))
. sum)
16)
Figure 1: Binary tree sum in Beginning Student and in the Class language
The structure of this data definition is analogous to the approach of the previous semester but thisexample brings to light an important difference with the functional approach. The method for computingthe sum of the empty tree is defined in the leaf class, while the method for computing the sum of a node
0. objects
1. shorthand method call
2. inheritance
3. overriding
4. first-class classes
5. mutation
0. objects
1. shorthand method call
2. inheritance
3. overriding
4. first-class classes
5. mutation
S. Tobin-Hochstadt & D. Van Horn 5
included with each method definition, following the principles of the design recipe studied in the firstsemester. In fact, the check-expect mechanism works exactly as it did before.
Methods can be defined to consume any number of arguments, but they are implicitly parameterizedover this, the object that was sent the message.
3.2 Where did the cond go?
Unions, and recursive unions in particular, are a fundamental kind of data definition that students arewell-versed in from the previous semester. A fundamental early lesson is how to represent (recursive)unions using classes and how to write recursive methods. As an example, figure 1 defines binary trees ofnumbers (an archetypal recursive union data definition) using the BSL language and the Class language.
#lang bsl
;; A Tree is one of:
;; - (make-leaf Number)
;; - (make-node Tree Number Tree)
(define-struct leaf (v))
(define-struct node (left v right))
;; sum : Tree -> Number
;; sums the elements of the given tree
(define (sum a-tree)
(cond [(leaf? a-tree) (leaf-v a-tree)]
[else
(+ (sum (node-left a-tree))
(node-v a-tree)
(sum (node-right a-tree)))]))
(check-expect (sum (make-leaf 7)) 7)
(check-expect
(sum (make-node
(make-leaf 1)
5
(make-node (make-leaf 0)
10
(make-leaf 0))))
16)
#lang class/1
;; A Tree is one of:
;; - (new leaf Number)
;; - (new node Tree Number Tree)
;; and implements
;; sum : -> Number
;; sums the elements of this tree
(define-class leaf
(fields v)
(define (sum) (this . v)))
(define-class node
(fields left v right)
(define (sum)
(+ (this . left . sum)
(this . v)
(this . right .sum))))
(check-expect ((new leaf 7) . sum) 7)
(check-expect
((new node
(new leaf 1)
5
(new node (new leaf 0)
10
(new leaf 0))))
. sum)
16)
Figure 1: Binary tree sum in Beginning Student and in the Class language
The structure of this data definition is analogous to the approach of the previous semester but thisexample brings to light an important difference with the functional approach. The method for computingthe sum of the empty tree is defined in the leaf class, while the method for computing the sum of a node
8 From Principles to Practice with Class in the First Year
From this point, almost any language that students might use in future co-op positions and courseswould be an appropriate follow-up. Our course transitions to Java, but C#, Python, Ruby, Eiffel, orJavaScript would all work naturally. The key lesson of the transition is that the fundamental principlesunderlying object-oriented programming remain the same between languages, and that learning a newlanguage is primarily a matter of mapping these concepts to specific constructs in the new language.Of course, particular languages also use unique specific mechanisms which need to be taught to use thelanguage effectively, but these are rarely as vital as the cross-language principles.
4.1 Functional Java
The transition begins with replicating the object-oriented style of our teaching languages in Java. In par-ticular, we do not introduce mutation, for loops, or mutable data structures such as arrays or ArrayListsuntil later in the semester. Instead, students design data representations using classes, with interfacesrepresenting unions of data. Additionally, we avoid mention of the distinction between primitive andother values in Java, which is made easier by not using standard libraries early. An example of this styleof programming is presented in figure 3, repeating the binary tree sum from the previous section.
Comparing this figure to the previous example illustrates a number of the differences that studentsare exposed to upon transition to Java.
1. Explicit representation of unions and interfaces in the language. Previously, interfaces were simplydescribed in stylized comments, following the How to Design Programs approach.
2. Types are now specified as part of the program, and are now enforced.3. Java syntax is substantially different and more verbose. For example, constructors must be defined
explicitly.4. The testing environment is somewhat different, and requires additional boilerplate, although we
are able to use the JavaLib framework [19] to support simple testing by structural equality.Of course, there are other differences which cannot be seen from a code snippet.
5. Students must use a new development environment and compiler. In class, we primarily developin a text editor and run the Java compiler at the command line. In labs and on homeworks, studentstypically use the Eclipse IDE.
6. Installing and configuring libraries is now required. Because we use a custom library for testing,students must cope with library installation and class paths on the first day.
Of course, all but the first two of these changes are unrelated to the fundamental lessons we hope toteach—the rest merely present additional hurdles for students.
4.2 Traditional Java
Thanks to the the preparation in the first half of the course, we can cover functional OO programming inJava in a just a few lectures. We then increase the subset of the language we use to encompass mutation,loops, and mutable data structures. We present ArrayLists, followed briefly by arrays. Students use,and then implement, hash tables as well as other mutable and immutable data structures. Conventionalinput and output are treated only very briefly, as we focus instead of both fundamentals and exercisesmaking use of real APIs such as hashing functions or Twitter posting. Finally, while, for, and for-eachloops are presented, following the methodology of How to Design Classes which connects loops tostylized use of recursive functions with accumulators, a technique the students now have two semestersof practice with.
S. Tobin-Hochstadt & D. Van Horn 9
import tester.*;
interface Tree {
// sums the elements of this tree
Integer sum();
}
class Leaf {
Integer v;
Leaf(Integer v) { this.v = v; }
public Integer sum() { return this.v; }
}
class Node {
Tree left; Integer v; Tree right;
Node(Tree l, Integer v, Tree r) {
this.left = l;
this.v = v;
this.right = r;
}
public Integer sum() {
return this.left.sum() + this.v + this.right.sum();
}
}
class Examples {
void test_tree(Tester t) {
t.checkExpect(new Leaf(7).sum(), 7);
t.checkExpect(new Node(new Leaf(1),
5,
new Node(new Leaf(0), 10, new Leaf(0))).sum(),
16);
}
}
Figure 3: Binary tree sum in How to Design Classes
Principles
Practice
Industrial co-op
S. Tobin-Hochstadt & D. Van Horn 5
included with each method definition, following the principles of the design recipe studied in the firstsemester. In fact, the check-expect mechanism works exactly as it did before.
Methods can be defined to consume any number of arguments, but they are implicitly parameterizedover this, the object that was sent the message.
3.2 Where did the cond go?
Unions, and recursive unions in particular, are a fundamental kind of data definition that students arewell-versed in from the previous semester. A fundamental early lesson is how to represent (recursive)unions using classes and how to write recursive methods. As an example, figure 1 defines binary trees ofnumbers (an archetypal recursive union data definition) using the BSL language and the Class language.
#lang bsl
;; A Tree is one of:
;; - (make-leaf Number)
;; - (make-node Tree Number Tree)
(define-struct leaf (v))
(define-struct node (left v right))
;; sum : Tree -> Number
;; sums the elements of the given tree
(define (sum a-tree)
(cond [(leaf? a-tree) (leaf-v a-tree)]
[else
(+ (sum (node-left a-tree))
(node-v a-tree)
(sum (node-right a-tree)))]))
(check-expect (sum (make-leaf 7)) 7)
(check-expect
(sum (make-node
(make-leaf 1)
5
(make-node (make-leaf 0)
10
(make-leaf 0))))
16)
#lang class/1
;; A Tree is one of:
;; - (new leaf Number)
;; - (new node Tree Number Tree)
;; and implements
;; sum : -> Number
;; sums the elements of this tree
(define-class leaf
(fields v)
(define (sum) (this . v)))
(define-class node
(fields left v right)
(define (sum)
(+ (this . left . sum)
(this . v)
(this . right .sum))))
(check-expect ((new leaf 7) . sum) 7)
(check-expect
((new node
(new leaf 1)
5
(new node (new leaf 0)
10
(new leaf 0))))
. sum)
16)
Figure 1: Binary tree sum in Beginning Student and in the Class language
The structure of this data definition is analogous to the approach of the previous semester but thisexample brings to light an important difference with the functional approach. The method for computingthe sum of the empty tree is defined in the leaf class, while the method for computing the sum of a node
DanBrown
Asumu Takikawa
Nicholas Labich
Principles
Practice
Industrial co-op
S. Tobin-Hochstadt & D. Van Horn 5
included with each method definition, following the principles of the design recipe studied in the firstsemester. In fact, the check-expect mechanism works exactly as it did before.
Methods can be defined to consume any number of arguments, but they are implicitly parameterizedover this, the object that was sent the message.
3.2 Where did the cond go?
Unions, and recursive unions in particular, are a fundamental kind of data definition that students arewell-versed in from the previous semester. A fundamental early lesson is how to represent (recursive)unions using classes and how to write recursive methods. As an example, figure 1 defines binary trees ofnumbers (an archetypal recursive union data definition) using the BSL language and the Class language.
#lang bsl
;; A Tree is one of:
;; - (make-leaf Number)
;; - (make-node Tree Number Tree)
(define-struct leaf (v))
(define-struct node (left v right))
;; sum : Tree -> Number
;; sums the elements of the given tree
(define (sum a-tree)
(cond [(leaf? a-tree) (leaf-v a-tree)]
[else
(+ (sum (node-left a-tree))
(node-v a-tree)
(sum (node-right a-tree)))]))
(check-expect (sum (make-leaf 7)) 7)
(check-expect
(sum (make-node
(make-leaf 1)
5
(make-node (make-leaf 0)
10
(make-leaf 0))))
16)
#lang class/1
;; A Tree is one of:
;; - (new leaf Number)
;; - (new node Tree Number Tree)
;; and implements
;; sum : -> Number
;; sums the elements of this tree
(define-class leaf
(fields v)
(define (sum) (this . v)))
(define-class node
(fields left v right)
(define (sum)
(+ (this . left . sum)
(this . v)
(this . right .sum))))
(check-expect ((new leaf 7) . sum) 7)
(check-expect
((new node
(new leaf 1)
5
(new node (new leaf 0)
10
(new leaf 0))))
. sum)
16)
Figure 1: Binary tree sum in Beginning Student and in the Class language
The structure of this data definition is analogous to the approach of the previous semester but thisexample brings to light an important difference with the functional approach. The method for computingthe sum of the empty tree is defined in the leaf class, while the method for computing the sum of a node
http://www.ccs.neu.edu/course/cs2510h/