Hi all,

I've found that when using racket/class, one syntactic pain point I keep
encountering is that the instantiation is clumsy. This is especially
true if I want to mix different styles of instantiation (keyword and
positional).

Is there any reason to not make the instantiation syntax of `new` more
flexible? I most prefer `new` since it's the shortest and also most
familiar of the three (the others being `make-object` and
`instantiate`).

In particular, I'm imagining the following syntax:

  (new c% 1 2 3)       => (instantiate c% (1 2 3))
  (new c% [x 1] [y 2]) => (instantiate c% [x 1] [y 2])
  (new c% [z 3] 1 2)   => (instantiate c% (1 2) [z 3])
  (new c% 1 [z 3] 2)   => (instantiate c% (1 2) [z 3])

and so on. Attached is a patch that implements this (modulo tests &
docs). Any thoughts?

Cheers,
Asumu
>From cb0bfa789dc9d0a1c59f8090e9b967bb56f9ff9d Mon Sep 17 00:00:00 2001
From: Asumu Takikawa <[email protected]>
Date: Fri, 1 Feb 2013 15:09:51 -0500
Subject: [PATCH] Add more flexible instantiation syntax for `new`

---
 collects/racket/private/class-internal.rkt |   41 ++++++++++++++++------------
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/collects/racket/private/class-internal.rkt b/collects/racket/private/class-internal.rkt
index 2c03780..57d08e7 100644
--- a/collects/racket/private/class-internal.rkt
+++ b/collects/racket/private/class-internal.rkt
@@ -3808,24 +3808,31 @@ An example
 ;;  instantiation
 ;;--------------------------------------------------------------------
 
+;; class instantiation syntax, allows mixed keywords and positionals
 (define-syntax (new stx)
-  (syntax-case stx ()
-    [(_ cls (id arg) ...)
-     (andmap identifier? (syntax->list (syntax (id ...))))
-     (quasisyntax/loc stx
-       (instantiate cls () (id arg) ...))]
-    [(_ cls (id arg) ...)
-     (for-each (lambda (id)
-                 (unless (identifier? id)
-                   (raise-syntax-error 'new "expected identifier" stx id)))
-               (syntax->list (syntax (id ...))))]
-    [(_ cls pr ...)
-     (for-each
-      (lambda (pr)
-        (syntax-case pr ()
-          [(x y) (void)]
-          [else (raise-syntax-error 'new "expected name and value binding" stx pr)]))
-      (syntax->list (syntax (pr ...))))]))
+  (syntax-parse stx
+    [(_ cls arg ...)
+     (define-values (kw-args pos-args)
+       (parse-init-args #'(arg ...)))
+     (with-syntax ([(kw ...) kw-args]
+                   [(pos ...) pos-args])
+      (quasisyntax/loc stx
+        (instantiate cls (pos ...) kw ...)))]))
+
+(begin-for-syntax
+ ;; listof<syntax> -> (values listof<syntax> listof<syntax>)
+ ;; parses arguments for `new` and collects them into two lists
+ (define (parse-init-args stx)
+   (define stxs (syntax->list stx))
+   (define-values (kw-args pos-args)
+     (for/fold ([kw-args '()]
+                [pos-args '()])
+               ([stx stxs])
+       (syntax-parse stx
+         [(kw:id arg)
+          (values (cons stx kw-args) pos-args)]
+         [arg (values kw-args (cons stx pos-args))])))
+   (values kw-args (reverse pos-args))))
 
 (define ((make-object/proc blame) class . args)
   (do-make-object blame class args null))
-- 
1.7.10.4

_________________________
  Racket Developers list:
  http://lists.racket-lang.org/dev

Reply via email to