kozima #4540(2007/12/01 09:22 GMT) [ Common Lisp ] Rating1/1=1.00
マクロ、クロージャ、高階関数を使って。わりと Lisp らしく書けたかも?
d,x,o,f,c,s,% に対応。フラグなどは実装してないし手抜き感はありますが。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
(defconstant *format-char-table* (make-hash-table)) (defmacro define-format-char (char lambda-list &body body) `(setf (gethash ,char *format-char-table*) (lambda ,lambda-list ,@body))) (defun process-format-char (char args stream) (let ((fn (gethash char *format-char-table*))) (if fn (funcall fn args stream) (error "Undefined format character: ~C" char)))) (defun sprintf (fmt &rest args) (let ((rest args)) (flet ((getarg (&optional n) (if n (nth n args) (pop rest)))) (with-output-to-string (out) (with-input-from-string (in fmt) (do () ((null (peek-char nil in nil))) (let ((c (read-char in))) (if (char= c #\%) (process-format-char (read-char in) #'getarg out) (write-char c out))))))))) (define-format-char #\f (fn stream) (write (funcall fn) :stream stream)) (define-format-char #\c (fn stream) (write-char (funcall fn) stream)) (define-format-char #\s (fn stream) (princ (funcall fn) stream)) (define-format-char #\% (fn stream) (write-char #\% stream)) (defun format-integer (n base stream) (write n :base base :stream stream)) (defmacro define-integer-format-char (char base) `(define-format-char ,char (fn stream) (format-integer (funcall fn) ,base stream))) (define-integer-format-char #\d 10) (define-integer-format-char #\x 16) (define-integer-format-char #\o 8) ;;; test (sprintf (sprintf "%s/%%%c" "%x/%d/%o" #\f) 11259375 (* 9 3607 3803) 2054353 3.141592653589793d0) ;; => "ABCDEF/123456789/7654321/3.141592653589793d0"
Rating1/1=1.00-0+
[ reply ]
kozima
#4540()
[
Common Lisp
]
Rating1/1=1.00
マクロ、クロージャ、高階関数を使って。わりと Lisp らしく書けたかも?
d,x,o,f,c,s,% に対応。フラグなどは実装してないし手抜き感はありますが。
(defconstant *format-char-table* (make-hash-table)) (defmacro define-format-char (char lambda-list &body body) `(setf (gethash ,char *format-char-table*) (lambda ,lambda-list ,@body))) (defun process-format-char (char args stream) (let ((fn (gethash char *format-char-table*))) (if fn (funcall fn args stream) (error "Undefined format character: ~C" char)))) (defun sprintf (fmt &rest args) (let ((rest args)) (flet ((getarg (&optional n) (if n (nth n args) (pop rest)))) (with-output-to-string (out) (with-input-from-string (in fmt) (do () ((null (peek-char nil in nil))) (let ((c (read-char in))) (if (char= c #\%) (process-format-char (read-char in) #'getarg out) (write-char c out))))))))) (define-format-char #\f (fn stream) (write (funcall fn) :stream stream)) (define-format-char #\c (fn stream) (write-char (funcall fn) stream)) (define-format-char #\s (fn stream) (princ (funcall fn) stream)) (define-format-char #\% (fn stream) (write-char #\% stream)) (defun format-integer (n base stream) (write n :base base :stream stream)) (defmacro define-integer-format-char (char base) `(define-format-char ,char (fn stream) (format-integer (funcall fn) ,base stream))) (define-integer-format-char #\d 10) (define-integer-format-char #\x 16) (define-integer-format-char #\o 8) ;;; test (sprintf (sprintf "%s/%%%c" "%x/%d/%o" #\f) 11259375 (* 9 3607 3803) 2054353 3.141592653589793d0) ;; => "ABCDEF/123456789/7654321/3.141592653589793d0"Rating1/1=1.00-0+
[ reply ]