Sto cercando di prendere una decisione sulla politica di Nim dietro expression has no address
. In particolare, ho una funzione C che prende un puntatore (+ lunghezza, ecc.) Di alcuni buffer di dati. So che questa funzione sarà non modificare i dati. Semplificata:Nim: Indirizzi di parametri e mutabilità
type
Buffer = object
data: seq[float]
proc wrapperForCCall(buf: Buffer) =
# accessing either buf.addr nor buf.data.addr produces
# Error: expression has no address
# workaround:
var tmp = buf.data # costly copy
callToC(tmp.len, tmp.addr) # now it works
Da un lato questo ha un senso, dal momento che un parametro sembra comportarsi esattamente come un let
vincolante, che anche "non ha un indirizzo". D'altra parte, sono perplesso da questa affermazione nel manuale:
i parametri var non sono mai necessari per il passaggio efficiente dei parametri.
Per quanto posso vedere, l'unico modo per evitare di copiare i dati sono da uno:
- passando il parametro come
buf: var Buffer
- passando un riferimento, cioè utilizzando un
ref object
.
In entrambi i casi questo suggerisce che la mia funzione modifica i dati. Inoltre, introduce la mutabilità sul sito del chiamante (ad esempio, gli utenti non possono più utilizzare i binding per i loro buffer). La domanda chiave per me è: poiché "so" che callToC
è di sola lettura, posso convincere Nim a consentire sia l'immutabilità senza una copia? Vedo che questo è pericoloso, dal momento che devo sapere con certezza che la chiamata è immutabile. Quindi, ciò richiederebbe una sorta di meccanismo di "indirizzo non sicuro" che consentisse di forzare i puntatori a dati immutabili?
E il mio ultimo mistero degli indirizzi dei parametri: ho cercato di rendere esplicita la necessità della copia cambiando il tipo in Buffer {.bycopy.} = object
. In questo caso la copia avviene già al momento della chiamata, e mi aspetto di avere accesso all'indirizzo ora. Perché l'accesso è negato anche in questo caso?
Grazie mille, sembra che questo sia esattamente quello che stavo cercando. Quello che non capisco ancora del tutto: che cosa è esattamente "copiato" in 'shallowCopy 'qui? Se ti capisco correttamente (ad esempio, se la performance è simile al caso no-copy), è piuttosto una sorta di "non sicuriAlias"? – bluenote10
'shallowCopy' è l'equivalente di un semplice compito in C; mentre '=' in Nim fa una copia strutturale (profonda) per stringhe, seq e oggetti non ref, non ptr che li contengono (in qualche modo simile a come l'assegnazione per il lavoro 'std :: string' e' std :: vector' in C++). –
Ah, vedo, per un 'seq',' stringa', o qualsiasi altro tipo 'ref', semplicemente" copia "il puntatore. – bluenote10