![]() |
![]() |
|
home—info—lectures—exams—hws—archive
(Recursive) union types in Java: We'll remind ourselves of scheme list-data-definition and an example function; then the same approach used for (singly-linked) lists in Java:
; A List is: ; - empty, or ; - (cons [any] [List]) ; (define (length some-list) (cond [(empty? some-list) 0] [(cons? some-list) (+ 1 (length (rest some-list))) |
/* The analagous thing in Java: 'singly-linked lists' */ abstract class SList { abstract int length(); } class Empty extends SList { int length() { return 0; } } class Cons extends SList { Object first; SList rest; int length() { return 1+rest.length(); } } |
Let's see another example of union-types in Java (starting by reminding ourselves of the scheme version:)
;;==== class anc-tree ; An anc-tree is ; - 'unknown ; - (make-child [string] [number] [symbol] [anc-tree] [anc-tree]) ; (define-struct/contract child ([name string?] [yob integer?] [eye symbol?] [ma anc-tree?] [pa anc-tree?]) (define (anc-tree? any) (or (and (symbol? any) (symbol=? any 'unknown)) (child? any))) ; Return the names of all baby-boomers. (define (bbs fam) (cond [(symbol? fam) empty] [(child? fam) (append (if (<= 1956 (child-yob fam) 1965) (list (child-name fam)) empty) (bbs (child-ma fam)) (bbs (child-pa fam)))])) |
abstract class AncTree { abstract List<String> bbs(); } class Unknown extends AncTree { // A class with no fields (?!) List<String> bbs() { return new ArrayList<String>(); // 'return empty' } } class Child extends AncTree { String name; int yob; String eye; AncTree ma; AncTree pa; List<String> bbs() { /* Direct translation of the scheme version: */ return ((1956 <= this.yob) && (this.yob <= 1965) ? new LinkedList<String>().add(this.name) : new LinkedList<String>()) .append( this.ma.bbs() ).append( this.pa.bbs() ); /* Ack! * [doesn't quite work because 'add' mutates] * and it doesn't translate well; the ternary '.. ? .. : ..' * feels much weirder than scheme's 'if'. * Here is equivalent code in more idiomatic Java: */ List<String> selfList = new LinkedList<String>(); if ((1956 <= this.yob) && (this.yob <= 1965)) selfList.add( this.name ); List<String> masBBs = this.ma.bbs(); List<String> pasBBs = this.pa.bbs(); return selfList.append( masBBs ).append( pasBBs ); } } |
Btw, compare this to the traditional approach to trees in CS2:
in our approach
we don't actually mention
class Node { String name; Node left; // well, a real Node *or* null Node right; // well, a real Node *or* null } |
The problem stems from the fact that the recursive data definition
has three types
(
Note that
Recall our grammar:
Expr ::= Number | Var | ParenExpr | BinExpr | IfZExpr ParenExpr ::= ( Expr ) BinExpr ::= ( Expr BinOp Expr ) IfZExpr ::= if Expr is0 then Expr else Expr ; BinOp ::= plus | minus | times |
Our project will:
How to represent
(define-struct/contract (bin-expr [left expr?] [op bin-op?] [right expr?))) (make-bin-expr 3 'plus 4) (make-bin-expr (make-bin-expr 3 'plus 4) 'minus 5) ; We need data def'ns for our union types; ; we'll make real code out of the union-type-def'n ; (so that we can use it in with 'define/contract', if you want): (define (expr? any-val) (or (number? any-val) (string? any-val) (paren-expr? any-val) (bin-op-expr? any-val) (if-Z-expr? any-val)))1 2 (define (bin-op? any-val) (member any-val (list 'plus 'minus 'times))) |
1
Rather than calling each function on
(map (lambda (f) (f any-val)) (list number? string? paren-expr? bin-op-expr? if-Z-expr?))) |
(foldl or false (map (lambda (f) (f any-val)) (list number? string? paren-expr? bin-op-expr? if-Z-expr?))) |
(ormap (map (lambda (f) (f any-val)) (list number? string? paren-expr? bin-op-expr? if-Z-expr?))) |
(define (is-expr? any-val) (ormap (map (lambda (f) (f any-val)) (list number? string? paren-expr? bin-op-expr? if-Z-expr?))) |
2
Well, if they were concerned about traversing the list
twice (once with
(define (is-expr? any-val) (foldl (lambda (f found-it) (or found-it (f any-val))) false (list number? string? paren-expr? bin-op-expr? if-Z-expr?))) |
home—info—lectures—exams—hws—archive
©2009, Ian Barland, Radford University Last modified 2009.Oct.26 (Mon) |
Please mail any suggestions (incl. typos, broken links) to ibarland ![]() |
![]() |