Автор Тема: [ocaml] Найдите ошибку в функции  (Прочитано 13193 раз)

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
[ocaml] Найдите ошибку в функции
« : Ноябрь 01, 2016, 01:04:14 am »
Продолжаем нашу рубрику неочевидных ошибок в программах на разных ЯП. На этот раз у нас будет строго статически типизированный функциональный язык - Ocaml.

Итак, вот функция, которая успешно компилируется, запускается, но выдает неверный результат (должна искать индекс минимального элемента массива):

let min_index a =
  let min i m =
    let m = if a.(i) < a.(m) then i else m in
    if (Array.length a) = (i+1) then
      m
    else
      min (i+1) m
  in
  min 0 0

Надо найти ошибку и ее исправить.
Y = λf.(λx.f (x x)) (λx.f (x x))

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: [ocaml] Найдите ошибку в функции
« Ответ #1 : Ноябрь 01, 2016, 04:33:26 am »
А если так:
let min_index a =
  let min i m =
    let m2 = if a.(i) < a.(m) then i else m in
    if (Array.length a) = (i+1) then
      m2
    else
      min (i+1) m2
  in
  min 0 0
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: [ocaml] Найдите ошибку в функции
« Ответ #2 : Ноябрь 01, 2016, 10:17:19 am »
А если так:
let min_index a =
  let min i m =
    let m2 = if a.(i) < a.(m) then i else m in
    if (Array.length a) = (i+1) then
      m2
    else
      min (i+1) m2
  in
  min 0 0

Неа.
Y = λf.(λx.f (x x)) (λx.f (x x))

Kemet

  • Hero Member
  • *****
  • Сообщений: 587
    • Просмотр профиля
Re: [ocaml] Найдите ошибку в функции
« Ответ #3 : Ноябрь 01, 2016, 06:00:28 pm »
Видимо, так как у функции min отсутствет указание рекурсивности rec, то при вызове min внутри min приведет к вызову предопределенной функции min

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: [ocaml] Найдите ошибку в функции
« Ответ #4 : Ноябрь 01, 2016, 06:11:00 pm »
Видимо, так как у функции min отсутствет указание рекурсивности rec, то при вызове min внутри min приведет к вызову предопределенной функции min

Да. Верно. указание рекурсивности rec приводит к изменению области видимости идентификатора данной функции. По умолчанию (без rec) идентификатор функции внутри самой функции не виден, поэтому рекурсивный вызов не возможен.

Подобные приколы также могут произойти не только с предопределенными функциями (входящими в автоимпортируемый модуль Pervasives (  https://caml.inria.fr/pub/docs/manual-ocaml/libref/Pervasives.html ) но и с функциями из других библиотечных модулей если их "импортируешь" через open. В окамле по умолчанию доступны все модули без импортов, просто к сущностям модулей нужно обращаться явно квалифицировав имя модуля. Использовав же open Modulename мы помещаем все сущности модуля Modulename в наш неймспейс (также как предопределенные функции и типы). Со всеми вытекающими.

Поэтому open используют редко. Ну а чтобы узнать какие именно модули использует данный модуль, можно воспользоваться соответствующей стандартной утилитой. Блока импортов там нет.
Y = λf.(λx.f (x x)) (λx.f (x x))

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: [ocaml] Найдите ошибку в функции
« Ответ #5 : Ноябрь 02, 2016, 04:36:06 am »
Ну пипец какой-то. И компилятор не предупреждает о таком переопределении? Что за аццкий ацтой?
to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…