Я играю с Racket и пропустил понимание байтовой строки. Когда я нашел for/fold/derived
примеры в документации, я решил свернуть свой собственный байт строки макроса на слух, как любой новичок будет:для/list vs custom for/bytes в Racket
(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))))))
У меня есть несколько взаимосвязанных вопросов:
- Is этот способ Racket так или иначе?
- Является ли макрос нормально? В основном я объединил примеры из документации
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
проигрывает, для размеров больше, чем выигрывает.
Интересно.Обычно я не пытаюсь кэшировать '{string, bytes} -length', как я бы сказал в C/C++, потому что в Racket я предполагаю, что это не намного больше, чем приложение плюс struct de-ref. Однако, даже если это правда, в этом случае это будет достаточно высокая доля внутренней петли для материи. Хорошее улучшение. –