Lanciare una citazione di codice non tipita?
-
13-11-2019 - |
Domanda
In MinicsVtypeProvider, vedo la seguente riga di codice:
let prop = ProvidedProperty(fieldName, fieldTy, GetterCode = fun [row] -> <@@ (%%row:float[]).[i] @@>)
con il tipo di code getter è: Quotations.expr Elenco -> Quotations.expr :
Non so davvero cosa la lambda divertimento sta facendo....
Abbina il suo input con un array di singoli elementi, che lo leghi a una variabile denominata "riga", delle citazioni di tipo.expr dalla firma GetTerCode.
Crea una citazione di codice in cambio
- All'interno della citazione del codice, usa %% riga: float [] e non so cosa significhi: È un vincolo di tipo float [] per citazioni di codice non tipite?
Soluzione
La risposta di Jack è corretta. Aggiungerò un po 'più di contesto. (%%)
è l'operatore di giunzione non tipizzato (cioè giunge a Quotations.Expr
in un'altra citazione digitata o non tipita), mentre (%)
è l'operatore di giunzione digitato (cioè giunta a Quotations.Expr<'t>
per alcuni 't
in un'altra citazione digitata o non tipita). (a : ty)
è solo un'annotazione di tipo, quindi (%%row : float[])
indica che quando row
è giuntato nella citazione il risultato è un float[]
. Senza questa annotazione, %%row
potrebbe essere un valore di qualsiasi tipo e il compilatore non sarebbe in grado di dedurre cosa intendiamo con .[]
indicizzatore (proprio come non può dedurre il tipo di arr
in fun arr i -> arr.[i]
).
Nel caso sia utile, ecco alcuni modi alternativi per esprimere all'incirca la stessa cosa di <@@ (%%row:float[]).[i] @@>
:
Possiamo convertire la citazione non tipita in una citazione tipizzata prima di girare:
let typedRow = Quotations.Expr.Cast<float[]> row <@@ %typedRow.[i] @@>
Qui stiamo usando l'operatore di giunzione digitato
(%)
, quindi il compilatore lo sa%typedRow
è unfloat[]
e quello il.[]
L'operatore è applicabile.Possiamo usare un modo diverso di indicizzare nell'array in modo che l'inferenza del tipo di F#possa determinare il tipo di
%%row
Senza un'annotazione:<@@ Array.get %%row i : float @@>
Qui, il
Array.get
Il metodo prende un'a[]
Come argomento e aggiungiamo un'annotazione di tipo che indica che il risultato è un galleggiante, quindi F# lo dedicherà%%row
è unfloat[]
.
Altri suggerimenti
Il: float [] è un tipo di annotazione esplicita (non vincolo, che è simile ma diverso); Sta dicendo che %% riga produrrà un valore di tipo float [].
Quindi avvolgendolo tra parentesi, è possibile utilizzare la sintassi. [Idx] per ottenere un elemento dell'array perché il compilatore F# influisce il tipo di valore all'interno della parentesi come float [].
Specificare esplicitamente un tipo di annotazione in questo modo può essere un modo utile per dare al compilatore F# un "suggerimento" e risolvere errori di inferenza del tipo.