I forgot the name of the site where Racket gists can be run…
pasterack
Thanks @soegaard2!
Is this for internal or external structs?
unsure what you mean by extermal/"internal", as in the standard library?
it works for nearly all functions
Is (void)
really a procedure call, or does the compiler replace it with nothing? I would like to collect some (potentially expensive) statistics sometimes, and at other times the forms that update the stats would be no-ops. So, it seems I’ll need a macro that expands to essentially nothing.
This is in a speed-sensitive portion of the program, so I’d prefer there to be absolutely zero effect when not in stats gathering mode.
https://stackoverflow.com/questions/40082458/can-a-racket-macro-expand-to-nothing (void)
or (begin)
is suggested. I’d just considered (begin)
before googling that.
I was thinking (begin)
#lang racket/base
(require (for-syntax racket/base))
(begin-for-syntax
(define debug? #f))
(define-syntax (do-the-thing stx)
(if debug?
#'(println "doing the thing")
#'(begin)))
(do-the-thing)
But I think in an expression context it may error?
(void)
is a procedure call. Macro expansion doesn’t do anything special with it. However, partial evaluator (cp0) can optimize away (void)
in specific situations
On the other hand, begin
is a form, so macro expander will do something with it.
Yep, it would be an error to write (begin)
in an expression context.
In my particular case, I suppose I could expand to just about any cheap value, e.g. #f
since the expression will be ignored. This is for my chess engine which necessitates coding in a mutating style in many places. It’s been fun, but man, do I appreciate functional programming even more after this experience :)
(begin)
probably makes the most sense, and hopefully the compiler will realize (begin)
doesn’t add any value and will optimize it away.
cp0 is really aggressive. Putting (void)
or #f
in a uselessly probably will have the same effect: they get optimized away
Yes, but I need to be sure, as in “take off and nuke ’em from space” sure :)
“sure” as in no function call is made - I don’t care as much about an unused value
If you use Racket CS, try
#lang racket
(provide f)
(define (f x)
(void)
(void)
(void)
(void)
(void)
(void)
(void)
(void)
#f
(+ x 1))
and run PLT_LINKLET_SHOW_CP0=1 racket filename.rkt
The resulting program after cp0 is:
(lambda (instance-variable-reference .get-syntax-literal!1
.set-transformer!2 f3)
(letrec ([f (lambda (x_1) (#2%+ x_1 1))])
(variable-set!/define f3 f 'consistent)))
Cool :)
Other magic compiler environment variables: https://docs.racket-lang.org/reference/compiler.html