[Haskell] Comportamento bizzarro, putStr vs putStrLn
Ciao 
Scorporo un pezzo di codice, semplificandolo anche, da una programma inteso per terminale.
Ok, interpretato fa quel che mi aspetto. Lo compilo (con successo)
e lo provo
niente, un rettangolino sta aspettando che io faccia qualcosa. Nel dubbio batto qualcosa
Che succede? Doveva chiedermi [tt]insert something:[/tt], invece no. Ha aspettato che io inserissi qualcosa, per poi farne la richiesta.
Allora provo ad usare [tt]putStrLn[/tt] al posto di [tt]putStr[/tt] in [tt]insertSomething[/tt] (perché non farlo?):
Intepretato fa quel che mi aspetto (va a capo ogni volta, ma fa niente) e , sorpresa!, anche da compilato:
Va bene, cosa non va in [tt]putStr[/tt]? O meglio: mi sfugge qualcosa?

Scorporo un pezzo di codice, semplificandolo anche, da una programma inteso per terminale.
-- hask.hs {- if you want to try that code by yourself, you may need to 'cabal install extra' first -} import Data.List.Extra (trim) -- force the user to type something! main :: IO () main = insertSomething >>= putStrLn . (">>> you\'ve typed: " ++) insertSomething :: IO String insertSomething = do putStr ">>> insert something: " h . trim =<< getLine where h :: String -> IO String h xs = if null xs then insertSomething else return xs
$ runghc hask.hs >>> insert something: something >>> you've typed: something
Ok, interpretato fa quel che mi aspetto. Lo compilo (con successo)
$ ghc hask.hs
e lo provo
$ ./hask
niente, un rettangolino sta aspettando che io faccia qualcosa. Nel dubbio batto qualcosa
$ ./hask something >>> insert something: >>> you've typed: something
Che succede? Doveva chiedermi [tt]insert something:[/tt], invece no. Ha aspettato che io inserissi qualcosa, per poi farne la richiesta.
Allora provo ad usare [tt]putStrLn[/tt] al posto di [tt]putStr[/tt] in [tt]insertSomething[/tt] (perché non farlo?):
-- hask.hs import Data.List.Extra (trim) -- force the user to type something! main :: IO () main = insertSomething >>= putStrLn . (">>> you\'ve typed: " ++) insertSomething :: IO String insertSomething = do putStrLn ">>> insert something: " h . trim =<< getLine where h :: String -> IO String h xs = if null xs then insertSomething else return xs
Intepretato fa quel che mi aspetto (va a capo ogni volta, ma fa niente) e , sorpresa!, anche da compilato:
$ ./hask >>> insert something: ciao >>> you've typed: ciao
Va bene, cosa non va in [tt]putStr[/tt]? O meglio: mi sfugge qualcosa?
Risposte
A me fa esattamente quello che deve... Che versione di ghc? Usi stack? Che versione?
ghc ha versione 8.6.5, versione pacchettizzata da Debian. Tieni conto però che l'ultima versione stabile è 8.10.* e vuoi che non si siano accorti di [tt]putStr[/tt] prima? Può essere.
Bello sapere almeno che per qualcuno funziona.
Può essere anche, adesso l'ho visto, questo (almeno tre anni fa), ma non so cosa sia il buffering... (non sono un informatico, né sto studiando per diventarlo...)
Non uso stack ancora.
Bello sapere almeno che per qualcuno funziona.
Può essere anche, adesso l'ho visto, questo (almeno tre anni fa), ma non so cosa sia il buffering... (non sono un informatico, né sto studiando per diventarlo...)
Non uso stack ancora.
Sembra effettivamente un problema di buffering. Significa in pratica che l'output viene scritto nel terminale tutto insieme quando inserisci un carattere di a capo (o dopo un certo numero di caratteri). Viene usato perché la stampa su terminale ha un grosso costo indipendente dal numero di caratteri stampati e si riduce quindi questo costo facendolo più raramente. Tuttavia la richiesta di input da terminale di solito causa la scrittura di tutto quello che era in attesa.
Potrebbe essere un bug di ghc o di qualche altra libreria del tuo sistema.
Potrebbe essere un bug di ghc o di qualche altra libreria del tuo sistema.
"apatriarca":
Potrebbe essere un bug di ghc o di qualche altra libreria del tuo sistema.
Ho provato cercare qualche parola chiave, e in generale si consiglia di usare [tt]hFlush[/tt]:
import Data.List.Extra (trim) import System.IO (hFlush, stdout) main :: IO () main = putStrLn . (">>> you have typed: " ++) =<< typeSomething typeSomething :: IO String typeSomething = h . trim =<< getAnswerOf ">>> type something: " where h, getAnswerOf :: String -> IO String h xs = if null xs then typeSomething else return xs getAnswerOf request = do putStr request hFlush stdout getLine
@solaàl, tu che versione di ghc hai?
The Glorious Glasgow Haskell Compilation System, version 8.10.2