Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用f#模拟linux touch命令,需要帮助实现_F#_Touch_F# Interactive - Fatal编程技术网

使用f#模拟linux touch命令,需要帮助实现

使用f#模拟linux touch命令,需要帮助实现,f#,touch,f#-interactive,F#,Touch,F# Interactive,我正在尝试编写一个f#程序,它模仿linux中的touch命令,它检查文件路径是否存在,是否更新了时间戳,是否不存在,是否创建了文件。如何正确地实现这一点 我尝试过使用.net函数,我认为它基本上实现了我需要的功能。我正在使用file.exists、file.create和file.setlastaccesstime //了解更多关于F#at的信息 opensystem.IO 类型Filepath=string 让触摸= 让我们检查存在的文件路径= 如果File.Exists文件路径 然后是Re

我正在尝试编写一个f#程序,它模仿linux中的touch命令,它检查文件路径是否存在,是否更新了时间戳,是否不存在,是否创建了文件。如何正确地实现这一点

我尝试过使用.net函数,我认为它基本上实现了我需要的功能。我正在使用file.exists、file.create和file.setlastaccesstime

//了解更多关于F#at的信息

opensystem.IO
类型Filepath=string
让触摸=
让我们检查存在的文件路径=
如果File.Exists文件路径
然后是Result.Ok(filePath:filePath)
else结果。错误“文件不存在”
let path=Console.ReadLine()
让我们更新=
path=Console.ReadLine()
如果文件.Exists(路径)
创建(路径)
else文件.SetLastAccessTime(路径,DateTime.Now)
[]
让主argv=
printfn“windows触摸命令”
->触摸
->更新()
0//返回整数退出代码```

您的代码有几个问题。我会一个接一个地看一遍

首先,问题中代码的缩进完全搞乱了。如果这是代码的直接复制和粘贴,我们需要做的第一件事就是修复缩进:在F#中,缩进是重要的,并确定代码块。(如果您的问题的缩进被弄乱了,因为您在堆栈溢出问题编辑器中篡改缩进,并且实际代码缩进是好的,那么请考虑这是关于F压痕如何工作的复习)。 在F#中,这两个代码块的作用不同:

if value = 5 then
    printfn "Five"
printfn "Value: %d" value
这将始终打印“Value:3”或“Value:27”或其他内容,如果值正好为5,也将打印单词“Five”。但下一个代码块还有其他功能:

if value = 5 then
    printfn "Five"
    printfn "Value: %d" value
这要么不打印任何内容,要么在下一行打印单词“5”,后跟“Value:5”。这是因为第二个
printfn
函数调用与第一个函数调用在同一级别缩进,这意味着它是
if
块的一部分

另外,
let
语句后面需要跟在同一行的值后面,或者跟在缩进块后面:

let value = 5

let otherValue =
    if value < 5 then
        5
    else
        3
现在你可以像这样调用这个函数:

let value = 5
let otherValue = calculateValue value
// Now otherValue is equal to 3
这给我们带来了代码的第二个问题,即您显然打算将
touch
update
作为函数,但没有给它们提供参数。这意味着它们是只执行一次的值。您需要将
let touch=
转换为
let touch()=
以使
touch
成为一个函数而不是一个值,对于
update
也是如此

您遇到的另一个问题更多的是设计问题:您的
update
函数正在做两件事。它从控制台读取一个值,并根据该值采取行动。更好的设计是让每个函数只做一件事:让您的
更新
函数将
路径
作为参数,然后在其他地方,您可以让代码从控制台读取
路径
,并调用
更新路径
。这使得编写测试
update
函数的单元测试变得更加容易,因为您不必想办法将单元测试连接到stdin,只需让测试调用
update
函数即可

古兰在评论中指出的另一个问题(谢谢!)是,
update
函数的逻辑是反向的。您写了“如果文件存在,创建文件,否则设置上次访问时间”。应该是相反的。我在这个答案的第一个版本中遗漏了这一点,因此我更新了下面的固定代码,以更正
更新中
if…then…else
块的顺序

我看到的另一个问题是:你的
touch
功能(目前它是一个值,但你显然有意让它成为一个功能)应该做什么?
let touch=
块中唯一的内容是其他函数定义;
touch
代码块从未实际调用它定义的函数。这意味着它是无用的:通过将这些函数定义放在
touch
代码块内,您可以对
touch
代码块外的任何代码隐藏它们,但是
touch
代码块从不调用它们。在模块顶层定义的函数对于任何可以访问该模块的代码都是可见的。在代码块内定义的函数(和变量)仅在该代码块的范围内可见。这对于封装外部世界看不到的内容非常有用,例如在以下示例中:

let counter() =
    let mutable value = 0
    let update() =
        value <- value + 1
        value
    update
这将打印“A1:1”、“A2:2”、“B1:1”,然后打印“B2:2”。现在作为练习,如果我在上面的代码中将
let counter()=
替换为
let counter=
,会发生什么?(我还必须将
let a=counter()
更改为
let a=counter
,对于
let b=…
,也是如此)。试着猜测会发生什么,然后试着去做,看看你是否是对的。(提示:与函数不同,值只执行一次)

还有最后一件事:
main
函数中的箭头不正确。这不是
->
操作符的作用。如果需要在一行中调用多个函数,只需逐个编写函数调用

好的,这就是我现在所能做的,帮助您解决代码问题的全部工作。还有更多的问题(例如,最好从
argv
获取路径,而不是从
Console.ReadLine()
)获取路径),但这些问题可以等到您有了更多的F#经验后再解决。这是您的代码,以及我到目前为止提到的修复程序。哦,还有一个解决办法:我正在删除
let touch=
行,因为我无法告诉您打算在
touch
函数中添加什么。下面是您的代码,虽然有些修复,但仍需要更多修复:

open System.IO

type Filepath = string

// NOTE: This function is unused. Why do you have it?
let checkExists filePath =
    if File.Exists filePath
    then Result.Ok (filePath:Filepath)
    else Result.Error "File does not exist"

let update path =
    // Note: the "then" and "else" blocks are swapped from your original code
    if File.Exists(path)
    then File.SetLastAccessTime(path, DateTime.Now)
    else File.Create(path)

[<EntryPoint>]
let main argv =
    printfn "Touch command for windows"
    let path = Console.ReadLine()
    update path

    0 // return an integer exit code
opensystem.IO
类型文件
let counter() =
    let mutable value = 0
    let update() =
        value <- value + 1
        value
    update
let a = counter()
let b = counter()
let a1 = a()
let b1 = b()
let a2 = a()
let b2 = b()
printfn "A1: %d" a1
printfn "A2: %d" a2
printfn "B1: %d" b1
printfn "B2: %d" b2
open System.IO

type Filepath = string

// NOTE: This function is unused. Why do you have it?
let checkExists filePath =
    if File.Exists filePath
    then Result.Ok (filePath:Filepath)
    else Result.Error "File does not exist"

let update path =
    // Note: the "then" and "else" blocks are swapped from your original code
    if File.Exists(path)
    then File.SetLastAccessTime(path, DateTime.Now)
    else File.Create(path)

[<EntryPoint>]
let main argv =
    printfn "Touch command for windows"
    let path = Console.ReadLine()
    update path

    0 // return an integer exit code