Что такое F #, недостающее OO или императив?

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

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

Вот список, который я придумал:

  • Много отсутствующей поддержки инструмента

  • F # все еще бета

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

    • Я бы не рассматривал эти моменты, поскольку они не являются подлинными для F #
  • Mutables нуждаются в "изменяемом" или должны быть ref, ref need! к разыменованию

  • Mutables присваивает с помощью < - и ref использует: = (они оба более одного символа, чем просто =)

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

  • F # не выводит неявные интерфейсы

  • Защищенным членам труднее иметь дело с

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

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

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

  • Нет stackalloc

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

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

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

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

  • Отсутствует специальная поддержка синтаксиса для аннотации Nullable (С#? type и оператора), а также использования операторов по значениям nullables.)

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

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

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

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

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

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

Ответы

Ответ 1

Что касается материалов OO, мой список может быть

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

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

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

(EDIT: Я также хочу вставить это, хотя вы явно решили исключить "инструментарий" из вопроса, я думаю, что инструментарий имеет значение, и в этом отношении другие управляемые языки VS превосходят.)

Ответ 2

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

Несмотря на это, в С# есть несколько обязательных/объектно-ориентированных вещей, которые вы просто не можете использовать в F #.

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

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

  • В F # у вас должно быть архитектурное наслаивание. Из-за вывода типа F # вы можете использовать только те классы, которые были объявлены "до" или в том же "блоке" объявлений типов. В С# однако вы можете иметь любую ссылку на класс любой другой. (Это фактически обеспечивает хорошие методы программирования.)

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

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

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

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

  • Совпадение шаблонов и активные шаблоны.

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

  • и др.

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

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

Ответ 3

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

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

F # - не все розы.

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

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

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

EDIT:

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

Ответ 4

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

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

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

Ответ 5

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

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