
@aowens5189 has joined the channel

Hi guys, I am thinking of writing a macro that wraps around contract-out
to selectively disable contracts at compile-time (I know this might be seen as bad, but it doubles the speed of my program). Is there already anything out there that does this?

@pocmatos see the code here: https://github.com/racket/typed-racket/blob/master/typed-racket-lib/typed-racket/utils/utils.rkt#L111

@samth exactly what I needed, thanks.

Hello. I am trying to return several (define ...)
expressions(?) with a macro. I managed to produce: '((define par-h (Parameter "h" "handling time" 123 kg)) (define par-a (Parameter "a" "attack rate" 321 kg)))

@redwynskaja you probably want (begin (define ...) (define ...))

My problem is the error define: not allowed in an expression context
… I have to get rid of the outermost pair of parentheses, i think

Try (let () (define ...) ...)

I think begin
may be closer, since begin
would let the define
s be available outside but let` won’t

I tried begin: (1) ?: literal data is not allowed;
no #%datum syntax transformer is bound in: "h"
(2) However, if i copy the resulting expression to the REPL, it works (w/o the quote): '(begin (define par-h (Parameter "h" "handling time" 123 kilogram)) (define par-a (Parameter "a" "attack rate" 321 kilogram)))

The problem is probably somewhere else. What is the code for this macro? Is it returning a quoted s-expression?

it is returning the code from (2) (above)

evaluating it in the repl works

(struct Parameter ([p-id : String]
[p-desc : String]
;[p-val : Measure]
[p-num : Number]
[p-unit : Unit])

And how is it defined? Using syntax-rules
or some other forms?

syntax-parse

(define-syntax (def-par stx)
(syntax-parse stx
[(_ [~seq name:id descr:string val:number punit:expr] ...)
#:fail-when (check-duplicate-identifier (syntax->list #'(name ...))) "duplicate identifier"
#:with [name-str ...] (map (compose symbol->string syntax-e) (syntax->list #'[name ...]))
#:with [ids ...] (map
(λ (s) (string->symbol (string-append "par-" ((compose symbol->string syntax-e) s))))
(syntax->list #'[name ...]))
#''(begin (define ids (Parameter name-str descr val punit)) ...)]))

This is how it would be used (def-par
h "handling time" 123 kilogram
a "attack rate" 321 kilogram)

Try this: #'(begin (define ids (Parameter name-str descr val punit)) ...)

i did. that leads to (1) (see above).

or am i missing something?

(1) -> “iteral data not allowed” error

?: literal data is not allowed;
no #%datum syntax
Just checking: Do you have an (require (for-syntax racket/base))
?

@redwynskaja here: #'(begin (define ids (Parameter 'name-str descr val punit)) ...)

I think the way name-str
is introduced give it no lexical information

therefore the expander failed to find the #%datum
for name-str

another point: the new ids
needs to be given the right scope in order to be visible outside: #:with [ids ...] (map
(λ (s)
(syntax-local-introduce ;; <- here
(datum->syntax #f (string->symbol (string-append "par-" ((compose symbol->string syntax-e) s))))))
(syntax->list #'[name ...]))

otherwise those ids
will only be visible to this macro

@shu—hung wow… with your last two tips it now works!

a few helpers: format-id
from racket/syntax
combines what you need for ids
, including introducing the right lexical context and format identifiers https://gist.github.com/shhyou/4e0090b8f9c33f2c02cf3b1a2290cd93

and to include the current lexical context in name-str
s, quasi-syntax + escape could help

or similarly (datum->syntax #'here (symbol->string ...))

Thank you a lot!

in addition to the TR code sam linked, you might be interested in Option Contracts (https://docs.racket-lang.org/option-contract/index.html). They’re more oriented towards runtime decision making about whether to use contracts or not as opposed to compile-time, and I find the API confusing, but they’re designed for exactly the use case you describe