[F#] Простые вопросы

 
0
 
Functional languages
ava
laMer007 | 27.12.2011, 21:16
Мне нравится F#. Но большой практики написания программ на нём не было. Писал только вспомогательные тулзы для проектов.

В этой теме хочу задавать вопросы по этому языку.


И так, первые вопросы:
1)Есть ли в F# функция высшего порядка, подобная std::find_if?
2)Как из тела цикла возвращать значение, если искомый результат обнаруживается в конце или в середине цикла?
Пример, когда результат обнаруживается в конце цикла:
let num n = 
  let t = [|for i in 1..n -> i*2|]
  t.[t.Length-1]
System.Console.Write(num 5)

(Понятно, что тут должен быть поиск в каком-нибудь массиве, но это просто пример).
3)Как правильно получить последний элемент массива, не используя такую убогую конструкцию t.[t.Length-1]?
4)Как вы возвращаете значение из сложной функции с несколькими циклами и ветвлениями, ведь return нет в языке? Мне приходилось делать хак в виде присвоения мутабильной переменной result результата с последующим киданием исключения и отловом около последней строки функции, возвращающей этот сохраненный ранее result. Простите, мой испорченный императивными языками стиль программирования. Как сделать возврат значения из относительно сложной функции правильно по функциональному?
Comments (7)
ava
k0rvin | 27.12.2011, 21:40 #
Цитата (laMer007 @ 27.12.2011,  20:16)
1)Есть ли в F# функция высшего порядка, подобная std::find_if?

наверное этот ответ(как и другие) легко найти в описании языка, впрочем можно и самому написать, заодно и попрактиковался бы

let rec find_if predicate xs =
    match xs with
    | [] -> None
    | hd::tl ->
        match predicate hd with
        | true  -> Some(hd)
        | false -> find_if predicate tl

как же ты писал тулзы для проектов?
ava
laMer007 | 28.12.2011, 01:07 #
Цитата ('k0rvin')
этот ответ легко найти в описании языка 
Не, не легко. Я думаю, в F# обобщённых функций в стандартной библиотеке нет. Про Array.find я знаю. Вы для List свой велосипед написали, но для него такая функция тоже есть. Но это все не то.

Ладно. А что с другими вопросами 2-4? Если они не очень понятны, то я могу объяснить подробнее с конкретными примерами.
ava
k0rvin | 28.12.2011, 08:43 #
Цитата (laMer007 @ 28.12.2011,  01:07)
Не, не легко. Я думаю, в F# обобщённых функций в стандартной библиотеке нет. Про Array.find я знаю. Вы для List свой велосипед написали, но для него такая функция тоже есть. Но это все не то.

что значит "не то"? и что ты подразумеваешь под обобщенными функциями?
ava
k0rvin | 28.12.2011, 09:11 #
3) опять же, ищите или пишите функцию last

added later:
2,4) думаю смотреть нужно в сторону продолжений (continuations), как-то так
ava
laMer007 | 28.12.2011, 14:12 #
Цитата (k0rvin @  28.12.2011,  08:43 findReferencedText)
что значит "не то"? и что ты подразумеваешь под обобщенными функциями? 

Пример:
auto pred=[](int v){return v%4==0;};

int main(void)
{
  int ca[]={1,2,3,7,4,6};
  array<int,6> a={{1,8,3,4,4,6}};
  vector<int> v={1,2,2,4,44,6};
  list<int> l={1,2,8,4,7,6};
  deque<int> d={1,3,3,8,5,6};
  cout<<*find_if(begin(ca), end(ca), pred)<<endl;
  cout<<*find_if(begin(a), end(a), pred)<<endl;
  cout<<*find_if(begin(v), end(v), pred)<<endl;
  cout<<*find_if(begin(l), end(l), pred)<<endl;
  cout<<*find_if(begin(d), end(d), pred)<<endl;
Как видите функция std::find_if работает для любого типа контейнера и всегда тип контейнера можно поменять без необходимости каких либо изменений в коде. В F# же приходится, например по всему коду заменять Array.find на List.find, если поменял тип контейнера с массива на список.


Цитата (k0rvin @  28.12.2011,  09:11 findReferencedText)
опять же, ищите или пишите функцию last
Не нашёл такой функции что-то для массивов. Понятно, что всё можно написать самому, но наиболее приятно пользоваться языком, если такие мелочи, как last есть в стандартной библиотеке.


Цитата (k0rvin @  28.12.2011,  09:11 findReferencedText)
2) думаю смотреть нужно в сторону продолжений (continuations) 

Спасибо:
let findModM arr n = seq{ for i in arr do if i%n=0 then yield i}
System.Console.Write(findModM [1..50] 5 |> Seq.head)
Лучше не написать?


Цитата (k0rvin @  28.12.2011,  09:11 findReferencedText)
4) думаю смотреть нужно в сторону продолжений (continuations) 

А можете накатать примерчик решения 4го вопроса, пожалуйста?
ava
k0rvin | 28.12.2011, 14:42 #
Цитата (laMer007 @ 28.12.2011,  14:12)
Пример:
auto pred=[](int v){return v%4==0;};



int main(void)

{
   int ca[]={1,2,3,7,4,6};
   array<int,6> a={{1,8,3,4,4,6}};
   vector<int> v={1,2,2,4,44,6};
   list<int> l={1,2,8,4,7,6};
   deque<int> d={1,3,3,8,5,6};
   cout<<*find_if(begin(ca), end(ca), pred)<<endl;
   cout<<*find_if(begin(a), end(a), pred)<<endl;
   cout<<*find_if(begin(v), end(v), pred)<<endl;
   cout<<*find_if(begin(l), end(l), pred)<<endl;
   cout<<*find_if(begin(d), end(d), pred)<<endl;
Как видите функция std::find_if работает для любого типа контейнера и всегда тип контейнера можно поменять без необходимости каких либо изменений в коде. В F# же приходится, например по всему коду заменять Array.find на List.find, если поменял тип контейнера с массива на список.

а, ты про это... это не "обобщенная функция", ну да не суть. я не знаю как там в F#, но наверное типы Array и List наследуются от одного какого-то общего предка Container или Collection, в котором определена find. иначе придется писать свои обертки.

мб просто преобразовывать в Sequence и юзать Seq.find

added later:
Цитата (laMer007 @ 28.12.2011,  14:12)
Не нашёл такой функции что-то для массивов. Понятно, что всё можно написать самому, но наиболее приятно пользоваться языком, если такие мелочи, как last есть в стандартной библиотеке.

а зачем раздувать стандартную библиотеку кучей мелочей? может быть у майкрософт есть набор дополнительных библиотек, где собраны различные полезные утилиты, не вошедшие в стандартную?

Цитата (laMer007 @ 28.12.2011,  14:12)
Лучше не написать?

А можете накатать примерчик решения 4го вопроса, пожалуйста?

хз, я не шарю в F#
ava
Kakadu | 28.12.2011, 15:29 #
Цитата


1)Есть ли в F# функция высшего порядка, подобная std::find_if?


Нет, для каждого контейнера (array, list, seq, etc) надо реализовывать свой поиск. естественно, желательно с той же сигнатурой. Тогда типовыводилка тип выведет и будет визуально как в плюсах.
Цитата


2)Как из тела цикла возвращать значение, если искомый результат обнаруживается в конце или в середине цикла? 

Пример, когда результат обнаруживается в конце цикла:

let num n = 
   let t = [|for i in 1..n -> i*2|]
   t.[t.Length-1]

System.Console.Write(num 5)


(Понятно, что тут должен быть поиск в каком-нибудь массиве, но это просто пример).


Про yeild_return для Ocaml в блоге JaneStreet Capitals
Цитата


3)Как правильно получить последний элемент массива, не используя такую убогую конструкцию t.[t.Length-1]?


Думаю так и получать. Но мне ни разу это пока не пригождалось. можно ещё List.reverse + List.head
Цитата
4)Как вы возвращаете значение из сложной функции с несколькими циклами и ветвлениями, ведь return нет в языке? Мне приходилось делать хак в виде присвоения мутабильной переменной result результата с последующим киданием исключения и отловом около последней строки функции, возвращающей этот сохраненный ранее result. Простите, мой испорченный императивными языками стиль программирования. Как сделать возврат значения из относительно сложной функции правильно по функциональному?


кидание исключений в Ocaml это норм, в диезе думаю тоже. Мутабельное значение иногда некрасиво. Ну и про yeild_return можно подумать.
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
advanced
Submit