Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

R6RS records: what are protocol and opaque?

3 views
Skip to first unread message

Grant Rettke

unread,
Feb 15, 2009, 4:34:17 PM2/15/09
to
In R6RS records, what are protocol and opaque for?

Derick Eddington

unread,
Feb 15, 2009, 11:47:25 PM2/15/09
to
On Feb 15, 1:34 pm, Grant Rettke <gret...@gmail.com> wrote:
> In R6RS records, what are protocol and opaque for?

protocol is for customizing record constructors and/or checking their
arguments. E.g.:

> (define-record-type thing (fields x y z)
(protocol
(lambda (c)
(lambda (a)
(c (- a) (/ a) (* a a))))))
> (make-thing 2)
#[thing -2 1/2 4]
>

I think I agree with Will Clinger [1] that protocol sucks and is not
needed.

opaque is to prevent records from being inspected by code that should
not be able to. E.g., your program puts sensitive information in your
record type and wants to pass instances of these records (directly, or
embedded somewhere in some non-opaque compound object) to someone
else's library your program uses and you want to ensure that this
library cannot access the sensitive information, not even indirectly
via inspection, printing, etc. This is very useful because people
should be able to use others' libraries without having to do a full
security audit of them; but record opacity is only part of the
solution, capability-based security and POLA (principle of least
authority) [2][3][4] (with hardware resources control) are the rest (I
believe). Capability-based security with records would involve not
giving untrusted code record accessors or mutators, record type
descriptors, etc. Because of Scheme's lexical scoping, closures, and
now libraries' with complete namespace / bindings control, I believe
Scheme is the ideal language to do capability-based security, and this
is one of my main long-term goals to use Scheme for.

[1] I can't remember where I saw Will's examples of not needing
protocol.
[2] http://en.wikipedia.org/wiki/Capability-based_security
[3] http://en.wikipedia.org/wiki/Principle_of_least_authority
[4] http://mumble.net/~jar/pubs/secureos/

P.S. One reason I'm voting for Jonathan Rees is because he
understands capability-based security.

--
: Derick
----------------------------------------------------------------

leppie

unread,
Feb 16, 2009, 12:03:20 AM2/16/09
to
On Feb 16, 6:47 am, Derick Eddington <derick.edding...@gmail.com>
wrote:

> [1] I can't remember where I saw Will's examples of not needing
> protocol.

Probably in his ERR5RS records SRFI :)

Cheers

leppie

Derick Eddington

unread,
Feb 16, 2009, 12:27:47 AM2/16/09
to

Yeah, that's where. Thanks.

http://srfi.schemers.org/srfi-99/

--
: Derick
----------------------------------------------------------------

Michael Sperber

unread,
Feb 16, 2009, 2:39:21 AM2/16/09
to

Grant Rettke <gre...@gmail.com> writes:

> In R6RS records, what are protocol and opaque for?

The rationale has a section on `protocol' at 18.4.

--
Cheers =8-} Mike
Friede, Völkerverständigung und überhaupt blabla

Derick Eddington

unread,
Feb 17, 2009, 4:45:44 AM2/17/09
to
On Feb 15, 8:47 pm, Derick Eddington <derick.edding...@gmail.com>
wrote:

> On Feb 15, 1:34 pm, Grant Rettke <gret...@gmail.com> wrote:
>
> > In R6RS records, what are protocol and opaque for?
>
> protocol is for customizing record constructors and/or checking their
> arguments.

> I think I agree with Will Clinger [1] that protocol sucks and is not
> needed.

I should say I don't think Will ever said `protocol' sucks or
suggested that in SRFI-99. I was assuming he thinks that because he
doesn't like the R6RS records. Now I'm wondering if `protocol'
doesn't suck. I apologize for getting carried away with Usenet
pyromania.

I had been thinking `protocol' was just syntactic sugar for
accomplishing the same thing shown in the examples of SRFI-99 and that
the sugar wasn't really better or clearer than doing it like the
examples of SRFI-99 so why is `protocol' justified? But I realized
`protocol' has an advantage over what the examples of SRFI-99 do (and
over what the procedural examples of R6RS Libraries 6.3 do).

To make a customized record constructor for a sub-type of a type which
also has a customized constructor, the R6RS syntactic layer and its
`protocol' do not need the protocol procedures (which SRFI-99 does) or
constructor descriptors (which R6RS procedural layer does) of the
parent type(s). This seems a significant advantage for creating sub-
types of types from separate libraries because needing the protocol
procedures (or constructor descriptors) means they have to be exported
and imported or they have to be manually dug out using inspection of
the parent record type descriptor(s). E.g:

;;;; R6RS syntactic layer

(library (A)
(export rt1)
(import (rnrs (6)))
(define-record-type rt1
(fields x1 x2)
(protocol
(lambda (p)
(lambda (a b c)
(p (+ a b) (+ b c)))))))

(library (B)
(export rt2)
(import (rnrs (6))
(A))
(define-record-type rt2 (parent rt1)
(fields x3 x4)
(protocol
(lambda (n)
(lambda (a b c d e f)
(let ((p (n a b c)))
(p (+ d e) (+ e f))))))))

(library (C)
(export make-rt3)
(import (rnrs (6))
(B))
(define-record-type rt3 (parent rt2)
(fields x5 x6)
(protocol
(lambda (n)
(lambda (a b c d e f g h i)
(let ((p (n a b c d e f)))
(p (+ g h) (+ h i))))))))

;;;; SRFI-99 -- note the protocol procedures must be exported

(library (A)
(export rtd1
protocol1)
(import (rnrs base)
(err5rs records procedural))
(define rtd1
(make-rtd 'rtd1 '#((immutable x1) (immutable x2))))
(define protocol1
(lambda (p)
(lambda (a b c)
(p (+ a b) (+ b c)))))
(define make-rt1
(protocol1 (rtd-constructor rtd1))))

(library (B)
(export rtd2
protocol2)
(import (rnrs base)
(err5rs records procedural)
(A))
(define rtd2
(make-rtd 'rtd2 '#((immutable x3) (immutable x4)) rtd1))
(define protocol2
(lambda (n)
(lambda (a b c d e f)
(let ((p (n a b c)))
(p (+ d e) (+ e f))))))
(define make-rt2
(let ((maker2 (rtd-constructor rtd2)))
(protocol2
(protocol1
(lambda (x1 x2)
(lambda (x3 x4)
(maker2 x1 x2 x3 x4))))))))

(library (C)
(export make-rt3)
(import (rnrs base)
(err5rs records procedural)
(A)
(B))
(define rtd3
(make-rtd 'rtd3 '#((immutable x5) (immutable x6)) rtd2))
(define protocol3
(lambda (n)
(lambda (a b c d e f g h i)
(let ((p (n a b c d e f)))
(p (+ g h) (+ h i))))))
(define make-rt3
(let ((maker3 (rtd-constructor rtd3)))
(protocol3
(protocol2
(protocol1
(lambda (x1 x2)
(lambda (x3 x4)
(lambda (x5 x6)
(maker3 x1 x2 x3 x4 x5 x6))))))))))

Comparing the two ways above, now R6RS's `protocol' sugar is looking
even better to me because you don't have to manually make all the
closures and call all the protocol procedures. I knew this before but
didn't care as much. Abstracting away this tedious manual task seems
a decent justification to me for R6RS having its `protocol' or at
least for it having constructor descriptors that make abstraction
possible.

So now I'm confused by SRFI-99. At the beginning of its protocol
examples, it says "R6RS library section 6.3 includes two extended
examples that provide a nice comparison of the R6RS and ERR5RS record
systems, especially since these two examples were designed to
highlight the use of R6RS record-constructor descriptors in
combination with inheritance.", which gives me the impression SRFI-99
is saying its protocol way is better (which no longer looks true to
me); but after the examples it says "The purpose of the R6RS record-
constructor descriptors is to automate the idiom shown in the
definitions of make-rtd1, make-rtd2, and make-rtd3 above", which gives
me the impression R6RS record constructor descriptors and `protocol'
sugar are justified. These two impressions conflict. I think these
statements of SRFI-99 should be clearer.

It doesn't look like a convenience similar to R6RS's `protocol' sugar
can even be made for a syntactic layer built on SRFI-99's procedural
and inspection layers; am I wrong?

--
: Derick
----------------------------------------------------------------

leppie

unread,
Feb 17, 2009, 5:49:01 AM2/17/09
to
On Feb 17, 11:45 am, Derick Eddington <derick.edding...@gmail.com>
wrote:

>   (define make-rt3


>     (let ((maker3 (rtd-constructor rtd3)))
>       (protocol3
>        (protocol2
>         (protocol1
>          (lambda (x1 x2)
>            (lambda (x3 x4)
>              (lambda (x5 x6)
>                (maker3 x1 x2 x3 x4 x5 x6))))))))))

I thought the whole idea was to eliminate needed access to the parent
protocol, at least when implementing the functionality in IronScheme.
What became clear is the close relation to objects in .NET. The same
constraints that protocol inflicts is similar to way constructors are
chained, like (assume A, B, C hierachy where A is the root):

Construct C
Construct B
Construct A
Process A constructor/protocol
Process B constructor/protocol
Process C constructor/protocol

What you are left is a conceptional list of computed values, mapping
to the fields in the record. In fact, you could substitute the last
'protocol' with list, and it should just return a list instead of the
constructed object.

Finally one would just call a generic record constructor, taking the
record type, and the values.

Cheers

leppie

William D Clinger

unread,
Feb 17, 2009, 11:31:46 AM2/17/09
to
Derick Eddington wrote:
> I should say I don't think Will ever said `protocol' sucks or
> suggested that in SRFI-99. I was assuming he thinks that because he
> doesn't like the R6RS records. Now I'm wondering if `protocol'
> doesn't suck.

The protocol idea makes sense, but the way it was
incorporated into R6RS records violates several
generally accepted principles of language design,
including but not limited to:

Thou shalt not hair up the common case just to
simplify unusual cases.

Orthogonal concepts should be provided by
orthogonal constructs.

Programming languages should be designed not by
piling feature on top of feature, but by removing
the weaknesses and restrictions that make additional
features appear necessary.

> To make a customized record constructor for a sub-type of a type which
> also has a customized constructor, the R6RS syntactic layer and its
> `protocol' do not need the protocol procedures (which SRFI-99 does) or
> constructor descriptors (which R6RS procedural layer does) of the
> parent type(s).

That's misleading. What the R6RS syntactic layer does
is to combine a record type descriptor with a favored
constructor descriptor, and packages that combination
into some mysterious syntactic record type, about which
the R6RS says essentially nothing further.

In fact, the R6RS does not even guarantee that the record
types defined by a syntactic record definition can be
exported. According to the R6RS, only variables and
syntax can be exported, and syntactic record types are
neither.

Furthermore the R6RS syntactic layer's treatment of
constructor descriptors is inconsistent with the R6RS
procedural layer's treatment. With the R6RS procedural
layer, there is no favored constructor descriptor. You
can define as many constructor descriptors as you want,
so long as you want at least one.

In the common case, however, you don't want any. The
R6RS makes you create one anyway.

> Abstracting away this tedious manual task seems
> a decent justification to me for R6RS having its `protocol' or at
> least for it having constructor descriptors that make abstraction
> possible.

Constructor descriptors make perfect sense, and should
(in my opinion) be the subject of a SRFI. The R6RS's
mistake (or one of them, anyway) was to bundle them so
tightly with record type descriptors that it became
impossible to create new instances of a record type
without creating at least one constructor descriptor.

Other mistakes include:

the most-favored-constructor status that is implicit
in the R6RS syntactic layer but non-existent in the
R6RS procedural layer;

the breakdown of abstraction that comes of having to
know whether a record type you want to extend was
defined using the procedural layer or the syntactic
layer;

the fundamental mistake of trying to use distinct
and incompatible notions of record type for the
procedural and syntactic layers.

> It doesn't look like a convenience similar to R6RS's `protocol' sugar
> can even be made for a syntactic layer built on SRFI-99's procedural
> and inspection layers; am I wrong?

Yes. Something analogous to R6RS's protocol sugar could
(and, in my opinion, should) be the subject of a SRFI.
Of course, that SRFI's design should avoid the mistakes
made in the design of R6RS records.

In my opinion, that SRFI should be separate from SRFI 99
because we need to emphasize that the concepts of protocols
and constructor descriptors are orthogonal to record types
and should be provided by an orthogonal construct.

Will

Derick Eddington

unread,
Feb 17, 2009, 8:46:25 PM2/17/09
to
Thank you, Will, for the informative response. My understanding has
increased.

On Feb 17, 8:31 am, William D Clinger <cesur...@yahoo.com> wrote:

> Other mistakes include:

> the fundamental mistake of trying to use distinct
> and incompatible notions of record type for the
> procedural and syntactic layers.

I've had to deal with this issue and didn't like it. My (xitomatl
match) library can match records, and to do so it needs record type
descriptors. Because I thought most users' record types would be
defined via the syntactic layer, I didn't want them to have to do:

(match ---
((:record (record-type-descriptor thing) ---)
---))

So I automatically wrap the record type in record-type-descriptor so
they can do:

(match ---
((:record thing ---)
---))

And to support expressions which evaluate to first-class record types,
which I absolutely want to be supported, they can do:

(match ---
((:record (RTD expr) ---)
---))

I'm not happy with this state of affairs of my matcher because, not
only do I not like the additional syntax, users are required to know
whether the record type was defined via the syntactic or procedural
layer, regardless of whether or not I provide automatic wrapping and
the RTD syntax.

I imagine similar issues will come up in many cases people will want
to use record types. So I fully support having only first-class
record types, also for the same reasons we love first-class for other
things.

> > It doesn't look like a convenience similar to R6RS's `protocol' sugar
> > can even be made for a syntactic layer built on SRFI-99's procedural
> > and inspection layers; am I wrong?
>
> Yes.

OK, good.

--
: Derick
----------------------------------------------------------------

0 new messages