Oberon space

General Category => Общий раздел => Тема начата: valexey_u от Ноябрь 01, 2016, 01:04:14 am

Название: [ocaml] Найдите ошибку в функции
Отправлено: valexey_u от Ноябрь 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

Надо найти ошибку и ее исправить.
Название: Re: [ocaml] Найдите ошибку в функции
Отправлено: Geniepro от Ноябрь 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
Название: Re: [ocaml] Найдите ошибку в функции
Отправлено: valexey_u от Ноябрь 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

Неа.
Название: Re: [ocaml] Найдите ошибку в функции
Отправлено: Kemet от Ноябрь 01, 2016, 06:00:28 pm
Видимо, так как у функции min отсутствет указание рекурсивности rec, то при вызове min внутри min приведет к вызову предопределенной функции min
Название: Re: [ocaml] Найдите ошибку в функции
Отправлено: valexey_u от Ноябрь 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 используют редко. Ну а чтобы узнать какие именно модули использует данный модуль, можно воспользоваться соответствующей стандартной утилитой. Блока импортов там нет.
Название: Re: [ocaml] Найдите ошибку в функции
Отправлено: Geniepro от Ноябрь 02, 2016, 04:36:06 am
Ну пипец какой-то. И компилятор не предупреждает о таком переопределении? Что за аццкий ацтой?