Comments 80
Под «Наследованием типов» я так полагаю подразумевается «выведение типов». (type inference)
Интересно вообще последнее время следить за функциональными языками программирования. А вообще какие перспективы у OCaml? Почему именно его начали изучать?
По-моему, более перспективно учить F# (наследник OCaml), который есть на .NET и Mono.
Ну это на любителя. Лично меня не радует перспектива тащить моно рантайм с приложением. Да и по скорости возникают вопросы — компилятор в код у ocaml сделан очень удачно. Не уверен, что моно код сможет конкурировать с ocaml в этом.
В последнем .NET JIT работает на ура, так что со скоростью работы проблем нет, и кроме того можно использовать любые .NET-сборки, написанные на любом языке, коих существует огромное количество :)
И ocaml и f# используют сборщик мусора, значит скорость будет примерно одинаковой. Единственные языки, которым дотнет уступает по скорости — это те, где нет GC, по понятным причинам.
ИМХО, если нет религиозных предубеждений перед тем, что ноги f# растут из МС, то он куда интереснее. Судя по тому, что это едва ли не первый функциональный язык, который активно продвигает крупная корпорация, он вообще имеет все шансы стать первым мейнстримовым функциональным языком.
Не холивора ради, просто посмотрите на C#, который в 2001 году выглядел практически клоном Java, а за десять лет и четыре версии из него сделали наверное самый красивый и мощный язык среди мейнстримовых. А в Java за это время сподобились разве что прикрутить дженерики, да и то на уровне языка, а не среды выполнения.
BTW, кто не знает, F# открыт и доступен под лицензией Apache.
ИМХО, если нет религиозных предубеждений перед тем, что ноги f# растут из МС, то он куда интереснее. Судя по тому, что это едва ли не первый функциональный язык, который активно продвигает крупная корпорация, он вообще имеет все шансы стать первым мейнстримовым функциональным языком.
Не холивора ради, просто посмотрите на C#, который в 2001 году выглядел практически клоном Java, а за десять лет и четыре версии из него сделали наверное самый красивый и мощный язык среди мейнстримовых. А в Java за это время сподобились разве что прикрутить дженерики, да и то на уровне языка, а не среды выполнения.
BTW, кто не знает, F# открыт и доступен под лицензией Apache.
В OCaml'е есть компиляция в нативный код.
Mono, кстати, умеет такое вообще из коробки без всяких 3rd-party утилит: tirania.org/blog/archive/2008/Nov-05.html
«И ocaml и f# используют сборщик мусора, значит скорость будет примерно одинаковой.»
Это мягко говоря неправда
Это мягко говоря неправда
Судя по этому shootout.alioth.debian.org/u32/benchmark.php?test=all&lang=fsharp&lang2=ocaml примерно правда
Примерно правда что? Что если есть сборщик мусора, то скорость должна быть одинакова? Тогда и питоп с psyco и erlang c hipe долджны давать одинаковый результат что и моно. Ведь откровенно неправда.
И кстати по ссылке, которую вы привели — ну ясно же видно, что F откровенно слабей.
Аргументировать можете? Я не спорю, что возможно в среднем F# будет чуть-чуть медленнее (или быстрее), но если эта разница в пару процентов, то сами понимаете.
Основная проблема F# — он генерирует не нативный код. Можно сколько угодно говорить про незначительность JIT, но это ровно до того момента, пока мы не подходим к серьёзным системным вопросам. На OCaml написан цитриксовский xapi, и одна из существенных особенностей кода на окамле — он не тащит за собой всякой дряни, а значит отлично подходит для содержимого стаб-доменов xen'а. Условно говоря, на OCaml можно написать псевдо-ядро для стаб-домена, на F# и прочих mono с грудами библиотек под жирные ядра (допустим, даже, линукса) — нет. То есть внутри уютненькой ОС — да, можно сравнивать. А если уютненькую ОС убрать?
Ну да, для кого-то куча библиотек это счастье, а для кого-то трагедия. Всё зависит от задач, так что я не спорю.
Куча библиотек — это здорово. Особенно здорово, когда при необходимости, их можно статически слинковать.
mono таки умеет компилится в нативный код со статически линковаными библиотеками. Я выше уже выложил ссылку на статью Мигеля двухлетней давности. Именно поэтому и возможны всякие MonoTouch'и, которые позволяют писать софт под те же айфоны, где никаких рантаймов моно никогда не было, нет и не будет.
Впрочем, наверное вы правы в том, что если уж писать софт для очень низкого уровня, то стоит выбирать для этого соответствующие инструменты.
Впрочем, наверное вы правы в том, что если уж писать софт для очень низкого уровня, то стоит выбирать для этого соответствующие инструменты.
Ну, у меня это исключительно производственная нужда. xapi написан на OCaml и демонстрирует, что строгая типизация и компиляция таки рулит в сравнении с питоновским охламонством xend'а.
Как раз, возможно, с кодом на OCaml работать придется скоро, спасибо!)
Вот зачем изобретать велосипед, с комментариями? Я про то, что они (*, а не как принято /*.
А в Великом и Ужасном Паскале, например, (*… *) (кроме {}). Вы, наверное, выросли на C-подобных языках. Есть куча языков, в которых не /*… */.
Это в C так принято. А ML примерно в то же время появился, что и C. В паскале, например, тоже (* комментарии.
Надеюсь вы дочитали статью не только до того момента, где говориться о комментариях.
Просто здесь много всего, что сделано «не как принято» и комментарии думаю не самая важная из этого списка вещь.
Просто здесь много всего, что сделано «не как принято» и комментарии думаю не самая важная из этого списка вещь.
Python, TCL, perl, bash, большинство конфиг-файлов — везде комменты начинаются с #. На самом деле, языков с C-подобными комментариями меньшинство.
> double average… Сравните с более компактной версией на OCaml.
Это спорная оценка.
Это спорная оценка.
а для комплексного, векторного, цветового и других видов умножений какие операторы используются?
как опредлить функцию sqr которая бы принимала на вход как целые так и вещественные числа? нельзя? тогда где тут полиморфизм?
как опредлить функцию sqr которая бы принимала на вход как целые так и вещественные числа? нельзя? тогда где тут полиморфизм?
let sqrt (a:'a)
1. Выведение типа:
# let hello x = «Hello » ^ x;;
val hello: string -> string = # let hello x = x;;
val hello: 'a -> 'a = (* 'a — означает любой тип *)
2. Ограничение типа:
# let hello (x:string) = «Hello » ^ x;;
val hello: string -> string = 3. Полиформизм
# let hello (x:'a) = «Hello » ^ x;;
val hello: string -> string =
И все равно этот вариант примет только строку.
# let hello (x:'a) = x;;
val hello: 'a -> 'a = (* то же самое что и let hello x = x;;, лишь с явным указанием того что доступен любой тип *)
# let hello x = «Hello » ^ x;;
val hello: string -> string = # let hello x = x;;
val hello: 'a -> 'a = (* 'a — означает любой тип *)
2. Ограничение типа:
# let hello (x:string) = «Hello » ^ x;;
val hello: string -> string = 3. Полиформизм
# let hello (x:'a) = «Hello » ^ x;;
val hello: string -> string =
И все равно этот вариант примет только строку.
# let hello (x:'a) = x;;
val hello: 'a -> 'a = (* то же самое что и let hello x = x;;, лишь с явным указанием того что доступен любой тип *)
и что полезного сможет сделать функция с «любым типом» кроме как вернуть переданное значение?
это просто пример, как указать, что функция может принимать аргумент любого типа.
С ними всё просто. Как и практически всегда, с ними нельзя сделать ничего иного, кроме как выбросить либо организовать в какую-либо структуру. Например, для организации произвольного дерева нужно знать тип данных? Нет, не нужно. Вот когда это дерево потребуется сделать упорядоченным, придётся писать специализированные функции. Кроме того, есть еще другие случаи, когда функции, работающие с 'a, определены в самом языке или импортируются из внешних библиотек. Например, хэш-таблица в окамле пользуется специальной сишной функцией, которая любой тип просто сжуёт как набор байт и создаст хэш.
Ну в данном случае можно сделать так:
# type num = First of int | Second of float | Triple of int*int*int;;
type num = First of int | Second of float | Triple of int * int * int
# let multiply_by_five x =
match x with
First(a) -> First(a*5)
| Second(b) -> Second(b*.5.)
| Triple(a,b,c) -> Triple(a*5,b*5,c*5);;
val multiply_by_five : num -> num = # multiply_by_five (First 42);;
- : num = First 210
# multiply_by_five (Triple (1,2,3));;
- : num = Triple (5, 10, 15)
Иначе говоря, вы можете на основе существующих типов определить некий общий тип (что-то вроде union в С, только сложнее и умнее), с которым и работать дальше. Заметьте, обобщив разрешенные входные данные в какой-то единый тип, мы можем легко и изящно определять «а какой тип данных скормили функции».
ничего не понял кроме того, что это совсем не функция sqr и на «легко и изящно» совсем не похоже.
Ок, напишу для Вас sqr:
# let sqr x =
match x with
First(a) -> First(a*a)
| Second(a) -> Second(a*.a)
| Triple(a,b,c) -> Triple(a*a,b*b,c*c);;
val sqr : num -> num = # sqr (First 5);;
- : num = First 25
# sqr (Triple (1,2,3));;
- : num = Triple (1, 4, 9)
Разница колоссальна, да.
А что касается «легко и изящно», тут надо понять две вещи. Чтобы вызвать операцию умножения (деления, прибавления 148) для какого-то аргумента, эта операция для данного типа должна быть определена. Если складывать штаны с табуретками, надо определить соответствующий оператор в любых языках. Просто в Си (бэйсик, пхп, ява, whatever) операторы и функции могут иметь одинаковые имена, вследствие чего выбор нужной функции и автоматическое приведение типа происходит автоматически на этапе компиляции. В чём-то это удобно, зачастую ещё и опасно. Окамл требует явного указания, какую функцию мы вызываем, взамен этого он позволяет нам выбирать поведение, в зависимости от типа, не только при вызове функции, но и абсолютно в любой момент. Более того, вышеупомянутым match можно, в зависимости от шаблонов, работать не только с типами, но и с конкретными значениями, содержимыми списков:
# let check_list x =
match x with
[] -> print_endline "list is empty"
| x :: [] -> print_endline "list has one element"
| x :: y :: [] -> print_endline "list has two elements"
| _ -> print_endline "too many";;
да, с перегрузкой туго во всех ML-подобных языках. что-то приходится жертвовать ради нормального выведения типов.
под полиморфизмом понимается совсем не то, что вы думаете. полиморфной функция может быть, только если она не зависит от типа.
sqr/sqrt делают разные вещи в зависимости от типа аргумента. поэтому это должны быть 2 разные функции. ведь в C бы это тоже было 2 разные функции, хоть и с одинаковым именем.
под полиморфизмом понимается совсем не то, что вы думаете. полиморфной функция может быть, только если она не зависит от типа.
sqr/sqrt делают разные вещи в зависимости от типа аргумента. поэтому это должны быть 2 разные функции. ведь в C бы это тоже было 2 разные функции, хоть и с одинаковым именем.
если функция не зависит от типа, то как она может зависеть от значения? а если она не зависит и от значения, то на кой чёрт вообще это значение передавать?
полиморфизм в том и заключается, что мы указываем что нужно сделать, но конкретная реализация для заданного типа подбирается автоматически.
полиморфизм в том и заключается, что мы указываем что нужно сделать, но конкретная реализация для заданного типа подбирается автоматически.
>> если функция не зависит от типа, то как она может зависеть от значения?
легко. в любом языке, поддерживающем параметрический полиморфизм вагон примеров. всякие List.Remove(T item) и ежи с ними.
легко. в любом языке, поддерживающем параметрический полиморфизм вагон примеров. всякие List.Remove(T item) и ежи с ними.
«Автоматически» формально к полиморфизму не относится, можно сказать, что это синтаксический сахар в некоторых языках :) Главное для полиморфизма, что можно выбрать одну из нескольких реализаций, а автоматически или ручками — не суть.
комментарии в OCaml очень похожи на комментарии в Си
Комментарии (* *) — это же в чистом виде Pascal. Когда-то давным-давно IDE не умели их нормально обрабатывать (например, считали, что выражение (*) — это открытый и тут же закрытый комментарий, и неправильно разукрашивали код). На этом можно было даже всякие приколы делать вроде:
write('Hello');
(*) write(', world!'); (*)
И срабатывают оба write'а. Естественно, что вместо вывода могло быть что-нить похлеще =)
Пардон, не так написал: срабатывает-то один write, но вот подсвечиваются как код оба, несмотря на то, что второй на самом деле закомментирован.
> Стандартная функция OCaml int_of_char casting:
Потеряли перевод слова casting.
Хорошо, что взяли для перевода этот мануал, он куда лучше, чем официальный.
Потеряли перевод слова casting.
Хорошо, что взяли для перевода этот мануал, он куда лучше, чем официальный.
val average: float -> float -> float =
fun? lol
fun? lol
Спасибо за перевод! Больше функциональщины разной в массы!
а сюда лучше не смотреть? ocaml.spb.ru/
И еще вопрос, тот окамл, что указан в статье (apt-get install ocaml) это компилятор в нативный код?
И еще вопрос, тот окамл, что указан в статье (apt-get install ocaml) это компилятор в нативный код?
За перевод, безусловно, спасибо — но местами стоило перечитать результат. Например:
Шайзе. Тем не менее:
«Пока что не очень понятно, почему полиморфные функции полезны, то на самом деле они очень полезны и очень распространены;» -> потеряно «если» в начале?
«Темой этого учебника является мысль, что...» -> "… мысль о том что..."
«Наша функция average, принимающая два числа с плавающей запятой и возвращающая одно число с плавающей запятой описывается так:» -> "… запятой, описывается так:"
«то мы записываем, что она возвращает» — не нужна запятая
«Как насчёт функции, которая принимает» — то же самое
«Мы можете подумать, что явное приведение уродливо, что это нудное занятие» — мы такие, мы можете. ну и первая запятая гоу хоум, да.
«оно работает даже для больших, и это экономит массу времени, потому что это удаляет целый класс ошибок» — гоу хоум обе две.
Ну и, вероятно, там кроется ещё некоторое количество. Но, повторюсь — за статью спасибо, было довольно интересно.
«Пока что не очень понятно, почему полиморфные функции полезны, то на самом деле они очень полезны и очень распространены;» -> потеряно «если» в начале?
«Темой этого учебника является мысль, что...» -> "… мысль о том что..."
«Наша функция average, принимающая два числа с плавающей запятой и возвращающая одно число с плавающей запятой описывается так:» -> "… запятой, описывается так:"
«то мы записываем, что она возвращает» — не нужна запятая
«Как насчёт функции, которая принимает» — то же самое
«Мы можете подумать, что явное приведение уродливо, что это нудное занятие» — мы такие, мы можете. ну и первая запятая гоу хоум, да.
«оно работает даже для больших, и это экономит массу времени, потому что это удаляет целый класс ошибок» — гоу хоум обе две.
Ну и, вероятно, там кроется ещё некоторое количество. Но, повторюсь — за статью спасибо, было довольно интересно.
вначале
(покорнейше прошу простить за занудство)
«Синтаксис OCaml изящен и лаконичен Вот функция»
«трёхкратно» — «троекратно»
«строка helo» — ll
«OCaml не осущетсвляет»
«плавающей запятой, используйте» =~ s/,//;
«Синтаксис OCaml изящен и лаконичен Вот функция»
«трёхкратно» — «троекратно»
«строка helo» — ll
«OCaml не осущетсвляет»
«плавающей запятой, используйте» =~ s/,//;
Не понял, почему Вы так не любите запятые в сложносочиненных и сложноподчиненных предложениях?
Во всех местах, про которые сказано, что запятая не нужна, запятые стоят правильно.
Во всех местах, про которые сказано, что запятая не нужна, запятые стоят правильно.
ну, «можете подумать, что явное приеведение уродливо» — тут как-то совсем не к месту.
«аже для больших, и это экономит» — это же не перечисление.
«времени, потому что» — тут я пожалуй неправ, но в другую сторону — «времени потому, что»
«аже для больших, и это экономит» — это же не перечисление.
«времени, потому что» — тут я пожалуй неправ, но в другую сторону — «времени потому, что»
почему ocalm, а не всемилюбимый haskell?
На всякий случай, для интересующихся: code.google.com/p/funprog-ru/
Перевод лекций по функциональному программированию, с примерами на ML.
Перевод лекций по функциональному программированию, с примерами на ML.
UFO just landed and posted this here
Допустим, вы написали функцию, назовём её repeated, которая берёт исходную строку s, число n и возвращает новую строку, состоящую из троекратно повторённой строки s.
Не троекратно, а n-кратно.
Sign up to leave a comment.
Введение в OCaml: The Basics [1]