这是财务算法的高度骨架化版本。在实际条件和数据处理中有更多的逻辑由" myFunc" - 在这个版本中真正意图有意义。
我的问题是:我如何理解为什么在这个区块中使用firstMultiple
是允许的和合理的。它为什么要起作用?
表达式直接从标记为A
的行映射到标记为C3
的行,其中使用了其值。但随后在C1
和C2
- (大致)相同级别的"缩进"作为C3
- 这里分配了firstMultiple
- 看起来好像它是可变的 - ??
我想我不明白为什么C3
使用firstMultiple
而C1
似乎会覆盖它。 (调试器,并运行它,表明它没关系)。
我希望这个问题和示例可以让我们深入了解如何思考(嵌套)范围。 (我很高兴当然也对设计有其他意见,但请记住,这段代码非常缺乏大量的分析。)(而且我可能在我剥离它时使算法不合逻辑,但我试图关注范围问题。)
let rec ListBuilder factor firstMultiple useFirstMultiple inputList outputList = // "A"
match inputList with
| [] -> []
| h::[] -> List.rev (inputList.Head :: outputList)
| _ ->
let nextInput = inputList.Head
let newOutputList, remInputList, firstMultiple = // "B"
match outputList with
| [] -> //first pass, capture firstMultiple now
let firstMultiple = nextInput * factor // "C1"
[nextInput], inputList.Tail, firstMultiple // "C2"
| _ ->
let lastOutput = outputList.Head
let multiple =
if useFirstMultiple then firstMultiple // "C3"
else lastOutput * factor
let newOutputList =
if (myfunc multiple nextInput: bool) then
nextInput :: outputList
else
outputList
let remInputList =
if not (myfunc multiple nextInput: bool) then
inputList.Tail
else
inputList
newOutputList, remInputList, firstMultiple
ListBuilder factor firstMultiple useFirstMultiple remInputList newOutputList
答案 0 :(得分:3)
由于此示例基本上是
的循环let rec ListBuilder
...
ListBuilder
C3
中每个项目的循环点击outputlist
,然后当outputlist
为空时,最终点击C1
和C2
仅在C3
firstMultiple
读取。
then firstMultiple // "C3"
在C1
和C2
,firstMultiple
为bound然后阅读,请注意我说bound
不是set
或mutated
let firstMultiple = nextInput * factor // "C1"
[nextInput], inputList.Tail, firstMultiple // "C2"
C1
firstMultiple
与firstMultiple
或A
或B
的{{1}}变量不同,它是一个新变量。因此,当您认为它在C3
位置firstMultiple
变异时,它不是。
如果您的示例转换正确,那么您可以将代码转换为:
C3
或更简单
let temp = nextInput * factor // "C1"
[nextInput], inputList.Tail, temp // "C2"
在此示例中[nextInput], inputList.Tail, (nextInput * factor) // "C2"
firstMultiple
和C1
只是一个重用的变量名称,因为允许使用阴影,但不需要。
修改
OP在评论中提出了进一步的问题:
为什么行" B"从" C2"中取出第一个多个而不是来自" A"。
原因是行C2
是三个值的元组,它们是由行B
后面的表达式的结果生成的。所有这些都是为元组创建三个值的表达式。
B
根据匹配结果生成三个元组值的两行是
let newOutputList, remInputList, firstMultiple = // "B"
match outputList with
| [] -> //first pass, capture firstMultiple now
let firstMultiple = nextInput * factor // "C1"
[nextInput], inputList.Tail, firstMultiple // "C2"
| _ ->
let lastOutput = outputList.Head
let multiple =
if useFirstMultiple then firstMultiple // "C3"
else lastOutput * factor
let newOutputList =
if (myfunc multiple nextInput: bool) then
nextInput :: outputList
else
outputList
let remInputList =
if not (myfunc multiple nextInput: bool) then
inputList.Tail
else
inputList
newOutputList, remInputList, firstMultiple
和
[nextInput], inputList.Tail, firstMultiple // "C2"
行newOutputList, remInputList, firstMultiple
不是以B
作为参数的函数,例如
firstMultiple
它是一个匹配函数,返回三个值的元组
let myFunc firstMultiple = ...
let newOutputList, remInputList, firstMultiple = // "B"
未通过firstMultiple
传递
但是被创建为一个新变量并绑定在B
C1
然后通过let firstMultiple = nextInput * factor // "C1"
C2
答案 1 :(得分:2)
内部范围可以捕获外部范围中的变量。我假设您的问题意味着您在分配新值时期望出现错误。阴影和实际可变变量之间存在差异。见这两个例子。
这里x不是实际可变的,虽然它感觉像是:
let testValue (l: int list) =
let x = l.[0]
printfn "%A" x
do
let x= l.[1]
printfn "%A" x
printfn "%A" x
let x = l.[2]
printfn "%A" x
这里x实际上是可变的:
let testValue2 (l: int list) =
let mutable x = l.[0]
printfn "%A" x
x <- l.[1]
printfn "%A" x
使用testValue [1;2;3]