让我们考虑以下列表:
// 2 2 2 1 1 1
let xs = [2;2;2;1;1;1]
// 2 2 2 1 1 1
let xs' = List.map (fun x -> x) list
// 4 4 4 1 1 1
let xs'' = List.map (fun x -> x * x) list
List.map
会在第二种情况下分配新列表吗?在第三种情况下,xs
会与[1;1;1]
共享尾部xs''
吗?
答案 0 :(得分:5)
标准库倾向于使用此类函数的简单实现。
因此,这种类型的优化没有完成。
可以在此处找到实施:https://github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/local.fs#L85
答案 1 :(得分:2)
正如John指出的那样,你提到的优化没有被执行。如果你真的需要它(这是非常不可能的),你可以编写自己的地图版本,它共享列表的尾部,如:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="table-styles.css">
<title>Register</title>
</head>
<body>
<form method='post' onsubmit="return confirm('Are you sure you want to submit?');">
<table id='table-left'>
<caption>11/22/33</caption>
<caption>ROUTS</caption>
<tr>
<th>ID</th>
<th>Date</th>
<th>Day</th>
<th>Month</th>
<th>Year</th>
<th>Arrival</th>
<th>Departure</th>
<th>S/N</th>
<th>Time Mark</th>
<th>Observation</th>
</tr>
<tr>
<td name="id-1">1</td> <!-- The value of this <td> tag needs to populate in the name of each next <td> 'name' parameter for this row!-->
<td name="ddate-1">03062016</td> <!-- Here I want to add this number "1" to the name of the <td> element.-->
<td name="day-1">Day</td> <!-- Here I want to add this number "1" to the name of the <td> element.-->
<td name="month-1">Month</td> <!-- Here I want to add this number "1" to the name of the <td> element.-->
<td name="year-1">Year</td> <!-- Here I want to add this number "1" to the name of the <td> element.-->
<td name="arrival-1">Arrival</td> <!-- Here I want to add this number "1" to the name of the <td> element.-->
<td name="departure-1">Departure</td> <!-- Here I want to add this number "1" to the name of the <td> element.-->
<td name="sn-1">S/N</td> <!-- Here I want to add this number "1" to the name of the <td> element.-->
<td name="time-mark-1">Time Mark</td> <!-- Here I want to add this number "1" to the name of the <td> element.-->
<td name="observation-1">Observation</td> <!-- Here I want to add this number "1" to the name of the <td> element.-->
</tr>
<tr>
<td name="id-2">2</td> <!-- The value of this <td> tag needs to populate in the name of each next <td> 'name' parameter for this row!-->
<td name="ddate-2">03062016</td> <!-- Here I want to add this number "2" to the name of the <td> element.-->
<td name="day-2">Day</td> <!-- Here I want to add this number "2" to the name of the <td> element.-->
<td name="month-2">Month</td> <!-- Here I want to add this number "2" to the name of the <td> element.-->
<td name="year-2">Year</td> <!-- Here I want to add this number "2" to the name of the <td> element.-->
<td name="arrival-2">Arrival</td> <!-- Here I want to add this number "2" to the name of the <td> element.-->
<td name="departure-2">Departure</td> <!-- Here I want to add this number "2" to the name of the <td> element.-->
<td name="sn-2">S/N</td> <!-- Here I want to add this number "2" to the name of the <td> element.-->
<td name="time-mark-2">Time Mark</td> <!-- Here I want to add this number "2" to the name of the <td> element.-->
<td name="observation-2">Observation</td> <!-- Here I want to add this number "2" to the name of the <td> element.-->
</tr>
<tr>
<td name="id-3">3</td> <!-- The value of this <td> tag needs to populate in the name of each next <td> 'name' parameter for this row!-->
<td name="ddate-3">03062016</td> <!-- Here I want to add this number "3" to the name of the <td> element.-->
<td name="day-3">Day</td> <!-- Here I want to add this number "3" to the name of the <td> element.-->
<td name="month-3">Month</td> <!-- Here I want to add this number "3" to the name of the <td> element.-->
<td name="year-3">Year</td> <!-- Here I want to add this number "3" to the name of the <td> element.-->
<td name="arrival-3">Arrival</td> <!-- Here I want to add this number "3" to the name of the <td> element.-->
<td name="departure-3">Departure</td> <!-- Here I want to add this number "3" to the name of the <td> element.-->
<td name="sn-3">S/N</td> <!-- Here I want to add this number "3" to the name of the <td> element.-->
<td name="time-mark-3">Time Mark</td> <!-- Here I want to add this number "3" to the name of the <td> element.-->
<td name="observation-3">Observation</td> <!-- Here I want to add this number "3" to the name of the <td> element.-->
</tr>
<tr>
<td><input class='hdl' type='text' name='id' value=''></input></td>
<td><input class='hdl' type='text' name='date' value=''></input></td>
<td><input class='hds' type='text' name='day' value=''></input></td>
<td><input class='rm' type='text' name='month' value=''></input></td>
<td><input class='hm' type='text' name='year' value=''></input></td>
<td><input class='ob' type='text' name='arr' value=''></input></td>
<td><input class='pre' type='text' name='dep' value=''></input></td>
<td><input class='prs' type='text' name='sn' value=''></input></td>
<td><input class='vol' type='text' name='tm' value=''></input></td>
<td><input class='obs' type='text' name='ob' value=''></input></td>
</tr>
</table>
<input id='submit' type='submit' name='submit' value='Submit' />
</form>
</body>
</html>
请注意:
此实现将执行更多内存分配,然后只使用/// Returns a copy of 'a' which shares a common suffix with 'b'.
/// 'a' and 'b' must me of equal length.
let shareSuffixWith (a : 'a list) (b : 'a list) : 'a list =
let discardLastNElements (n: int) (li : 'a list) =
List.take (li.Length - n) li
let commonSuffix =
let zippedLists = List.zip a b
let lastDifferentElemIndex =
List.tryFindIndexBack (fun (e1, e2) -> e1 <> e2) zippedLists
match lastDifferentElemIndex with
| None -> b
| Some(index) -> List.skip (index+1) b
let aPreffix = discardLastNElements commonSuffix.Length a
aPreffix @ commonSuffix
/// Maps elements of a list using a mapping and shares
/// common tail between input list and the result.
let mapAndShareSuffix (mapping :'T -> 'T) (li : 'T list) : 'T list =
let resultOfMap = List.map mapping li
shareSuffixWith resultOfMap li
,但在垃圾收集期间将释放部分内存。
F#列表不占用太多空间 - 每个元素只有指针大小的两倍,因此在大多数情况下通过共享尾部获得的内存量最小
共享列表的尾部需要处理和GC时间
上面的实现是次优的而不是惯用的