将命令行参数写入文件

时间:2018-05-04 09:16:16

标签: command-line arguments sml smlnj

我在完成这项任务时遇到了麻烦。我们应该将命令行参数作为输入并将它们写入文件。 到目前为止,我已经完成了以下代码:

val args = CommandLine.arguments()

val a = length args;

val os = TextIO.openOut "rodr4719.txt";

TextIO.output(os, "rodr4719");


fun writeFile(os, args, a) = 


if a = -1 then

TextIO.output(os, "rodr4719")
TextIO.closeOut os
OS.Process.exit(OS.Process.success)

else

val str = nth (args, a);
TextIO.output(os, str ^"\n" );
a = a-1;
writeFile(os, args, a)
end;

writeFile(os, args, a-1)

我得到的错误是

.sml:22.1 Error: syntax error: inserting EQUALOP

1 个答案:

答案 0 :(得分:0)

这有点与以下两个Q& A的重复:

以下是一些一般性反馈:

  • 缩进:您可以通过添加缩进来使代码更具可读性。

    fun writeFile (os, args, a) = 
        if a = -1 then
            TextIO.output(os, "rodr4719")
            TextIO.closeOut os
            OS.Process.exit(OS.Process.success)
        else
            val str = nth (args, a);
            TextIO.output(os, str ^"\n" );
            a = a-1;
            writeFile(os, args, a)
    end
    

    (由于以下列举的原因,此代码仍然存在。)

  • end :当您宣布fun时,不需要此关键字。它出现在SML语法的几个地方,特别是let ... in ... end,你可能已经在那里看到了它。

  • 变量名称:我以不同的方式命名输入参数:os听起来像操作系统,当它可能是缩写时 outstream 。只需将其称为outstream即可。有些人喜欢将其称为fd以获取文件描述符,但这完全取决于对目标受众的理解。 args可能更通用:此函数可以编写任何字符串列表,而不仅仅是命令行参数。只需将其称为lines即可。 a听起来可能是任何类型,但它只是一个整数。我将其称为n,但我实际上并未使用数字来确定我的停止条件。

  • 分号:当您的函数使用副作用执行多项操作时,您可以使用;运算符。您在然后 -part中没有这样做,并且您在 else -part中做错了,因为{{1} SML中的}运算符是syntactically confusing

    简短版本:;中的分号与val foo = x; val bar = y;中的分号不同。

    如果需要分号表达式运算符,请将分号的表达式包装在括号或let-expression中。否则,它将被解释为(可选)分号声明运算符。

  • 当迭代行列表而不是保留计数器时,在列表上执行模式匹配。这大大简化了递归结束的时间,因为无论如何,您总是一次只能找到一个列表的头部。

  • 不要退出:您可能不想在完成后退出该计划;退出该功能应该足够了。这样,您可以在更复杂的控制流中重复使用该功能,而无需代表整个程序退出。

  • 打开和关闭相同范围内的文件:这是一般编程建议:当您处理副作用时,确保您不会忘记关闭你打开的东西并且你不会关闭某些东西两次,在相同的代码附近做这件事会让你更容易推理出正确性。你可以a simple function that always deals with the opening and closing

  • val foo = (TextIO.output (fd, x); TextIO.output (fd, y))在函数体内:当您需要在函数体或某个表达式中绑定临时值时,请使用val - 表达式。顺便说一句,今天有人问过Why do I use `let` and not just `val` to declare a variable inside a function in SML?

  • 不可变的值:在SML中,您无法更新类似let的值。 a = a-1不是变量,而是值绑定。您可以将其重新绑定到基于旧值的新值,从而遮蔽旧值,但这不是必需的。而是使用更新后的值执行递归调用。

我已经考虑到这些事情修改了你的程序:

a

fun writeFile (outstream, []) = () | writeFile (outstream, line::lines) = ( TextIO.output (outstream, line ^ "\n") ; writeFile (outstream, lines) ) (* Demo *) val myFile = TextIO.openOut "rodr4719.txt" val _ = writeFile (myFile, CommandLine.arguments ()) val _ = TextIO.closeOut myFile 是一种在顶级评估表达式而不直接在顶层表达式的奇特方式。在交互式REPL val _ = ...中它自己的行意味着{ {1}},但是一旦你编译你的程序来生成独立的二进制可执行文件,这就不再有用了。foo();在执行之后基本上抛弃了计算的结果,并且因为val it = foo();val _ = ...返回writeFile,他们不值得绑定任何内容。)