|
|
1
sshine
8 年前
以下是对您编写的代码的一些反馈:
-
功能
TextIO.input1
具有类型
文本IO。流内文本。elem选项
. 当你
inspect the TextIO structure
(例如,通过书面形式
open TextIO;
在sml提示中),您将找到定义
type elem = char
. 因此,将输出视为
烧焦
而不是
一串
. 您可以使用该功能
str
的类型
字符字符串
. 但考虑使用行缓冲,因为一次读取一个字符的文件在系统调用和分配方面很昂贵。
-
我已删除
unnecessary semicolons
:后面的那些
fun
,
val
只有在REPL中需要其他声明才能立即得到结果。这个
;
表达式之间是运算符。
-
我去掉了不必要的括号。构造元组时确实需要括号(
(x,y)
)以及在声明优先级时。例如
echoFile infile (TextIO.input1 infile) (x,y)
他说
echoFile
是一个有三个参数的函数,第二个参数是
TextIO.input1 infile
文本IO。输入1填充
与
TextIO.input1(infile)
,就像你不费心写信一样
(42)
每次你有电话号码
42
.
这意味着您的
fileSubst
在这一行:
echoFile infile TextIO.input1(infile) (x,y)
因为这被解释为
echoFile文件
有四个参数:
infile
,
文本IO。输入1
,
(infile)
和
(x,y)
. 可能看起来
文本IO。输入1
和
(填充)
粘在一起是因为没有空格,但函数应用程序被认为是函数在其参数前面的定位,
不
括号的存在。此外,函数应用程序关联到左边,因此如果我们在上面的行中添加显式括号,它将变为:
(((echoFile infile) TextIO.input1) (infile)) (x,y)
为了克服左关联性,我们写道:
echoFile infile (TextIO.input1 infile) (x,y)
将其解释为(粗体括号为显式括号):
((echoFile infile)
(
文本IO。输入1填充
)
) (x,y)
-
看来你的功能
文件子集
应该替换角色的每次出现
x
与角色
y
. 我可能会称之为“文件映射”,因为它与库函数非常相似
String.map
的类型
(char–char)–string–string
. 是否保留
(x,y)
映射或
字符–字符
功能非常相似。
我可能会写一个函数
fileMap
使用类型
(char–in-stream–out-stream)
相似
一串地图
:
fun fileMap f inFile outFile =
let fun go () =
case TextIO.inputLine inFile of
NONE => ()
| SOME s => ( TextIO.output (outFile, String.map f s) ; go () )
in go () end
然后使用它,例如:
fun cat () = fileMap (fn c => c) TextIO.stdIn TextIO.stdOut
fun fileSubst pairs =
fileMap (fn c => case List.find (fn (x,y) => x = c) pairs of
NONE => c
| SOME (x,y) => y)
关于这些问题的一些想法:
-
类似函数的参数可以是
文件夹
或
文件名
,我希望在变量名称上的区别更加明确。例如。
inputFile
vs。
填充
不是为我做的。我宁愿吃。
inFile
和
filePath
.
-
函数应采用文件路径还是
河道内
,我想,这取决于你想如何创作它。所以一个非常通用的函数
文件映射
可能需要
河道内
/
扩展
,但它也可以采用文件路径。如果您正在创建这两种类型的函数,那么最好通过名称来区分它们,或者将它们分为不同的模块。
-
你可能想处理武断的
扩展
s、 不仅仅是
TextIO.stdOut
,因为你处理的是武断
河道内
s、 我也是。您可以始终使用特殊情况下的标准输入/输出,如
cat
.
-
我做了一个辅助函数,
go
在…内
文件映射
处理递归。在这种情况下,我也可以不用
文件映射
直接调用自身:
fun fileMap f inFile outFile =
case TextIO.inputLine inFile of
NONE => ()
| SOME s => ( TextIO.output (outFile, String.map f s)
; fileMap f inFile outFile )
自从
文件映射
不会在其他参数中累积任何状态。但是递归函数通常需要额外的参数来保持其状态,同时,我不想污染函数的类型签名(比如
echoFile文件
的
c
). 这是monad的一个主要用例。
而不是
的情况
在…上
List.find
,我可以使用各种库函数来处理
NONE
/
SOME
在中找到
Option
:
local
val getOpt = Option.getOpt
val mapOpt = Option.map
val find = List.find
in
fun fileSubst pairs =
fileMap (fn c => getOpt (mapOpt #2 (find (fn (x,y) => x = c) pairs), c))
end
|