
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