Пользователь
0,0
рейтинг
1 апреля 2011 в 15:55

Разработка → Введение в F#, или полезное о бесполезном из песочницы

.NET*

Вступление



А зачем оно мне?

image

А почему бы и нет? К примеру, для общего развития, или просто для интереса, а впоследствии, может быть, для того, чтобы убедиться, что F# — не просто язык для ознакомления.

И что дальше?

image

А дальше я, пожалуй, начну. F# — мультипарадигменный язык, корни которого растут от OCaml, который смешивает в себе функциональную, императивную и объектно-ориентированную парадигмы, что, собственно, и является одним из его самых больших плюсов. Еще один плюс — это интеграция с .NET Framework. Еще один — то, что я постараюсь долго не расписывать как все это круто и удобно и перейду ближе к делу: мы получаем возможность использовать аж три парадигмы, да еще и с огромным количеством вкусностей, запакованных в коробку под названием .NET Framework. Многие задачи решаются намного проще и короче на F#, чем на том же C#, однако, справедливо и обратное.

Замечательно, ты, кажется, обещал перейти ближе к делу

image

Ну что ж, закончив классическое вступление, перейдем к классическому HelloWorld!
printfn "Hello, world!" 

Да, это все. Впечатляет? И меня нет, поэтому пойдем дальше.

Ближе к делу


Начнем мы с функциональной части F# и, пожалуй, самого главного ключевого слова: let. Служит оно, как ни странно, для определения идентификатора и его значения.
let someId = 5
// F# также поддерживает unicode имена:
let число = 1

Есть пара оговорок:
  • Идентификатор — это имя, к которому привязано какое-либо значение, причем изменить его нельзя, идентификатор можно только переопределить. С этим, кстати, можно столкнуться не только в F#, но и во всех других функциональных языках программирования.
  • Значение — это все что угодно. Функция, константное значение, другой идентификатор и все, что душе угодно, только бы возвращало значение или являлось им

Немного примеров:
// в данном случае F# автоматически определит тип идентификатора
let someFloat = 0.5

// тут мы явно указываем тип идентификатора - int
let someCalculation : int = 2 + 2

// здесь идентификатору helloWorld присвоится объединение двух строк
let someString = "Hello"
let anotherString = ", World"
let helloWorld =  someString + anotherString 

Теперь пойдем еще дальше, и пощупаем функции.
let add x y = x + y

let someFunc x y = 
    let val = x + y
    val / y

Cначала обсудим более абстрактное понятие функции в F#.
fun x y -> x + y

Это — анонимная функция, или лямбда-функция. Ее аргументы — x и y, оператор -> указывает на то, что дальше будет находится тело функции. В этом примере телом является выражение x + y, оно же будет и возвращаемым значением. Для тех, кто никогда не встречался с «лямбдами» на этот момент достаточно понимать, что у них просто-напросто нет имени. Все функции в F# так или иначе представляются в похожем виде, к примеру
let add = fun x y -> x + y

Тут можно увидеть как в F# на самом деле представляются функции: к идентификатору привязывается анонимная функция. То, что приводилось в качестве примера выше — упрощенный синтаксис.
Рассмотрим наш пример:
let add x y = x + y

Тут хотелось-бы порассуждать о типе аргументов. Дело в том, что F# автоматически определяет тип аргументов и возвращаемого значения, в данном случае аргументы могут быть любого типа, если они поддерживает операцию сложения.
let someFunc x y = 
    let val = x + y
    val / y

Тут функция имеет более сложное тело, в котором используется промежуточный идентификатор. Область видимости кода определяется его отступом, то есть идентификатор val будет виден только внутри тела функции someFunc. Возвращаемое значение — val / y

Напоследок приведу небольшой пример, который покажет как функции можно вызывать в коде:
let add x y = x + y

// 2. - то же самое, что и 2.0
let avg x y = add x y / 2.

printfn "%A" add 5. 2.

// тут будет ошибка
//printfn "%A" add "Hello" ", World!"

printfn "%A" avg 2. 10.

— Почему во втором вызове printfn будет ошибка?
— Потому что функция avg возвращает тип float.
— Почему она возвращает float?
— Потому что мы делим результат add x y на float.
— Причем здесь ошибка при попытке сложения строк?
— При том, что оба аргумента функции add имеют тип float, соответственно она возвращает float
— Как так?!
— Просто для того, чтобы avg возвращала float, надо чтобы левый и правый операнды оператора деления были типа float, вот об этом F# и позаботился, так как типы аргументов в add явно не указаны.

Надеюсь, мы не прощаемся

image
На этом заканчивается краткое выступление в F#, тут написано далеко не все, и далеко не полностью, и не без изъянов. Но, если всем понравится, то постараюсь писать дальше, больше и подробнее, ведь целью данного поста была совсем не в том, чтобы дать всеобъемлющее представление о F#, а только чуток приоткрыть дверь в мир FP, а вот зайдем мы в нее в последующих статьях.

Что почитать/посмотреть?

Для тех, у кого с английским все хорошо, можно почитать Beginning F#. Не смотря на название, книга дает достаточно глубокое представление о F# и его применениях.
Еще можно посмотреть An Introduction to Microsoft F#
А вот ссылка на RIA (спасибо ApeCoder'у), позволяющее использовать F# Interactive прямо в окне браузера.
[Следующий пост]
@kernelmode
карма
18,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (15)

  • +1
    хорошо, жаль что статья под замком, ссылку в твиттер дать не выйдет
  • +7
    вы номер поста видели?
  • +3
    юникод, это еще что — а пробелы в именах не хотите?:

    let ``хабра хабр`` = 1

    используется, например, в FsUnit чтобы давать чеговеческие имена тестам

    [<TestFixture>]
    type ``A game of bowling`` ()=
        [<Test>] member x.
         ``with simple scores should get the expected score.`` ()=
                scoreBowls [1;2;3] |> should equal 6
        
        [<Test>] member x.
         ``with a spare should get the expected score (spare).`` ()=
                scoreBowls [2;8;1] |> should equal 12
        
        [<Test>] member x.
         ``with a strike should get the expected score (strike).`` ()=
                scoreBowls [10;1;2] |> should equal 16
        
        [<Test>] member x.
         ``that is perfect should get a score of 300.`` ()=
                scoreBowls [for i in 1..18 -> 10] |> should equal 300
    
    


    • 0
      Я то думал, где можно применить данную особенность языка, а оказалось все лежит под носом. Действительно, для тестов очень удобно.
  • 0
    Еще надо обязательно дать ссылку на:
    www.tryfsharp.org/Tutorials.aspx
    чтоб можно было попробовать не отходя от кассы
  • +2
    Осмелюсь еще дать ссылку на статью про F#, которую в соавторстве писал мой коллега Максим Моисеев — fprog.ru, там немного побольше информации;)
    • 0
      Зашел в комменты давать на нее ссылку.
  • –1
    У нас в проекте в продакшене используется достаточно большой модуль, который написан целиком на F#. Модуль генерирует на лету SQL для запросов в базу на основе фильтров, которые пользователи создают. Так что совсем не бесполезный язык)
    • 0
      Согласен, просто цикл статей для всех, а многие думают, что он бесполезен, вот и решил так назвать пост.
    • 0
      А почему именно F#, в чем будет преимущество, например, перед C# для данной задачи?
  • +3
    Отступы уплыли. А они ох как важны…
  • –1
    > Идентификатор — это имя, к которому привязано какое-либо значение, причем изменить его нельзя, идентификатор можно только переопределить. С этим, кстати, можно столкнуться не только в F#, но и во всех других функциональных языках программирования.

    А Хабранарод, тем временем, продолжает настаивать что Common Lisp — функциональный…
    • 0
      Common Lisp, так же как и F# — мультипарадигменный. На самом деле в F# тоже есть способ создавать переменные:
      • 0
        let mutable a = 5
        a < — 10
        Common Lisp, согласно вики, представляет собой объединение нескольких диалектов Lisp'а. Короче, можно сделать вывод, что оба языка не pure functional.
        P.S. Про mutable не написал в этом посте, т.к. собирался рассказать о нем в последующих.
  • 0
    А для тех, у кого с русским все хорошо, порекомендую совсем недавно вышедшую книгу Криса Смита «Программирование на F#».

    Что особо ценно — очень грамотно переведена.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.