2010-09-12 19 views
6

Lisp'den OCaml'a geldiğimde, işlevlerin ne zaman döndüğü ve ne zaman gelmediği konusunda kendimi çok şaşırıyorum. Sihirli teklifimi özledim! Neyse ki, çoğu zaman, OCaml, değerlendirilen bir işlev istediğimde ve yapmadığım zaman otomatik olarak biliyor. Bununla birlikte, sık sık kendim gibi bir işlevin dönüş değerini, aşağıdaki gibi bir ifade ifadesinde atamaya çalışıyorum.OCaml'de bir fonksiyonun geri dönüş değerine atanması garanti edilmesi

let start = Sys.time in 
(* 
* do something here 
*) 
; 
let ending = Sys.time in 
Printf.printf "did something in %f seconds\n" (ending -. start) 

ama sonra ocamlc başlangıç ​​ve bitiş Bana söylemen

Error: This Expression has type unit -> float 
     but an expression was expected of type float 

şikayet, Sys.time için Sys.time değil dönüş değeri bağlıdırlar.

Bu davranış, OCamly almaya çalışmıyorum mu? Başka bir şey yapmak mı isterim? Tamamen açık bir şey eksik mi?

cevap

10

Bir bağımsız değişkene uygulandığında bir işlev değerlendirilir. Yani f yaptığınızda, f asla değerlendirmeye alınmaz. f x'u yaptığınızda, f her zaman değerlendirilir. Bu konuda büyülü bir şey yok.

doğru belirttiği gibi, Sys.time sadece start için bu işlevi atar ve let start = Sys.time (tip unit -> float ait) bir fonksiyonudur.

(tip unit tek değerdir) argümanı () fonksiyonu Sys.time geçerlidir sadece istediğiniz let start = Sys.time() yapmak davranışı, almak için.

3

Sadece adını yazarak bir işlevi arayamazsınız. Eğer bir fonksiyonun adını yazarsanız, dönüş değerini değil, fonksiyonun kendisini döndürüyorsunuz. Bu hata, işlevin bir unit argümanını aldığını söylüyor - yani, işlevi gerçekten uygulamak ve sonuçta elde edilen float değerini almak için Sys.time() yazmalısınız. Lisp için kullanılan insanlara yardım etmek

0

, ben ocaml sadece iki değerlendirme kuralları olduğunu söyleyebilirim:

  • Gecikmeli değerlendirme kuralı: Bir fonksiyon değeri, bu tür herhangi bir argüman uygulanmadığı fun x -> body olarak , daha fazla değerlendirilmeyecek. (Bir işlev gövdesinin değerlendirilmesi “gecikmeli” dir.) Bunun yerine, “beden” ifadesi bilgisayar koduna derlenmiştir. Bu bilgisayar kodu, fonksiyon ifadesinin gerçek “değeri” dir ve işlev argümana uygulandığında kod çalıştırılacaktır.
  • Eager değerlendirme kuralı: f x değerlendirmesinde, ilk önce x argümanı değerlendirilir. (İşlevler “argümanlarını değerlendirmek için istekli” dir.) Daha sonra f işlev ifadesi değerlendirilir, bu da genellikle fun x -> body gibi bir işlev değeri verir. (Burada body henüz değerlendirilmemiştir, sadece fun x -> body işlev değeri elde ettiğimiz kadar değerlendirilir. Örneğin, f sonuç olarak böyle bir işlev değeri veren karmaşık bir ifade olabilir.) Son olarak, sonuç işlevinin gövdesi argümanın fiili olarak hesaplanan değerine uygulanır (yani, body, argümanın hesaplanan değeri ile ikame edilen x ile değerlendirilir).

Bu nedenle, yalnızca bir ifade ifadesinin gövdesine yerleştirerek, bazı ifadelerin değerlendirmesini geciktirmek istiyorsanız, OCAML'de "alıntı" uygulayabilirsiniz.

let delay_f() = f 3;; 

Şimdi değerlendirmek yalnızca 4 alacak: Eğer varsa, örneğin, daha önce let f = fun x->x+1 tarafından f bilgisayarlı ve şimdi f 3 değerlendirmesini geciktirmek istiyor, bir fonksiyonun vücuda bu f 3 koyabilirsiniz delay_f(). delay_f değerini başka bir işleve iletebilirsiniz ve f 3, biri delay_f() değerini değerlendirinceye kadar değerlendirmeden kalır.