06 input and output functional programming. streams two kinds of streams character streams binary...
TRANSCRIPT
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)
(abc)(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” zNIL
Output
> (format nil “~10,2,0,’*, ‘ F” 26.21875)“ 26.22”Rounded to 2 decimal placesWith the decimal point shifted right 0 placesRight-justified in a field of 10 charactersPadded on the left by blanksIf 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}1314void 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}3132int main() {33 int ia[] = {1, 2, 3};34 35 cout << "Odd" << endl;36 printArrayOdd(ia, ia + 3);3738 39 cout << "Even" << endl;40 printArrayEven(ia, ia + 3);41 42 cout << "Greater than 2" << endl;43 printArrayGreaterThan2(ia, ia + 3);44}
Execution results
Odd13Even2Greater than 23
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>1011using namespace std;1213typedef bool (*predicate)(int);1415bool isOdd(int i) {16 return i%2? true : false;17}1819bool 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}2627void printArray(int* beg, int* end, predicate fn) {28 while(beg != end) {29 if ((*fn)(*beg))30 cout << *beg << endl;31 32 beg++;33 }34}3536int 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
Odd13Even2Greater than 23
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
> (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) ;:test-> keyword argument
((A) (Z))> (member ‘a ‘((a b) (c d)) :key #’car)
((A B) (C D)) Ask if there is an element whose car is a
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 arrayB
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) )ab23 -> 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))Number9
> ((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) ;on each iteration, x gets its previousNIL ;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 DDONE
dotimes > (dotimes (x 5 x) ; for x = 0 to 5-1, return x
(format t “~A “ x))0 1 2 3 4 5
Review
Multiple values> (values ‘a nil (+ 2 4))
ANIL6
(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)