Functional Programming 06 INPUT AND OUTPUT Streams Two kinds of streams Character streams Binary streams Character streams are Lisp objects representing sources and/or destinations of characters To read from or write to a file, you open it as a stream, but streams are not identical with files When you read or print at the toplevel, you also use a stream Streams Default input is read from the stream *standard-input* Default output is write to *standard-output* Initially *standard-input* and *standard-output* will be the same place: a stream presenting the toplevel Streams Make the file > (setf path (make-pathname :name “myfile”)) #P”myfile” Open the file > (setf str (open path :direction :output :if-exists :supersede)) #<BUFFERED FILE-STREAM CHARACTER #P”myifle” @1> Write to the stream > (format str “Something~%”) NIL Close the stream > (close str) NIL Streams Read the file Open a stream with :direction :input > (setf str (open path :direction :input)) #<BUFFERED FILE-STREAM CHARACTER #P”myifle” @1> > (read-line str) “Something” with-open-file macro > (with-open-file (str path :direction :output :if-exists :supersede) (format str “Something~%”)) The stream is automatically closed Input Most popular input functions read-line read > (progn (format t “Please enter your name: “) (read-line)) Please enter your name: Rodrigo de Bivar “Rodrigo de Bivar” NIL → is true only if read-line ran out of input before encountering a newline Input (defun pseudo-cat (file) (with-open-file (str file :direction :input) (do ((line (read-line str nil ‘eof) (read-line str nil ‘eof))) ((eql line ‘eof)) (format t “~A~%” line)))) If you want input parsed into Lisp objects, use read > (read) (a b c) (A B C) Output Three simplest output functions prin1 Generates output for programs > (prin1 “Hello”) “Hello” “Hello” princ Generates output for people > (princ “Hello”) Hello “Hello” terpri Prints a new line Output format > (format nil “Dear ~A, ~% Our records indicate…” “Mr. Malatesta”) “Dear Mr. Malatesta, Our records indicate…” > (format t “~S ~A” “z” “z”) “z” z NIL Output > (format nil “~10,2,0,’*, ‘ F” 26.21875) “ 26.22” Rounded to 2 decimal places With the decimal point shifted right 0 places Right-justified in a field of 10 characters Padded on the left by blanks If it is too long to fit in the space allowed by the first argument, the character * is printed > (format nil “~,2,,,F” 26.21875) “26.22” > (format nil “~,2F” 26.21875) “26.22” Review – Function pointer in C 1#include <iostream> 2 3using namespace std; 4 5void printArrayOdd(int* beg, int* end) { 6 while(beg != end) { 7 if ((*beg)%2) 8 cout << *beg << endl; 9 10 beg++; 11 } 12} 13 14void printArrayEven(int* beg, int* end) { 15 while(beg != end) { 16 if (!((*beg)%2)) 17 cout << *beg << endl; 18 19 beg++; 20 } 21} 22 Review – Function pointer in C 23void printArrayGreaterThan2(int* beg, int* end) { 24 while(beg != end) { 25 if ((*beg)>2) 26 cout << *beg << endl; 27 28 beg++; 29 } 30} 31 32int main() { 33 int ia[] = {1, 2, 3}; 34 35 cout << "Odd" << endl; 36 printArrayOdd(ia, ia + 3); 37 38 39 cout << "Even" << endl; 40 printArrayEven(ia, ia + 3); 41 42 cout << "Greater than 2" << endl; 43 printArrayGreaterThan2(ia, ia + 3); 44} Execution results Odd 1 3 Even 2 Greater than 2 3 Review – Function pointer in C 1/**//* 2 (C) OOMusou 2007 http://oomusou.cnblogs.com 3 4Filename : FuntionPointer.cpp 5Compiler : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++ 6Description : Demo how to use function pointer 7Release : 05/01/2007 1.0 8*/ 9#include <iostream> 10 11using namespace std; 12 13typedef bool (*predicate)(int); 14 15bool isOdd(int i) { 16 return i%2? true : false; 17} 18 19bool isEven(int i) { 20 return i%2? false : true; 21} 22 Review – Function pointer in C 23bool greaterThan2(int i) { 24 return i > 2; 25} 26 27void printArray(int* beg, int* end, predicate fn) { 28 while(beg != end) { 29 if ((*fn)(*beg)) 30 cout << *beg << endl; 31 32 beg++; 33 } 34} 35 36int main() { 37 int ia[] = {1, 2, 3}; 38 39 cout << "Odd" << endl; 40 printArray(ia, ia + 3, isOdd); 41 42 cout << "Even" << endl; 43 printArray(ia, ia + 3, isEven); 44 45 cout << "Greater than 2" << endl; 46 printArray(ia, ia + 3, greaterThan2); 47} Execution results Odd 1 3 Even 2 Greater than 2 3 Review – Function pointer in C By using function pointer, C can pass a function as an argument to another function C++ and C# also provide similar idea C++: Function object (Functor) C# (pronounced as C sharp): Delegate But…., how to return a function? C also could return a function pointer http://www.newty.de/fpt/fpt.html However, it needs more complex consideration to write such a function with higher feasibility Review – Closure Functional programming languages use “closures” to provide feasibility of functions, so that returning a function becomes easier and more practical (defun make-adder (n) #’(lambda (x) (+ x n))) → returns a function (setf add3 (make-adder 3)) #<CLOSURE: LAMBDA (X) (+ X N)> > (funcall add3 2) 5 Review > (list ‘my (+ 2 1) “Sons”) (MY 3 “Sons”) > (list ‘(+ 2 1) (+ 2 1)) ((+ 2 1) 3) > (cons ‘a ‘(b c d)) (A B C D) > (cons ‘a (cons ‘b nil)) (A B) > (car ‘(a b c)) A > (cdr ‘(a b c)) (B C) Review > (setf x (list ‘a ‘b ‘c)) (A B C) > (setf (car x ) ‘n) N >x (N B C) Review > (apply #’+ ‘(1 2 3)) 6 > (mapcar #’(lambda (x) (+ x 10)) ‘(1 2 3)) (11 12 13) > (mapcar #’list ‘(a b c) ‘(1 2 3 4)) ((A 1) (B 2) (C 3)) > (maplist #’(lambda (x) x) ‘(a b c)) ((A B C) (B C) (C)) Review > (member ‘b ‘(a b c)) (B C) > (member ‘(b) ‘((a) (b) (c))) NIL Why? Equal: the same expression? Eql: the same symbol or number? member compares objects using eql > (member ‘(a) ‘((a) (z)) :test #’equal) ((A) (Z)) > (member ‘a ‘((a b) (c d)) :key #’car) ((A B) (C D)) Ask if there is an element whose car is a ;:test-> keyword argument Review > (subseq ‘(a b c d) 1 2) (B) > (every #’oddp ‘(1 3 5)) ;everyone is … T > (some #’evenp ‘(1 2 3)) ;someone is … T > (every #’> ‘(1 3 5) ‘(0 2 4)) T Review Dotted list: is an n-part data structure (A . B) (setf pair (cons ‘a ‘b)) (A . B) > ‘(a . (b . (c . nil))) (A B C) > (cons ‘a (cons ‘b (cons ‘c ‘d))) (A B C . D) Review make-array > (setf arr (make-array ‘(2 3) :initial-element nil)) #<Array T (2 3)> Maximum: 7 dimensions Each dimension can have 1023 elements Initial-element Optional Whole array will be initialized to this value > (aref arr 0 0) NIL > (setf (aref arr 0 0) ‘b) B > (aref arr 0 0) ; access the array B Review One-dimensional array > (setf vec (make-array 4 :initial-element nil)) #(NIL NIL NIL NIL) > (vector “a” ‘b 5 “c”) #(“a” B 5 “c”) > (setf vec (vector “a” ‘b 5 “c”)) > (svref vec 1) ;access the vector (sv: simple vector) B String: a vector of characters > (sort “elbow” #’char<) “below” Retrieve an element of a string > (aref “abc” 1) #\b > (char “abc” 1) #\b Review Replace elements of a stirng > (let ((str (copy-seq “Merlin”))) (setf (char str 3) #\k) str) “Merkin” Compare two strings > (equal “fred” “fred”) T > (equal “fred” “Fred”) NIL > (string-equal “fred” “Fred”) T Building strings > (format nil “~A or ~A” “truth” “dare”) “truth or dare” > (concatenate ‘string “not “ “to worry”) “not to worry” Review > (progn (format t “a”) (format t “b”) (+ 11 12) ) ab 23 -> only the value of the last expression is returned > (block head (format t “Here we go.”) (return-from head ‘idea) (format t “We’ll never see this.”)) Here we go. Review > (let ((x 7) (y 2)) (format t “Number”) (+ x y)) Number 9 > ((lambda (x) (+ x 1)) 3) 4 (let ((x 2) (y (+ x 1))) (+ x y)) ((lambda (x y) (+ x y)) 2 (+ x 1)) Review (if <test> <then form> <else form>) (if <test> <then form>) (when <test> <then form>) (if <test> nil <else form>) (unless <test> <else form>) Review cond (cond (<test 1> <consequent 1-1> …) (<test 2> <consequent 2-1> …) … (<test m> <consequent m-1> …) );cond case (case <key form> (<key 1> <consequent 1-1> …) (<key 2> <consequent 2-1> …) ... (<key m> <consequent m-1> …) ) ;case Review do (do ((<parameter 1> <initial value 1> <update form 1>) (<parameter 2> <initial value 2> <update form 2>) … (<parameter n> <initial value n> <update form n>)) (<termination test> <intermediate forms, if any> <result form>) <body> ) ;do > (let ((x ‘a)) (do ((x 1 (+ x 1)) (y x x)) ((> x 5)) (format t “(~A ~A) “ x y))) (1 A) (2 1) (3 2) (4 3) (5 4) NIL ;on each iteration, x gets its previous ;value plus 1; y also gets the previous ;value Review do* Has the same relation to do as let* does to let > (do* ((x 1 (+ x 1)) (y x x)) ((> x 5)) (format t “(~A ~A) “ x y)) (1 1) (2 2) (3 3) (4 4) (5 5) NIL Review dolist > (dolist (x ‘(a b c d) ‘done) (format t “~A “ x)) A B C D DONE dotimes > (dotimes (x 5 x) (format t “~A “ x)) 0 1 2 3 4 5 ; for x = 0 to 5-1, return x Review Multiple values > (values ‘a nil (+ 2 4)) A NIL 6 (labels ((add10 (x) (+ x 10)) (consa (x) (cons ‘a x))) (consa (add10 3))) (A . 13) > (labels ((len (lst) (if (null lst) 0 (+ (len (cdr lst)) 1)))) (len ‘(a b c))) 3 Review (defun our-funcall (fn &rest args) (apply fn args)) > (defun keylist (a &key x y z) (list a x y z)) Review (defun disjoin (fn &rest fns) (if (null fns) fn (let ((disj (apply #’disjoin fns))) #’(lambda (&rest args) (or (apply fn args) (apply disj args)))))) > (mapcar (disjoin #’integerp #’symbolp) ‘(a “a” 2 3)) (T NIL T T) Midterm exam Time: April 21 Classroom: 資工所(應用科學大樓)/B1演講廳