dastapov: (Default)
[personal profile] dastapov
Последняя серия про ocamldep, и потом я перейду к ocamlbuild.

Создадим три файла, a.ml, b.ml и c.ml:
a.ml
====
let a = 1

module B = struct let b = 1 ; end

b.ml
====
let b = 1

module C = struct let c = 1 ; end

c.ml
====
let c = 1


Теперь создадим две "программы" abc.ml и bc.ml, которые их используют:
abc.ml
======
open A
open B
open C

bc.ml
=====
open B
open C


Для того, чтобы собрать abc.ml, достаточно предварительно скомпилировать a.ml и c.ml.

Для того, чтобы собрать bc.ml, достаточно иметь скомпилированным только b.ml.

Теперь поглядим, что думает по этому поводу ocamldep:

% ocamldep -native abc.ml bc.ml
abc.cmx: c.cmx b.cmx a.cmx
bc.cmx: c.cmx b.cmx


А все потому, что ocamldep не анализирует .cmi файлы и не заглядывает
в .ml файлы, и поэтому он не знает, какие еще модули определены в
a.ml. Для языка с first-class modules это непростительно.

Еще раз напомню, что ocamldep используется всеми без исключения
существующими инструментами для сборки, и все они, волей-неволей,
вынуждены обходить ограничения ocamldep как-то по своему.

(no subject)

Date: 2011-11-21 12:53 pm (UTC)
From: [identity profile] lionet.livejournal.com
Из твоих постов создаётся впечатление, что тебе не очень нравится OCaml, в частности, его инфраструктура. Так ли это?

(no subject)

Date: 2011-11-21 01:03 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Мне не нравится сочетание двух факторов:
1)Из коробки все плохо
2)Мало документации для того, чтобы самому сделать хорошо

А у меня тут сейчас немерянный объем кода, который худо-бедно собирался тем, что есть, периодически все это ломалось, или собирало не то, или собирало не так, и вот наконец произошел количественно-качественный переход, и кол-во проблем стало переваливать через "болевой порог" слишком уж часто.

Мне надо сделать все красиво, я стал копать глубже, чтобы понять, от чего проблемы, там - вот такое ...

Да, по факту мне сейчас не нравится инфраструктура, а точнее - то, что проблемы в ней чинятся не там, где возникают, а заплатками где-то еще. Сам OCaml - OK.

(no subject)

Date: 2011-11-21 01:05 pm (UTC)
From: [identity profile] lionet.livejournal.com
У нас всё на Makefile с ручными зависимостями и `make clean && make`. И ниипёт.

(no subject)

Date: 2011-11-21 02:44 pm (UTC)
From: [identity profile] sergei lebedev (from livejournal.com)
Не думаете переезжать на OASIS? он решает львиную долю проблем со сборкой для большинства проектов.

(no subject)

Date: 2011-11-21 02:52 pm (UTC)
From: [identity profile] lionet.livejournal.com
У нас нет проблем, чтобы их решать. Кода мало.

(no subject)

Date: 2011-11-21 02:44 pm (UTC)
From: [identity profile] bytebuster463.livejournal.com
Что-то я совсем туплю.
Как соберётся abc, если вообще в природе нет модуля А?
F# в таком случае заругается на строку:
open A

(no subject)

Date: 2011-11-21 02:54 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Модуль A определен в файле a.ml. Имя .ml файла - это имя модуля, который в этом файле описан.

(no subject)

Date: 2011-11-21 03:13 pm (UTC)
From: [identity profile] bytebuster463.livejournal.com
Кхм, всё равно не понял.
То есть, если в файле a.ml определён module B, то его полное имя A.B - правильно?
А если нет (имя модуля плоское, без неймспейсов), то как будет работать такое:
a.ml
====
module B = let x=1; end

b.ml
====
let x=2

Это один и тот же x из одного и того же модуля, или разные?

Фа-диез на файлы плюёт, кроме условия, что модуль не может быть разорван на два файла.
open применяется (http://msdn.microsoft.com/en-us/library/dd393787.aspx) только к неймспейсам и модулям. Которые должны быть или в assembly references, или в файлах, которые идут в этом же проекте перед текущим файлом.
C этой точки зрения проще, но с майкрософтовским "шармом": циклические ссылки могут быть только в рамках одного файла.

(no subject)

Date: 2011-11-21 05:03 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Да, про A.B - правильно.

Без open-ов можно ссылаться по полному имени: A.B.b и B.b, и это будут разные "b"

Только в ocaml нету неймспейсов, и это просто модули определенные внутри модулей.

(no subject)

Date: 2011-11-21 06:48 pm (UTC)
From: [identity profile] bytebuster463.livejournal.com
Спасибо, теперь понял. Про неймспейсы я упомянул только в контексте дотнета.

А ещё вопрос - тогда, в Вашем примере, как трактуется команда:
open B
-- это эквивалент "open *.B"? В смысле, который из "B" будет открыт - тот, который A.B, или тот, который в файле b.ml?

И второе. А зачем вообще нужно, чтобы модуль был first-class? Вы его собираетесь в closure вставлять или в переменную? Если заглянуть в то, что делает компилятор фа-диеза, то модули как раз рендерятся в static классы. Вот код a.fs (определение модуля в первой строке обязательно, потому что не соберётся):
module A
let a = 1
module B = begin let b = 1 ; end


А вот, во что оно рендерится:

public static class A
{
    public static int a { get; }

    public static class B
    {
        public static int b { get; }
    }
}


Только вот зачем?

(no subject)

Date: 2011-11-21 09:43 pm (UTC)
From: [identity profile] http://users.livejournal.com/_adept_/
Лучше на "ты", ага?

Конструкция "open B" помещает в текущий scope все определения из того B, который "есть под рукой". Т.к. у нас уже есть B, определенный в A - будет взят именно он. А если никакого нет - компилятор пойдет искать по search path.

Зачем модули first-class - это вопрос, скорее, к авторам языка. Наверное, затем, чтобы type classes не делать и отмазываться - вот, мол, есть же модули, нафига вам еще что-то? :)

Моя конкретно претензия в том, что модули first-class в наличии есть, а нормальный dependency analyzer - не завезли.

(no subject)

Date: 2011-11-21 10:51 pm (UTC)
From: [identity profile] bytebuster463.livejournal.com
На "ты" - с удовольствием. Мы даже заочно немного знакомы по старофидошным делам.

"Есть под рукой" - имхо, это очень опасный паттерн. Лично для меня он примерно равен тому, как если бы у нас были A.doSomething и B.doSomething, и компилятор бы молча схавал конструкцию вида doSomething (как в случае отсутствия open, так и в случае, если <open> оба их них). Лучше пусть падает.

> чтобы type classes не делать

Здесь тоже неочевидно.
В случае mutable типов - всё понятно, как минимум, два кита ООП обязательны: инкапсуляция и полиморфизм.
А в случае чистого ФП - хоть я и не являюсь большим идеологом - но мне кажется, что closures являются более "идейным" решением. То есть, передавать не "A", а "A.doSomething". Ведь после вызова никаких артефактов в вызываемом коде ("A") не останется.
Опять же, фа-диез изначально строится на IL, там без классов никуда - но только в реализации.
Но передавать в качестве аргументов модули - это, имхо, глубокий изврат - разве нет? :)

> нормальный dependency analyzer - не завезли.

dependency любого модуля - это список его <open> минус список тех из них, которые реально не используются :)) Потому модули first-class - скорее, бага, чем фича.

Everything above - это глубокое имхо человека, который только изучает ФП.

(no subject)

Date: 2011-11-22 10:42 am (UTC)
From: [identity profile] usovalx.livejournal.com
> Лучше пусть падает

Вроде в ocaml если два модуля импортируют один и тот-же символ то будет конфликт при его использовании без уточнения имени модуля.

У тебя какая-то странная мешанина из модулей и замыканий. Они как-бы разные вещи. Основное (нетривиальное) назначение модулей -- протаскивание типов в функторы.

Пары-тройку годных примеров использования first-class модулей можно увидеть например тут (http://caml.inria.fr/pub/docs/manual-ocaml/manual021.html#toc81).

Profile

dastapov: (Default)
Dmitry Astapov

May 2022

M T W T F S S
       1
2345678
9101112131415
161718 19202122
23242526272829
3031     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags