Здравствуйте, <Аноним>, Вы писали:
А>Как такое реализовать на Lisp? Может кто поделится бинарником и какой рантайм и откуда скачать для Windows?
А ты возьми Nemerle. Если знаешь дотнет, то и вопросы задавать в основном не прийдется. А то с Лиспом у тебя порог вхождения будет очень высок. Придется разбираться не только с функциональным стилем и его скобками, но и с незнакомыми средами, компиляторами, библиотеками...
А тут можно с места, и как говорится, в карьер.
Код может выглядить, например, так:
using System.Console;
using Nemerle.Utility;
using System.IO;
def strToFind = "partition";
def strs = File.ReadAllLines(@"C:\boot.ini");
WriteLine($"Lines in file: $(strs.Length)");
WriteLine();
WriteLine($"Lines contained '$strToFind':");
WriteLine(strs.ToList().Filter(_.Contains(strToFind)));
ReadLine();
Рельное обеяснение тут пожалуй требует только строка:
WriteLine(strs.ToList().Filter(_.Contains("partition")));
strs.ToList() превращает массив возвращенный стандартной .net-ной фукнцией File.ReadAllLines() в список (односвязанный). Метод Filter() в соотвествии со своим именем отфильтровывает элементы списка удовлетворяющие условию. Условие передается в виде фукнции через параметр. Собственно то что можно передавать фукнции в качестве параметра — это и есть функциональный стиль. Но это можно сделать и в C# 2.0.
А вот '_.Contains(strToFind)' это пожалу самое интересное.
Это так называемое частичное применение функций, да еще и с замыканием. Этот код заменяется на создание невидимой (анонимной) функции. Эта функция захватывает переменную strToFind из контекста где она определена. Знак "_" заменяется параметром этой анонимной функции. Таким образом написав '_.Contains(strToFind)' мы получаем функцию принимающую один аргумент типа "строка" и возращающую булево выражение. То что тип аргумента строка компилятор вычисляет из контекста куда должна передаваться фукнция, а то чт возвращаемое значение должно быть булевым выясняется из возвращаемого значения функции Contains().
Это код можно переписать более явно (и естественно более громоздко):
WriteLine(strs.ToList().Filter(elem => elem.Contains(strToFind)));
данный вариант соотвествует тому что будет доступно в C# 3.0.
А чтобы код уж совсем стал похож на традиционные императивные языки можно переписать его так:
using System.Console;
using Nemerle.Utility;
using System.IO;
def strToFind = "partition";
def strs = File.ReadAllLines(@"C:\boot.ini");
WriteLine($"Lines in file: $(strs.Length)");
WriteLine();
WriteLine($"Lines contained '$strToFind':");
foreach (str in strs)
when (str.Contains(strToFind))
WriteLine(str);
ReadLine();
... << RSDN@Home 1.2.0 alpha rev. 637>>