Почему 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
, который дает вам больше контроля и, например, позволяет явно ждать окончания графика.