这种声明式 I/O 方法有什么问题(如果有的话)
我不确定这在多大程度上属于“编程”而不是“程序语言设计”。但问题是这样的:
比如说,为了简单起见,我们有两个“特殊”列表/数组/向量/任何我们为简单起见而称之为“端口”的东西,一个名为 stdIn
,另一个名为 stdOut
。这些在概念上分别表示
- 在程序持续时间内给予程序的所有用户输入在程序
- 持续时间内写入终端的所有输出
在受 Haskell 启发的伪代码中,应该可以创建这个完全声明性的程序
let stdOut = ["please input a number",
"and please input another number",
"The product of both numbers is: " ++ stdIn[0] * stdIn[1]]
:会做预期的事情,要求两个数字,然后打印他们的产品。诀窍在于 stdOut 表示程序完成时写入终端的字符串列表,而 stdIn 表示输入字符串列表。为了简单起见,键入错误以及需要某种保护措施才能在输入新行后仅打印下一行的事实在这里被保留,解决这个问题可能很容易。
那么,在我开始实施这个想法之前,我是否忽略了其中的任何陷阱?我不知道已经存在类似的构造,因此不考虑到我忽略的一个明显的陷阱是天真的。
否则,我当然知道:
let stdOut = [stdIn[50],"Hello, World!"]
如果这些结果需要以与上面类似的方式交织在一起,那将是一个错误。
I'm not sure exactly how much this falls under 'programming' opposed to 'program language design'. But the issue is this:
Say, for sake of simplicity we have two 'special' lists/arrays/vectors/whatever we just call 'ports' for simplicity, one called stdIn
and another stdOut
. These conceptually represent respectively
- All the user input given to the program in the duration of the program
- All the output written to the terminal during the duration of the program
In Haskell-inspired pseudocode, it should then be possible to create this wholly declarative program:
let stdOut = ["please input a number",
"and please input another number",
"The product of both numbers is: " ++ stdIn[0] * stdIn[1]]
Which would do the expected, ask for two numbers, and print their product. The trick being that stdOut represents the list of strings written to the terminal at the completion of the program, and stdIn the list of input strings. Type errors and the fact that there needs to be some safeguard to only print the next line after a new line has been entered left aside here for simplicity's sake, it's probably easy enough to solve that.
So, before I go of to implement this idea, are there any pitfalls to it that I overlooked? I'm not aware of a similar construct already existing so it'd be naïve to not take into account that there is an obvious pitfall to it I overlooked.
Otherwise, I know that of course:
let stdOut = [stdIn[50],"Hello, World!"]
Would be an error if these results need to be interwoven in a similar fashion as above.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Haskell 的早期版本中使用了类似的方法,只不过 stdin 和 stdout 通道的元素不是字符串,而是通用 IO“动作”——事实上,输入和输出被概括为“响应”和“请求”。只要两个通道都是惰性的(即它们实际上是“迭代器”或“枚举器”),运行时就可以简单地遍历请求通道,对每个请求进行操作并将适当的响应添加到响应通道上。不幸的是,该系统很难使用,因此被废弃,转而采用单子 IO。请参阅以下论文:
A similar approach was used in early versions of Haskell, except that the elements of the stdin and stdout channels were not strings but generic IO 'actions'--in fact, input and output were generalized to 'response' and 'request'. As long as both channels are lazy (i.e. they are actually 'iterators' or 'enumerators'), the runtime can simply walk the request channel, act on each request and tack appropriate responses onto the response channel. Unfortunately, the system was very hard to use, so it was scrapped in favor of monadic IO. See these papers:
您描述的方法听起来像“对话”。 Phil Wadler 和 Simon Peyton Jones 在 1993 年获奖的论文命令式函数式编程中给出了一些对话框确实不能很好地工作的例子,并解释了为什么单子 I/O 更好。
The approach you're describing sounds like "Dialogs." In their award-winning 1993 paper Imperative Functional Programming, Phil Wadler and Simon Peyton Jones give some examples where dialogs really don't work very well, and they explain why monadic I/O is better.
考虑到这个示例与您自己的示例相比,我不知道您将如何编织它们:
如果程序在输出一行(如您的示例中)或两行后提示由
stdIn[0]
表示的数字线?如果索引0
表示来自 stdin 的第 0 个输入,那么似乎需要类似于: 的内容来协调输出和输入的时间。
我喜欢你的想法。将
some_annotation
替换为您的偏好,也许类似于“同步?”我想不出一个尖锐的词来形容它。I don't see how you will weave them considering this example compared to your own:
Should the program prompt for the number represented by
stdIn[0]
after outputting one line (as in your example) or two lines? If the index0
represents the 0th input from stdin, then it seems something similar to:will be required in order to coordinate the timing of output and input.
I like your idea. Replace
some_annotation
with your preference, perhaps something akin "synchronize?" I couldn't come up with the incisive word for it.这种方法似乎是向纯 λ 演算添加 I/O 的“最明显”方法,其他人提到 Haskell 和 Miranda 已经尝试过类似的方法。
然而,我知道有一种语言,不是基于 λ 演算,仍然使用非常相似的系统:
(...)
(...)
也许您喜欢在 Lazy K 中进行一些编程?
This approach seems to be the "most obvious" way to add I/O to a pure λ-calculus, and other people have mentioned that something along those lines has been tried in Haskell and Miranda.
However, I am aware of a language, not based on a λ-calculus, that still uses a very similar system:
(...)
(...)
Perhaps you would enjoying doing some programming in Lazy K?