Re: [Scheme-reports] Formal Response #382: Allow "if" to accept arbitrarily many if-then pairs Sam TH 12 Oct 2012 02:17 UTC

On Thu, Oct 11, 2012 at 10:11 PM, John Boyle <johnthescavenger@gmail.com> wrote:
> The difficulty is using the newly defined "if" in the definition of
> low-level macros, or otherwise at compile-time.  This seems to be due to
> Racket's phase separation.  Is there a way to turn that off?
>
> #lang racket
>
>
> (require syntax/parse/define)
> (define-simple-macro (if (~seq test result) ... final)
>   (cond [test result] ... [else final]))
>
> (if (even? 7) "seven" (odd? 8) "eight" "neither")
>
> (require mzlib/defmacro)
>
> (defmacro meh (x)
>   (if (> x 5)
>       1
>       (> x 2)
>       2
>       3))
>
> Running this in DrRacket produces:
>
> if: bad syntax;
>  has 5 parts after keyword in: (if (> x 5) 1 (> x 2) 2 3)
>
> The same happens if you put (begin-for-syntax (if #f 1 #f 2 3)) or
> (define-for-syntax n (if #f 1 #f 2 #f 3)) after your supplied definition.
> (For those not familiar, the "-for-syntax" forms in Racket execute things at
> compile-time, or I believe "phase 1" rather than "phase 0".)  However, it
> works to use "if" with three arguments there: it is using the built-in
> definition of "if", which appears to be present at all of Racket's
> compilation phases by default.

Right, phases are a fundamental part of Racket.

> What I want is the intermixing of runtime and compilation time that the
> phase separation seems determined to prevent (e.g. define a macro, use that
> macro in the definition--not expansion--of another macro, use that macro in
> the definition of another macro, and so on).  I tried this a long time ago
> and became convinced it was impossible without insane workarounds.

This seems unrelated to the original topic, which is the redefinition
of built-in forms.

However, there are many ways to achieve what you want in Racket
without losing the advantages of phases.

Here's one:

#lang racket
(require (for-syntax mzlib/defmacro))

(begin-for-syntax
  (require syntax/parse/define)
  (define-simple-macro (if (~seq test result) ... final)
    (cond [test result] ... [else final])))

(defmacro meh (x)
  (if (> x 5)
      1
      (> x 2)
      2
      3))

And here's another:

#lang racket

(module m racket
  (provide if)
  (require syntax/parse/define)
  (define-simple-macro (if (~seq test result) ... final)
    (cond [test result] ... [else final])))

(require 'm mzlib/defmacro (for-syntax 'm))

(defmacro meh (x)
  (if (> x 5)
      1
      (> x 2)
      2
      3))

(define (meh2 x)
  (if (> x 5)
      1
      (> x 2)
      2
      3))

>
>
> On Thu, Oct 11, 2012 at 6:54 PM, Sam Tobin-Hochstadt <samth@ccs.neu.edu>
> wrote:
>>
>> On Thu, Oct 11, 2012 at 9:29 PM, John Boyle <johnthescavenger@gmail.com>
>> wrote:
>> > While all Schemes I've tested that support define-syntax do allow
>> > redefinition of "if"... on Racket, it does not play well with low-level
>> > macros (using datum->syntax, or the "mzlib/defmacro" library) due to
>> > their
>> > phase-separation.
>>
>> This is somewhat off-topic for the formal comment, but it's quite easy
>> to do this in Racket:
>>
>> #lang racket ;; https://gist.github.com/3876906
>>
>> (require syntax/parse/define)
>> (define-simple-macro (if (~seq test result) ... final)
>>   (cond [test result] ... [else final]))
>>
>> (if (even? 7) "seven" (odd? 8) "eight" "neither")
>>
>> I'm not sure what difficulty you ran into, but it shouldn't be
>> necessary to use `datum->syntax`, `defmacro`, or any other low-level
>> features.
>> --
>> sam th
>> samth@ccs.neu.edu
>
>

--
sam th
samth@ccs.neu.edu

_______________________________________________
Scheme-reports mailing list
Scheme-reports@scheme-reports.org
http://lists.scheme-reports.org/cgi-bin/mailman/listinfo/scheme-reports