Я пытаюсь записать простую рекурсивную функцию, которые просматривают список и возвращают пару целого числа. Это легко записать в c/c ++/java, но я плохо знаком с ocaml так так или иначе трудно для обнаружения решения, должного вводить конфликт
это должно идти как..
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)
таким образом, проблема состоит в том, как может я рекурсивно возвращаемое значение на кортеже..
На какое-то время был вдали от 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);;
. Вы можете использовать вложенные операторы сопоставления для извлечения частей кортеж для изменения
РЕДАКТИРОВАТЬ: Я не знал о синтаксисе Паскаль Куок, упомянутом в его комментарии ниже, вот такой код, он более аккуратный и немного короче:
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);;
Но принятый ответ все же намного лучше, особенно с хвостовой рекурсией;).
Одна из проблем здесь в том, что вы возвращаете два разных типа: int для пустого списка или кортеж в противном случае. Должно быть либо одно, либо другое.
Другая проблема в том, что вы пытаетесь добавить 1 к test
, но test
- это функция, а не значение. Вам нужно вызвать test на чем-то другом, чтобы он вернул значение, но даже тогда он должен вернуть кортеж, который вы не можете добавить к целому числу.
Я не могу понять, что вы хотите, чтобы код сделал, но если вы обновите свой вопрос с этой информацией, я смогу помочь больше.
Я предполагаю, что вы хотите подсчитать положительные числа в списке, в этом случае вы можете написать так:
let rec test l =
match l with [] -> 0
| x::xs -> if x > 0 then 1 + (test xs)
else test xs;;
Обновление: поскольку вы отредактировали вопрос, чтобы прояснить проблему, измените приведенный выше код следующим образом:
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;;
Использование аккумуляторов очень помогает в этом случае. Это также делает функцию хвостовой рекурсивной, что всегда является хорошей практикой.