
Если бы кто-нибудь сказал мне несколько месяцев назад, что я буду снова экспериментировать с .NET после более чем пятнадцатилетней паузы, то я бы, наверно, рассмеялся1. В начале своей карьеры я пробовал работать с .NET и Java, и хотя некоторые вещи .NET делал лучше, чем Java (у него была возможность научиться на ошибках ранней Java), я быстро остановился на Java, потому что это была по-настоящему портируемая среда.
Наверно, читающие мой блог знают, что последние несколько лет я время от времени экспериментировал с OCaml, и я могу с уверенностью сказать, что он стал одним из моих любимых языков программирования наряду с Ruby и Clojure. Недавно работа с OCaml привлекла моё внимание к F# — это разработанный компанией Microsoft ML (Meta Language) для .NET , функциональная копия объектно-ориентированного (по большей мере) C#. Самый новый ML-язык…
Что такое F#?
К сожалению, никому нельзя объяснить, что такое Матрица. Ты должен увидеть её сам.
– Морфеус, «Матрица»
Прежде, чем мы перейдём к обсуждению F#, наверно, мне нужно сначала ответить на вопрос, что же такое F#. Для ответа на него я частично процитирую официальную страницу.
F# — универсальный язык программирования для написания краткого, надёжного и высокопроизводительного кода.
F# позволяет писать чёткий самодокументирующийся код, уделяя внимание предметной области задачи, а не деталям программирования.
При этом он не жертвует скоростью и совместимостью — он кроссплатформенный, опенсорсный и функционально совместимый.
open System // Получаем доступ к функциональности в пространстве имён System. // Определяем список имён let names = [ "Peter"; "Julia"; "Xi" ] // Определяем функцию, получающую имя и создающую приветствие. let getGreeting name = $"Hello, {name}" // Выводим приветствие для каждого имени! names |> List.map getGreeting |> List.iter (fun greeting -> printfn $"{greeting}! Enjoy your F#")
Любопытный факт: F# — это язык, сделавший популярным оператор конвейера (|>).
F# обладает множеством особенностей, в том числе:
-
Легковесный синтаксис
-
Иммутабельность по умолчанию
-
Вывод типов и автоматическое обобщение
-
Функции первого класса
-
Мощные типы данных
-
Сопоставление паттернов
-
Асинхронное программирование
Полный список возможностей задокументирован в руководстве по языку F#.
Выглядит многообещающе, правда?
F# 1.0 был официально выпущен Microsoft Research в мае 2005 года. Изначально он разрабатывался Доном Саймом из Microsoft Research в Кембридже, развившись из раннего исследовательского проекта Caml.NET, нацеленного на перенос OCaml на платформу .NET2. В 2010 году F# официально совершил переход из Microsoft Research в Microsoft (как часть отдела инструментария для разработчиков), что совпало по времени с релизом F# 2.0.
С тех пор F# стабильно развивался, а самый новый релиз F# 9.0 был выпущен в ноябре 2024 года. F# попал в зону моего внимания в год своего двадцатилетия!
Я хотел попробовать F# по множеству причин:
-
Несколько лет назад .NET стал опенсорсным и портируемым, и мне хотелось оценить прогресс на этом фронте
-
Мне было любопытно, есть ли у F# какие-то преимущества перед OCaml
-
Я слышал хорошие отзывы об инструментарии F# (например, Rider и Ionide)
-
Я люблю играться с новыми языками программирования
Ниже я расскажу о своих первых впечатлениях в разных областях.
Язык
Это член семейства ML-языков, поэтому его синтаксис не удивит людей, знакомых с OCaml (как будто таких людей много…). Стоит отметить, что программистам на Haskell синтаксис тоже будет родным. Как и программистам на Lisp.
А всем остальным будет достаточно просто освоить базу.
// применение функции printfn "Hello, World!" // определение функции let greet name = printfn "Hello, %s!" name greet "World" // пробелы важны, как и в Python let foo = let i, j, k = (1, 2, 3) // выражение: i + 2 * j + 3 * k // условные выражения let test x y = if x = y then "equals" elif x < y then "is less than" else "is greater than" printfn "%d %s %d." 10 (test 10 20) 20 // Циклический обход списка let list1 = [ 1; 5; 100; 450; 788 ] for i in list1 do printfn "%d" i // Обход последовательности кортежей let seq1 = seq { for i in 1 .. 10 -> (i, i*i) } for (a, asqr) in seq1 do printfn "%d squared is %d" a asqr // Простой цикл for...to. let function1 () = for i = 1 to 10 do printf "%d " i printfn "" // Цикл for...to с обратным отсчётом let function2 () = for i = 10 downto 1 do printf "%d " i printfn "" // Записи // Если метки определяются в одной строке, то они разделяются точкой с запятой type Point = { X: float; Y: float; Z: float } // Можно определять метки на отдельных строках без точки с запятой. type Customer = { First: string Last: string SSN: uint32 AccountNumber: uint32 } let mypoint = { X = 1.0; Y = 1.0; Z = -1.0 } // Дизъюнктное объединение type Shape = | Circle of radius: float | Rectangle of width: float * height: float // Функция с сопоставлением паттернов let area shape = match shape with | Circle radius -> System.Math.PI * radius * radius | Rectangle (width, height) -> width * height let circle = Circle 5.0 let rectangle = Rectangle(4.0, 3.0) printfn "Circle area: %f" (area circle) printfn "Rectangle area: %f" (area rectangle)
Вроде бы ничего неожиданного?
А вот ещё один пример, чуть более сложный:
open System // Сэмплируем данные - простые записи о продажах type SalesRecord = { Date: DateTime; Product: string; Amount: decimal; Region: string } // Датасет let sales = [ { Date = DateTime(2023, 1, 15); Product = "Laptop"; Amount = 1200m; Region = "North" } { Date = DateTime(2023, 2, 3); Product = "Phone"; Amount = 800m; Region = "South" } { Date = DateTime(2023, 1, 20); Product = "Tablet"; Amount = 400m; Region = "North" } { Date = DateTime(2023, 2, 18); Product = "Laptop"; Amount = 1250m; Region = "East" } { Date = DateTime(2023, 1, 5); Product = "Phone"; Amount = 750m; Region = "West" } { Date = DateTime(2023, 2, 12); Product = "Tablet"; Amount = 450m; Region = "North" } { Date = DateTime(2023, 1, 28); Product = "Laptop"; Amount = 1150m; Region = "South" } ] // Конвейер быстрого анализа let salesSummary = sales |> List.groupBy (fun s -> s.Product) // Группируем по товару |> List.map (fun (product, items) -> // Преобразуем каждую группу let totalSales = items |> List.sumBy (fun s -> s.Amount) let avgSale = totalSales / decimal (List.length items) let topRegion = items |> List.groupBy (fun s -> s.Region) // Вложенная группировка |> List.maxBy (fun (_, regionItems) -> regionItems |> List.sumBy (fun s -> s.Amount)) |> fst (product, totalSales, avgSale, topRegion)) |> List.sortByDescending (fun (_, total, _, _) -> total) // Сортируем по сумме продаж // Отображаем результаты salesSummary |> List.iter (fun (product, total, avg, region) -> printfn "%s: $%M total, $%M avg, top region: %s" product total avg region)
Можно сохранить этот код в файле Sales.fsx, и запустить его следующим образом:
dotnet fsi Sales.fsx
Теперь вы знаете, что F# — отличный выбор для написания скриптов! Кроме того, при запуске fsi dotnet откроется F# REPL, в котором можно изучать язык.
Я не буду особо вдаваться в подробности, потому что многое из того, что я писал об OCaml, применимо и к F#. Также рекомендую пройти краткий тур по F#, чтобы лучше освоить его синтаксис.
Совет: взгляните на шпаргалку по F#, если вам нужен краткий справочник по синтаксису.
На меня хорошее впечатление произвело то, что разработчики языка стремились сделать F# понятным для новичков, добавив множество мелких удобных улучшений. Ниже приведено несколько примеров, которые для вас, вероятно, будут мало значить, но их оценят люди, знакомые с OCaml:
// строчные комментарии (* классические комментарии ML тоже присутствуют *) // изменяемые значения let mutable x = 5 x <- 6 // диапазоны и срезы let l = [1..2..10] name[5..] // Вызовы методов C# выглядят достаточно естественно let name = "FOO".ToLower() // операторы можно перегружать для разных типов let string1 = "Hello, " + "world" let num1 = 1 + 2 let num2 = 1.0 + 2.5 // универсальный вывод printfn "%A" [1..2..100]
Возможно, некоторые из этих аспектов могут показаться спорными пуристам ML-языков, но я считаю, что повышать популярность ML следует любыми способами.
А я говорил о том, что в языке удобно работать со строками Unicode и регулярными выражениями?
Люди часто говорят, что F# — это по большей мере полигон для будущих фич C# и возможно, это правда. Я недостаточно долго наблюдал за обоими языками, чтобы иметь собственное мнение по этой теме, но меня впечатлило, что async/await (в C#, а потом и в JavaScript) впервые появились… в F# 2.0.
Всё изменилось в 2012 году, когда был выпущен C#5, где появилась популярная пара ключевых слов async/await. Эта возможность позволяла писать код со всеми преимуществами асинхронного кода, например, отсутствием блокировки UI при запуске долговременного процесса, однако код читался, как обычный синхронный код. Этот паттерн async/await сегодня добрался до множества современных языков программирования: Python, JS, Swift, Rust и даже C++.
Подход F# к асинхронному программированию немного отличается от async/await, но решает ту же задачу (на самом деле, async/await — это урезанная версия подхода F#, появившегося несколько лет назад в F#2).
– Айзек Эйбрахам, F# in Action
Время покажет, что будет дальше, но я не думаю, что C# когда-нибудь сможет полностью заменить F#.
Кроме того, я обнаружил вдохновляющий комментарий 2022 года о том, что Microsoft, возможно, готова вкладываться больше в F#:
Хорошие новости для вас. Спустя 10 лет разработки F# двумя с половиной людьми и с приходящей время от времени помощью от сообщества, Microsoft наконец-то решила вложиться в F# и создать этим летом полнофункциональную команду в Праге. Я разработчик из этой команды; как и вы, я давний фанат F# и очень рад, что дело наконец начало двигаться.
Если посмотреть на изменения между F# 8.0 и F 9.0, то можно прийти к выводу, что полнофункциональная команда отлично справляется!
Экосистема
После столь короткого периода изучения мне сложно оценить экосистему F#, но в целом мне кажется, что существует приличное количество «нативных» библиотек и фреймворков F#, а большинство людей активно использует API core .NET и множество сторонних библиотек и фреймворков, созданных для C#. Такое достаточно часто бывает с hosted-языками, так что в этом тоже нет ничего удивительного.
Если вы когда-нибудь пользовались другим hosted-языком (например, Scala, Clojure, Groovy), то, вероятно, знаете, чего можно ожидать.
Awesome F# ведёт список популярных библиотек, инструментов и фреймворков F#. Я перечислю здесь несколько библиотек для веб-разработки и data science:
Веб-разработка
-
Giraffe: легковесная библиотека для создания веб-приложений с использованием ASP.NET Core. Обеспечивает функциональный подход к веб-разработке.
-
Suave: простая и легковесная библиотека веб-сервера с комбинаторами для маршрутизации и построения задач. (Стала источником вдохновения для разработчиков Giraffe.)
-
Saturn: построена на основе Giraffe и ASP.NET Core; обеспечивает фреймворк в стиле MVC, вдохновлённый Ruby on Rails и Elixir Phoenix.
-
Bolero: фреймворк для создания клиентских приложений на F# с использованием WebAssembly и Blazor.
-
Fable: компилятор, транслирующий код на F# в JavaScript, что обеспечивает интеграцию с популярными экосистемами JavaScript наподобие React и Node.js.
-
Elmish: архитектура model-view-update (MVU) для создания веб-UI на F#; часто используется с Fable.
-
SAFE Stack: сквозной стек с упором на функциональное программирование для создания веб-приложений для облаков. Сочетает в себе такие технологии, как Saturn, Azure, Fable и Elmish, обеспечивая типобезопасный процесс разработки.
Data Science
-
Deedle: библиотека для манипуляций с данными и исследовательского анализа, схожая с pandas для Python.
-
DiffSharp: библиотека для автоматического дифференцирования и машинного обучения.
-
FsLab: коллекция библиотек, предназначенных для data science, в том числе инструменты визуализации и работы со статистикой.
Пока я не особо экспериментировал с ними, поэтому не буду пока давать никаких отзывов и рекомендаций.
Документация
Официальная документация достаточно хороша, однако мне кажется странным, что часть её хостится на сайте Microsoft, а часть — на https://fsharp.org/ (это сайт F# Software Foundation).
Мне очень понравились следующие части документации:
-
F# Design — репозиторий RFC (такой должен быть у каждого языка!)
https://fsharpforfunandprofit.com/ — это ещё один хороший ресурс для обучения (хотя ощущается немного устаревшим).
Инструментарий разработки
История инструментария разработки F# довольно непростая — раньше поддержка F# была отличной только в Visual Studio, а в других местах довольно посредственной. К счастью, за последнее десятилетие ситуация с инструментарием улучшилась:
В 2014 году произошёл технический прорыв: Томас Петричек, Райан Райли, Дейв Томас и другие последующие контрибьюторы написали пакет FSharp.Compiler.Service (FCS). В нём содержится базовая реализация компилятора F#, инструментарий редактора и скриптовый движок в виде единой библиотеки; его можно использовать для создания инструментария F# в широком спектре ситуаций. Это позволило реализовать поддержку F# во множестве других редакторов, инструментов скриптинга и документирования, а также обеспечило разработку альтернативных бэкендов F#. Основным разрабатываемым сообществом редактором стал Ionide Кшиштофа Чешлака, используемый для поддержки удобного редактирования в кроссплатформенном редакторе VSCode, на момент написания статьи скачанный более одного миллиона раз.
– Дон Сайм, The Early History of F#
Я попробовал плагины F# для различных редакторов:
-
Emacs (fsharp-mode)
-
Zed (сторонний плагин)
-
Helix (встроенная поддержка F#)
-
VS Code (Ionide)
-
Rider (JetBrains .NET IDE)
В целом, Rider и VS Code обладают наибольшим количеством (и качеством) возможностей, но другими вариантами тоже вполне можно пользоваться. В основном это связано с тем, что LSP-сервер F# server fsautocomplete достаточно надёжен, и любой редактор с хорошей поддержкой LSP сразу получает богатую функциональность.
Тем не менее, должен сказать, в некоторых отношениях инструментарий хромает:
-
fsharp-mode не использует TreeSitter (пока) и, похоже, не особо активно разрабатывается (судя по коду, он производный от caml-mode)
-
Поддержка F# в Zed достаточно спартанская
-
В VS Code, как ни странно, поломано развёртывание и сворачивание выбранного, что довольно странно, ведь он должен быть основным редактором для F#
У меня возникают серьёзные проблемы с привязками клавиш в VS Code (слишком много клавиш-модификаторов и функциональных клавиш, на мой взгляд) и моделью редактирования, поэтому в дальнейшем я, вероятно, выберу Emacs. Или наконец-то качественно разберусь с neovim!
Похоже, что все пользуются одним и тем же форматировщиком кода (Fantomas), в том числе и команда F#, что здорово! С линтером история у F# не такая хорошая (похоже, единственный популярный линтер FSharpLint ныне заброшен), но когда компилятор настолько прекрасен, линтер особо не требуется.
Выглядит так, как будто Microsoft не особо вкладывается в инструментарий F#, ведь практически все крупные проекты в этой сфере разрабатываются сообществом.
ИИ-помощники в кодинге (например, Copilot) работают с F# достаточно хорошо, но я мало их тестировал.
В конечном итоге, вероятно, подойдёт любой редактор, если вы используете LSP.
Кстати, я сделал любопытное наблюдение в процессе программирования на F# (да и на OCaml) — когда работаешь на языке с очень хорошей системой типов, то от редактора на самом деле требуется не столь многое. Чаще всего мне вполне достаточно информации об inline-типах (например, что-то типа CodeLenses), автоматического дополнения и возможности простой отправки кода в fsi. Простота по-прежнему остаётся высшей степенью утончённости…
Другие инструменты, о которых следует знать:
-
Paket — менеджер зависимостей для проектов .NET. Можно считать его чем-то вроде bundler, npm или pip, но для экосистемы пакетов NuGet .NET.
-
FAKE — DSL для создания задач и тому подобного, благодаря которому можно использовать F# для формулирования задач. Чем-то напоминает rake в Ruby. Некоторые считают его самым простым способом встраивания F# в уже существующий проект .NET.
Сценарии использования
Учитывая глубину и ширину .NET, вероятно, вас ничто не будет сдерживать!
Мне кажется, что F# особенно хорош для анализа данных и манипуляций с ними благодаря фичам наподобие поставщиков типов. Вот небольшая демонстрация работы поставщика типов JSON:
#r "nuget: FSharp.Data" open System open FSharp.Data // Определяем тип на основании примера элемента JSON type PeopleJson = JsonProvider<""" [ { "name": "Alice", "age": 30, "skills": ["F#", "C#", "Haskell"] } ] """> // Симулированный список JSON (может загружаться из файла или API) let jsonListString = """ [ { "name": "Alice", "age": 30, "skills": ["F#", "C#", "Haskell"] }, { "name": "Bob", "age": 25, "skills": ["F#", "Rust"] }, { "name": "Carol", "age": 28, "skills": ["OCaml", "Elixir"] }, { "name": "Dave", "age": 35, "skills": ["Scala", "F#"] }, { "name": "Eve", "age": 32, "skills": ["Python", "F#", "ML"] }, { "name": "Frank", "age": 29, "skills": ["Clojure", "F#"] }, { "name": "Grace", "age": 27, "skills": ["TypeScript", "Elm"] }, { "name": "Heidi", "age": 33, "skills": ["Haskell", "PureScript"] }, { "name": "Ivan", "age": 31, "skills": ["Racket", "F#"] }, { "name": "Judy", "age": 26, "skills": ["ReasonML", "F#"] } ] """ // Парсим JSON let people = PeopleJson.Parse(jsonListString) // Выводим printfn "People in the list:\n" for p in people do printfn "%s (age %d) knows:" p.Name p.Age p.Skills |> Array.iter (printfn " - %s") printfn ""
Когда я в первый раз увидел это, мне показалось это магией, ведь F# извлекает структуру и типы данных из небольшого примера данных, после чего мы получаем парсер для них. Можно сохранить код в файл TypeProvidersDemo.fsx, а потом запустить его следующим образом:
dotnet fsi TypeProvidersDemo.fsx
Более того, можно выполнять такие задачи, как извлечение данных напрямую из таблиц HTML и визуализация данных:
#r "nuget:FSharp.Data" #r "nuget: Plotly.NET, 3.0.1" open FSharp.Data open Plotly.NET type LondonBoroughs = HtmlProvider<"https://en.wikipedia.org/wiki/List_of_London_boroughs"> let boroughs = LondonBoroughs.GetSample().Tables.``List of boroughs and local authorities`` let population = boroughs.Rows |> Array.map (fun row -> row.Borough, row.``Population (2022 est)``) |> Array.sortBy snd |> Chart.Column |> Chart.show
Если запустить скрипт, то в вашем браузере появится красивая диаграмма населения разных районов Лондона. Отличная штука!
Здесь стоит также отметить простоту использования внешних библиотек (например, Plotly.NET) в скриптах на F#!
Думаю, F# хорошо подойдёт для бэкенд-сервисов и даже фулстек-приложений, хоть я особо и не изучал первые решения на F# в этой сфере.
Благодаря Fable и Elmish язык F# вполне можно использовать для программирования клиентской части; к тому же они могут позволить языку F# проникнуть в вашу повседневную работу.
Примечание: в прошлом целевой платформой Fable был JavaScript, но с версии Fable 4 можно использовать и другие платформы, такие как TypeScript, Rust, Python и другие.
Вот пример того, насколько просто транспилировать кодовую базу F# на какой-нибудь другой язык:
# Транспиляция на JavaScript dotnet fable # Транспиляция на TypeScript dotnet fable --lang typescript # Транспиляция на Python dotnet fable --lang python
Круто!
Сообщество
На первый взгляд, сообщество языка довольно маленькое, вероятно, даже меньше, чем у OCaml. Похоже, самые активные площадки для обсуждения F# — это Reddit и Discord (указанный в Reddit). Должен быть и ещё какой-то Slack по F#, но я не смог получить туда инвайта. (Кажется, автоматизированный процесс выпуска этих инвайтов уже какое-то время поломан.)
Я по-прежнему пока не очень понимаю, какую роль в сообществе играет Microsoft, потому что в целом сообщений от компании я видел не так много.
Для меня малый размер сообщества — не проблема, если оно остаётся активным и бурным. К тому же я заметил, что мне всегда были симпатичны маленькие объединения. При переходе от Java к Ruby перемена очень заметна, повышается вовлечённость в сообщество и чувство причастности.
Я не нашёл особо много книг и сайтов/блогов, посвящённых F#, но и не очень ждал этого.
Вот самые заметные общественные инициативы:
-
Amplifying F# — проект по продвижению F# и привлечению к нему компаний
-
F# for Fun and Profit — коллекция туториалов и эссе по F#
-
F# Lab — создаваемый сообществом инструментарий для data science на F#
-
F# Weekly — еженедельная рассылка о последних разработках в мире F#
Мне кажется, что для продвижения языка и привлечения новых программистов и бизнесов сделано более, чем достаточно, хоть это и всегда непросто для проекта с двадцатилетней историей. Я по-прежнему немного недоумеваю, почему Microsoft не продвигает F# активнее, ведь мне кажется, что он был бы отличным средством маркетинга.
Состязания в популярности
Люди по-разному относятся к «популярности» языков программирования. Меня часто спрашивают, почему я трачу много времени на языки, которые вряд ли принесут мне какие-то карьерные перспективы, например:
-
Emacs Lisp
-
Clojure
-
OCaml
-
F#
Возможности профессионального роста, разумеется, важны, но важно и:
-
развлекаться (а F в названии F# означает «fun»)
-
изучать новые парадигмы и идеи
-
бросать себе вызов, думая и работая иначе
Тем не менее, нужно отметить, что F# по большинству традиционных метрик остаётся непопулярным языком. У него не очень высокий рейтинг TIOBE, StackOverflow и на большинстве сайтов с вакансиями. Но в то же время он и не менее популярен, чем большинство «мейнстримных» функциональных языков программирования. Увы, функциональное программирование по-прежнему не мейнстримное, и, возможно, никогда таким не станет.
Ещё пара ресурсов по теме:
-
-
Есть и видео к приведённой выше статье
-
F# и OCaml
Первоначальная концепция была простой F#: привнести преимущества OCaml в .NET и .NET в OCaml; создать союз между функциональным программированием со строгой типизацией и .NET. Здесь под «OCaml» подразумевается и само ядро языка, и прагматичный подход к функциональному программированию со строгой типизацией. Изначально задача была сформулирована чётко: я должен был реализовать заново ядро языка OCaml и часть его базовой библиотеки для целевой платформы .NET Common Language Runtime. Для юридической чистоты реализация должна была стать новой, то есть не использовать никакие части кодовой базы OCaml.
– Дон Сайм, создатель F#, The Early History of F#
Язык F# стал производным от OCaml, поэтому эти языки имеют много общей ДНК. На ранних этапах F# предпринимал усилия по поддержке максимально возможного объёма синтаксиса OCaml и даже позволял использовать расширения файлов .ml и .mli в коде на F#. Однако со временем пути языков начали расходиться3.
Разумеется, с самого начала рассматривалось создание языка, независимого от OCaml. Это отразилось и в выборе названия F#, хотя первые версии языка назывались Caml.NET:
Хотя первую версию F# презентовали, как «Caml для .NET», на самом деле, это всегда был новый язык, спроектированный с нуля для .NET. F# никогда не был полностью совместимым с какой-либо версией OCaml, хоть и имел общее совместимое подмножество и взял Caml-Light и OCaml за принципиальные источники вдохновения для своего дизайна.
– Дон Сайм, The Early History of F#
Если спросить у людей о плюсах и минусах F# по сравнению с OCaml, то большинство, вероятно, даст следующие ответы:
Плюсы F#
-
Работает на .NET
-
Доступна куча библиотек
-
-
Поддерживается Microsoft
-
Немного проще изучать новичкам (особенно тем, кто работал только с объектно-ориентированным программированием)
-
Немного проще разобраться в синтаксисе (мне кажется)
-
Ошибки и предупреждения компилятора более «дружественные» (их легче понять)
-
Проще отлаживать проблемы (частично связано с предыдущим пунктом)
-
-
Сильная поддержка асинхронного программирования
-
Имеет крутые фичи, которых нет в OCaml, например:
-
Анонимные записи
-
Активные паттерны
-
Вычислительные выражения
-
Sequence comprehension
-
Поставщики типов
-
Единицы измерения
-
Минусы F#
-
Работает на .NET
-
Взаимодействие с .NET повлияло на множество решений при проектировании языка (например, наличие допущения null)
-
-
Поддерживается Microsoft
-
Не всем нравится Microsoft
-
Похоже, Microsoft выделяет на F# довольно скромные ресурсы
-
Непонятно, насколько вовлечённой будет Microsoft в долговременной перспективе
-
-
Соглашения об именах: мне нравится snake_case гораздо больше, чем camelCase и PascalCase
-
Отсутствуют некоторые крутые фичи OCaml
-
Модули первого класса и функторы
-
GADT
-
-
Нет миленького логотипа с верблюдом
-
Название F# звучит круто, но поиск и имена файлов — это настоящий кошмар (довольно часто его называют FSharp)
И F#, и OCaml могут использовать в качестве целевой платформы среды выполнения JavaScript: F# при помощи Fable, OCaml — при помощи Js_of_ocaml и Melange. На первый взгляд Fable кажется наиболее совершенным решением, но я недостаточно долго пользовался ими тремя, чтобы моё мнение было достаточно веским.
В конечном итоге, оба остаются практически одинаково надёжными, хотя и нишевыми языками, которые вряд ли станут очень популярными в будущем. Предполагаю, что вероятность профессиональной работы с F# выше, потому что .NET очень популярен; могу представить, что можно вставлять куски F# тут и там в готовые кодовые базы на C#.
Я заметил в проектах на F# одну странную штуку — в них по-прежнему используются XML-манифесты проектов (.fsproj), в которых нужно вручную перечислять файлы исходников в порядке их компиляции (чтобы учесть зависимости между ними). Меня поразило то, что компилятор не может обрабатывать зависимости автоматически, но, думаю, дело в том, что в F# нет прямого соответствия между файлами исходников и модулями. Как бы то ни было, мне гораздо больше нравится процесс компиляции OCaml (и Dune).
Так как мой интерес к ML в основном образовательный, я склоняюсь к OCaml, но если бы мне пришлось создавать веб-сервисы на ML-языке, то я бы, вероятно, выбрал F#. Ещё я крайне уважаю все языки с собственной средой выполнения, потому что маловероятно, что среда выполнения заставит идти на какие-то компромиссы в языке.
В заключение
Вопрос: что может C# и не может F#? Ответ: NullReferenceException!
– Шутка из сообщества F#
В конечном итоге, F# мне понравится гораздо больше, чем я ожидал! В каком-то смысле он напомнил мне прежний опыт работы с Clojure в том смысле, что Clojure был самым практичным Lisp из всех выпущенных, в основном благодаря своему отличному взаимодействию с Java.
У меня есть ощущение, что если бы .NET был портируемым (и опенсорсным) изначально, то ClojureCLR, вероятно, мог бы стать столь же популярным, как и Clojure, а F#, возможно, образовал более обширное сообщество и получил больше популярности. Я уверен, что больше никогда бы не связался с .NET, если бы не .NET Core, и сомневаюсь, что я один такой. Не способствовало популярности и то, что F# не был опенсорсным до 2010 года.
Кажется, так думаю не только я:
Ошибки сложно признавать, и они лучше понятны в историческом контексте. С самого начала огромной ошибкой для F# было то, что ни .NET, ни язык не были опенсорсными и не использовали открытой разработки. Эту ошибку хорошо понимали основные контрибьюторы, и многие люди в Microsoft призывали перейти на опенсорс. Если говорить просто, инновационный язык развивался в исследовательской лаборатории компании, которая ещё не была готова принять опенсорс: участники делали всё возможное благодаря периодической публикации исходников, а в конечном итоге проблема была решена переходом на опенсорсную разработку в 2011-2014 годах. Осознание этой ошибки — вероятно, самый важный шаг в истории языка. F# способен был развиваться в 2002-2011 годах, несмотря на закрытую разработку, в основном благодаря признанию его полезных качеств ответственными лицами в Microsoft.
– Дон Сайм, The Early History of F#
Изучать OCaml точно не очень сложно, но я думаю, что людям, желающим научиться какому-нибудь диалекту ML, будет проще с F#. И, как я говорил выше, его будет проще протолкнуть в «продакшен».
Мне кажется, любой, имеющий опыт в .NET, выиграет от изучения F#. А тот, кто хочет больше использовать возможности семейства ML-языков, определённо должен задуматься о F#, это отличный язык сам по себе, дающий вам доступ к одной из самых мощных платформ программирования.
И давайте не будем забывать о Fable, благодаря которому можно использовать F# в средах выполнения JavaScript, Dart, Rust и Python!
Итак, зачем же выбирать F#? В сообществе F# есть поговорка: «»F» в слове F# обозначает «Fun»». Судя по моему очень кратковременному опыту работы с F#, это правда! Более того, я считаю, что F# и по-настоящему fun, и по-настоящему практичный!
Кроме того, если ваш код компилируется, то он с большой вероятностью будет работать, как задумано. Я слышал, что такое обычно приветствуется в мире программирования!
Вот и всё, что я хотел сказать.
Что дальше?
Если вам нужны другие аргументы для изучения F#, то крайне рекомендую следующие ресурсы:
-
F# Code I Love (доклад Дона Сайма)
«The Early History of F#», которую я часто цитировал — тоже настоящее золото!
Также стоит подписаться на Reddit языка F# и присоединиться к Discord F#.
-
У меня были курсы по C# в университете и я написал свой диплом бакалавра на C#. Это был переписанный pacman для Arch Linux, работающий в Mono. Произошло это в 2007 году.
ссылка на оригинал статьи https://habr.com/ru/articles/897504/
Добавить комментарий