Чего не хватает F # для объектно-ориентированного проектирования или что является императивом?

Много раз я слышал, что F # не подходит для конкретных задач, таких как UI. «Используйте правильный инструмент» - это обычная фраза.

Помимо отсутствующих инструментов, таких как конструктор WinForms / WPF / ORM, я не уверен, что именно отсутствует в F # - честно говоря! Тем не менее, особенно с пользовательским интерфейсом, мне сказали, что C # просто делает это лучше. Итак, каковы фактические различия и упущения в F # при его императивном использовании?

Вот список, который я составил:

  • Отсутствует поддержка инструментов

  • F # все еще находится в стадии бета-тестирования

  • Ваши разработчики не знают F #

    • I'd like to not consider those points, as they aren't really intrinsic to F#
  • Изменяемые должны быть "изменяемыми" или должны быть ref, ref need! разыменовать

  • Изменяемые значения назначаются с помощью ‹- и ref использует: = (они оба на 1 символ больше, чем просто =)

  • val требуется атрибут DefaultValueAttribute, чтобы получить значение по умолчанию

  • F # не генерирует неявные интерфейсы

  • С защищенными членами сложнее иметь дело

  • Нет автоматических свойств

  • Реализованные виртуальные члены в абстрактных классах требуют двух определений

  • Quotations-to-LINQ-Expression-Trees создает деревья, немного отличающиеся от C # / VB (раздражает API-интерфейсы, которые ожидают свои выражения в определенном формате)

  • Нет stackalloc

  • В F # нет условного оператора?:

  • Указатели могут считаться более громоздкими в F #

  • Делегаты / мероприятия, возможно, могут считаться более громоздкими (я бы сказал, что они проще, но как минимум они разные)

  • Нет автоматического преобразования типов (например, int в float или неявного приведения типов)

  • Нет специальной поддержки синтаксиса для значений Nullable (аннотация типа? И оператор в C #, а также использование операторов для значений NULL).

  • Нет автоматического повышения до общего базового класса или бокса (например: let x: obj = if true then 1 else "hi" // проверка типов не выполняется)

  • Значения не могут быть отброшены без предупреждения ("игнорируйте", чтобы обойти это)

  • Не имеет синтаксиса в стиле C :)

На вопрос: что из этого мешает написанию императивного или объектно-ориентированного кода? Почему (короткие примеры)? Какие из них я пропустил? Каковы лучшие обходные пути и почему их недостаточно?

Обратите внимание, я не говорю о написании так называемого идиоматического F # и уж точно не говорю о функциональном программировании. Меня больше интересует следующий вопрос: «Если бы я заставил себя написать пользовательский интерфейс или императивный / объектно-ориентированный код на F #, используя F # OO / императивные функции и типы классов, что больше всего повредит?»

Бонус. Если вы не знаете F #, но используете C # или VB.NET и считаете, что это лучший инструмент для некоторых ситуаций, укажите конкретные языковые функции и синтаксис, которые вам нравятся.


person Community    schedule 16.07.2009    source источник
comment
Похоже, вы хотите, чтобы F # был C # или VB. Вы будете тратить много времени на написание в императивном стиле.   -  person leppie    schedule 16.07.2009
comment
Пожалуйста, не поймите меня неправильно. Многие вещи в списке мне нравятся и я считаю их положительными. Нет, меня интересуют различия, которые разделяют C # и VB.NET, которые помогают им лучше справляться с такими задачами. Не в общем, о, это не было предназначено для этого, но отсутствие защищенных элементов означает, что F # просто не может справиться с фреймворками x y и z.   -  person MichaelGG    schedule 16.07.2009
comment
Дизайнер не должен быть большой проблемой, так как вы можете использовать другие dll. Обычно проблема только в небольших проектах.   -  person Dykam    schedule 21.08.2009
comment
Все, что вы можете делать с условным оператором, можно сделать с помощью блока соответствия. И хотя он более подробный, он также более гибкий.   -  person Steve Severance    schedule 03.10.2009


Ответы (5)


Что касается OO, мой список мог бы быть

  • Вы упомянули некоторые вещи об интерфейсах и виртуальных машинах, которые могут мешать или раздражать; отсутствие автоподдержки, о которой вы упомянули, тоже позор
  • Для объектно-ориентированных фреймворков иногда требуется много взаимно рекурсивных классов, которые F # в настоящее время заставляет вас помещать в один файл (в блоке типа ... и ... и ...)
  • Если вам нужно вызвать два разных базовых конструктора в производном классе, вы должны использовать «явный» синтаксис класса (как уже упоминалось здесь)

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

(Я почти не занимался программированием пользовательского интерфейса, поэтому не имею права на то, чтобы в этом разбираться.)

(РЕДАКТИРОВАТЬ: я также хочу добавить, что, хотя вы явно решили исключить «инструменты» из вопроса, я думаю, что инструменты имеют немного значение, и в этом отношении другие управляемые языки VS превосходны.)

person Brian    schedule 16.07.2009
comment
О да, вся эта рекурсивная история типа может быть неприятной. Но ... вы, ребята, это исправляете, верно? :) - person MichaelGG; 16.07.2009
comment
Ваша ссылка на объектно-ориентированную версию не подходит. Вы имеете в виду статическую типизацию? Или обязательно? - person leppie; 16.07.2009
comment
@MichaelGG: Со временем это будет исправлено, но неясно, сделает ли это VS2010 первым выпуском. ИМО, это ограничение - единственное, что в принципе может помешать вам создавать, например. ОО-фреймворк на 100 000 строк на F #. - person Brian; 16.07.2009
comment
@leppie: Я имел в виду OO. Например, создание небольшого класса на F # часто проще / проще, чем на C # (благодаря выводу типов и простому синтаксису). - person Brian; 16.07.2009
comment
А как насчет защищенных членов? Похоже, что большой объектно-ориентированный фреймворк тоже пострадает. - person MichaelGG; 16.07.2009
comment
Мое личное мнение таково, что защищенный - это чушь; Я не скучаю по нему ни на секунду. Но я легко могу представить, что другие сочтут это нежелательным, поэтому обязательно добавьте это в список. :) - person Brian; 16.07.2009
comment
Да, я согласен, что небольшие классы легче. Этот вспомогательный класс NHibernate: stackoverflow.com/questions/729687/ может быть выражением объекта в одну строку в F #: P. - person MichaelGG; 16.07.2009
comment
Инструменты огромны. Насчет этого сомнений нет. Но что насчет других языков заставляет их преуспеть в этом? - person MichaelGG; 16.07.2009
comment
Я очень не люблю, когда рекурсивные типы помещаются в один файл. В целом определение объема должно быть проще - и без использования файлов сигнатур. - person Dario; 05.12.2010

Я не большой поклонник этого вопроса, поскольку он жалуется на то, что F # не поддерживает идиоматический C #. Например, я не считаю справедливым критиковать F # за использование ‹- и: = для присвоения переменных, потому что язык по умолчанию делает вещи неизменными.

Тем не менее, есть несколько императивных / объектно-ориентированных вещей, которые вы можете сделать на C #, чего вы просто не можете сделать в F #.

  • F # не поддерживает вложенные классы. В C # вы можете объявить класс в теле другого класса как механизм для определения типов. F # не поддерживает это.

  • F # не позволяет реализовать один и тот же общий интерфейс дважды. Например, в C # вы можете реализовать IComparable<int> и IComparable<string> для одного и того же типа.

  • В F # у вас должно быть архитектурное наслоение. Из-за вывода типа F # вы можете использовать только классы, которые были объявлены «раньше» или в том же «блоке» объявлений типов. Однако в C # вы можете иметь любую ссылку на любой другой класс. (На самом деле это требует некоторых хороших практик программирования.)

  • В F # нет «собственной» поддержки LINQ, как в ключевом слове no from. Однако вы можете использовать LINQ API и лямбда-выражения для достижения того же результата.

То, что F # может сделать, чего не может C #:

  • Дискриминационные союзы. Это делает тривиальным создание древовидных структур данных в F #, тогда как в C # вам придется прибегать к сложной иерархии типов.

  • Асинхронные рабочие процессы. Эта функция библиотеки F # делает асинхронное и параллельное программирование гораздо более палитрой, абстрагируясь от всей боли, связанной с APM.

  • Сопоставление с образцом и активные образцы.

  • Единицы измерения для устранения ошибок, связанных с использованием неправильных единиц. (Например, прибавив футы к метрам.)

  • и Т. Д.

Вы не должны сосредотачиваться на том, что F # «не может делать так, как C #», потому что весь смысл изучения F # состоит в том, чтобы по-новому взглянуть на решение проблем. Если вы напишете идиоматический код C # на F #, вы на самом деле ничего не получите.

AFAIK F # не пропускает никаких "обязательных" для взаимодействия .NET / COM. В F # вы можете делать такие вещи, как параметры out и byref, объявлять строковые литералы и поддерживать добавление атрибутов практически ко всему.

person Chris Smith    schedule 21.08.2009
comment
Да, боюсь, я не очень ясно изложил свою точку зрения. Я не жалуюсь на F # и не критикую его - просто указываю на различия. Мой настоящий вопрос: почему C # больше подходит для пользовательского интерфейса, чем F # или что-то в этом роде. Я определенно не верю, что C # часто или когда-либо является правильным инструментом. Я просто хотел посмотреть, сможет ли кто-нибудь это подтвердить. (Меня тошнит, когда мне нужно писать на C #. Даже если я собираюсь писать на C #, я предпочитаю делать это на F # и иметь логический вывод, сопоставление с образцом и т. Д.) - person MichaelGG; 22.08.2009
comment
Например, в C # вы можете реализовать IComparable и IComparable для одного и того же типа. - не имеет особого смысла! - person Casebash; 17.03.2010

Императивное программирование на F # намного лучше, чем вы думаете. в F # является классно. Почему другие языки не реализовали это, я не знаю. Что касается синтаксиса (изменяемый, ref и т. Д.), С ними легко работать. Вы испорчены разреженностью F #, и легко пожаловаться, если синтаксис больше обычного. Кортежи тоже великолепны . Они также будут в C # 4.0. Currying - еще один бонус для Imperative.

Что касается объектно-ориентированного программирования, я редко использую наследование в проектах на чистом F # и предпочитаю композицию и интерфейсы. В основном это связано с использованием основного contructor, который позволяет вам использовать его параметры как частные свойства в ваших методах (не уверен, правильно ли я это сформулировал). Другие языковые конструкции, такие как сопоставление с образцом, также уводят вас от наследования. Я не делал смешанных проектов C # / F #, поэтому не могу это комментировать.

F # - это не только розы.

Моя самая большая проблема с F # и программированием игр - это производительность. Реализация на F # происходит очень быстро, и я часто запускаю и запускаю прототип того, что я хочу сделать, в тот же день, когда я думаю об этом, однако я обнаруживаю, что переписываю код из соображений производительности гораздо чаще, чем на C #.

Частично проблема заключается в моем отсутствии опыта в функциональном стиле программирования, который заключается в использовании Seq, List, Map и всех сопутствующих им методов, таких как map, iter, fold, scan. Мое первое функциональное решение почти никогда не бывает самым быстрым, в то время как мое первое процедурное решение почти всегда близко к наилучшему из возможных. Я хочу сказать, что частично это не я. Это функциональное программирование не дает производительности в некоторых ситуациях.

Сейчас я использую меньше функциональных типов данных в F #, чем когда начинал.

РЕДАКТИРОВАТЬ:

Прошло много месяцев с тех пор, как я опубликовал это, и у меня больше нет проблем с производительностью. Мои первые функциональные решения теперь часто проще и почти оптимальны, а неизменяемые структуры данных просты. Единственные проблемы с производительностью, которые у меня сейчас возникают, связаны с интерфейсом командной строки, и я всегда могу использовать c ++ / cli, если мне нужно. Сейчас я использую наследование помимо интерфейсов, но только для анонимных объектов.

person gradbot    schedule 16.07.2009
comment
сложный f # на XNA всегда будет более болезненным, пока JIT не выполнит надежный анализ или не добавит сборщик мусора поколений. Распределения, присущие текущим (и, вероятно, фиксированным) реализациям многих полезных аспектов, таких как FastFunc, Tuples и замыкания. В C # такая же проблема с делегатами, замыканиями (и кортежами начиная с 4.0), но это не так сильно способствует их использованию. Избегание выделения ресурсов в жестких игровых циклах - важное соображение при проектировании для обеспечения производительности XNA. - person ShuggyCoUk; 22.08.2009
comment
F # должен быть как минимум таким же быстрым, как C #, и часто на намного быстрее. Если вам нужно переписать свой F # на C #, чтобы получить адекватную производительность, значит, вы делаете что-то серьезно неправильно и вам нужно научиться оптимизировать код F #. - person J D; 06.02.2010
comment
@Jon Harrop, действительно был. Если вы новичок в функциональном программировании, вам нужно время, прежде чем вы начнете по-другому подходить к проблемам. - person gradbot; 24.02.2010
comment
Согласитесь с вашим EDIT. Производительность моей программы F # также близка к производительности C #, и мне также очень нравится C ++ / CLI в крайнем случае :) Я также иногда использую PInvoke, так как есть машинно-независимая оптимизация с использованием кода, например BLAS / ATLAS. - person Yin Zhu; 06.06.2010

Моя самая большая проблема со статически типизированными функциональными языками - это невозможность иметь переменные аргументы для метода, который необходимо вывести. Как функция карты. В F # вам понадобится map2 map3 и т. Д.

С другой стороны, в C # этого тоже нет, если только вы не хотите использовать отражение.

Возьмем, к примеру, схему, которая не является статически типизированной. У вас нет проблемы с определением единственной функции, которая может обрабатывать все случаи map_1 ... map_n. Конечно, вы теряете безопасность статического типа, но она меркнет по сравнению с дополнительным удобством написания краткого кода.

person leppie    schedule 16.07.2009
comment
Для ненавистников PHP стараюсь не затыкать рот, но я все еще использую PHP для создания скриптов из-за его динамических типов и сопутствующего множества функций. - person gradbot; 16.07.2009
comment
Хм, не думаю, что я слишком часто сталкивался с необходимостью абстрагироваться по количеству параметров. Но, опять же, и F #, и C # позволяют вам смешивать динамически, если вы чувствуете к этому склонность по какой-то причине. Если вы хотите передавать массивы объектов и динамически вызывать делегатов, проблем быть не должно. Я просто не хотел бы отказываться от типобезопасности в большинстве случаев. - person MichaelGG; 17.07.2009

Для записи: F # имеет распределение стека - попробуйте бесконечную рекурсию, которая не является хвостовой рекурсией, и вы получите переполнение стека. На самом деле это не отличается от распределения стека в C #, кроме того, что вы знаете, что можете безопасно использовать хвостовую рекурсию F # (в C # это зависит).

Кроме того, я хотел бы указать, что когда вы получаете действительно тяжелый код, ориентированный на события, F # масштабируется лучше, чем C #, с точки зрения создания инфраструктуры для выполнения «сантехники» отправки событий обработчикам и т. Д. Без необходимости превращения сантехники в большая часть вашего кода. Для простого пользовательского интерфейса C # или VB могут подойти большему количеству людей. В сложных ситуациях F # идет впереди, и лично мне нужна помощь в сложных ситуациях больше, чем в простых.

person RD1    schedule 17.09.2009
comment
О, и я думаю прямо противоположное о том, что вы теряете безопасность статического типа, но это бледнеет по сравнению с дополнительным удобством написания краткого кода. Вы можете сэкономить 10% вашего набора текста, но вы потратите намного больше времени на отладку во время выполнения. Если вам нужно переменное количество аргументов, просто используйте список! На самом деле вы можете очень легко реализовать тот же универсальный монотип, который схема использует в F #, но вы можете сделать лучше и выбрать статическую типизацию именно там, где вы этого хотите. - person RD1; 17.09.2009
comment
Я имел в виду прямой stackalloc для получения указателя на принадлежащий вам блок памяти в стеке. В F # я полагаю, вам придется создать большую структуру и взять ее адрес. Но в целом это звучит так, как будто вы говорите, что C # не имеет большого преимущества, что было моей точкой зрения. - person MichaelGG; 18.09.2009