2010-06-15 8 views
7

Я пытаюсь написать простую рекурсивную функцию, которая просматривает список и возвращает пару целых чисел. Это легко написать в C/C++/Java, но я новичок в OCaml так или иначе трудно найти решение в зависимости от типа конфликтаocaml pattern question question

это должен идет как ..

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) 

поэтому проблема как я могу рекурсивно возвращать значение на кортеж.

+2

Не могли бы вы предоставить более подробную информацию о том, что должна возвращать эта функция? Что представляет собой пара целых чисел? – goggin13

+0

поэтому он должен возвращать пару целых чисел (x, y), которые являются кортежами в ocaml , что только проблема, с которой я столкнулся, - это вычисление кортежа .. так что это похоже, если элемент списка меньше некоторого числа тогда (x +1, y) else (x, y + 1), поэтому возвращаемое значение будет (x, y), где x - количество элементов, которое больше некоторого числа, и y меньше – REALFREE

ответ

4

Been от OCaml немного, но я думаю, что это будет делать трюк в отношении описания REALFREE в комментариях

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);; 

Вы можете использовали вложенные операторы матча вытаскивать куски кортежа изменить

EDIT: Я не знал о синтаксисе Pascal Cuoq упоминается в комментариях ниже, вот код так, это аккуратное и немного короче:

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);; 

Но принятый ответ все еще намного лучше, особенно с рекурсией хвоста;).

+2

, и если вы пишете 'match .. with ..' с одним шаблоном, вы можете вместо этого использовать' let': 'let x, y = test xs in ...' –

5

Одна из проблем заключается в том, что вы возвращаете два разных типа: int для пустого списка или кортеж в противном случае. Он должен быть тем или иным.

Другая проблема заключается в том, что вы пытаетесь добавить 1 к test, но test - это функция, а не значение. Вам нужно вызвать тест на что-то еще, чтобы вернуть значение, но даже тогда оно должно возвращать кортеж, который вы не можете добавить к целому.

Я не могу понять, что вы хотите сделать, но если вы обновите свой вопрос с помощью этой информации, я могу помочь больше.

Одно предположение, что у меня есть то, что вы хотите, чтобы сосчитать положительные числа в списке, в этом случае вы могли бы написать это следующим образом:

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

Update: так как вы отредактировали уточнить проблема, измените приведенный выше код следующим образом:

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;; 

Использование аккумуляторов помогает в этом случае. Он также делает функцию tail-recursive, которая всегда является хорошей практикой.

+0

, как я могу изменить его на рекурсивный ? – REALFREE