LINUX.ORG.RU

тупой вопрос про Haskell и этот его IO

 ,


0

2

изучаю ввод-вывод в Haskell.

main = do
	putStrLn "Enter a: "
	a <- readLn
	print (a + 5)
даёт, например
Enter a: 
2
7
Но вот не нравится мне перевод строки после «Enter a: ». Заменяю putStrLn на putStr:
main = do
	putStr "Enter a: "
	a <- readLn
	print (a + 5)
теперь программа не выводит «Enter a: », пока пользователь не введёт это самое a сам:
2
Enter a: 7
как это вообще может быть и как это исправить?

Ответ на: комментарий от hateyoufeel

А почему в Haskell не происходит автоматический flush при вызове readln (перед вызовом)?

Просто это единственный язык, виденный мной, с таким поведением

monk ★★★★★
()
Ответ на: комментарий от unC0Rr
#include <stdio.h>

int main()
{
    int a;
    printf("Enter a:");
    sleep(5);
    scanf("%i", &a);
    printf("%i\n", a+5);
}

При запуске строка «Enter a:» появляется через 5 секунд, значит буферизация есть. Но появляется перед тем как запросить ввод. Получается

Enter a:2
7
, а не как у ТС
2
Enter a: 7

И такое поведение во всех известных мне языках.

Получить поведение как в Haskell можно только извратившись, например:

$ cat | ./a.out 
2
Enter a:7

monk ★★★★★
()
Ответ на: комментарий от unC0Rr

А как ты определяешь, что перед тем как запросить ввод, а не после

Клавиатуру не трогаю. Через 5 секунд на экране появляется «Enter:». Если убрать sleep, то появляется сразу.

monk ★★★★★
()
Ответ на: комментарий от anonymous

Это особенность реализации

Особенность. Но общепринятая. По крайней мере точно есть в Turbo C, Turbo Pascal, Visual C, gcc.

Пишут, что уже с 1980 года была: In the Berkeley fast stdio, circa 1980, _filbuf() on any interactive input file called _flsbuf() on any interactive output file.

monk ★★★★★
()
Последнее исправление: monk (всего исправлений: 1)
Ответ на: комментарий от monk

In the Berkeley fast stdio, circa 1980, _filbuf() on any interactive input file called _flsbuf() on any interactive output file.

А как определяется, файл interactive или не interactive?

korvin_ ★★★★★
()
Последнее исправление: korvin_ (всего исправлений: 1)
Ответ на: комментарий от monk

man isatty

Какой ужас. Т.е. флушатся все открытые файловые дескрипторы, удовлетворяющие isatty, независимо от того, нужно мне это или нет? И, я так понимаю, на не-POSIX системах это не работает? А если я хочу интерактивный не-tty (псевдо)файл, то мне нужно проверять isatty и флушить или можно просто флушнуть и не важно, что чтение повторно флушнет и, раз так, то зачем мне автофлуш?

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

Какой ужас.

Похоже я получил ответ на вопрос «Почему в Haskell не так, как у всех?»

Т.е. флушатся все открытые файловые дескрипторы, удовлетворяющие isatty, независимо от того, нужно мне это или нет?

Да, все открытые на запись файловые дескрипторы, удовлетворяющие isatty.

И, я так понимаю, на не-POSIX системах это не работает?

В MS DOS/Windows работает. Для C++ включено в стандарт в слегка другой формулировке http://www.cplusplus.com/reference/ios/ios/tie/

monk ★★★★★
()
Ответ на: комментарий от korvin_

или можно просто флушнуть и не важно, что чтение повторно флушнет и, раз так, то зачем мне автофлуш

Если буфер пуст, то флуш почти мгновенен. Поэтому можно «на всякий случай», если не уверен.

monk ★★★★★
()
Ответ на: комментарий от qnikst
cat 2.hs 
import System.IO
main = do print =<< hGetBuffering stdin 
          putStr "puu"
          putStrLn =<< getLine
qnikst@localhost ~ $ ./2 
LineBuffering
^Cpuu
qnikst@localhost ~ $ runhaskell 2.hs 
LineBuffering
puu^C
qnikst ★★★★★
()
Ответ на: комментарий от qnikst

к слову в ghci/runhaskell поведение такое же как у всех

А это ещё более странно. Зачем разная семантика при тестах и в работе? Что в Racket есть «выполнение в DrRacket» и «просто выполнение», что в Haskell...

monk ★★★★★
()
Ответ на: комментарий от qnikst

ну и из документации:

The default buffering mode when a handle is opened is implementation-dependent and may depend on the file system object which is attached to that handle. For most implementations, physical files will normally be block-buffered and terminals will normally be line-buffered.

про flush при read ничего нет.

qnikst ★★★★★
()
Ответ на: комментарий от monk

мне тоже странно, но логично т.к. интерпретатор устанавливает NoBuffering на терминал (что логично с его use cases), а программа нет.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

Ghci - NoBuffering покажет

Я про это:

qnikst@localhost ~ $ runhaskell 2.hs 
LineBuffering
puu^C

Если у ghci NoBuffering, то это как раз нормально. В windows c/c++ если stdout в файл, то FullBuffering становится.

А вот разная семантика при одинаковом внутреннем состоянии программы — нехорошо.

monk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.