提问人:fulverin 提问时间:3/20/2023 更新时间:3/24/2023 访问量:98
Javascript 和 haskell 之间的交互 (stdin/stdout)
interaction between Javascript and haskell (stdin/stdout)
问:
我有一个练习要做,其中:
- 我们需要用我们想要的任何语言编写一个程序(我选择了 Haskell), 该程序采用 stdin 并返回 stdout(以无限的 while 循环方式)。当我从终端尝试时,这部分工作正常
- 然后提供的 JS 服务器必须调用我们编写的程序,提供输入并对其输出执行某些操作。(实际上 JS 服务器应该调用调用程序的 bash 脚本,但是,我可以绕过它)这部分不起作用(服务器在与 Golang 版本交互时工作正常,但它听起来对我的 Haskell 版本没有响应)
以下是 Haskell IO 循环的简化片段:
main = do
guess_loop []
guess_loop xs = do
x <- readLn
let new_list = x:xs
putStr $ show $ doSmothing new_list
putStr "\n"
guess_loop new_list
这是与我的程序通信的片段 JS(我认为):
//executes the program with the numbers as stdin entries and saves its ouput in `output`
let output
try {
output = execSync(test_file, {
input: values_to_test,
})
} catch (err) {
res.send({ status: 500, msg: 'No file found: ' + guesser })
throw Error('No file found\n' + err)
}
let value = output.toString().split('\n')
value.pop()
let result = 0
let returning = []
let correct = 0
这是简化的工作 golang 版本片段
func main() {
reader := bufio.NewScanner(os.Stdin)
var k []float64
for reader.Scan() {
t := reader.Text()
n, err := strconv.Atoi(t)
k = append(k, float64(n))
fmt.PrintLn(do_something(k)) // return []float64
}
}
我对JS一无所知(也不需要),我知道一些golang,我正在学习haskell
实际上什么也没发生,所以没有错误可以分享。
我知道 haskell 关于 IO 的懒惰方面可能在起作用,所以我在 IO 循环(下面)之前添加了徒劳无功。hSetBuffering stdin LineBuffering hSetBuffering stdout LineBuffering
main = do
我试图将 console.log('hint') 放在 JS 代码的任何地方,以弄清楚发生了什么,但没有运气。我还制作了 haskell IO 循环以将输出写入文件,以检查它在 JS 调用时是否真的处于活动状态,并且确实如此。
我的直觉告诉我,这两者之间有些不对劲try { output = execSync(test_file,inputs}
PutStr result
如果你能以任何方式帮助我:发现一个明显的错误或让我走上正轨;那太好了。理想情况下,我宁愿对 haskell 做点什么,而不触及 JS 的。 如果您有任何线索,请分享。 谢谢
答:
问题可能是您的示例程序永远读取输入,当它遇到文件末尾时,它会以错误终止。Golang 版本读取输入,直到遇到文件末尾,然后正常退出。
Javascript 驱动程序似乎提供有限数量的输入,并且它会响应程序成功运行的任何失败并出现错误,忽略在程序失败之前可能产生的任何输出。values_to_test
500 No File Found
您可以尝试重写 Haskell 程序,以在循环开始时检查文件末尾:
import Control.Monad (when)
import System.IO (isEOF)
main = do
guess_loop []
guess_loop xs = do
eof <- isEOF
when (not eof) $ do
x <- readLn
let new_list = x:xs
putStr $ show $ doSomething new_list
putStr "\n"
guess_loop new_list
这可能看起来很尴尬,但随着你对 Haskell 的体验越来越丰富,你会发现编写这个程序的更自然的方式是这样的:
import Data.List
main = do
input <- getContents -- read all of stdin, lazily
let values = map read (lines input) -- read one value per line
let output = map doSomething (tail (inits values))
-- run the computation on every initial part of the list
putStr $ unlines (map show output) -- write outputs one per line
评论
interact
进一步简化。eof
评论
hFlush stdout
readLn
hSetBuffering stdout LineBuffering
hFlush stdout
let new_list :: [Int] ; new_list = x:xs
Int
readLn