[gambit-list] questions about define-type, and structures in general
Marc Feeley
feeley at iro.umontreal.ca
Mon May 23 17:12:49 EDT 2011
On 2011-05-22, at 4:10 PM, Matthew Koichi Grimes wrote:
>
>
> On Sun, May 22, 2011 at 6:39 AM, Mikael <mikael.rcv at gmail.com> wrote:
>
> Why would you want this?
>
> As Adrien mentioned, it's a common practice in other languages, which I got used to (Python: override __repr__(), c++: override operator<<(), Java: override ToString(), etc). In my particular case, I was writing a doubly-linked list type, and wanted it to print (up to) its first three and last three values when displayed in the REPL.
>
> Anyhow, you could make your own Gambit patch that adds a pp: procedure argument to define-type. Feel free to publish your patch on the Dumping grounds.
>
>
> I'll start by learning how to write macros! :D
Alternatively you can add a hook for your types in the "printer:
(define-type foo
field1
field2)
(set! ##wr
(lambda (we obj)
(cond ((foo? obj)
(##wr-str we "#s(FOO ")
(##wr we (foo-field1 obj))
(##wr-str we " ")
(##wr we (foo-field2 obj))
(##wr-str we ")"))
(else
(##default-wr we obj)))))
(pp (make-foo 11 22)) ;; prints: #s(FOO 11 22)
>
>
> Similarly, how can I define a custom constructor that does something more complicated than assign arguments to slots?
>
> By defining your own procedure that does the job.
>
> I figured it out. Here's an expanded answer for other beginners. It's actually as easy as:
>
> (define-type my-type
> ...
> constructor: (lambda (<args>) <body>)
> ...)
That's not correct. The constructor: clause specifies the name of the constructor to override the default name, i.e.
(define-type foo
constructor: make-bar
field1
field2)
(pp (make-bar 11 22))
You want something like this:
(define-type foo
field1
field2)
(define (construct-a-foo x)
(make-foo x (* x x)))
>
>
> Someone else please verify that Gambit's define-record-type is just an alternative name for define-type, just like what call/cc is to call-with-current-continuation .
>
> It seems that they aren't equivalent. Gambit's define-record-type comes from srfi-9, which uses positional arguments rather than define-type's keyword arguments:
>
> http://srfi.schemers.org/srfi-9/srfi-9.html
>
> From the example in the above link, we see that you can define a "pare" (pair) type as follows:
> (define-record-type :pare
>
>
> (kons x y)
>
> pare?
> (x kar set-kar!)
> (y kdr))
>
> We can then do a quick smoke-check to see that it worked:
> > (pare? (kons 1 2))
> #t
>
> If we restart the interpreter and repeat the above two steps, this time using define-type instead of define-record type, we get:
>
> > (define-type :pare (kons x y) pare? (x kar set-kar!) (y kdr))
>
>
> > (pare? (kons 1 2))
>
> *** ERROR IN (console)@2.2 -- Unbound variable: pare?
>
> That said, define-record-type does seem to be defined in terms of define-type, as can be seen in ~~/lib/nonstd.scm. Also, define-structure is equivalent to define-type:
>
>
>
>
> (define-runtime-macro (define-type . args)
> (##define-type-expand 'define-type #f #f args))
>
> (define-runtime-macro (define-structure . args)
> (##define-type-expand 'define-structure #f #f args))
>
>
>
>
> (define-runtime-macro (define-record-type name constructor predicate . fields)
> `(define-type ,name
> constructor: ,constructor
> predicate: ,predicate
> , at fields))
Yes all three forms share a common implementation. So wether you define a structure with a define-type or define-structure or define-record-type (with their respective syntaxes) the same implementation is obtained.
Marc
More information about the Gambit-list
mailing list