lexi.lambda
2017-2-6 17:26:37

@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?


robby
2017-2-6 18:50:49

Sounds promising!


lexi.lambda
2017-2-6 19:04:40

@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


robby
2017-2-6 19:04:54

@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.


lexi.lambda
2017-2-6 19:06:25

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.


lexi.lambda
2017-2-6 19:09:23

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?


robby
2017-2-6 19:15:20

@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.


lexi.lambda
2017-2-6 19:17:19

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.


lexi.lambda
2017-2-6 19:23:46

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


lexi.lambda
2017-2-6 19:25:12

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.


lexi.lambda
2017-2-6 19:27:19

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.


lexi.lambda
2017-2-6 19:30:19

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.


lexi.lambda
2017-2-6 19:31:09

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.


lexi.lambda
2017-2-6 22:10:32

@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


lexi.lambda
2017-2-6 22:11:44

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


robby
2017-2-6 22:12:33

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?


robby
2017-2-6 22:12:41

Sprry


lexi.lambda
2017-2-6 22:13:17

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


notjack
2017-2-7 07:04:33