2010-06-15 22 views
7

Próbuję napisać prostą funkcję rekursywną, która wygląda na liście i zwraca parę całkowitą. Jest to łatwe do pisania w C/C++/JAVA ale jestem nowy SML tak jakoś trudno znaleźć się rozwiązanie ze względu na rodzaj konfliktuWzór pasujące do wzoru ocaml

to powinno idzie tak ..

let rec test p l = ... ;; 
val separate : (’a -> bool) -> ’a list -> int * int = <fun> 
test (fun x -> x mod 2 = 0) [-3; 5; 2; -6];; 
- : int * int = (2, 2) 

więc problem jak mogę rekursywnie zwracać wartość na krotce ..

+2

Czy możesz podać więcej szczegółów na temat funkcji, która ma powrócić? Co oznacza para liczb całkowitych? – goggin13

+0

, więc powinien zwrócić parę liczb całkowitych jako (x, y), która jest krotką w ocaml , że jedynym problemem, z którym się spotkałem, jest obliczenie krotki .. tak to jest, jeśli element listy jest mniejszy niż pewna liczba (x +1, y) else (x, y + 1), więc zwracana wartość będzie (x, y), gdzie x to liczba elementów większa od pewnej liczby, a y jest mniejsza niż – REALFREE

Odpowiedz

4

Byłeś dala od SML na trochę, ale myślę, że to załatwi w odniesieniu do opisu REALFREE w komentarzu

let rec test l = 
    match l with 
     [] -> (0,0) 
    | x::xs -> 
     if x > 0 then match (test xs) with (x,y) -> (x+1, y) 
     else match (test xs) with (x,y) -> (x, y+1);; 

Można stosować zagnieżdżone instrukcje meczu wyciągnąć kawałki krotki do modyfikować

EDIT: nie wiedziałem o składni Pascala Cuoq wymienionego w swoim komentarzu poniżej, oto kod tak, to neater i nieco krótsza:

let rec test l = 
    match l with 
     [] -> (0,0) 
    | x::xs -> 
    if x > 0 then let (x,y) = test xs in (x+1, y) 
    else let (x,y) = test xs in (x, y+1);; 

Ale zaakceptowana odpowiedź jest nadal znacznie lepsza, szczególnie przy rekurencji ogona;).

+2

i jeśli piszesz 'match .. with ..' z jednym wzorem, możesz użyć' let' zamiast: 'let x, y = test xs w ...' –

5

Jeden problem polega na tym, że zwracasz dwa różne typy: int dla pustej listy lub krotkę w inny sposób. Musi to być jedno lub drugie.

Innym problemem jest to, że próbujesz dodać 1 do test, ale test to funkcja, a nie wartość. Musisz wywołać test na czymś innym, aby zwrócił wartość, ale nawet wtedy powinien zwrócić krotkę, której nie możesz dodać do liczby całkowitej.

Nie mogę określić, co ma zrobić kod, ale jeśli zaktualizujesz pytanie o te informacje, mogę pomóc.

się domyślać, że mam to, że chcesz liczyć na pozytywne numery na liście, w którym to przypadku można napisać tak:

let rec test l = 
    match l with [] -> 0 
    | x::xs -> if x > 0 then 1 + (test xs) 
       else test xs;; 

Aktualizacja: odkąd edytowane w celu wyjaśnienia problem, zmień powyższy kod w następujący sposób:

let test l = 
    let rec test_helper l pos nonpos = 
    match l with [] -> (pos, nonpos) 
    | x::xs -> if x > 0 then test_helper xs 1+pos, nonpos 
       else test_helper xs pos 1+nonpos 
    in test_helper l 0 0;; 

Korzystanie z akumulatorów bardzo pomaga w tym przypadku. Powoduje także funkcję rekursywną, która jest zawsze dobrą praktyką.

+0

jak mogę ją zmodyfikować, aby przekazywać dalej rekursywne ? – REALFREE