среда, 11 марта 2009 г.

Реальное приложение на F#

В своём прошлом посте я вскользь упомянул новый функциональный язык программирования от Microsoft - F#. Он вызвал достаточно сильный интерес с моей стороны и сегодня попробую показать вам что-нибудь относительно полезное, написанное на нём. Но надо заметить, что я не знаю ни F#, ни C#, да и чего там скрывать... вообще не знаком с платформой .Net. Этот пример я взял с презентации этого языка на PDC2008 и . Несколько примеров также можно найти тут и тут. Для реализации нам понабятся Visual Studio 2008 и Microsoft F# CTP 1.9.6.2. Чтобы интегрировать F# в VS придётся проделать несложные манипуляции. В некоторых местах я буду приводить для сравнения участки кода, написанного на C#.

Ну чтож... начнём) Наша задача: получить данные с сайта и обработать их (например отобразим первый и последний столбец).

Первым делом подключим необходимые библиотеки:

open System
open System.Windows.Forms
open System.Net
open System.IO

Далее нам нужна ссылка на файл данных. Поэтому перейдём на сайт, спустимся вниз и найдём кнопку Download To Spreadsheet. Кликнем по ней правой клавишей и скопируем ссылку.

let url = "http://ichart.finance.yahoo.com/table.csv?s=MSFT&d=2&e=9&f=2009&g=d&a=2&b=13&c=1986&ignore=.csv"

- это следущая строчка, после поключения библиотек, где let фактически создаёт псевдоним выражения. Кстати тип url задавать не нужно, F# сам определяет его. В С# это будет выглять так: string url = "ссылка';

Следующим этапом будет создание веб-запроса, потока обмена данными и чтением их в строку:

let req = WebRequest.Create(url)
let resp = req.GetResponse()
let stream = resp.GetResponseStream()
let reader = new StreamReader(stream)
let csv = reader.ReadToEnd()


Аналогичные действия на С#:

WebRequest request = WebRequest.Create(url);
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
csv = reader.ReadToEnd();

Итак у нас есть последовательность с записей и нам их нужно разделить. Для этого используем функции Split, но пропустим первую строчку, т.к. там в исходном файле имена столбцов:

let prices =
csv.Split([|'\n'|])
|> Seq.skip 1
|> Seq.map (fun line -> line.Split([|','|]))
|> Seq.filter (fun values -> values |> Seq.length = 7)
|> Seq.map (fun values ->
System.DateTime.Parse(values.[0]),
float values.[6])

Здесь мы сталкиваемся с ещё 2-мя очень важными элементами F# - это fun (как можно догаться из названия задаёт функцию) и символ |> , который берёт входные данные слева от себя, производит действия и возвращает полученный результат, который может использоватться в следующей строчке с |>.

Мне удалось сделать это на C# в таком виде:

csv.Split('\n');
string [] line = str.Split('\n');
string[] elements;
for (int i = 1; i <= line.Length; i++)
{ elements = line[i].Split(','); ichTextBox1.Text = richTextBox1.Text + i + " " + elements[0] + " " + elements[5]+"\n";
}
И если мы, выделив всё написанное выше, запустим на выполнение и в F#Interactive введём prices;; , то всё будет неплохо работать, но вывод данных неочень приятен и понятен, поэтому добавим форму и таблицу:
let grid (prices:seq)=
let form = new Form(Width = 400, Height = 500, Visible = true, Text = "Prices")
let grid = new DataGridView(Width = 282, Height = 374, Visible = true)
form.Controls.Add(grid)
grid.DataSource <- prices |> Seq.to_array

Вот и всё. У меня получилась вот такая штука:



















На сегодня на этом и закончим. Если у вас есть идеи как изменить код к лучшему, то с удовольствием вас выслушаю.

Комментариев нет:

Отправить комментарий