2011-09-11 13 views
7

Czy można umieścić instrukcje drukowania dla debugowania/testowania w blokach kodu? Na przykład w Javie można użyć System.out.println("") w środku metod sprawdzania zmiennych lub innych rzeczy, ale w OCaml, czy polecenie takie jak print_string zadziała? Czy nie zwróciłby wartości jednostki typu, powodując błąd, zamiast pozwalać na jej wydrukowanie?OCaml Instrukcje drukowania

+0

Ocaml różni się od Javy, nie masz nadruku na cokolwiek chcesz. Na przykład, aby wydrukować listę, musisz ją napisać ... Ponieważ w ocaml nie masz tylko obiektu. –

Odpowiedz

14

Będzie dobrze, jeśli osadzisz wydruk w postaci expression sequence.

UPDATE

Oto konkretny przykład, ponieważ odpowiedź powyżej była dość krótka i dobrze, tylko odpowiedzi z linkami nie są dobre odpowiedzi. Jest to klasyczny ogon rekurencyjnej sformułowanie silnia (yeah, nudny, ale znajomy):

# let fac n = 
    let rec f i n acc = 
    if i >= n 
    then acc 
    else (Printf.printf "%8d%8d%8d\n" i n acc; f (i+1) n ((i+1)*acc)) 
    in 
    f 0 n 1;; 
val fac : int -> int = <fun> 
# fac 5;; 
     0  5  1 
     1  5  1 
     2  5  2 
     3  5  6 
     4  5  24 
- : int = 120 

Tutaj można zobaczyć efekty uboczne druku, ale wynik nadal okazało się być 120, jak oczekiwano.

+0

Świetnie, dziękuję bardzo! Właśnie tego szukałem. Czy sekwencje ekspresji są zwykle używane do czegokolwiek innego, czy też jest to ich główne użycie? Sądzę, że możesz go również użyć do zmiany wartości zmiennych? – dxu

+0

Tak, wszystko, co wymaga stanu aktualizacji, takie jak aktualizacja wartości odniesień, jest generalnie obsługiwane w ten sposób. Istnieje bardzo miła i szczegółowa dyskusja na ten temat [tutaj] (http://caml.inria.fr/pub/docs/oreilly-book/html/book-ora028.html), patrz rozdział "Sekwencja". –

10

Ponieważ OCaml nie jest językiem funkcyjnym czystego, istnieje wiele sposobów, aby to zrobić. Oto sposób, w jaki piszę ten rodzaj kodu, tylko dla konkretnego przykładu.

let rec mylength list = 
(* DEBUG *) 
let() = Printf.printf "mylength here, null list: %b\n%!" (list = []) 
in 
(* DEBUG *) 
    match list with 
    | [] -> 0 
    | _ :: rest -> 1 + mylength rest 

Po uruchomieniu można usunąć rzeczy z komentarzy (* DEBUG *).

Uwaga na użycie%! aby opróżnić bufor. Jeśli robisz dużo debugowania z printf (tak jak ja), naprawdę warto się o tym dowiedzieć.

+0

byłoby łatwiej napisać '(* DEBUG *) Printf.printf" mylength tutaj, null list:% b \ n%! " (lista = []); (* DEBUG *) ' – newacct

+1

Oczywiście; tak jak powiedziałem, pokazuję tylko, jak naprawdę to piszę. Nie boję się używać średników poza parens, ponieważ mam wiele precedensów, których nauczyłem się. –

2

Oto prosty przykład, który pokazuje, że sekwencje ekspresyjne jak wspomniano w Ray Toal's answer nie muszą nawias wokół nich:

let get_a_string = 
    let a_string = "a string" in 
    (* The semicolon causes the return value of the statement to be discarded *) 
    Printf.printf "Debug: %s\n" a_string; 
    a_string 

let() = Printf.printf "Result: %s\n" get_a_string 

Innym sposobem, aby odrzucić wartości zwracanej przez funkcję jest za pomocą ignore:

ignore (Printf.printf "Debug info");