The actual accessor functions are in there as well, not just the names. On Sun, Oct 31, 2021, 9:58 AM Jens Axel Søgaard <[email protected]> wrote:
> A quick example: > > #lang racket > (require racket/require) > (require (filtered-in (λ (name) (regexp-replace #rx"struct[+][+]" name > "struct")) > struct-plus-plus)) > > (struct horse (breed color legs)) > > (define beauty (horse 'arabian 'black 4)) > > (define info (force (struct-ref beauty))) > (map struct-field-name (struct-info-fields info)) > > The result is: > '(breed color legs) > > Den søn. 31. okt. 2021 kl. 13.06 skrev David Storrs < > [email protected]>: > >> >> >> On Sun, Oct 31, 2021, 7:49 AM Jens Axel Søgaard <[email protected]> >> wrote: >> >>> Hi Brian, >>> >>> A few random thoughts: >>> >>> > I would like, given only the symbol foo referring to the struct type >>> itself, >>> > to discover (at least) the list of procedures foo?, foo-a, foo-b, plus >>> > anything else the author of foo (the type) wants me to see. >>> >>> When you want to look this up, is it in the repl (i.e. at runtime)? >>> >>> The standard `struct` construct doesn't store much reflection >>> information. >>> Instead of fighting the standard construct, you can consider making a >>> little variation. >>> >>> If you are satisfied with having info for the structs defined in your >>> own program >>> (i.e. modules you have written yourself), then you can consider making a >>> module, say, `fancy-struct` that exports a macro where >>> >>> (fancy-struct yada ...) >>> >>> expands into >>> >>> (begin >>> (fancy-struct yada ...) >>> <store reflection information>) >>> >>> Using `rename-out` you can export it as `struct`, so it can be used >>> without changing any existing code. >>> >>> /Jens Axel >>> >> >> Coincidentally, that module exists! >> >> >> https://docs.racket-lang.org/struct-plus-plus/index.html#%28part._.Reflection%29 >> >> >> >>> >>> >>> Den søn. 31. okt. 2021 kl. 11.42 skrev Matt Jadud <[email protected]>: >>> >>>> Hi Brian, >>>> >>>> Does this help move you forward? >>>> >>>> It has been a while since I've stared at macros in Racket, so this >>>> might be easier... >>>> >>>> Also, make sure you're executing this code in a module. If you're >>>> working in a REPL, I suspect all bets are off. It is certainly the case >>>> that you could combine several of my exploration steps into a >>>> simpler/cleaner macro, instead of generating lists of symbols, converting >>>> them back to syntax objects, and so on. >>>> >>>> Also, as a solution/exploration, I... don't know how this would >>>> interact with the full range of possible structs. Someone who knows more >>>> about syntax and structs should be able to speak to how you'd find out all >>>> of the defined functions that spawn from struct definition/creation. (It >>>> might also be useful to know *why* you want to destructure structs this >>>> way? Knowing that may illuminate some other path forward.) >>>> >>>> #lang racket >>>> (require racket/struct-info) >>>> >>>> (struct A (b c)) >>>> >>>> (struct B (e f) #:transparent) >>>> >>>> (require (for-syntax racket/struct-info)) >>>> (define-syntax (get-field-names stx) >>>> (syntax-case stx () >>>> [(_ sym) >>>> #`(quote >>>> #,(struct-field-info-list >>>> (syntax-local-value #'sym))) >>>> ])) >>>> >>>> ;; These let me see the field names >>>> (get-field-names A) >>>> ;; Returns '(c b) >>>> (get-field-names B) >>>> ;; Returns '(f e) >>>> >>>> ;; >>>> https://stackoverflow.com/questions/20076868/how-to-know-whether-a-racket-variable-is-defined-or-not >>>> (define-syntax (defined? stx) >>>> (syntax-case stx () >>>> [(_ id) >>>> (with-syntax ([v (identifier-binding #'id)]) >>>> #''v)])) >>>> >>>> (define-syntax (proc-names stx) >>>> (syntax-case stx () >>>> [(_ sym) >>>> (let ([names (map (λ (s) >>>> (string->symbol >>>> (format "~a-~a" (syntax-e #'sym) s))) >>>> (struct-field-info-list >>>> (syntax-local-value #'sym)) >>>> )]) >>>> #`(quote #,names))])) >>>> >>>> ;; This... >>>> (proc-names A) >>>> ;; Returns '(A-c A-b) >>>> >>>> (define-syntax (names-exist? stx) >>>> (syntax-case stx () >>>> [(_ sym) >>>> (let ([names (map (λ (s) >>>> (string->symbol >>>> (format "~a-~a" (syntax-e #'sym) s))) >>>> (struct-field-info-list >>>> (syntax-local-value #'sym)) >>>> )]) >>>> #`(andmap (λ (s) >>>> (equal? 'lexical s)) >>>> (map (λ (s) >>>> (defined? s)) >>>> (quote #,names))) >>>> )])) >>>> >>>> (names-exist? A) >>>> (names-exist? B) >>>> >>>> >>>> On Sat, Oct 30, 2021 at 10:33 PM Brian Beckman <[email protected]> >>>> wrote: >>>> >>>>> Here are some of my latest (failed) experiments: >>>>> >>>>> #lang racket >>>>> >>>>> (require (for-syntax racket/struct-info)) >>>>> (require racket/pretty) >>>>> >>>>> (struct foo (a b) #:transparent) >>>>> >>>>> (displayln `("a foo object is transparent: I can see inside: \n >>>>> (struct->vector (foo 1 2)) ~~> " >>>>> ,(struct->vector (foo 1 2)))) >>>>> >>>>> (displayln `("syntax object is opaque I can't see inside: \n >>>>> (struct->vector #'foo) ~~> " >>>>> ,(struct->vector #'foo))) >>>>> >>>>> ;;; Why do two copies of the syntax display? (One copy >>>>> ;;; is a side-effect. The other is a result). >>>>> >>>>> ;;; At expansion time, I can get some graphics in Dr-Racket for >>>>> ;;; definition of foo, but I cannot get likewise >>>>> ;;; not into the definition of syntax. >>>>> (begin-for-syntax >>>>> (displayln >>>>> (extract-struct-info >>>>> (syntax-local-value >>>>> #'foo)))) ; #'syntax)))) >>>>> >>>>> ;;; But the access procedures for #'syntax are known!?!? (I just >>>>> ;;; happen to know that there is a procedure named 'syntax-position'; >>>>> ;;; my whole issue is in trying to find out the list of all >>>>> ;;; procedures defined in the system when the syntax type is created!) >>>>> >>>>> (syntax-position #'42) >>>>> >>>>> ;;; Whereas #'foo is known in this module scope, >>>>> ;;; (syntax struct:foo) is not known! Looks like the shorthand >>>>> ;;; #'whatever for making a syntax object is known, but the longhand, >>>>> ;;; presumably (syntax 'whatever), is not known. >>>>> >>>>> (begin-for-syntax >>>>> (displayln >>>>> (extract-struct-info >>>>> (syntax-local-value >>>>> #'syntax)))) >>>>> >>>>> ~~~~~~~~ >>>>> >>>>> Welcome to DrRacket, version 8.2 [cs]. >>>>> Language: racket, with debugging; memory limit: 128 MB. >>>>> (.#<syntax:GSI/nanosim-apu-docs/WIKIS/BELEX_3/racket-sandbx-public.rkt:6:8 >>>>> struct:foo> >>>>> .#<syntax:GSI/nanosim-apu-docs/WIKIS/BELEX_3/racket-sandbx-public.rkt:6:8 >>>>> foo> >>>>> .#<syntax:GSI/nanosim-apu-docs/WIKIS/BELEX_3/racket-sandbx-public.rkt:6:8 >>>>> foo?> >>>>> (.#<syntax:GSI/nanosim-apu-docs/WIKIS/BELEX_3/racket-sandbx-public.rkt:6:8 >>>>> foo-b> >>>>> .#<syntax:GSI/nanosim-apu-docs/WIKIS/BELEX_3/racket-sandbx-public.rkt:6:8 >>>>> foo-a>) (#f #f) #t) >>>>> . . >>>>> ../../../../../../usr/share/racket/pkgs/errortrace-lib/errortrace/stacktrace.rkt:690:2: >>>>> extract-struct-info: contract violation >>>>> expected: struct-info? >>>>> given: #<procedure:...rivate/template.rkt:563:0> >>>>> > >>>>> >>>>> On Friday, October 29, 2021 at 4:10:37 PM UTC-7 Siddhartha Kasivajhula >>>>> wrote: >>>>> >>>>>> I was able to find this interface >>>>>> <https://docs.racket-lang.org/reference/inspectors.html#%28def._%28%28quote._~23~25kernel%29._struct-type-info%29%29>, >>>>>> but it doesn't quite provide the same information. E.g. (struct-type-info >>>>>> struct:foo) >>>>>> >>>>>> The ability to "introspect" values in a shell (or in the application) >>>>>> is useful in languages like python (e.g. dir(object) tells you what >>>>>> methods it provides, help(anything) gives you the interface/function >>>>>> signature, docstrings, etc.). I haven't seen this style emphasized in >>>>>> Racket documentation, and that may be because racket isn't >>>>>> object-oriented >>>>>> by default as python is, so that there often isn't a single object >>>>>> encapsulating all of this information. >>>>>> >>>>>> But all the same, if there are analogous facilities in racket, like >>>>>> the kind Brian asked about, I'd love to know as well. >>>>>> >>>>>> >>>>>> On Fri, Oct 29, 2021 at 3:14 PM Brian Beckman <[email protected]> >>>>>> wrote: >>>>>> >>>>>>> Well, as I understand it, a struct (usually? always?), #:transparent >>>>>>> or not, when declared, defines symbols that are meant to be visible in >>>>>>> the >>>>>>> current scope, so (struct foo (a b)) defines foo #|constructor|#, foo? >>>>>>> #|instance-predicate|# foo-a and foo-b #|data accessors|# , that I can >>>>>>> call >>>>>>> on instances: >>>>>>> >>>>>>> (struct foo (a b)) >>>>>>> (let ([my-foo (foo 42 37)] >>>>>>> (list (foo? my-foo) >>>>>>> (foo-a my-foo) >>>>>>> (foo-b my-foo))) ~~> '(#t 42 37) >>>>>>> >>>>>>> I would like, given only the symbol foo referring to the struct type >>>>>>> itself, to discover (at least) the list of procedures foo?, foo-a, >>>>>>> foo-b, >>>>>>> plus anything else the author of foo (the type) wants me to see. >>>>>>> >>>>>>> >>>>>>> On Fri, Oct 29, 2021 at 1:45 PM John Clements < >>>>>>> [email protected]> wrote: >>>>>>> >>>>>>>> In the text below, you refer to the “public” interface. Can I ask >>>>>>>> what you mean by “public” in this context? >>>>>>>> >>>>>>>> John >>>>>>>> >>>>>>>> > On Oct 29, 2021, at 11:16 AM, Brian Beckman <[email protected]> >>>>>>>> wrote: >>>>>>>> > >>>>>>>> > I believe that run time will be the most plausible use case. I >>>>>>>> may write macros that refer to struct-procedure names at macro-writing >>>>>>>> time, but I don't expect to invoke the struct procedures at >>>>>>>> macro-expansion >>>>>>>> time. My primary issue is "discoverability:" how can I find out the >>>>>>>> interface of any struct? >>>>>>>> > >>>>>>>> > On Thursday, October 28, 2021 at 1:00:15 PM UTC-7 >>>>>>>> [email protected] wrote: >>>>>>>> > Are you intending to use the struct procedure names at compile >>>>>>>> time (such as in a macro) or runtime? >>>>>>>> > >>>>>>>> > On Tuesday, October 26, 2021 at 5:02:46 PM UTC-7 >>>>>>>> [email protected] wrote: >>>>>>>> > I understand why structs are opaque, by default, but I want to >>>>>>>> discover the public interface of some struct type, that is, a list of >>>>>>>> the >>>>>>>> procedures defined by the struct. >>>>>>>> > >>>>>>>> > Here is an example. Suppose I want to find out all the procedures >>>>>>>> defined on an instance of the syntax struct >>>>>>>> > >>>>>>>> > #'42 >>>>>>>> > >>>>>>>> > Dr. Racket shows an expander clicky that shows some formatted >>>>>>>> information inside the instance : >>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>>> > Uncapitializing the names in the display reveals the interface: >>>>>>>> > >>>>>>>> > (syntax-position #'42) ~~> 790 >>>>>>>> > (syntax-span #'42) ~~> 2 >>>>>>>> > (syntax-original? #'42) ~~> #t >>>>>>>> > >>>>>>>> > etc. >>>>>>>> > >>>>>>>> > I want to discover those procedure names in my racket program, >>>>>>>> not manually by visually inspecting graphics in Dr Racket. >>>>>>>> > >>>>>>>> > I found this trick for structs that I define: >>>>>>>> > >>>>>>>> > #lang racket >>>>>>>> > (require (for-syntax racket/struct-info)) >>>>>>>> > (require racket/pretty) >>>>>>>> > >>>>>>>> > (struct foo (a b)) >>>>>>>> > (begin-for-syntax >>>>>>>> > (displayln >>>>>>>> > (extract-struct-info >>>>>>>> > (syntax-local-value >>>>>>>> > #'foo)))) >>>>>>>> > >>>>>>>> > ~~> >>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>>> > but it doesn't work for the syntax type >>>>>>>> > >>>>>>>> > (begin-for-syntax >>>>>>>> > (displayln >>>>>>>> > (extract-struct-info >>>>>>>> > (syntax-local-value >>>>>>>> > #'syntax)))) >>>>>>>> > >>>>>>>> > ~~> >>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>>> > I'd be grateful for advice and an example of how to get the >>>>>>>> interface of "syntax" without Dr Racket and without grovelling docs. >>>>>>>> > >>>>>>>> > -- >>>>>>>> > 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 [email protected]. >>>>>>>> > To view this discussion on the web visit >>>>>>>> https://groups.google.com/d/msgid/racket-users/8e4ca03e-e276-4c42-a662-4fcf7c994387n%40googlegroups.com >>>>>>>> . >>>>>>>> >>>>>>>> -- >>>>>>> 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 [email protected]. >>>>>>> >>>>>> To view this discussion on the web visit >>>>>>> https://groups.google.com/d/msgid/racket-users/CAK2VK6tMxFH0oEq4iCgk7PW-4yJTB8xNr_b3F6GPwQS1MZVLwQ%40mail.gmail.com >>>>>>> <https://groups.google.com/d/msgid/racket-users/CAK2VK6tMxFH0oEq4iCgk7PW-4yJTB8xNr_b3F6GPwQS1MZVLwQ%40mail.gmail.com?utm_medium=email&utm_source=footer> >>>>>>> . >>>>>>> >>>>>> -- >>>>> 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 [email protected]. >>>>> To view this discussion on the web visit >>>>> https://groups.google.com/d/msgid/racket-users/c1c4f0f3-9c8d-430d-8615-4ec2cbea90f4n%40googlegroups.com >>>>> <https://groups.google.com/d/msgid/racket-users/c1c4f0f3-9c8d-430d-8615-4ec2cbea90f4n%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>> . >>>>> >>>> -- >>>> 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 [email protected]. >>>> To view this discussion on the web visit >>>> https://groups.google.com/d/msgid/racket-users/CAAGM456vwtx80%3DX44UiLZAMjbL6O0zMHOZSyc32L6opM89Bjew%40mail.gmail.com >>>> <https://groups.google.com/d/msgid/racket-users/CAAGM456vwtx80%3DX44UiLZAMjbL6O0zMHOZSyc32L6opM89Bjew%40mail.gmail.com?utm_medium=email&utm_source=footer> >>>> . >>>> >>> >>> >>> -- >>> -- >>> Jens Axel Søgaard >>> >>> -- >>> 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 [email protected]. >>> To view this discussion on the web visit >>> https://groups.google.com/d/msgid/racket-users/CABefVgwBi8-2cLuA7-dtiM%2BnbxN5ZriPLcG1JX3ATTw2xyQd8w%40mail.gmail.com >>> <https://groups.google.com/d/msgid/racket-users/CABefVgwBi8-2cLuA7-dtiM%2BnbxN5ZriPLcG1JX3ATTw2xyQd8w%40mail.gmail.com?utm_medium=email&utm_source=footer> >>> . >>> >> -- >> 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 [email protected]. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/racket-users/CAE8gKofkEmZ4M64_QjSLrLAz_LH0CdDG%3DhrWX%2B-fRxJt6RcR0Q%40mail.gmail.com >> <https://groups.google.com/d/msgid/racket-users/CAE8gKofkEmZ4M64_QjSLrLAz_LH0CdDG%3DhrWX%2B-fRxJt6RcR0Q%40mail.gmail.com?utm_medium=email&utm_source=footer> >> . >> > > > -- > -- > Jens Axel Søgaard > > -- 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 [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/racket-users/CAE8gKoedHwEh%3D7d%3DWPXuoU_fg6%2BgfmaiVVfUKM%2Bb72ypcA%2BBdg%40mail.gmail.com.

