crsib
> Ты определись, компилятор или рантайм? Компилятор не может следить за ошибками времени исполнения. У std::vector тоже есть at(), который не позволит тебе выйти за границы массива. И с точки зрения конечного программиста, он (программист) не проверяет на выход за границы массива.
Наверное, я плохо объяснил. В ATS ничто не делается автоматически (там даже GC можно не использовать). Просто компилятор (а более точно -- проверка типов) следит за тем, чтобы программист, выделивший память, не забыл ее где-нибудь освободить (естественно, после того, как кусок памяти освободили, его уже нельзя будет использовать -- за этим тоже следит компилятор).
Это не то же самое, что RAII, хотя используется для (примерно) тех же целей.
> Эээ, автоматически закрывать открытые файлы? Автоматичски удалять хиповую память? А в чем проблема? При условии, что известен lifetime объекта. Для памяти вообще есть куча готовых решение, позволяющих тонко и точно контроллировать lifetime и отсутствие утечек.
Нет, не автоматически. :)
> Этим еще пользуются O_O? Один фиг, в приведенном тобой примере glEnd вызывается явно.
В приведенном мной примере glBegin()/glEnd() неважны. Важно то, что компилятор разрешает только "правильное" использование этих двух функций, на основе их типов.
> А они typesafe?
Еще как. :)
chiaroscuro
> Наверное, я плохо объяснил. В ATS ничто не делается автоматически (там даже GC можно не использовать). Просто компилятор (а более точно -- проверка типов) следит за тем, чтобы программист, выделивший память, не забыл ее где-нибудь освободить (естественно, после того, как кусок памяти освободили, его уже нельзя будет использовать -- за этим тоже следит компилятор).
Ты говорил о нем в контексте встроенного ПО. Я правильно понимаю, что если у меня ресурс выделяется в прерывании, а освобождается в потоке, которому передается через примитив ОС, то этому ATS придется объяснить, как работает железо и ОС?
PS
У меня еще есть вариант, когда мутекс лочится в потоке, а разлочивается в прерывании.
du_hast
> Ты говорил о нем в контексте встроенного ПО. Я правильно понимаю, что если у
> меня ресурс выделяется в прерывании, а освобождается в потоке, которому
> передается через примитив ОС, то этому ATS придется объяснить, как работает
> железо и ОС?
>
> PS
> У меня еще есть вариант, когда мутекс лочится в потоке, а разлочивается в
> прерывании.
Во-первых, всегда есть inline C (там вообще очень просто с Си связываться) -- ибо некоторые конструкции языка навевают ужас (например, там сложно работать с сишными нуль-завершаемыми строками, потому что такой код содержит очень много инвариантов, которые никак не отражаются в Си, зато отражаются в ATS).
Во-вторых, таки нет. :)
chiaroscuro
> таки нет. :)
Как ATS тогда поймет, что все в порядке? Что мутекс, который залочил поток в этом же потоке разлочивать не нужно, а он разлочится в прерывании, когда отработает железо. Железо, кстати, может не "отработать" если неправильно настроено или таки в нем косяк.
du_hast
> Как ATS тогда поймет, что все в порядке? Что мутекс, который залочил поток в
> этом же потоке разлочивать не нужно, а он разлочится в прерывании, когда
> отработает железо. Железо, кстати, может не "отработать" если неправильно
> настроено или таки в нем косяк.
По многопоточности в ATS я не читал и не делал (хотя примеры есть), поэтому не знаю. Вместо этого покажу пример на файловом IO (все равно паттерн со всеми ресурсами одинаковый: создание/выделение, потом использование, потом освобождение/удаление). Магии тут никакой.
(* функция actions принимает на вход path и ничего не возвращает *)
fun actions (path: string): void = let
(* пробуем открыть файл по указанному пути на чтение, fp будет указателем FILE, а pfopt -- что-то типа переменной
* если удалось, то fp будет ненулевым, а pfopt будет "ресурсом"
*)
prval (pfopt | fp) = fopen_err (path, file_mode_r)
in
(* проверяем по указателю *)
if fp <> null then let
(* все ништяк, pf содержит доказательство того,
* что по указателю fp лежит хэндл на открытый на чтение файл по пути path;
* pf нам пригодится при работе с файлом, потому что каждой такой функции надо "предъявлять" его
* (поэтому, если бы pf не было, то и работать дальше мы бы не смогли)
*)
prval Some_v (pf) = pfopt
in
(* тут должны быть какие-то дополнительные действия, но мы их опускаем.
* закрывая файл, мы больше не можем использовать pf (ресурс "освобождается"), и следовательно, fp тоже *)
fclose_exn (pf | fp)
(* если fclose_exn пропустить, то компилятор скажет, что pf "выделен, но не освобожден" *)
end else let
(* никакого "токена" не получили *)
prval None_v () = pfopt
in
(* выдаем ошибку в stderr *)
prerrf ("actions(\"%s\"): failed to open\n", @(path))
end
endlet ... in ... end -- это примерно то же самое, что в Си, когда в начале блока определяются все переменные.
Надо заметить, что никаких pfopt и pf во время работы программы не будет: они существуют только во время проверки типов.
правка: синтаксис
Тема в архиве.