Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add 'eachLine' to BufferedReader #391

Open
Dierk opened this issue Jun 19, 2020 · 2 comments
Open

add 'eachLine' to BufferedReader #391

Dierk opened this issue Jun 19, 2020 · 2 comments

Comments

@Dierk
Copy link
Member

Dierk commented Jun 19, 2020

Here is a suggestion to improve the usage of the BufferedReader that does not require to read the full content but allows line-by-line processing:

-- only for testing
data StringReader = native java.io.StringReader where
    native new      :: String -> STMutable s StringReader

-- convenience output
printIOValue prefix ioValue = do  -- same as:  (prefix ++) . show <$> ioValue >>= println
    value <- ioValue
    println $ prefix ++ show value


eachLine :: Mutable s BufferedReader → a → (a → String → ST s a) → ST s a
eachLine bufferedReader value handler = do
    line <- bufferedReader.readLine
    case line of
        Nothing   -> do
            bufferedReader.close
            return value
        Just line -> do
            newValue <- handler value line
            eachLine bufferedReader newValue handler

main = do
    testFile = File.new "TestFile.txt"              -- since version 3.25, otherwise <- instead of =

    -- delete test file if it already existed
    printIOValue "Test file deleted to clean up before start: " testFile.delete

    println "create test file"
    writeFile testFile.getPath $ unlines ["first line","second line","third line"]
    printIOValue "File now exists: " testFile.exists

    println "read test file in toto"
    content <- readFile testFile.getPath
    println "file content was:"
    println content

    println "append 2 lines"
    appendFile testFile.getPath $ unlines ["fourth line","fifth line"]

    println "processing each line, while keeping track of line numbers"
    bufferedReader <- openReader testFile.getPath
    count <- eachLine bufferedReader 0 $ \num line -> do
        println $ show (num + 1) ++ ": " ++ line
        return  $ num + 1
    println $ "total number of lines: " ++ show count

    println "pushing each line on a stack"
    bufferedReader <- openReader testFile.getPath
    stack <- eachLine bufferedReader [] $ \stack line -> return (line : stack)
    println $ "total stack" ++ show stack

    println "processing each line with a non-IO impure reader, here: StringReader. (great for testing)"
    stringReader <- StringReader.new $ unlines ["first","second","third"]
    bufStrReader <- BufferedReader.new stringReader
    result <- eachLine bufStrReader 0 $ \num _ -> return  $ num + 1
    println $ "processing strings with eachLine works as expected: " ++ show (result == 3)

    println "command line input (send EOF via Cmd/Ctrl-D)"
    eachLine stdin 0 $ \num line -> do
        println $ show (num + 1) ++ ": " ++ line
        return  $ num + 1

    return ()

@Dierk
Copy link
Member Author

Dierk commented Jun 22, 2020

Hi, @Ingo60, please find my latest ideas under https://github.com/Dierk/fregeTutorial/blob/e3dc0b5e2dfc131c11dcd95be5ecd4a44eec6eef/src/main/frege/suggest/LineProducer.fr#L10
Suggestions for improvement highly welcome!

If you think this makes sense, then please give me a thumbs-up and I will add it to the stdlib with examples and test cases extra.

It requires the changes shown in line 51 and 54 (IOMutable to STMutable s for BufferedReader and FileInputStream).

@Ingo60
Copy link
Member

Ingo60 commented Jun 24, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants