Command line 将命令行参数写入文件

Command line 将命令行参数写入文件,command-line,arguments,sml,smlnj,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,

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

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

这是以下两个问答的重复:

以下是一些一般性反馈:

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

    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
    
    (由于以下列出的几个原因,此代码仍然被破坏。)

  • 结束
    如果您只是在声明一个
    乐趣
    ,则不需要此关键字。它出现在SML语法中的几个地方,特别是
    let。。。在里面结束
    ,您可能已经在那里看到了它

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

  • 分号:当您的函数执行多个具有副作用的操作时,您可以使用
    操作员。在then部分你没有这样做,而在else部分你做得不对,无可否认是因为
    运算符为

    简短的版本是:
    valfoo=x中的分号;val bar=y
    val foo=(TextIO.output(fd,x);TextIO.output(fd,y))中的分号不同

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

  • 迭代行列表时,不要保留计数器,而是对列表执行模式匹配。这大大简化了递归结束时的处理,因为您总是一次一个地处理列表的标题

  • 不退出:您可能不想在完成后退出程序;退出该功能就足够了。通过这种方式,您可以在更复杂的控制流中重用该函数,而无需代表整个程序退出该函数

  • 打开和关闭同一范围内的文件:这是一般编程建议:在处理副作用时,确保不要忘记关闭已打开的文件,也不要关闭两次,在代码的同一个区域内执行此操作,可以更容易地对正确性进行推理。你可以做些什么

  • val
    函数体内部:
    当需要在函数体或某个表达式内部绑定临时值时,请使用
    let
    -表达式。顺便说一句,今天有人问

  • 不可变值:在SML中,您不能更新像
    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

val_=…
s是一种在顶级计算表达式的奇特方法,而不直接在顶级计算表达式。在交互式REPL中,它自己的行上的
val it=foo();
表示
val it=foo()
,但一旦你编译程序以生成独立的二进制可执行文件,这就不再有效了。
val=…
基本上会在执行后丢弃计算结果,因为
writeFile
TextIO.closeOut
返回
()
,它们不值得绑定任何东西。)

哇,非常感谢你。我很抱歉。在使用堆栈溢出的6年中,这是我问的第一个问题。我会记住所有这些要点。经过您的更正,它现在在修改后的代码的第3行给了我一个“错误:语法错误:插入RPAREN”。我搜索了堆栈溢出,似乎找不到此错误的解释。抱怨什么错误?哦,负一的整数文本是
~1
,而不是
-1