
@robby: After toying with and thinking about things some more, you’ve convinced me that expr/c
is impossible to get right. :) I guess the right way to write these sorts of macros would be to expand to with-contract
?

Sounds promising!

@robby: I ended up jury-rigging something that seems to abuse the contract system a little less but still provides a relatively nice interface to the macro author: http://pasterack.org/pastes/18443 Pasterack doesn’t produce the contract error for some reason, but it does get produced, and it blames the macro itself when it violates its own contract: app-integer-fn: broke its own contract
promised: integer?
produced: "hi"
in: the 1st argument of
a use of app-integer-fn
contract from: app-integer-fn
blaming: app-integer-fn
(assuming the contract is correct)
at: unsaved-editor:65.2

@lexi.lambda FWIW, I think that there will be common patterns that you’ll discover about where sensible boundaries go. I think it will make sense to codify those in a library somehow, once you’ve identified them.

Yes, I think this macro->/c
and with-contracted-expressions
are my first crack at codifying them. The names are probably terrible, but I haven’t put too much thought into them just yet.

Do you have an idea for where this sort of thing should go? Probably in the syntax
collection somewhere, but would it make more sense to put it in base
or in some new package?

@lexi.lambda that code looks like it has a suboptimial implementation of and/c
baked into it (and and/c
is kind of questionable anyway). I think you should just accept a contract and an expression and put the contract on the expression; no need for another contract combinator. The real complexity is in the names of the parties.

Isn’t it more a reimplementation of ->
than and/c
? The idea was basically to expand into a procedure with an ->
-ish contract attached to it, but using a custom combinator to report errors in terms of the macro rather than positional arguments.

Basically, the trouble I ran into was that the simpler approach worked ok for flat contracts, but not for more complex contracts, which sort of defeats the purpose. The easy example of a complex case actually came from the syntax/contract
docs themselves: http://docs.racket-lang.org/syntax/wrapc.html

All the contract violations in that set of examples are nonsense. The first and last one claim that the given value “broke its own contract”, which doesn’t make any sense, because they broke the macro’s contract. However, the second one is also wrong, because really the macro broke its own contract, which wrap-expr/c
fails to report.

Most of the macros I want to write that should have contracts on subexpressions are really semantically like functions, but have nicer syntax. So I looked to ->
and define/contract
to see what the right behavior probably was here.

There are two key steps to making this work, both of which involve manipulating the blame object. First, I needed to add the macro name as an “important” piece of context so that contract violations would be reported in terms of the macro, and I needed to swap the blame on expressions inside the contracted region, since the macro is semantically a function.

I could see a way to achieve that with some cheating contract combinators like blame-swapped/c
, but that seems much more hacky than this. :/ And I don’t know how to manipulate the blame in the necessary way without a custom combinator of some kind.

@robby: After working on it more, I’ve come up with a much simpler combinator that seems to restore the expr/c
interface but keeps the blame assignment correct. http://pasterack.org/pastes/83501

The boundary is still effectively between the macro itself and the module that compiles the macro’s expansion.

I can’t keep up with a technical conversation here (as it will disappear into the ether) and I have to do other things right now. Email?

Sprry

Sure, I don’t mean to put any obligation on you to respond. This is not high priority. :)
