14 отлични причини да използвате F #

F # е силно типизиран, функционален език за програмиране, който ви позволява да решавате сложни проблеми, като пишете прост код. Въз основа на ML и изграден върху .NET Framework, F # предлага добра оперативна съвместимост, преносимост и скорост на изпълнение, както и „Петте Cs“ - лаконичност, удобство, коректност, паралелност и пълнота.

Първоначално F # беше достъпен само за Windows като проект на Microsoft Research, но сега е първокласен език на редица платформи. Можете да използвате F # на Mac и Linux с поддръжка на инструменти в Xamarin Studio, MonoDevelop, Emacs и други; на Windows с Visual Studio, Xamarin Studio и Emacs; и на устройства с Android и iOS и в мрежата с помощта на HTML5. В допълнение към програмирането с общо предназначение, F # е приложим за GPU код, големи данни, игри и много други.

Защо да използвам F #? Позволете ми да ви дам 14 причини.

F # е интерактивен

Едно от предимствата на F # е, че има интерактивен REPL (четене, оценка, печат, цикъл), където можете да изпробвате кода, както е показано на изображението на екрана по-долу. По посока на часовниковата стрелка, горе вляво, виждаме прозорци F # Interactive от Visual Studio в Windows, от TryFSharp, работещ в Chrome, и от Xamarin Studio, работещ под Mac OS X. ;;Казва F # Interactive да оцени какво сте въвели; на TryFSharp бутонът „изпълнение“ изпраща същия сигнал. Използването на REPL за компилиране и тестване на код, преди да влезе в пълна програма, едновременно ускорява разработката и намалява грешките.

F # е за скриптове

F # може да се използва като скриптов език, както и като език за програмиране. По-долу виждаме пример на Visual Studio, в който F # скрипт зарежда четири F # програмни файла и отваря две .NET библиотеки, преди да изпълни собствения си код. [|…|]Използваната тук нотация декларира масив. Нотацията |>е тръба напред, която предава резултата от лявата страна към функцията от дясната страна. Новите редове тук не са синтактично значими. Те просто правят кода по-лесен за четене, отколкото да имат цели изрази на тръби на един ред.

F # е функционален

F # поддържа конструкции за функционално програмиране като третиране на функции като стойности, използване на неназовани функции в изрази, състав на функции за формиране на нови функции, изкривени функции и имплицитно дефиниране на функции чрез частично приложение на аргументи на функцията. В горния екран на снимката по-долу дефинираме и използваме addфункция. Тялото на функцията е с отстъп (като Python) и типовете аргументи се извеждат като цели числа поради +оператора. В долната снимка на екрана ние предоставяме анотация на типа след името на аргумента, използвайки двоеточие и име на тип, така че F # знае, че това phraseе stringтип.

F # е кратък

Кодът по-долу е подобен на Quicksort алгоритъм, внедрен във F # (от Scott Wlaschin). В recключовата дума показва, че функцията е рекурсивна. В match..withсинтаксиса е switchизявление на стероиди, с |които показват случаи. В []указва празен списък. В firstElemи otherElementsсе създават автоматично.

Имайте предвид, че няма декларации за типове, споменати никъде в кода, което означава, че функцията може да сортира списъци, съдържащи всеки тип, който поддържа оператори за сравнение. В funключовата дума е за определяне на анонимен функция ламбда.

нека rec quicksort list =

   списък с мачове с

   | [] -> // Ако списъкът е празен

        [] // връща празен списък

   | firstElem :: otherElements -> // Ако списъкът не е празен 

        нека smallElements = // извлича по-малките

            други Елементи            

            |> List.filter (забавно e -> e <firstElem)

            |> quicksort // и ги сортирайте

        let largerElements = // извличане на големите

            други Елементи

            |> List.filter (забавно e -> e> = firstElem)

            |> quicksort // и ги сортирайте

        // Комбинирайте 3-те части в нов списък и го върнете

        List.concat [по-малкиElements; [firstElem]; по-големиЕлементи]

//тест

printfn "% A" (бързо сортиране [1; 5; 23; 18; 9; 1; 3])

За сравнение, разгледайте традиционното изпълнение на C # по-долу.

публичен клас QuickSortHelper

{

   публичен статичен списък QuickSort (стойности на списъка)

      където T: IСравним

   {

      if (values.Count == 0)

      {

         връщане на нов Списък ();

      }

      // получаваме първия елемент

      T firstElement = стойности [0];

      // получаваме по-малките и по-големите елементи

      var smallElements = нов Списък ();

      var largerElements = нов Списък ();

      for (int i = 1; i <values.Count; i ++) // i започва от 1

      {// не 0!

         var elem = стойности [i];

         ако (elem.CompareTo (firstElement) <0)

         {

            smallElements.Add (elem);

         }

         друго

         {

            largerElements.Add (elem);

         }

      }

      // връщаме резултата

      var резултат = нов Списък ();

      result.AddRange (QuickSort (smallElements.ToList ()));

      result.Add (firstElement);

      result.AddRange (QuickSort (largerElements.ToList ()));

      връщане на резултат;

   }

}

Ще забележите колко допълнително качество има кодът C # в сравнение с кода F #. 

F # е наистина кратък

Според Скот Влашчин, версията на бързата сортировка, показана по-долу - и четирите й реда, има типичния кратък вид на F #, написан от опитен функционален кодер. Разбира се, той ще бъде първият, който ще изтъкне, че това не се подрежда на място. Отне ми няколко четения, за да осмисля кода, но си заслужаваше времето.

нека rec quicksort2 = функция

   | [] -> []                        

   | първо :: почивка ->

        оставете по-малко, по-голямо = List.partition ((> =) първо) почивка

        List.concat [quicksort2 по-малък; [първо]; quicksort2 по-голям]

// тест код 

printfn "% A" (quicksort2 [1; 5; 23; 18; 9; 1; 3])

Накратко, първият случай връща празен списък, ако е приет, като предоставя критерий за изход; вторият случай разделя списъка на първия елемент, а останалите, присвоявайки подсписъка, започвайки с по-малката стойност, smallerи другия подсписък larger. В рамките на конкатенацията на подсписъци функцията рекурсивно сортира smallerи largerсписъци.

F # намалява грешките чрез силно писане

За разлика от JavaScript, Ruby и Python, F # е силно написан, а не динамично въведен. За разлика от C и C ++, които също са силно набрани, но изискват всички типове да бъдат декларирани, F # извършва извод за тип, когато е възможно. Когато изводът за тип не е възможен, но типът трябва да бъде известен, компилаторът F # ще изведе грешка и ще предложи да предоставите анотация на типа, както трябваше да направим в по-ранен пример за (phrase:string)аргумента на toHackerTalkфункцията. Улавянето на несъответствие на типа по време на компилация елиминира цял клас грешки по време на изпълнение, към които са склонни динамично въведените езици.

Между другото, F # letобвързванията са неизменни, освен ако не ги декларирате специално mutable.

F # има голям, добре подбран набор от обекти, включително Списък, Низ и Масив

Както можете да видите от IntelliSense по-долу, F # има богати списъчни, низови и масивни модули, базирани на .NET Framework. В това отношение той е и обектно-ориентиран език, въпреки че е преди всичко функционален език. Забележете, че няма значение дали използвате името на модула или въведеното име на променлива - когато добавите точката, членовете ще изскачат. Някои хора твърдят, че изричното използване на името на модула е по-добър стил за функционален език от пунктираните променливи, но не купувам напълно този аргумент.

F # е полезен за MapReduce

MapReduce е ефективен двустепенен процес, често използван за големи данни и изрично поддържан в Hadoop. В този пример за F # ние картографираме и намаляваме списък с цели числа. Първо филтрираме списъка до четни числа, след това удвояваме всяко число и накрая вземаме сумата от всички елементи в списъка, за да обобщим или намалим резултата. List.mapе мощна функция от по-висок ред; функция от по-висок ред е тази, която приема друга функция като аргумент. В допълнение към списъци и масиви, F # поддържа записи, последователности, доставчици на тип данни и LINQ (езиково интегрирана заявка).

F # има записи

Записите F # представляват прости съвкупности от наименовани стойности, по избор с членове. В примера по-долу първо дефинираме тип Bookзапис с четири именувани стойности и след това създаваме запис, използвайки същите четири имена. Компилаторът F # правилно извежда Bookтипа чрез съвпадение на имената.

Записите F # могат да имат незадължителни стойности

Записите не винаги трябва да включват всичките им именувани стойности. Ако дадете име на стойност на optionатрибута, когато дефинирате типа, тогава той може да бъде оставен извън записа. Когато зададете незадължителна стойност, тя може или да бъде None, която завършва като a null, или може да бъде Someпоследвана от стойността, която искате да зададете. Записните полета се различават от класовете по това, че автоматично се излагат като свойства. Класовете и структурите във F # са .NET класове и структури, съвместими с C # и Visual Basic .NET, така че ще се откажа от примерите.

F # има последователности

Последователността във F # е логическа поредица от елементи, всички от един тип. Поредиците са особено полезни, когато имате голямо, подредено събиране на данни, но не е задължително да очаквате да използвате всички елементи. Отделните елементи на последователността се изчисляват само според изискванията, така че една последователност може да осигури по-добра производителност от списък в ситуации, в които не се използват всички елементи. В Seqмодул осигурява подкрепа за манипулации, включващи последователности. На изображението по-долу демонстрираме прости последователности, последователности с изрази и последователности с филтри.

F # поддържа доставчици на данни и LINQ

По-долу използваме редактора TryFSharp, за да отворим онлайн набор от метеорологични данни на Freebase и да поискаме доставчика на данни за циклони, които са регистрирали най-високите стойности на вятъра. В query { }инвентара синтактични LINQ за F #. Използването на тази DLL е специфично за TryFSharp. В Visual Studio бихте open Microsoft.FSharp.Data.TypeProvidersизползвали съответната услуга на доставчик на данни и след това.

Резултатът:

 [Hurricane Andrew; Hurricane Hugo; 1900 Galveston hurricane;

   Tropical Storm Allison; Cyclone Tracy; Hurricane Iniki; Hurricane Ivan;

   1999 Odisha cyclone; Hurricane Katrina; Typhoon Talim; Hurricane Rita;

   Typhoon Herb; Hurricane Wilma; Typhoon Vera; 1962 Pacific typhoon season;

   Typhoon Ike; Typhoon Mireille; Typhoon Babe; Tropical Storm Arlene;

   Hurricane Irene; Typhoon Zeb; Typhoon Maemi; Typhoon Bess; Typhoon Chanchu;

   Typhoon Patsy; Typhoon Ewiniar; Hurricane Ioke; Typhoon Xangsane;…

F # може да анализира данните на Hadoop

В този пример използваме редактора TryFsharp, за да отворим екземпляр на Hadoop Hive, който съдържа, наред с други набори от данни, измервания на характеристиките на цветя на ириса, заедно с анотации на мерни единици. Съответно сме разрешили използването на единични анотации в свойствата на HiveTypeProvider.

Това изчисление връща:

val avgPetalLength : float = 0.0374966443

F # прави съвпадение на шаблона

Изразът F # matchосигурява контрол на разклоняване, който се основава на сравнението на израз с набор от модели. Редове 1-7 от примера по-долу дефинират рекурсивна isPalindromeфункция. Редове 8-10 дефинират функция за обвивка, isPalindromeкоято я извиква за първи път, използвайки целия низ. Тъй като „аба“ е палиндром, thenклаузата на ред 9 се задейства и връща Some s, а matchизявлението в ред 11 генерира „низът аба е палиндром“. Редът _ pattern14 е случаят по подразбиране.

В match..|изявление в F # има много предимства над switch..caseизявление в C #, C ++ и Java, най-важната от които е, че тя води до по-малко грешки.

F # поддържа асинхронни работни потоци

F # има достъп до цялата .NET Framework, но има и собствен синтаксис за асинхронни работни потоци. В async { expression }синтаксис определя без блокиране на изчисление. В do!ключова дума извършва асинхронен работа и чака за резултата. На let!чака за ключови думи в асинхронен експлоатация и правоприемници на резултата. И use!изчаква асинхронна операция, присвоява резултата и освобождава ресурса. Async.RunSynchronouslyизпълнява асинхронна операция и чака нейния резултат. За да добавите паралелизъм, използвайте Async.Parallelфункцията, която взема списък на Asyncобектите, настройва кода за всеки Asyncобект на задачата да се изпълнява паралелно и връща Asyncобект, който представлява паралелното изчисление. След това насочете резултата към Async.RunSynchronously. (Примерът по-долу е отF # за забавление и печалба .)

F # ресурси

За повече информация относно F #, следвайте връзките по-долу.

  • Опитайте F #
  • F # за забавление и печалба
  • F # Езиков справочник
  • Функционално програмиране в реалния свят
  • F # книги за Amazon
  • F # 3 Бяла книга
  • Допълнителни препратки