more api for batch-io

svn: r18808
This commit is contained in:
Matthias Felleisen 2010-04-13 15:34:09 +00:00
parent 8d1871b4c9
commit 11f6859cb2
3 changed files with 97 additions and 48 deletions

View File

@ -2,41 +2,54 @@
(require htdp/error) (require htdp/error)
;; todo
;; -- read files as "white space separated tokens"
;; -- read csv files
;; -- tokenization? how? map-file? on a string?
(provide
read-file ;; String -> String
;; read the file f (in current-directory) as a string
read-file-as-lines ;; String -> [Listof String]
;; read the file f (in current-directory) as a list of strings
read-file-as-1strings ;; String -> [Listof 1String]
;; read the file f (in current-directory) as a list of 1strings
write-file ;; String String -> Boolean
;; write str to file f (in current-directory);
;; false, if f exists
;; true, if f doesn't exist
)
(define (read-file f) (define (read-file f)
(check-file f 'read-file) (check-file f 'read-file)
(check-arg 'read-file (file-exists? f) "name of file in program's folder" "first" f) (check-arg 'read-file (file-exists? f) "name of file in program's folder" "first" f)
(list->string (list->string (read-chunks f read-char drop-last-newline)))
(with-input-from-file f
(lambda ()
(let loop ([accu '()])
(define nxt (read-char))
(if (eof-object? nxt)
(reverse (if (char=? (car accu) #\newline) (cdr accu) accu))
(loop (cons nxt accu))))))))
(define (read-file-as-lines f)
(check-file f 'read-file-as-lines)
(with-input-from-file f
(lambda ()
(let loop ([accu '()])
(define nxt (read-line))
(if (eof-object? nxt)
(reverse accu)
(loop (cons nxt accu)))))))
(define (read-file-as-1strings f) (define (read-file-as-1strings f)
(check-file f 'read-file-as-1strings) (check-file f 'read-file-as-1strings)
(read-chars f string)) (map string (read-chunks f read-char drop-last-newline)))
;; (define (read-file-as-lines f)
(define (read-chars f action) (check-file f 'read-file-as-lines)
(read-chunks f read-line reverse))
;; String (-> X) ([Listof X] -> [Listof X]) -> [Listof X]
;; read a file as a list of X where process-accu is applied to accu when eof
(define (read-chunks f read-chunk process-accu)
(with-input-from-file f (with-input-from-file f
(lambda () (lambda ()
(let loop ([accu '()]) (let loop ([accu '()])
(define nxt (read-char)) (define nxt (read-chunk))
(if (eof-object? nxt) (if (eof-object? nxt) (process-accu accu) (loop (cons nxt accu)))))))
(reverse (if (char=? (car accu) #\newline) (cdr accu) accu))
(loop (cons nxt accu))))))) ;; [Listof Char] -> [Listof Char]
(define (drop-last-newline accu)
(reverse (if (char=? (car accu) #\newline) (cdr accu) accu)))
;; -----------------------------------------------------------------------------
(define (write-file f str) (define (write-file f str)
(check-arg 'write-file (string? f) "name of file (string)" "first" f) (check-arg 'write-file (string? f) "name of file (string)" "first" f)
@ -49,25 +62,22 @@
;; ----------------------------------------------------------------------------- ;; -----------------------------------------------------------------------------
(provide
read-file-as-lines ;; String -> [Listof String]
;; read the fule f (in current-directory) as a list of strings
read-file ;; String -> String
;; read the file f (in current-directory) as a string
write-file ;; String String -> Boolean
;; write str to file f (in current-directory);
;; false, if f exists
;; true, if f doesn't exist
)
;; String[file name] Symbol -> Void ;; String[file name] Symbol -> Void
;; effect: ensure that f is a file in current directory or report error for t ;; effect: ensure that f is a file in current directory or report error for t
(define (check-file f t) (define (check-file f t)
(check-arg t (string? f) "string" "first" f) (check-arg t (string? f) "string" "first" f)
(check-arg t (file-exists? f) "name of file in program's folder" "first" f)) (check-arg t (file-exists? f) "name of file in program's folder" "first" f))
;; -----------------------------------------------------------------------------
#|
(require scheme/class)
(require scheme/gui)
(define (read-image-file file-name)
(make-object image-snip% file-name))
|#
; ;
; ;
; ;
@ -86,7 +96,9 @@
#| #|
For basic i/o, I find the following two functions extremely helpful to provide as a teachpack along with what batch-io gives. Perhaps it would be possible to include them in the standard teachpack? For basic i/o, I find the following two functions extremely helpful to provide as a
teachpack along with what batch-io gives. Perhaps it would be possible to include
them in the standard teachpack?
;; split : String String -> Listof[String] ;; split : String String -> Listof[String]
;; splits a string into a list of substrings using the given delimiter (space ;; splits a string into a list of substrings using the given delimiter (space

View File

@ -19,16 +19,31 @@ eos
(second test2-as-list)))) (second test2-as-list))))
(or (write-file file test1) (or (write-file file test1)
(check-true (string=? (read-file file) test1) "read-file 1")) (check-true (string=? (read-file file) test1) " 1"))
(or (write-file file test2) (or (write-file file test2)
(check-true (string=? (read-file file) test2) "read-file 2")) (check-true (string=? (read-file file) test2) " 2"))
(or (write-file file test1) (or (write-file file test1)
(check-equal? (read-file-as-lines file) (list test1) "read-file-as-lines 1")) (check-equal? (read-file-as-lines file) (list test1) "-as-lines 1"))
(or (write-file file test2) (or (write-file file test2)
(check-equal? (read-file-as-lines file) test2-as-list "read-file-as-lines 2")) (check-equal? (read-file-as-lines file) test2-as-list "-as-lines 2"))
(define as-1strings1 (map string (string->list test1)))
(or (write-file file test1)
(check-equal? (read-file-as-1strings file) as-1strings1 "-as-1strings 1"))
(define as-1strings2
(map string
(apply append
(map string->list
(cdr
(foldr (lambda (f r) (cons "\n" (cons f r))) '()
test2-as-list))))))
(or (write-file file test2)
(check-equal? (read-file-as-1strings file) as-1strings2 "-as-lines 2"))
(check-exn exn:fail:contract? (lambda () (write-file 0 1))) (check-exn exn:fail:contract? (lambda () (write-file 0 1)))
@ -41,3 +56,6 @@ eos
(check-exn exn:fail:contract? (lambda () (read-file-as-lines 0))) (check-exn exn:fail:contract? (lambda () (read-file-as-lines 0)))
(check-exn exn:fail:contract? (lambda () (read-file-as-lines '("test")))) (check-exn exn:fail:contract? (lambda () (read-file-as-lines '("test"))))
(check-exn exn:fail:contract? (lambda () (read-file-as-1strings 0)))
(check-exn exn:fail:contract? (lambda () (read-file-as-1strings '("test"))))

View File

@ -6,16 +6,35 @@
(error-print-source-location #f) (error-print-source-location #f)
(define legal "on-tick: not a legal clause in a world description") (define legal "~a: not a legal clause in a world description")
(define double ", on-tick has been redefined") (define double
(string-append (format legal 'on-tick) ", on-tick has been redefined"))
(with-handlers ((exn:fail:syntax? (with-handlers ((exn:fail:syntax?
(lambda (x) (lambda (x)
(unless (unless (string=? (exn-message x) double) (raise x)))))
(string=? (exn-message x) (string-append legal double))
(raise x)))))
(eval '(module a scheme (eval '(module a scheme
(require 2htdp/universe) (require 2htdp/universe)
(local ((define (run) (big-bang 0 (on-tick on-tick))) (local ((define (run) (big-bang 0 (on-tick on-tick)))
(define (on-tick t) 0)) (define (on-tick t) 0))
10)))) 10))))
;; purpose: catch illegal shapes of the form (kwd . stuff)
(with-handlers ((exn:fail:syntax?
(lambda (e)
(unless (string=? (exn-message e) (format legal 'on-tic))
(raise e)))))
(eval '(module a scheme
(require 2htdp/universe)
(big-bang 0 (on-tic add1)))))
;; purpose: catch illegal atomic clauses
(with-handlers ((exn:fail:syntax?
(lambda (e)
(unless (string=? (exn-message e) (format legal 'stop-when))
(raise e)))))
(eval '(module a scheme
(require 2htdp/universe)
(big-bang 0 (on-tick add1) stop-when))))