Что такое 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 # продвигается вперед, и лично мне нужна помощь в сложных ситуациях больше, чем простые.