Functional Programming

advertisement
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演講廳
Download