Почему gnuplot plot не получает полный stdin от getContents?

У меня проблема с ленивым IO, но я не знаю, как это исправить.
У меня есть три небольшие тестовые программы, но V2 - это то, что я действительно хочу.
Где-то кажется, что либо getContents рано останавливается, либо gnuplot заканчивает писать рано.

Суть вопроса в том, "как я могу взять что-то из stdin и построить его с помощью gnuplot здесь", но я также хотел бы знать, как отладить основную проблему.

Версия 1, не связанная с gnuplot. Бежать с paste <(seq 10000) <(seq 10000) | runhaskell /tmp/hasktest2.hs, распечатывает (10000.0,10000.0) как и ожидалось. Ясно, что все stdin загружен.

import Data.List
main = do
  contents <- getContents
  print . last . map f . lines $ contents

f :: String -> (Double, Double)
f s = (read x, read y)
  where
    [x,y] = words s

V2: Попытка построить все, что исходит от стандартного ввода. Это выполняется так же, как V1 - временный файл, который создает gnuplot, усекается, поэтому я не получаю заговор. Однако, если я запускаю с 1000 вместо 10 КБ, это работает - в какой-то момент оно усекается при записи файла gnuplot csv, поэтому у меня есть строка, которая выглядит следующим образом 1767.0, 1767 без \n,

main = do
  contents <- getContents
  plotPathStyle [] (PlotStyle Points (DefaultStyle (1))) . map f . lines $ contents

f :: String -> (Double, Double)
f s = (read x, read y)
  where
    [x,y] = words s

V3: Просто для того, чтобы проверить, что gnuplot может обработать 10 тыс. Точек, и записать их в файл - это, как и ожидалось, дает график.

import Graphics.Gnuplot.Simple

main = plotPathStyle [] (PlotStyle Points (DefaultStyle (1))) (zip [1..10000] [1..10000] :: [(Double, Double)])

1 ответ

Решение

Это очень сильно зависит от состояния гонки, что вы в итоге получите, и получите ли вы заговор вообще.

Функция plotPathStyle разветвляется новая нить на Haskell, в которой gnuplot называется. Этот поток использует список, который вы передаете, поэтому, если список получен с помощью ленивого ввода-вывода, только этот поток будет фактически читать файл. Функция plotPathStyle немедленно возвращается более или менее, и в конце основного потока программа закрывается.

Таким образом, в зависимости от того, как происходит планирование, вы можете увидеть усеченный вывод или окно gnuplot вообще. (Если я на самом деле скомпилировать программу, а не вызывать через runhaskellЯ обычно не получаю никакого заговора.) Даже форсирование списка не спасет вас от этого условия. Если вы хотите неинтерактивное использование (т. Е. Не из GHCi), кажется, что gnuplot Пакет рекомендует интерфейс в Graphics.Gnuplot.Advanced, который дает вам больше контроля и, например, позволяет явно ждать окончания графика.

Другие вопросы по тегам