printf
için OCaml'ın özel yazım hilesi ve değer polimorfizmi.
Bildiğiniz gibi, Printf.printf
, string
, ancak format
veri tipini almaz. OCaml tipi denetleyicisi printf
için dize hazır tiplendirilmesinde için özel bir kural vardır: Bağlam talep ederse bu format
olarak yazıldığında ise:
# "%d";;
- : string = "%d"
# ("%d" : _format);;
- : (int -> 'a, 'b, 'a) format = ...
OCaml tür sistemi başka hüner denilen değer polimorfizm vardır (daha doğrusu, bu rahat değerdir polimorfizmi). Amacı, yan etkilerle doğru ifadeler yazmaktır. Ben ayrıntılarını açıklamak yok ama polimorfizm kısıtlar: kimlik işlevi fun x -> x
sahipken, (fun x -> x) (fun x -> x)
hiçbir polimorfik türü vardır, yukarıda ise
# fun x -> x;;
- : 'a -> 'a = <fun>
# (fun x -> x) (fun x -> x)
- : '_a -> '_a = <fun>
: polimorfik türleri içeremez "geniş" olarak adlandırılan ifadelerin bazı formları. Bu, (fun x -> x) (fun x -> x)
ifadesinin şekli nedeniyle: "geniş". '_a
garip tip değişkeni, monomorfik tip değişkendir: Bu, sadece bir kez bir türe örneklenebilir. Öte yandan, 'a
gibi polimorfik değişkenler, her bir vue kullanımı için farklı bir tipte başlatılabilir.
en Kodunuzdaki geri dönelim: Burada
# let (a, p) = (2, Printf.printf);;
val a : int
val p : ('a, out_channel, unit) format -> 'a
, p
bir polimorfik tipi ('a, out_channel, unit) format -> 'a
sahiptir. 'a
, birden fazla türe göre başlatılabilir, bu nedenle p "abc"; p "%d" 3
yazılabilirdir: polimorfik tür, p
ilk kullanımı için (unit, out_channel, unit) format -> unit
ve p
ikinci kullanımı için (int -> unit, out_channel, unit) format -> int -> unit
olarak başlatılabilir.
Eğer geniş olan 2+2
, sürekli 2
, tüm ifadesinde çok geniş hale gelir değiştirmek ve sonra yazarak değişiklikleri:
İşte
# let (a, p) = (2+2, Printf.printf);;
val a : int
val p : ('_a, out_channel, unit) format -> '_a
, p
artık polimorfik değişkenleri 'a
ama monomorfik '_a
sahiptir. Bu monomorfik değişken, p
'un ilk kullanımında unit
'a birleştirilmiş (örneklendirilmiştir) ve sonuç olarak p
'un türü (unit, out_channel, unit) format -> unit
olur. Sadece 1 argüman alabilir, bu yüzden 2 argüman ile p
ikinci kullanımının yazılması başarısız olur.Bu durumdan kaçınmak için
kolay bir yolu ikiye sizin tanımını bölmek geçerli:
let a = 2 + 2 in
let p = Printf.printf in
p "abc"; p "%d" 3
Ben de cevap ilgileniyorum, bu ilk bakışta garip. –