LINUX.ORG.RU
решено  
JackYF

[ФП] пример работы с файлами?


0

0

Есть известная поговорка, что на функциональных языках красиво пишутно две программы: вычисление чисел фибоначчи и сортировка.

Я уверен, что ФП-ники с этим не согласны, но не видел примеров, собственно, программ. Кто-нибудь может дать ссылку на или написать коротенькую программу на любом функциональном ЯП на базовую работу с файлами (типа: вывести в файл abc.dat список всех файлов в текущем каталоге, имя которых заканчивается на '.so'). Желательно, с обработкой ошибок.

Спасибо.


[#]  
AITap
#!/usr/bin/perl
use warnings;
use strict;

open LIST,">","abc.dat" or die "abc.dat: $!\n";
for (glob "*.so") {
print LIST "$_\n";
}
close LIST or die "abc.dat: $!\n";

В случае юникодных имён файлов может ругаться на wide charachter in print, это не смертельно и лечится open LIST,">:utf8","abc.dat".

***** ()
[#]  
Rastafarra

> вывести в файл abc.dat список всех файлов в текущем каталоге, имя которых заканчивается на '.so'

бугага.

 ls | grep \.so$ | sort > abc.dat [\code]

и скажи еще что это не функционально ;) 
**# ()
[#] Ответ на: комментарий от jtootf 30.08.2010 16:24:20  

Глупость функциональщиков, да? На поцвставленный вопрос то никто конкретно не ответил. Где код на какацкеле, который был бы короче вышеприведенного императивного кода на bash?!?

anonymous ()
[#] Ответ на: комментарий от AITap 30.08.2010 16:11:54  
JackYF

Перл - не функциональный язык.

*** ()
[#] Ответ на: комментарий от Rastafarra 30.08.2010 16:14:04  
JackYF

>и скажи еще что это не функционально ;)

Скажу. Bash - императивный язык.

*** ()
[#] Ответ на: комментарий от anonymous 30.08.2010 16:33:57  
GotF

>> короче вышеприведенного императивного кода на bash

В каком месте он на bash? ls, grep и sort уже стали командами bash?

***** ()
[#] Ответ на: комментарий от anonymous 30.08.2010 16:33:57  

(grep-all-so-files-to-abc-dat)

anonymous ()
[#] Ответ на: комментарий от JackYF 30.08.2010 16:37:27  
Rastafarra

ты нормальный, не? :)

покажи, где там императивщина?

**# ()
[#] Ответ на: комментарий от jtootf 30.08.2010 16:24:20  
JackYF

>http://book.realworldhaskell.org/read/systems-programming-in-haskell.html

Много букв, в середине есть большой исходник с IO, почти без обработки ошибок.

>http://www.haskell.org/haskellwiki/Tutorials/Programming_Haskell/String_IO


Обработки ошибок нет совсем.

> http://www.haskell.org/tutorial/io.html


Здесь, по большому счёту, тоже.

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

*** ()
[#] Ответ на: комментарий от Rastafarra 30.08.2010 16:40:56  
JackYF

>покажи, где там императивщина?

Я просил программу на ФП. Ты мне привёл вызов императивных программ из императивного языка.

*** ()
[#] Ответ на: комментарий от GotF 30.08.2010 16:37:30  
annulen

>В каком месте он на bash?

От баша здесь разрыв строки в качестве управляющего символа )

** ()
[#] Ответ на: комментарий от JackYF 30.08.2010 16:47:05  
jtootf
>>-----Цитата---->>

Здесь, по большому счёту, тоже.

<<-----Цитата----<<

раздел 7.3, не?

***** ()
[#] Ответ на: комментарий от JackYF 30.08.2010 16:47:05  
main = (readFile "input.txt" >>= writeFile "output.txt") `catch` (\_ -> print "wtf?")
anonymous ()
[#] Ответ на: комментарий от JackYF 30.08.2010 16:48:39  
Rastafarra

> вызов _императивных_ _программ _

wtf??? :)

**# ()
[#] Ответ на: комментарий от jtootf 30.08.2010 16:49:24  
JackYF

>смотри раздел I/O Exceptions:

>http://book.realworldhaskell.org/read/error-handling.html


Извини, я хочу конкретный маленький исходник, а не общие принципы. Я хочу увидеть примитивную, но законченную программу.

*** ()
[#] Ответ на: комментарий от jtootf 30.08.2010 16:52:19  
JackYF

>раздел 7.3, не?

Мм, да, в конце раздела теперь заметил. Но: что напечает строка

catch getLine'' (\err -> return ("Error: " ++ show err))

если, скажем, read(2) свалится с EIO? Или EINTR? Это мне интереснее всего.

*** ()
[#] Ответ на: комментарий от Rastafarra 30.08.2010 17:03:32  
JackYF

>> вызов _императивных_ _программ _

> wtf??? :)


Программ, написанных на императивных языках. Self-fix.

*** ()
[#] Ответ на: комментарий от anonymous 30.08.2010 16:54:07  
JackYF

>main = (readFile "input.txt" >>= writeFile "output.txt") `catch` (\_ -> print "wtf?")

Обработка ошибок включает в себя вывод человекочитаемой (или хотя бы машиночитаемой) информации, при работе с каким файлом произошла ошибка и какая именно ошибка.

*** ()
[#]  
unC0Rr
import System.Directory import Data.List

main = getDirectoryContents "." >>= writeFile "abc.dat" . unlines . filter (\a -> ".so" `isSuffixOf` a)

без обработки ошибок

*** ()
[#] Ответ на: комментарий от unC0Rr 30.08.2010 17:20:17  
JackYF

> main = getDirectoryContents "." >>= writeFile "abc.dat" . unlines . filter (\a -> ".so" `isSuffixOf` a)

Спасибо.

*** ()
[#] Ответ на: комментарий от JackYF 30.08.2010 17:25:15  

[code]main = (readFile "input.txt" >>= writeFile "output.txt") `catch` print[/code]

anonymous ()
[#] Ответ на: комментарий от JackYF 30.08.2010 16:37:27  
Waterlaz

>Скажу. Bash - императивный язык.

Ну... а вот пиведеный код весьма функционален =)

** ()
[#] Ответ на: комментарий от anonymous 30.08.2010 17:34:14  
JackYF

>[code]main = (readFile "input.txt" >>= writeFile "output.txt") `catch` print[/code]

Гм, что напечает эта программа, если input.txt запрещён для чтения?

*** ()
[#] Ответ на: комментарий от Waterlaz 30.08.2010 17:38:11  
JackYF

>Ну... а вот пиведеный код весьма функционален =)

Ну, всё же не Bash меня сейчас интересует :)

*** ()
[#] Ответ на: комментарий от JackYF 30.08.2010 17:40:47  
Waterlaz
>>-----Цитата---->>

>

main = (readFile "input.txt" >>= writeFile "output.txt") `catch` print

Гм, что напечает эта программа, если input.txt запрещён для чтения?

<<-----Цитата----<<

Что-то в духе..

$ runhaskell tst.hs
input.txt: openFile: permission denied (Permission denied)
** ()
[#] Ответ на: комментарий от JackYF 30.08.2010 17:40:47  
unC0Rr

> Гм, что напечает эта программа, если input.txt запрещён для чтения?

input.txt: openFile: permission denied (Permission denied)
*** ()
[#] Ответ на: комментарий от Waterlaz 30.08.2010 17:54:41  
JackYF

> input.txt: openFile: permission denied (Permission denied)

О! Вот это то, что я хотел увидеть.

Открытым остаётся вопрос организации более сложной обработки (допустим, мы делаем fork(), и на EAGAIN нужно не закрыться с ошибкой, а подождать 5 секунд и попробовать ещё раз), но общая картина прояснилась, спасибо приславшим свои варианты.

*** ()
[#] Ответ на: комментарий от JackYF 30.08.2010 18:03:21  
dave

Используй окамл.

***** ()
[#] Ответ на: комментарий от Rastafarra 30.08.2010 16:14:04  

>[code=bash] ls | grep \.so$ | sort > abc.dat [\code] и скажи еще что это не функционально ;)

Ф-но. Но аж 2 ошибки.

***** ()
[#] Ответ на: комментарий от Rastafarra 30.08.2010 16:40:56  

Это ты ненормальный. Есть сайд-эффект, устанавливается значение переменной окружения "$?".

anonymous ()
[#] Ответ на: комментарий от DonkeyHot 30.08.2010 20:36:58  

>аж 2 ошибки

А посмотришь - даже 3.

***** ()
[#] Ответ на: комментарий от unC0Rr 30.08.2010 17:20:17  

Это безобразно, ящитаю. Какацкель в очередной раз сливает даже перлу с башем.

anonymous ()
[#] Ответ на: комментарий от anonymous 30.08.2010 20:40:38  

>в очередной раз сливает даже перлу с башем

Не согласен. В приведённом реешнии "import"ы сойдут за пропущеный в bash-варианте PATH=, отсутствие которого в скрипте можно считать четвёртой ошибкой. Лямбда там не нужна, можно «... filter (isSuffixOf ".so")», т.ч. если дождёмся исправленого башевского варианта, он может оказаться не сильно лучшим.

***** ()
[#] Ответ на: комментарий от Rastafarra 30.08.2010 20:51:48  

>не вижу багфикса

Это же ты вызвался башлить :)

***** ()
[#] Ответ на: комментарий от anonymous 30.08.2010 20:38:36  
Rastafarra

> Есть сайд-эффект

ну... без них даже IO не работает, да? :)

**# ()
[#] Ответ на: комментарий от Rastafarra 30.08.2010 21:00:03  

>"у меня все работает"

Эка невидаль. Мои скрипты тоже все в некоторых условиях работают.

***** ()
[#]  
pavel38
#!/bin/bash
for i in *.so ; do [[ -f $i ]] && echo "$i" >> abc.dat ; done

не?

()
[#] Ответ на: комментарий от DonkeyHot 30.08.2010 20:56:28  

>> аж 2 ошибки

> А посмотришь - даже 3.

Почему не 300? А лучше 300!

***** ()
[#] Ответ на: комментарий от JackYF 30.08.2010 16:48:39  
vertexua

Так сильно не понимать что такое ФП...

*** ()
[#]  
vertexua
package scalaapp1

import java.io._;

object Main {

  def main(args: Array[String]): Unit = {
    var k = new PrintWriter(new FileOutputStream("abc.dat"))
    
    k.println(
        new File(".").
        listFiles.
        filter({_.isFile}).
        filter({_.getName.toLowerCase.endsWith(".so")}).
        foldLeft("")((A,B)=>A+B+"\n")
      )
    
    k.close()
  }

}

Более функционально на Scala нельзя, потому что без явного close ничего не записывает.

*** ()
[#] Ответ на: комментарий от vertexua 30.08.2010 23:50:41  
vertexua

Чуть красивее

toFile("abc.dat"){
      new File(".").
      listFiles.
      filter({_.isFile}).
      filter({ _.getName.toLowerCase.endsWith(".so")}).
      foldLeft("")((A,B)=>A+B+"\n")
}

но необходим все тот же костыль

def toFile(s:String)(f: =>String){
    var k = new PrintWriter(new FileOutputStream(s))
    k.println(f)
    k.close()
  }

*** ()
[#] Ответ на: комментарий от DonkeyHot 30.08.2010 20:40:34  
balodja

Первая -- неэкранированный $, вторая -- sort без -. А третья какая?

*** ()
[#] Ответ на: комментарий от balodja 31.08.2010 0:53:51  
balodja

А, вижу, обратный слеш один вместо двух.

*** ()
[#] Ответ на: комментарий от balodja 31.08.2010 0:53:51  
balodja

Хм, даже в POSIX'е sort без указанных файлов берет ввод из stdin, так что отсутствие - -- это не ошибка. Где же тогда третья?

*** ()