
https://twitter.com/samth/status/1249818179653832710?s=20 Impressed by the size of the implementation.

I’m trying to implement an in-list+rest
form for for
and friends and came up with this: (define (list+rest l)
(let loop ([l l])
(unless (null? l)
(yield (car l) (cdr l))
(loop (cdr l)))))
; Ex:
(for/list ([(x r) (in-generator (list+rest '(a b c)))])
(list x r))
--> '((a (b c)) (b (c)) (c ()))
However, this is about 500× slower than a bare named let loop. Is there a proper and fast way to make such an in-list+rest
?

In my experience, generator is very very slow in Racket BC

Use define-sequence-syntax
with :do-in

I think it improved significantly in Racket CS

Or perhaps make-do-sequence
: https://www.mail-archive.com/racket-users@googlegroups.com/msg41296.html

Honestly, I’m not a fan of make-do-sequence
. It’s just… so unintuitive to use.

I attempted to read its docs for numerous times. Still couldn’t get through it. I understand that it needs to be complex to support various use cases. Still…

The trick is to have the template in mind. Use the template to implement the loop, then give names to the various parts.
Once upon a time I reimplemented srfi–42 (Eager Comprehensions) so I got used to thinking this way.

What page is this from?


Thank you both. Yeah, I agree with all you said. The template does help for :do-in indeed.

Is there anything similar in the Racket? https://code.tutsplus.com/tutorials/speeding-python-with-cython--cms-29557

Excellent, define-sequence-syntax
is just as fast as a named let loop, that’s really cool. Code in the thread for reference.

(define-sequence-syntax in-list+rest
(lambda () #'in-list+rest/proc)
(lambda (stx)
(syntax-case stx ()
[[(x r) (_ lst)]
#'[(x r)
(:do-in
([(l) lst])
(unless (list? l)
(raise-argument-error 'in-list+rest "list?" l))
([l l])
(not (null? l))
([(x r) (values (car l) (cdr l))])
#true
#true
[r])]]
[_ #f])))
(define (in-list+rest/proc l)
(for/list ([(x r) (in-list+rest l)]) (list x r)))
Thank you @soegaard2 @sorawee

Found something fun to play with. If you define symbols in Chinese characters, you can write something like.
(定義 (階乘 某數) (若 (等於 某數 1) 1 (乘 某數 (階乘 (減 某數 1)))))

I think there is already some “Chinese translation” version on the package catalog.

No, there’s nothing that much like Cython for Racket. However: 1. Racket is usually a lot faster than pure Python so you don’t need it nearly as much 2. If what you want to is generate very low level code, you might be interested in Sham: https://github.com/rjnw/sham

Oh, wow, that’s cool.

I tried both versions in Racket CS
(define xs (range 1000000))
(time (void (for/list ([(x r) (in-generator (list+rest xs))])
(list x r))))
(time (void (for/list ([chunk (in-list+rest xs)])
chunk)))

Here’s the result:
cpu time: 1182 real time: 1245 gc time: 223
cpu time: 544 real time: 577 gc time: 217

In Racket BC, the result is:
cpu time: 13851 real time: 14674 gc time: 6684
cpu time: 372 real time: 379 gc time: 175

Good news is that generator is indeed much faster.

Bad news is that the performance of define-sequence-syntax
somehow decreases, though not significantly

@wanpeebaw if you want to view source code, in DrRacket, right click at an identifier and click “Open Defining File”/“Jump to Definition”

You can probably define a macro that extract an information from the identifier to do something like “Open Defining File”. See https://docs.racket-lang.org/drracket-tools/Accessing_Check_Syntax_Programmatically.html for instance

@feariel has joined the channel

why do you use in-list+rest/proc
instead of in-list+rest
? The proc version is for use in map
, say.

thanks for the results all the same :slightly_smiling_face:

Oh lol, I misread it.

Actually this is a thing already: https://docs.racket-lang.org/whereis/index.html

Did the time change too?

In BC, here’s the proc version:
cpu time: 401 real time: 404 gc time: 205
cpu time: 391 real time: 393 gc time: 183
cpu time: 464 real time: 467 gc time: 236
cpu time: 456 real time: 458 gc time: 250
cpu time: 3780 real time: 3785 gc time: 3563
cpu time: 393 real time: 398 gc time: 197
cpu time: 424 real time: 428 gc time: 214
cpu time: 432 real time: 436 gc time: 228
cpu time: 408 real time: 411 gc time: 204
cpu time: 377 real time: 379 gc time: 180
And here’s the direct version:
cpu time: 452 real time: 454 gc time: 253
cpu time: 3860 real time: 3875 gc time: 3625
cpu time: 385 real time: 393 gc time: 182
cpu time: 405 real time: 410 gc time: 193
cpu time: 393 real time: 395 gc time: 191
cpu time: 398 real time: 401 gc time: 195
cpu time: 377 real time: 380 gc time: 180
cpu time: 422 real time: 425 gc time: 212
cpu time: 403 real time: 408 gc time: 208
cpu time: 413 real time: 416 gc time: 202

I’d say no significant difference

Thanks - that’s reassuring.

Quick question. I have two programs that use exn->string
. One produces a detailed message and the other doesn’t. What causes the difference?
In particular, one produces:
arity mismatch;\n the expected number of arguments does not match the given number\n expected: at least 3\n given: 2\n
and the other produces:
arity mismatch;\n the expected number of arguments does not match the given number\n expected: at least 3\n given: 2\n arguments...:\n 1\n 2

Does the first one use Racket CS?

No. They are both in 3m

Does racket have a CLOS/emacslisp like advice capability?

I’ve defined a struct using prop:procedure to give a function advising capability. However, I have a separate struct I’ve defined with prop:procedure to augment a function definition with separate capability. Is there a way to “compose” these two structs (a la multiple inheritance) such that all capabilities are available at once?

@wlbberman I don’t believe so; that’s a CL/Elisp feature that, to my knowledge, doesn’t really have a Racket equivalent. At least, not one that’s built-in. (I may be wrong.)

Is this with regards to the advice, the struct composition, or both?