私は Racket で遊んでいて、バイト文字列の理解を逃しました。ドキュメントの例を見つけたときfor/fold/derived
、初心者なら誰でもそうするように、独自のバイト文字列理解マクロを作成することにしました。
(define-syntax (for/bytes stx)
(syntax-case stx ()
((_ clauses . defs+exprs)
(with-syntax ((original stx))
#'(let-values
(((bstr i max-length)
(for/fold/derived original ((bstr (make-bytes 16)) (c 0) (ln-incr 32)) clauses
(define el (let () . defs+exprs))
(let-values (((new-bstr new-ln-incr)
(if (eq? c (bytes-length bstr))
(values (bytes-append bstr (make-bytes ln-incr)) (* ln-incr 2))
(values bstr ln-incr))))
(bytes-set! new-bstr c el)
(values new-bstr (+ c 1) new-ln-incr)))))
(subbytes bstr 0 i))))))
関連する質問がいくつかあります。
- とにかくこれはラケットのやり方ですか?
- マクロは大丈夫ですか?基本的に、
for/fold/derived
ドキュメントの例をマクロ展開されたものと組み合わせましたfor/vector
- 明らかなパフォーマンスの最適化はありますか?
残念ながら、(list->bytes (for/list ...
このマイクロベンチマークよりも実際には高速ではありません:
(define size 50000)
(define (custom-byte-test) (for/bytes ((i (in-range size))) (modulo i 256)))
(define (standard-list-test) (list->bytes (for/list ((i (in-range size))) (modulo i 256))))
(profile-thunk custom-byte-test #:repeat 1000)
(profile-thunk standard-list-test #:repeat 1000)
3212ms 対 3690ms になります。50000 より小さいサイズの場合はfor/bytes
負け、それより大きいサイズの場合は勝ちです。