Il problema si verifica molto più ampiamente rispetto all'operatore ^
. Fondamentalmente, il compilatore OCaml deve sapere che la stringa di formato è una stringa letterale e che la stringa letterale deve essere conosciuta al momento della compilazione. Oppure, OCaml non può trasmettere la stringa in fase di compilazione a questo tipo di BLAHBLAH format6
. Il modulo Printf
funziona correttamente solo con stringhe di formato che sono completamente note al momento della compilazione o con stringhe di formato già convertite nel tipo BLAHBLAH format
.
In genere è possibile risolvere questo problema utilizzando l'operatore ^^
e lanciando esplicitamente tutte le stringhe letterali alla BLAHBLAH format
tipo prima utilizzare tali stringhe in codice.
Ecco un altro esempio:
# Printf.sprintf (if true then "%d" else "%d ") 2;;
Error: This expression has type string but an expression was expected of type
('a -> 'b, unit, string) format =
('a -> 'b, unit, string, string, string, string) format6
(* define a type abbreviation for brevity *)
# type ('a,'b) fformat = ('a ->'b, unit, string) format;;
type ('a, 'b) fformat = ('a -> 'b, unit, string) format
# Printf.sprintf (if true then ("%d":('a,'b)fformat) else ("%d ":('a,'b)fformat)) 2;;
- : string = "2"
Il sistema OCaml non può riconoscere che if ... then "a" else "b"
può essere gettato a BLAHBLAH format
. Se lanci ogni stringa letterale a BLAHBLAH format
, allora tutto funziona. (Nota: non funziona se si tenta di lanciare l'intero if/then/else
-BLAHBLAH format
, poiché OCaml non può verificare che la stringa è un letterale.)
L'origine del problema è il requisito di sicurezza di tipo: OCaml richiede che ci è un argomento del tipo corretto per ogni %d
e %s
ecc. e garantisce questo al tempo di compilazione. Non è possibile garantire la sicurezza del tipo con Printf
a meno che l'intera stringa di formato non sia nota in fase di compilazione. Pertanto, è impossibile utilizzare Printf
con una stringa di formato calcolata tramite un complicato algoritmo, ad es. Selezionando %s
e %d
a caso.
Quando si utilizza if/then/else
per calcolare la stringa di formato, quindi OCaml cose, oh gee, questo è un algoritmo complicato ed è inutile verificare la sicurezza del tipo in fase di compilazione. L'operatore ^^
conosce i tipi BLAHBLAH format
e produce il risultato corretto quando concatena le stringhe di formato.Ma if/then/else
non sa di BLAHBLAH format
e non esiste un'alternativa incorporata a if/then/else
(ma credo che potresti definire una cosa simile).
Una bella spiegazione, grazie. Un punto minore, trovo la tua formulazione "l'operatore (^^) crea un contesto di digitazione .." non chiaro; questo operatore non ha alcuna magia dentro, è semplicemente digitato '... format -> ... format -> ... format', e type inferenza fa il lavoro di verificare che i suoi parametri siano di questo tipo, stringhe costanti. – gasche
gasche ha ragione. Ciò che deve essere compreso è che quando si assegna una stringa a 'Print. * Printf' non gli si attribuisce un valore di tipo' Pervasives.string' gli si attribuisce un valore di tipo 'Pervasives.format6' (che non è uguale a 'Pervasives.string'). –
Giusto, avrei dovuto dire che (^^) ha dato il tipo di benzina. Non c'è assolutamente magia in quella parte. L'unica magia (a quanto ho capito) è nella promozione delle costanti di stringa al tipo 'format' appropriato. –