LINUX.ORG.RU

[ocaml] Точка выхода из функции

 


0

0

Функция:

# let rec interval a b =
  if a = b then
    []
  else if a > b then
    a::(interval (a - 1) b)
  else
    a::(interval (a + 1) b)
;;
val interval : int -> int -> int list = <fun>

# interval 20 30 ;;
- : int list = [20; 21; 22; 23; 24; 25; 26; 27; 28; 29]

# interval 30 20 ;;
- : int list = [30; 29; 28; 27; 26; 25; 24; 23; 22; 21]

# interval 30 30 ;;
- : int list = []

# interval 29 30 ;;
- : int list = [29]

Отлично, все работает так, как и задумано. Единственное, я не особенно понимаю как она работает. Вернее как она возвращает значение. По-сути, в любом случае, точка выхода из функции вот:

if a = b then
    []
Т.е. должен возвращаться пустой список, но возвращается именно тот список, который функция аккумулировала, который и надо. Каким образом это происходит?

Т.е., каким-то неявным образом в хвост аккумулированному списку присоединяется список из 

if a = b then
    []

Например, немного изменив исходную функцию:

# let rec interval a b =
  if a = b then
    [b + 100]
  else if a > b then
    a::(interval (a - 1) b)
  else
    a::(interval (a + 1) b)
;;
val interval : int -> int -> int list = <fun>

# interval 20 30 ;;
- : int list = [20; 21; 22; 23; 24; 25; 26; 27; 28; 29; 130]

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

compose
() автор топика
Ответ на: комментарий от www_linux_org_ru

.лять, ну что за закон подлости, думаешь маешься, как только запостишь вопрос, так сразу все доходит. Спросил, конечно, глупость, все эта нехорошая рекурсия, совсем запутала :)

compose
() автор топика
Ответ на: комментарий от compose

# let rec interval a b =
  if a = b then
    []                              - первый точк
  else if a > b then
    a::(interval (a - 1) b)         - второй точк
  else
    a::(interval (a + 1) b)         - третий точк
;;

Spectr ★★★
()
Ответ на: комментарий от Spectr

как я понимаю, a::list - возвращает список list с добавленным спереди элементом a.

Если у тебя a > b, то пойдет по второй точке, вызывая саму себя (разворачивая стек) с уменьшением на еденицу a и неизменным b; при этом наступит момент, когда у тебя выполнится условие a == b - тогда вернется из первой точки, вернув пустой список (реальное значение) а не результат рекурсивного вызова - тогда у тебя стек начнет обратно сворачиватся, возвращая реальные значения - куда будет к пустому списку добавлять все значения 'a' которые раньше передавал при вызове.

Если a < b - то будет раскручиватся стек по третьей точке, вернув по первой точке реальное значение - пустой стек.

Сорри, если путанно описал - преподаванием не занимался :)

Spectr ★★★
()

рекурсия обыкновенная. сначала у тебя по ветке a <|> b собирается список, потом к нему добавляется [] и вся эта конструкция возвращаяется. что непонятно?

Rastafarra ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.