2015-08-19 1 views

Antwort

8

Um eine Strukturtyp transparent, verwenden Sie die # machen: transparent Schlüsselwort nach dem Feldnamen Sequenz:

(struct posn (x y) 
     #:transparent) 

> (posn 1 2) 
(posn 1 2) 

eine Instanz eines transparenten druckt Typ Struktur wie ein Aufruf an den Konstruktor, so dass es zeigt, die Strukturfeldwerte. Ein transparenter Strukturtyp ermöglicht auch reflektive Operationen wie struct? und struct-info, die auf ihren Instanzen verwendet werden.

Obwohl ein transparenter Strukturtyp so gedruckt wird, dass sein Inhalt angezeigt wird, kann die gedruckte Form der Struktur nicht in einem Ausdruck verwendet werden, um die Struktur im Gegensatz zur gedruckten Form einer Zahl, Zeichenfolge, eines Symbols oder einer Liste zurückzuerhalten .

Ein vorfabrizierter ("vorher gefertigter") Strukturtyp ist ein integrierter Typ, der dem Racket-Drucker und dem Expression-Reader bekannt ist. Unendlich viele solcher Typen existieren, und sie sind durch Namen, Feldzählung, Obertyp und andere solche Details indiziert. Das gedruckte Formular einer vorfabrizierten Struktur ähnelt einem Vektor, aber es startet #s statt nur #, und das erste Element in der gedruckten Form ist der Name des vorgefertigten Strukturtyps.

Schließlich denke ich, dass Sie brauchen #: transparent die meiste Zeit über #: prefab, basierend auf meiner Erfahrung verwende ich normalerweise #: transparent.

+0

Zusätzlich zu "exotischen" reflektiven Ops funktioniert eine sehr einfache Sache nur mit '#: transparent'' struct's - 'equal?'. Gegeben '(struct x (y))' '(gleich? (X 1) (x 1))' ist '# f'! Es ist nur '# t' mit' #: transparent'. –

+2

In gewisser Hinsicht ist "#: transparent" die "warme Schale mit Brei" zwischen opak und vorgefertigt. Im Nachhinein sollte es der Standard sein, mit '#: opaque' und' #: prefab' Modifikatoren, IMHO. –

+1

Diese Antwort sollte wahrscheinlich [Link zu den Dokumenten] (http://docs.racket-lang.org/guide/define-struct.html?q=prefab#%28tech._prefab%29), woher der Text stammt. – stchang

6

Die racket guide hat wahrscheinlich eine sanftere Einführung in Prefab-Strukturen.

Der größte Unterschied besteht darin, dass eine transparente Struktur immer noch den struct-Konstruktor benötigt, um einen von ihnen zu erstellen.

Zum Beispiel angesichts der folgenden Struktur Definition:

(struct foo (a b) #:prefab) 

Im Folgenden sind zwei Möglichkeiten, die genau die gleiche Struktur zu erstellen. Diese

> (foo 1 2) 
'#s(foo 1 2) 
> #s(foo 1 2) 
'#s(foo 1 2) 

bedeutet, dass jedes Modul eine Schlägers foo prefab struct schaffen kann, auch ohne dass es zuerst definiert werden. Dies ist sehr nützlich, wenn Sie es in ein Makro einfügen oder es an eine separate Instanz von Racket senden möchten, die auf einem anderen Computer ausgeführt wird.

Generell würde ich empfehlen, mit #:transparent Strukturen zu gehen, es sei denn, Sie benötigen die volle Leistung eines #:prefab struct.

6

die anderen Antworten zu erweitern und einige weitere Beispiele für den zweiten Teil der Frage geben:

#lang racket 

(struct A (x y)) 
(displayln (A 1 2)) ; => #<A> 
(equal? (A 1 2) (A 1 2)) ; => #f 
;(equal? (A 1 2) (read (open-input-string (~a (A 1 2))))) ; => ERR: bad syntax 

(struct B (x y) #:transparent) 
(displayln (B 3 4)) ; => #(struct:B 3 4) 
(equal? (B 3 4) (B 3 4)) ; => #t 
(equal? (B 3 4) (read (open-input-string (~a (B 3 4))))) ; => #f 

(struct C (x y) #:prefab) 
(displayln (C 5 6)) ; => #s(C 5 6) 
(equal? (C 5 6) (C 5 6)) ; => #t 
(equal? (C 5 6) (read (open-input-string (~a (C 5 6))))) ; => #t 
  • Verwenden undurchsichtigen structs, wenn Sie die Struktur Abstraktion ohne Ausnahmen durchsetzen wollen, das heißt, die Struktur kann nur mit den Accessoren erstellt und inspiziert werden.
  • Verwenden Sie transparente Strukturen, um Zugriff auf den Drucker und gleich?
  • Verwenden Sie vorgefertigte Strukturen, wenn Sie Serialisierung, z. beim Schreiben und Lesen von der Festplatte.
3

Ein weiteres wichtiges Detail noch nicht erwähnt: transparent (und normal) structs generative sind. Das heißt, wenn Sie dieselbe Struktur zweimal definieren, sind Werte, die mit der ersten Instanz der Strukturdefinition erstellt wurden, nicht equal? für Werte, die mit der zweiten Definition erstellt wurden. Sie können selbst in einer REPL Sitzung sehen:

> (struct posn (x y) #:transparent) 
> (define origin1 (posn 0 0)) 
> (struct posn (x y) #:transparent) 
> (define origin2 (posn 0 0)) 
> (equal? origin1 origin2) 
#f 

Trotz der gleiche Definition zu sein und mit dem gleichen Inhalt, die beiden Instanzen sind nicht equal?. Obwohl die Strukturen transparent sind, werden sie als separate Definitionen aus dem Grund betrachtet, Leif Anderson wies darauf hin, nur die Verwendung von #: transparent erfordert immer noch, dass die einzige Möglichkeit, die Struktur mit dem Konstruktor zu erstellen die Strukturform definiert. Zwei Definitionen bedeuten zwei verschiedene Konstruktoren.

Mit vorgefertigten Strukturen, diese Beschränkung geht weg - Sie können vorfabrizieren Strukturen selbst erstellen, indem Sie nur die Leserform von ihnen wie #s(posn 0 0) schreiben. Es gibt keinen Grund mehr, alle Instanzen der Struktur erfordern mit ihren definierten Konstruktor erstellt werden und somit keinen Grund, zwei unterschiedliche, aber identische Struktur Definitionen würde erkennen einander nicht:

> (struct posn (x y) #:prefab) 
> (define origin1 (posn 0 0)) 
> (struct posn (x y) #:prefab) 
> (define origin2 (posn 0 0)) 
> (equal? origin1 origin2) 
#t 
> (equal? origin1 #s(posn 0 0)) 
#t 

Ich bin der Meinung, dass structs Das bedeutet, dass nur einige der zusammengefassten Rohdaten vorgefertigt sein sollten, um eine einfache, sichere Serialisierung zu erhalten. Strukturen, die Beschränkungen für ihre Konstruktion aufweisen, sollten transparent sein. Strukturen, die ein Verhalten kapseln und Informationen verbergen, sollten weder transparent noch transparent sein Fertig Dies sind nur Richtlinien, jedoch kann Ihre Laufleistung variieren.