Why struct type doesn't include field names?

65 views
Skip to first unread message

Sorawee Porncharoenwase

unread,
Jun 13, 2019, 11:50:48 PM6/13/19
to Racket list

Several struct extensions need to construct accessors unhygienically even though the accessors can be extracted from struct types. The reason is that there’s not enough information to establish connection between field names and accessors.

For instance, consider struct* from racket/match.

#lang racket

(module submodule racket
  (provide struct-id)
  #;(provide struct-id-a struct-id-b)
  (struct struct-id (a b)))

(require 'submodule)

(match (struct-id 1 2)
  [(struct-id p q) (printf "~a ~a\n" p q)])

#;(match (struct-id 1 2)
  [(struct* struct-id ([a p] [b q])) (printf "~a ~a\n" p q)])

The above code runs fine. Notice that we only provide struct-id from the submodule, but match could still destruct the struct correctly because it can obtain accessors from the struct type inside struct-id.

However, if we uncomment the second comment, the code fails with the error:

; struct*: field name not associated with given structure type
;   at: struct-id-b
;   in: (struct* struct-id ((a p) (b q)))

By uncommenting code inside the submodule to provide struct-id-b and struct-id-a, the code now runs fine again.

As I understand, the reason why struct* and other struct extensions like kw-make-struct couldn’t use accessors extracted from struct-id is that there’s no mapping from field name to accessors.

Hence the question: why struct type doesn’t include field names?


Matthew Flatt

unread,
Jun 14, 2019, 10:57:46 AM6/14/19
to Sorawee Porncharoenwase, Racket list
At Thu, 13 Jun 2019 20:50:34 -0700, Sorawee Porncharoenwase wrote:
> Hence the question: why struct type doesn’t include field names?

It was an early design decision. There didn't seem to be a need to keep
field names, and so we left them out for simplicity. That may seem
difficult to believe, given that all the functionality that structure
types eventually acquired, but that's how it went.

I think omitting field names was probably a mistake. Other decisions
that were probably mistakes: making structure types opaque by default
and including "auto" fields. Those are to point to reconsider in a
design for Racket 2.

David Storrs

unread,
Jun 14, 2019, 11:09:28 AM6/14/19
to Sorawee Porncharoenwase, Racket list
On Thu, Jun 13, 2019 at 11:50 PM Sorawee Porncharoenwase <sorawe...@gmail.com> wrote:
Hence the question: why struct type doesn’t include field names?

<plug class="shameless">
  struct-plus-plus  (https://docs.racket-lang.org/struct-plus-plus/index.html#%28part._.Reflection%29) gives you full reflection data, including field names.  Also, field contracts, field wrappers, keyword constructor, functional setters, field transformers, field validation, inter-field integrity checking, and easy syntax for converting struct++ types to and from other values.  It doesn't support supertypes or field options (#:auto or #:mutable on a field), but it has strictly superior functionality to replace #:auto and you can always make the full struct #:mutable.
</plug>





















</plug>


--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/CADcuegvjQ_%2BgYg_VQb4TG-czSAMzZJOtZ0K3Ge7c_XNUO2QzCQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Dmitry Pavlov

unread,
Jun 14, 2019, 6:37:40 PM6/14/19
to racket...@googlegroups.com
Hello,

While we are at it: is it theoretically possible in Racket or Typed Racket (or will be possible in Racket 2 or Typed Racket 2) to access struct fields without repeating the name of the struct type again?

Like in C

typedef struct
{
  double x;
  double y;
} VeryLongStructureName;

VeryLongStructureName a;

double z = a.x + a.y;


The analogous Racket code for the last line would be

(define z (+ very-long-structure-name-x a) (+ very-long-structure-name-y a))

and I am wondering whether it can be shortened to something like (define z (+ (. x a) (. x b)))

(I know that match can work with structs, but it is not always as convenient as the C way with the dot)


Best regards,

Dmitry


Sorawee Porncharoenwase

unread,
Jun 15, 2019, 2:34:44 AM6/15/19
to Dmitry Pavlov, Racket list

First of all, . won’t work in standard Racket because . has a special meaning (see https://docs.racket-lang.org/reference/reader.html#%28part._parse-pair%29).

But yes, this is directly related to the discussion above because with the field name information, you can write your own accessor.

#lang racket

(module submodule racket
  (provide @)
  (require syntax/parse/define)

  (define (access e fld)
    (match-define-values (info _) (struct-info e))

    ;; for now we hard code it; would be able to extract it from struct-type-info in Racket 2
    (define fields '(bar baz))

    (match-define-values (name _ _ accessor _ _ _ _) (struct-type-info info))
    (accessor e (index-of fields fld)))

  (define-simple-macro (@ e:expr fld:id) (access e 'fld)))

(require 'submodule)

(struct foo (bar baz) #:transparent)
(define my-foo (foo 1 2))

(@ my-foo baz) ;=> 2

Note that your struct must not be opaque for this to work. Typed Racket might have enough compile-time data to make this to work with opaque structs, though.

But for now, https://docs.racket-lang.org/struct-define/index.html might be a good workaround for your problem.






--
You received this message because you are subscribed to the Google Groups "Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to racket-users...@googlegroups.com.

Ben Greenman

unread,
Jun 15, 2019, 1:18:36 PM6/15/19
to Sorawee Porncharoenwase, Dmitry Pavlov, Racket list
On 6/15/19, Sorawee Porncharoenwase <sorawe...@gmail.com> wrote:
> First of all, . won’t work in standard Racket because . has a special
> meaning (see
> https://docs.racket-lang.org/reference/reader.html#%28part._parse-pair%29).

The `read-cdot` parameter can change the standard meaning

https://docs.racket-lang.org/reference/reader.html#(part._parse-cdot)

Dmitry Pavlov

unread,
Jun 15, 2019, 3:32:48 PM6/15/19
to Sorawee Porncharoenwase, Racket list




But yes, this is directly related to the discussion above because with the field name information, you can write your own accessor.

Yes it will be a way to go in Racket 2.


But for now, https://docs.racket-lang.org/struct-define/index.html might be a good workaround for your problem.

Thank you, I did not know about it. define-struct-define is indeed very handy.

Best regards,

Dmitry


Reply all
Reply to author
Forward
0 new messages