https://gambitscheme.org/wiki/api.php?action=feedcontributions&user=Taylor+Venable&feedformat=atomGambit wiki - User contributions [en]2024-03-28T09:19:35ZUser contributionsMediaWiki 1.35.3https://gambitscheme.org/wiki/index.php?title=Special:Badtitle/NS100:Special_form_define-record-type&diff=2574Special:Badtitle/NS100:Special form define-record-type2012-01-28T16:21:48Z<p>Taylor Venable: /* Field attributes */ Expand more on the usage of field attributes</p>
<hr />
<div><texinfo><br />
<br />
@deffn {special form} define-record-type @dots{}<br />
@deffnx {special form} define-type @dots{}<br />
@end deffn<br />
<br />
</texinfo><br />
<br />
<hr><br />
<br />
===User contributed comments, clarifications and examples===<br />
<br />
[http://www.r6rs.org/r6rs-editors/2005-June/000664.html Mark Feeley explains Gambit-C Records on r6rs-editors]<br />
<br />
<br />
==== Content from define-type on main wiki page ====<br />
<br />
== define-type / define-structure usage ==<br />
<br />
Here is a traduction of some of Marc's slides from an introduction to scheme course. I believe they might be usefull since define-type / define-record are very lightly documented in the official doc.<br />
<br />
=== Syntax ===<br />
<br />
(define-type type-name <attribute or field>...)<br />
<br />
Attribute is a keyword. An attribute may have arguments?<br />
<br />
Field is a symbol or a list. If a list, the first element is the field name, optionally followed by getter and setter, then field attributes<br />
<br />
The simplest form of syntax specifies only the type name and the name of each fields<br />
*ex:<br />
<br />
:C: '''typedef struct { int x; int y; } point2d;'''<br />
:Gambit : '''(define-type point2d x y)'''<br />
<br />
*Such type definition are equivalent to multiple definitions:<br />
(define (make-point2d x y)...) ;constructor<br />
(define (point2d? obj)... ) ;predicate<br />
(define (point2d-x p)...) ;access to x field<br />
(define (point2d-x-set! p x)...) ;mutation of x field<br />
(define (point2d-y p)...) ;access to y field<br />
(define (point2d-y-set! p y)...) ;mutation of y field<br />
<br />
*ex:<br />
<br />
> (define-type point2d x y)<br />
> (define p (make-point2d 11 22))<br />
> p<br />
#<point2d #2 x: 11 y: 22><br />
> (point2d? p)<br />
#t<br />
> (point2d-x p)<br />
11<br />
> (point2d-x-set! p 33)<br />
> p<br />
#<point2d #2 x: 33 y: 22><br />
<br />
=== define-type attributes ===<br />
<br />
*These structures also supports inheritance<br />
*The parameter '''extender:''' ''name'' specifies the name of the definition form to use to define a subtype:<br />
> (define-type point2d<br />
extender: define-type-of-point2d<br />
x<br />
y)<br />
> (define-type-of-point2d point3d z)<br />
> (define p3 (make-point3d 11 22 33))<br />
> p3<br />
#<point3d #2 x: 11 y: 22 z: 33><br />
> (point2d? p3)<br />
#t<br />
> (point3d? p3)<br />
#t<br />
> (point2d-x p3)<br />
11<br />
> (point3d-z p3)<br />
33<br />
* '''id:''' ''uuid''<br />
Specifies an identifier that is used to name this precise type uniquely, which is used during (de)serialization via <tt>object->u8vector</tt> and <tt>u8vector->object</tt>.<br />
* '''constructor:''' ''name''<br />
Specifies the name of the generated constructor macro.<br />
* '''predicate:''' ''name''<br />
Specifies the name of the generated function/macro for testing if a value has this type.<br />
* '''prefix:''' ''pfx''<br />
All generated functions/macros will have ''pfx'' before their regular name. For example:<br />
> (define-type foo prefix: xyz a b)<br />
> (xyzmake-foo 1 2)<br />
#<foo #2 a: 1 b: 2><br />
> (xyzfoo-a (xyzmake-foo 1 2))<br />
1<br />
* '''macros:'''<br />
Do not generate procedures for any purpose; the predicate and all field getters/setters will be macros.<br />
> (define-type foo a b)<br />
> foo-a<br />
#<procedure #2 foo-a><br />
> (define-type bar macros: a b)<br />
> bar-a<br />
*** ERROR IN (console)@4.1 -- Macro name can't be used as a variable: bar-a<br />
<br />
TODO other define-type's parameters:<br />
*'''constant-constructor:'''<br />
*'''implementer:'''<br />
*'''type-exhibitor:'''<br />
*'''opaque:'''<br />
<br />
=== Field attributes ===<br />
<br />
* '''read-write:'''<br />
Default option. A setter procedure/macro is generated.<br />
<br />
* '''read-only:'''<br />
No setter is generated, effectively rendering the field read-only after it is set by the constructor.<br />
<br />
* '''equality-test:'''<br />
Default option. Testing type instances using <tt>equal?</tt> will check the values of this field as part of that test.<br />
<br />
* '''equality-skip:'''<br />
Testing type instances using <tt>equal?</tt> will ignore the values of this field.<br />
<br />
> (define-type alpha x y)<br />
> (equal? (make-alpha 0 1) (make-alpha 0 2))<br />
#f<br />
> (define-type beta x (y equality-skip:))<br />
> (equal? (make-beta 0 1) (make-beta 0 2))<br />
#t<br />
<br />
* '''printable:'''<br />
Default option. The field will be printed when the type instance itself is.<br />
<br />
* '''unprintable:'''<br />
The field will not be printed when the type instance is printed.<br />
<br />
> (define-type foo a (b unprintable:))<br />
> (make-foo 1 2)<br />
#<foo #3 a: 1><br />
<br />
* '''init:''' ''cst''<br />
Set the initial value to literal value ''cst''. Note that this does not make the field optional in the constructor; the field can not be provided when using the constructor.<br />
<br />
> (define-type alpha a (b init: 1))<br />
> (make-alpha 0 99)<br />
*** ERROR IN (console)@2.1 -- Wrong number of arguments passed to procedure<br />
(make-alpha 0 99)<br />
> (make-alpha 0)<br />
#<alpha #2 a: 0 b: 1><br />
<br />
==== Examples ====<br />
<br />
> (define-type noeud<br />
(a unprintable:)<br />
(b read-only: init: 9)<br />
(c equality-skip:))<br />
> (define x (make-noeud 1 2))<br />
> (noeud-a-set! x x)<br />
> x<br />
#<noeud #2 b: 9 c: 2><br />
> (equal? x (make-noeud x 3))<br />
#t<br />
> (noeud-b-set! x 999)<br />
*** ERROR -- Unbound variable: noeud-b-set!<br />
<br />
==== Other Information ====<br />
<br />
All field attributes except '''init:''' can be specified at define-type level and will affect all fields. A field can specify its own field attributes to override default attributes.<br />
<br />
*ex:<br />
> (define-type foo unprintable: a (b printable:))<br />
> (make-foo 1 2)<br />
#<foo #3 b: 2><br />
<br />
*Field may have non-conventional getter and setter names, specified after field name in that order<br />
<br />
*ex:<br />
> (define-type foo (a get-a) (b get-b set-b))<br />
> (define x (make-foo 1 2))<br />
> (get-a x)<br />
1<br />
> (set-a x 2)<br />
*** ERROR IN (console)@14.2 -- Unbound variable: set-a<br />
> (get-b x)<br />
2<br />
> (set-b x 3)<br />
> (get-b x)<br />
3</div>Taylor Venablehttps://gambitscheme.org/wiki/index.php?title=Special:Badtitle/NS100:Special_form_define-record-type&diff=2573Special:Badtitle/NS100:Special form define-record-type2012-01-27T12:17:19Z<p>Taylor Venable: /* define-type attributes */ Add some define-type attributes: id, constructor, predicate, prefix, macros</p>
<hr />
<div><texinfo><br />
<br />
@deffn {special form} define-record-type @dots{}<br />
@deffnx {special form} define-type @dots{}<br />
@end deffn<br />
<br />
</texinfo><br />
<br />
<hr><br />
<br />
===User contributed comments, clarifications and examples===<br />
<br />
[http://www.r6rs.org/r6rs-editors/2005-June/000664.html Mark Feeley explains Gambit-C Records on r6rs-editors]<br />
<br />
<br />
==== Content from define-type on main wiki page ====<br />
<br />
== define-type / define-structure usage ==<br />
<br />
Here is a traduction of some of Marc's slides from an introduction to scheme course. I believe they might be usefull since define-type / define-record are very lightly documented in the official doc.<br />
<br />
=== Syntax ===<br />
<br />
(define-type type-name <attribute or field>...)<br />
<br />
Attribute is a keyword. An attribute may have arguments?<br />
<br />
Field is a symbol or a list. If a list, the first element is the field name, optionally followed by getter and setter, then field attributes<br />
<br />
The simplest form of syntax specifies only the type name and the name of each fields<br />
*ex:<br />
<br />
:C: '''typedef struct { int x; int y; } point2d;'''<br />
:Gambit : '''(define-type point2d x y)'''<br />
<br />
*Such type definition are equivalent to multiple definitions:<br />
(define (make-point2d x y)...) ;constructor<br />
(define (point2d? obj)... ) ;predicate<br />
(define (point2d-x p)...) ;access to x field<br />
(define (point2d-x-set! p x)...) ;mutation of x field<br />
(define (point2d-y p)...) ;access to y field<br />
(define (point2d-y-set! p y)...) ;mutation of y field<br />
<br />
*ex:<br />
<br />
> (define-type point2d x y)<br />
> (define p (make-point2d 11 22))<br />
> p<br />
#<point2d #2 x: 11 y: 22><br />
> (point2d? p)<br />
#t<br />
> (point2d-x p)<br />
11<br />
> (point2d-x-set! p 33)<br />
> p<br />
#<point2d #2 x: 33 y: 22><br />
<br />
=== define-type attributes ===<br />
<br />
*These structures also supports inheritance<br />
*The parameter '''extender:''' ''name'' specifies the name of the definition form to use to define a subtype:<br />
> (define-type point2d<br />
extender: define-type-of-point2d<br />
x<br />
y)<br />
> (define-type-of-point2d point3d z)<br />
> (define p3 (make-point3d 11 22 33))<br />
> p3<br />
#<point3d #2 x: 11 y: 22 z: 33><br />
> (point2d? p3)<br />
#t<br />
> (point3d? p3)<br />
#t<br />
> (point2d-x p3)<br />
11<br />
> (point3d-z p3)<br />
33<br />
* '''id:''' ''uuid''<br />
Specifies an identifier that is used to name this precise type uniquely, which is used during (de)serialization via <tt>object->u8vector</tt> and <tt>u8vector->object</tt>.<br />
* '''constructor:''' ''name''<br />
Specifies the name of the generated constructor macro.<br />
* '''predicate:''' ''name''<br />
Specifies the name of the generated function/macro for testing if a value has this type.<br />
* '''prefix:''' ''pfx''<br />
All generated functions/macros will have ''pfx'' before their regular name. For example:<br />
> (define-type foo prefix: xyz a b)<br />
> (xyzmake-foo 1 2)<br />
#<foo #2 a: 1 b: 2><br />
> (xyzfoo-a (xyzmake-foo 1 2))<br />
1<br />
* '''macros:'''<br />
Do not generate procedures for any purpose; the predicate and all field getters/setters will be macros.<br />
> (define-type foo a b)<br />
> foo-a<br />
#<procedure #2 foo-a><br />
> (define-type bar macros: a b)<br />
> bar-a<br />
*** ERROR IN (console)@4.1 -- Macro name can't be used as a variable: bar-a<br />
<br />
TODO other define-type's parameters:<br />
*'''constant-constructor:'''<br />
*'''implementer:'''<br />
*'''type-exhibitor:'''<br />
*'''opaque:'''<br />
<br />
=== Field attributes ===<br />
<br />
*Field attributes:<br />
**'''read-write:'''<br />
**'''read-only:''' non mutable field<br />
**'''equality-test:'''<br />
**'''equality-skip:''' the '''equal?''' function will ignore this field<br />
**'''printable:'''<br />
**'''unprintable:''' the '''write''' function will ignore it<br />
**'''init:''' ''cst'' initial value<br />
<br />
*ex:<br />
> (define-type noeud<br />
(a unprintable:)<br />
(b read-only: init: 9)<br />
(c equality-skip:))<br />
> (define x (make-noeud 1 2))<br />
> (noeud-a-set! x x)<br />
> x<br />
#<noeud #2 b: 9 c: 2><br />
> (equal? x (make-noeud x 3))<br />
#t<br />
> (noeud-b-set! x 999)<br />
*** ERROR -- Unbound variable: noeud-b-set!<br />
<br />
All field attributes except '''init:''' can be specified at define-type level and will affect all fields. A field can specify its own field attributes to override default attributes.<br />
<br />
*ex:<br />
> (define-type foo unprintable: a (b printable:))<br />
> (make-foo 1 2)<br />
#<foo #3 b: 2><br />
<br />
*Field may have non-conventional getter and setter names, specified after field name in that order<br />
<br />
*ex:<br />
> (define-type foo (a get-a) (b get-b set-b))<br />
> (define x (make-foo 1 2))<br />
> (get-a x)<br />
1<br />
> (set-a x 2)<br />
*** ERROR IN (console)@14.2 -- Unbound variable: set-a<br />
> (get-b x)<br />
2<br />
> (set-b x 3)<br />
> (get-b x)<br />
3</div>Taylor Venable