6

Supponiamo di avere questa semplice classe:Generazione immutabili strutture dati ciclici

public class Pair { 
    public readonly object first; 
    public readonly object second; 

    public Pair(object first, object second) { 
     this.first = first; 
     this.second = second; 
    } 
} 

Sarebbe impossibile generare un grafico ciclico di coppie.

Come crei una classe simile, che è ancora immutabile, ma che può essere utilizzata in qualche modo per generare grafici ciclici?

+0

Mi sembra impossibile, a proposito. – configurator

+0

Una buona risposta sarà specifica della lingua. Dovresti taggare questo nella tua lingua preferita. –

+2

Utilizzare la valutazione lazy e definire i cicli in modo ricorsivo – Dario

risposta

0

Non penso che sia possibile con una classe immutabile del tipo che hai proposto. L'unica cosa che mi viene in mente è di aggiungere una proprietà con un setter che controlli se un campo è o meno nullo e permette di impostarlo se lo è. In questo modo è possibile lasciare il campo first nel primo oggetto null e, una volta creato l'ultimo oggetto nel ciclo, impostare tale campo in modo appropriato per chiudere il ciclo. Una volta impostato, non è più nullo e il setter non consente più di modificarlo. Sarebbe ancora possibile che il campo venga modificato dal codice interno alla classe, naturalmente, ma sarebbe essenzialmente immutabile dall'esterno.

Qualcosa di simile (C#):

public class Pair { 
    private object first; 
    private object second; 

    public Pair(object first, object second) { 
     this.first = first; 
     this.second = second; 
    } 

    public object First { 
     get { return first; } 
     set 
     { 
      if (first == null) 
      { 
       first = value; 
      } 
     } 
    } 

    // and a similar property for second 
} 
+0

Attenzione alla sicurezza del thread ... Spesso l'immutabilità è associata alla sicurezza del thread, ma in questo caso l'apparente immutabilità del tuo tipo 'Pair' non lo rende assolutamente sicuro! Ad esempio, supponiamo di avere 'var a = new Pair (1, null); var b = new Pair (null, 2); b.first = a; a.second = b', e quindi pubblica l'oggetto referenziato da 'a' (in modo che altri thread possano vederlo). Senza una corretta sincronizzazione, altri thread potrebbero effettivamente vedere 'a.second == null'! –

3

ci sono un'infinità di modi per rappresentare strutture grafico. Uno di questi è con una matrice. ogni riga e colonna è indicizzata dal vertice e ogni cella nella matrice rappresenta un bordo diretto (possibilmente ponderato). Un semplice grafico ciclico, con 0 di esempio non bordo di attacco e 1 con un bordo di attacco sarebbe solo in questo modo:

| 0 1 | 
| 1 0 | 

Come con molte strutture immutabili, nel modo che costruisce è restituendo nuove strutture basate sulla relazione desiderata di date matrici. per esempio, se volessimo prendere il grafico sopra e aggiungere un bordo sul primo vertice su se stesso, la matrice che rappresenta quello è giusta.

| 1 0 | 
| 0 0 | 

e per combinarlo con l'altra matrice, li aggiungiamo tutti insieme.

| 0 1 | + | 1 0 | == | 1 1 | 
| 1 0 |  | 0 0 |  | 1 0 | 

Naturalmente, ci sono molti modi per rappresentare matrici, con differenti compromessi per la velocità, lo spazio, e alcune altre operazioni, ma questa è una questione diversa.

0

Vorrei adottare un approccio funzionale, passando una continuazione nel ctor. In alternativa, potrebbe prendere invece una sequenza di elementi simili (si pensi a IEnumerable come argomento).