Вот смотрите: SML был вполне бодрячком. Причем язык довольно маленький, простой и энергичный, его бы и в микронтроллеры можно было бы. Но врезал дуба, а вместо него загадочный OCaml, который сходу и не скажешь, чем лучше. Неисповедимы пути в IT.
расскажу вкратце, чем ocaml лучше sml: 1. активно поддерживается и развивается 2. умеет в подтипизацию на индуктивных типах данных и на записях (они почему-то называются объектами) 3. модули являются first-class values 4. gadts 5. rank-2 полиморфизм на уровне полей записей и методов объектов 6. умеет компилировать код, который экстрактит coq 7. куча разного, касающегося модулей и функторов над модулями (все они важны как средство абстракции и декомпозиции) 8. private data types (как abstract, но не скрывают представление) 9. манипуляции с ast посредством ppx (extension points) Остальное, несущественное -- получше инфраструктура, больше библиотек, норм сообщество.
там не interpreter, но вопрос понятен. Ответ: да, не только планы, но и реализация. Тем не менее, ещё пилят её. Но занимаются этим серьёзные люди, скорее всего доделают успешно.
Тем не менее, это не мешает в большинстве случаев: для параллельного ввода-вывода есть lwt, для спасения от shared global mutable state есть message passing, ну и fork работает. Не такая уж и проблема, вообще.
Про сложение -- ну бля... Семантика ведь разная, зачем путать мозг, рассуждающий о программе, одинаковыми обозначениями разных по смыслу операций?
А так -- есть pa_do, старый и рабочий.
В относительно новом окамле можно передавать модуль с операциями (типа х-евых тайпклассов):
# let add (type n) (module N : NUM with type t = n) a b = let open N in a + b;; val add : (module NUM with type t = 'a) -> 'a -> 'a -> 'a = Ну и далее "add m_int 1 2", где "m_int = (module Int : NUM with type t = int
( ... )
> зачем путать мозг, рассуждающий о программе, > одинаковыми обозначениями разных по смыслу операций?
Предположительно, в одном классе типов, операции "в достаточной степени" одинаковые, чтоб не парить себе мозгЪ их реальной неодинаковостью. Но это не мешает нагородить чОрти что, конечно.
1. ну SML небось тоже развивался, пока не сдох, и пункты 3, 4, 5, 7, 9 наверное в SML отсутствуют потому, что он сдох.
А вот вопрос - чем точный сборщик, который берет информацию об указателях из карт контекста плох? Зачем вот было устраивать историю с подрезанием бита у всей арифметики? Это просто вторая вещь, которая меня в окамле сильно раздражает.
я не помню точно про карты контекста, но помню, что это такая шняга, известная на момент компиляции, которая указывает, где целые, а где указатели. Так? Если да, то встречный вопрос: представим функцию "fun x -> (do_something (); x)". Она имеет тип "'a -> 'a" (полиморфна по x). Представим, что при выполнении do_something возникла нужда вызвать сборщик мусора. Собираем x (если он указатель), или не трогаем (если он целое)?
Ну я так понимаю, что в точке, где фунция вызывается, оно уже мономорфно. Если не вызывается нигде, то функция вообще выкинута, а так два инстанса --- для примитивного типа и для комплексного.
mkay. Раздувание кода уже есть. Далее интересно: имеем какую-нибудь запись или индуктивный тип данных. В ней поле имеет тип, равный типовому параметру. type 'a myrec = { field : 'a }. И let map_myrec f r = { field = f r.field }. Как будет рассматривать это дело, тоже разный код генерить на случай, если f (которая неизвестна в общем случае) отображает целые на указатели, наоборот, или ещё как?
Если важно не раздувать код, то можно делать полиморфные типы boxed, например и там, где это важно, специально их анбоксить.
То как решено в Окамле это как отрубить ноги, если они кривые. Более того, задача решена без подрезания арифметики во многих схожих языках. По бенчмаркам тот же MLton не факт, что много хуже окамла, т.е. я делаю вывод, что способ с картами довольно годный, и на все заданные вопросы ответы есть.
Если так делают в х-е, значит, так делать нельзя. За исключением тех случаев, когда в OCaml тоже так сделали (через десять, примерно, лет, когда за него Jane Street взялся).
Хам (ивр. חָם, греч. Χαμ, Cham, араб. حام, xam, «горячий») - библейский персонаж, переживший Всемирный потоп, один из трёх сыновей Ноя, брат Иафета и Сима (Быт. 5:32; 6:10), легендарный прародитель африканских народов, давший начало понятию «хамства», которое означает пренебрежительное отношение к культурным запретам.Можете ли вы указать на моё пренебрежение выше культурными запретами
( ... )
В момент отпочковывания OCaml от SML OCaml исправлял ровно две ошибки дизайна - наследие лиспа в виде возможности сравнивать тройки через вложенные пары ((1,2,3) можно было сравнить с (x,(y,z))) и возможное несоответствие исходников и реализации из-за top level (при изменении исходников они не подгружались в общий образ).
Moscow ML version 2.10 Enter `quit();' to quit. - val (x, y, z) = (1, (2, 3)) ;; ! Toplevel input: ! val (x, y, z) = (1, (2, 3)) ! ^^^^^^^^^^^ ! Type clash: expression of type ! 'a * 'b ! cannot have type ! 'c * 'd * 'e ! because the tuple has the wrong number of components - - val (x, y) = (1, 2);;
1. активно поддерживается и развивается
2. умеет в подтипизацию на индуктивных типах данных и на записях (они почему-то называются объектами)
3. модули являются first-class values
4. gadts
5. rank-2 полиморфизм на уровне полей записей и методов объектов
6. умеет компилировать код, который экстрактит coq
7. куча разного, касающегося модулей и функторов над модулями (все они важны как средство абстракции и декомпозиции)
8. private data types (как abstract, но не скрывают представление)
9. манипуляции с ast посредством ppx (extension points)
Остальное, несущественное -- получше инфраструктура, больше библиотек, норм сообщество.
Reply
есть ли ближайшие планы в сообществе ocaml убрать global interpreter lock?
и, я где-то слышал, есть способ убрать разные операторы сложения для разных типов чисел, и использовать один (если да, как это можно сделать?)
Reply
там не interpreter, но вопрос понятен. Ответ: да, не только планы, но и реализация. Тем не менее, ещё пилят её. Но занимаются этим серьёзные люди, скорее всего доделают успешно.
Тем не менее, это не мешает в большинстве случаев: для параллельного ввода-вывода есть lwt, для спасения от shared global mutable state есть message passing, ну и fork работает. Не такая уж и проблема, вообще.
Про сложение -- ну бля... Семантика ведь разная, зачем путать мозг, рассуждающий о программе, одинаковыми обозначениями разных по смыслу операций?
А так -- есть pa_do, старый и рабочий.
В относительно новом окамле можно передавать модуль с операциями (типа х-евых тайпклассов):
# let add (type n) (module N : NUM with type t = n) a b =
let open N
in a + b;;
val add : (module NUM with type t = 'a) -> 'a -> 'a -> 'a =
Ну и далее "add m_int 1 2", где "m_int = (module Int : NUM with type t = int ( ... )
Reply
Reply
> одинаковыми обозначениями разных по смыслу операций?
Предположительно, в одном классе типов, операции "в достаточной степени" одинаковые, чтоб не парить себе мозгЪ их реальной неодинаковостью.
Но это не мешает нагородить чОрти что, конечно.
Reply
наверное в SML отсутствуют потому, что он сдох.
А вот вопрос - чем точный сборщик, который берет информацию об
указателях из карт контекста плох? Зачем вот было устраивать
историю с подрезанием бита у всей арифметики? Это просто вторая
вещь, которая меня в окамле сильно раздражает.
Reply
Если да, то встречный вопрос: представим функцию "fun x -> (do_something (); x)". Она имеет тип "'a -> 'a" (полиморфна по x). Представим, что при выполнении do_something возникла нужда вызвать сборщик мусора. Собираем x (если он указатель), или не трогаем (если он целое)?
Reply
Если не вызывается нигде, то функция вообще выкинута, а так два инстанса ---
для примитивного типа и для комплексного.
Reply
Далее интересно: имеем какую-нибудь запись или индуктивный тип данных. В ней поле имеет тип, равный типовому параметру. type 'a myrec = { field : 'a }. И let map_myrec f r = { field = f r.field }. Как будет рассматривать это дело, тоже разный код генерить на случай, если f (которая неизвестна в общем случае) отображает целые на указатели, наоборот, или ещё как?
Reply
например и там, где это важно, специально их анбоксить.
То как решено в Окамле это как отрубить ноги, если они кривые. Более
того, задача решена без подрезания арифметики во многих схожих языках.
По бенчмаркам тот же MLton не факт, что много хуже окамла, т.е. я делаю вывод, что
способ с картами довольно годный, и на все заданные вопросы ответы есть.
Вон и в джаве, по моему, так делают.
Reply
Reply
Это же слепое пятно у начавшего ветку. ;)
Если так делают в х-е, значит, так делать нельзя. За исключением тех случаев, когда в OCaml тоже так сделали (через десять, примерно, лет, когда за него Jane Street взялся).
Reply
_Так_ -- сделать можно. Другое дело -- последствия. Будет ли лучше от этого?
Reply
Хам (ивр. חָם, греч. Χαμ, Cham, араб. حام, xam, «горячий») - библейский персонаж, переживший Всемирный потоп, один из трёх сыновей Ноя, брат Иафета и Сима (Быт. 5:32; 6:10), легендарный прародитель африканских народов, давший начало понятию «хамства», которое означает пренебрежительное отношение к культурным запретам.Можете ли вы указать на моё пренебрежение выше культурными запретами ( ... )
Reply
В момент отпочковывания OCaml от SML OCaml исправлял ровно две ошибки дизайна - наследие лиспа в виде возможности сравнивать тройки через вложенные пары ((1,2,3) можно было сравнить с (x,(y,z))) и возможное несоответствие исходников и реализации из-за top level (при изменении исходников они не подгружались в общий образ).
Забавно.
Reply
Moscow ML version 2.10
Enter `quit();' to quit.
- val (x, y, z) = (1, (2, 3))
;;
! Toplevel input:
! val (x, y, z) = (1, (2, 3))
! ^^^^^^^^^^^
! Type clash: expression of type
! 'a * 'b
! cannot have type
! 'c * 'd * 'e
! because the tuple has the wrong number of components
- - val (x, y) = (1, 2);;
Reply
Leave a comment