mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 11:40:18 +02:00
Optionally allow duplicate field names in core records
* NEWS: Update. * doc/ref/api-data.texi (Records): Update docs. * module/ice-9/boot-9.scm (make-record-type): Add #:allow-duplicate-field-names? keyword argument. (record-accessor, record-modifier): Allow passing indexes to identify fields. * module/rnrs/records/procedural.scm (make-record-type-descriptor): Allow duplicate field names. Fixes #38611.
This commit is contained in:
parent
cf53854d42
commit
86a9f9a271
4 changed files with 48 additions and 18 deletions
7
NEWS
7
NEWS
|
@ -79,6 +79,13 @@ Somewhat embarrassingly, the R7RS support added earlier in 2.9 failed to
|
||||||
include an implementation of `define-library'. This oversight has been
|
include an implementation of `define-library'. This oversight has been
|
||||||
corrected :)
|
corrected :)
|
||||||
|
|
||||||
|
** Optionally allow duplicate field names in core records
|
||||||
|
|
||||||
|
See the new #:allow-duplicate-field-names? keyword argument to
|
||||||
|
`make-record-type' in the manual, for more. This restores a needed
|
||||||
|
feature to R6RS records.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Changes in alpha 2.9.x (since the stable 2.2 series):
|
Changes in alpha 2.9.x (since the stable 2.2 series):
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
@c -*-texinfo-*-
|
@c -*-texinfo-*-
|
||||||
@c This is part of the GNU Guile Reference Manual.
|
@c This is part of the GNU Guile Reference Manual.
|
||||||
@c Copyright (C) 1996, 1997, 2000-2004, 2006-2017, 2019
|
@c Copyright (C) 1996, 1997, 2000-2004, 2006-2017, 2019-2020
|
||||||
@c Free Software Foundation, Inc.
|
@c Free Software Foundation, Inc.
|
||||||
@c See the file guile.texi for copying conditions.
|
@c See the file guile.texi for copying conditions.
|
||||||
|
|
||||||
|
@ -8649,6 +8649,7 @@ promise that records are disjoint with other Scheme types.
|
||||||
@deffn {Scheme Procedure} make-record-type type-name field-names [print] @
|
@deffn {Scheme Procedure} make-record-type type-name field-names [print] @
|
||||||
[#:parent=@code{#f}] [#:uid=@code{#f}] @
|
[#:parent=@code{#f}] [#:uid=@code{#f}] @
|
||||||
[#:extensible?=@code{#f}] [#:opaque?=@code{#f}] @
|
[#:extensible?=@code{#f}] [#:opaque?=@code{#f}] @
|
||||||
|
[#:allow-duplicate-field-names?=@code{#t}]
|
||||||
Create and return a new @dfn{record-type descriptor}.
|
Create and return a new @dfn{record-type descriptor}.
|
||||||
|
|
||||||
@var{type-name} is a string naming the type. Currently it's only used
|
@var{type-name} is a string naming the type. Currently it's only used
|
||||||
|
@ -8656,7 +8657,8 @@ in the printed representation of records, and in diagnostics.
|
||||||
@var{field-names} is a list of elements of the form @code{(immutable
|
@var{field-names} is a list of elements of the form @code{(immutable
|
||||||
@var{name})}, @code{(mutable @var{name})}, or @var{name}, where
|
@var{name})}, @code{(mutable @var{name})}, or @var{name}, where
|
||||||
@var{name} are symbols naming the fields of a record of the type.
|
@var{name} are symbols naming the fields of a record of the type.
|
||||||
Duplicates are not allowed among these symbols.
|
Duplicates are not allowed among these symbols, unless
|
||||||
|
@var{allow-duplicate-field-names?} is true.
|
||||||
|
|
||||||
@example
|
@example
|
||||||
(make-record-type "employee" '(name age salary))
|
(make-record-type "employee" '(name age salary))
|
||||||
|
@ -8723,9 +8725,16 @@ Return a procedure for reading the value of a particular field of a
|
||||||
member of the type represented by @var{rtd}. The returned procedure
|
member of the type represented by @var{rtd}. The returned procedure
|
||||||
accepts exactly one argument which must be a record of the appropriate
|
accepts exactly one argument which must be a record of the appropriate
|
||||||
type; it returns the current value of the field named by the symbol
|
type; it returns the current value of the field named by the symbol
|
||||||
@var{field-name} in that record. The symbol @var{field-name} must be a
|
@var{field-name} in that record.
|
||||||
member of the list of field-names in the call to @code{make-record-type}
|
|
||||||
that created the type represented by @var{rtd}.
|
If @var{field-name} is a symbol, it must be a member of the list of
|
||||||
|
field-names in the call to @code{make-record-type} that created the type
|
||||||
|
represented by @var{rtd}. If multiple fields in @var{rtd} have the same
|
||||||
|
name, @code{record-accessor} returns the first one.
|
||||||
|
|
||||||
|
If @var{field-name} is an integer, it should be an index into
|
||||||
|
@code{(record-type-fields @var{rtd})}. This allows accessing fields
|
||||||
|
with duplicate names.
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} record-modifier rtd field-name
|
@deffn {Scheme Procedure} record-modifier rtd field-name
|
||||||
|
@ -8735,9 +8744,8 @@ accepts exactly two arguments: first, a record of the appropriate type,
|
||||||
and second, an arbitrary Scheme value; it modifies the field named by
|
and second, an arbitrary Scheme value; it modifies the field named by
|
||||||
the symbol @var{field-name} in that record to contain the given value.
|
the symbol @var{field-name} in that record to contain the given value.
|
||||||
The returned value of the modifier procedure is unspecified. The symbol
|
The returned value of the modifier procedure is unspecified. The symbol
|
||||||
@var{field-name} must be a member of the list of field-names in the call
|
@var{field-name} is a field name or a field index, as in
|
||||||
to @code{make-record-type} that created the type represented by
|
@code{record-modifier}.
|
||||||
@var{rtd}.
|
|
||||||
@end deffn
|
@end deffn
|
||||||
|
|
||||||
@deffn {Scheme Procedure} record-type-descriptor record
|
@deffn {Scheme Procedure} record-type-descriptor record
|
||||||
|
|
|
@ -984,7 +984,7 @@ VALUE."
|
||||||
(make-hash-table))
|
(make-hash-table))
|
||||||
|
|
||||||
(define* (make-record-type type-name fields #:optional printer #:key
|
(define* (make-record-type type-name fields #:optional printer #:key
|
||||||
parent uid extensible?
|
parent uid extensible? allow-duplicate-field-names?
|
||||||
(opaque? (and=> parent record-type-opaque?)))
|
(opaque? (and=> parent record-type-opaque?)))
|
||||||
;; Pre-generate constructors for nfields < 20.
|
;; Pre-generate constructors for nfields < 20.
|
||||||
(define-syntax make-constructor
|
(define-syntax make-constructor
|
||||||
|
@ -1060,7 +1060,7 @@ VALUE."
|
||||||
(fields (cdr fields)))
|
(fields (cdr fields)))
|
||||||
(unless (symbol? field)
|
(unless (symbol? field)
|
||||||
(error "expected field to be a symbol" field))
|
(error "expected field to be a symbol" field))
|
||||||
(when (memq field fields)
|
(when (and (not allow-duplicate-field-names?) (memq field fields))
|
||||||
(error "duplicate field" field))
|
(error "duplicate field" field))
|
||||||
(check-fields fields))))
|
(check-fields fields))))
|
||||||
|
|
||||||
|
@ -1069,7 +1069,7 @@ VALUE."
|
||||||
tail
|
tail
|
||||||
(let ((field (car head))
|
(let ((field (car head))
|
||||||
(tail (append-fields (cdr head) tail)))
|
(tail (append-fields (cdr head) tail)))
|
||||||
(when (memq field tail)
|
(when (and (not allow-duplicate-field-names?) (memq field tail))
|
||||||
(error "duplicate field" field))
|
(error "duplicate field" field))
|
||||||
(cons field tail))))
|
(cons field tail))))
|
||||||
|
|
||||||
|
@ -1201,10 +1201,17 @@ VALUE."
|
||||||
(eq? (vector-ref parents pos) rtd))))))))
|
(eq? (vector-ref parents pos) rtd))))))))
|
||||||
(lambda (obj) (and (struct? obj) (eq? rtd (struct-vtable obj))))))
|
(lambda (obj) (and (struct? obj) (eq? rtd (struct-vtable obj))))))
|
||||||
|
|
||||||
(define (record-accessor rtd field-name)
|
(define (record-accessor rtd field-name-or-idx)
|
||||||
|
(define vtable-index-size 5) ; FIXME: pull from struct.h
|
||||||
|
(define (record-nfields rtd)
|
||||||
|
(struct-ref/unboxed rtd vtable-index-size))
|
||||||
(let ((type-name (record-type-name rtd))
|
(let ((type-name (record-type-name rtd))
|
||||||
(pos (or (list-index (record-type-fields rtd) field-name)
|
(pos (cond
|
||||||
(error 'no-such-field field-name)))
|
((and (exact-integer? field-name-or-idx)
|
||||||
|
(<= 0 field-name-or-idx (record-nfields rtd)))
|
||||||
|
field-name-or-idx)
|
||||||
|
((list-index (record-type-fields rtd) field-name-or-idx))
|
||||||
|
(else (error 'no-such-field field-name-or-idx))))
|
||||||
(pred (record-predicate rtd)))
|
(pred (record-predicate rtd)))
|
||||||
(lambda (obj)
|
(lambda (obj)
|
||||||
(unless (pred obj)
|
(unless (pred obj)
|
||||||
|
@ -1214,10 +1221,17 @@ VALUE."
|
||||||
#f))
|
#f))
|
||||||
(struct-ref obj pos))))
|
(struct-ref obj pos))))
|
||||||
|
|
||||||
(define (record-modifier rtd field-name)
|
(define (record-modifier rtd field-name-or-idx)
|
||||||
|
(define vtable-index-size 5) ; FIXME: pull from struct.h
|
||||||
|
(define (record-nfields rtd)
|
||||||
|
(struct-ref/unboxed rtd vtable-index-size))
|
||||||
(let ((type-name (record-type-name rtd))
|
(let ((type-name (record-type-name rtd))
|
||||||
(pos (or (list-index (record-type-fields rtd) field-name)
|
(pos (cond
|
||||||
(error 'no-such-field field-name)))
|
((and (exact-integer? field-name-or-idx)
|
||||||
|
(<= 0 field-name-or-idx (record-nfields rtd)))
|
||||||
|
field-name-or-idx)
|
||||||
|
((list-index (record-type-fields rtd) field-name-or-idx))
|
||||||
|
(else (error 'no-such-field field-name-or-idx))))
|
||||||
(pred (record-predicate rtd)))
|
(pred (record-predicate rtd)))
|
||||||
(unless (logbit? pos (record-type-mutable-fields rtd))
|
(unless (logbit? pos (record-type-mutable-fields rtd))
|
||||||
(error "field is immutable" rtd field-name))
|
(error "field is immutable" rtd field-name))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
;;; procedural.scm --- Procedural interface to R6RS records
|
;;; procedural.scm --- Procedural interface to R6RS records
|
||||||
|
|
||||||
;; Copyright (C) 2010, 2017 Free Software Foundation, Inc.
|
;; Copyright (C) 2010, 2017, 2019-2020 Free Software Foundation, Inc.
|
||||||
;;
|
;;
|
||||||
;; This library is free software; you can redistribute it and/or
|
;; This library is free software; you can redistribute it and/or
|
||||||
;; modify it under the terms of the GNU Lesser General Public
|
;; modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -53,6 +53,7 @@
|
||||||
(define (make-record-type-descriptor name parent uid sealed? opaque? fields)
|
(define (make-record-type-descriptor name parent uid sealed? opaque? fields)
|
||||||
(make-record-type name (vector->list fields) #:parent parent #:uid uid
|
(make-record-type name (vector->list fields) #:parent parent #:uid uid
|
||||||
#:extensible? (not sealed?)
|
#:extensible? (not sealed?)
|
||||||
|
#:allow-duplicate-field-names #t
|
||||||
#:opaque? (or opaque?
|
#:opaque? (or opaque?
|
||||||
(and parent (record-type-opaque? parent)))))
|
(and parent (record-type-opaque? parent)))))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue