我真的可以做一些F#中尾部呼叫優化的幫助。 我想解析一個樹狀結構,並在每一片葉子上進行計算。F#中的尾部呼叫優化#
我有問題的功能是calcLength
type Location = float * float
type Radius = float
type Width = float
type Angle = float
type Primitive =
| Circle of Location * Radius
| Ellipse of Location * Radius * Radius
| Square of Location * Width * Angle
| MultiPrimitive of Primitive List
type Primitive with
member x.Length =
let rec calcLength x =
match x with
| Circle (_,r) -> System.Math.PI * r * 2.
| Ellipse (_,r1,r2) -> System.Math.PI * 2. * sqrt( (r1 * r1) + (r2 * r2)/2.)
| Square (_, w,_) -> w * 4.
| MultiPrimitive [] -> 0.
| MultiPrimitive (head::tail) -> calcLength (MultiPrimitive tail) + (calcLength head)
[<Fact>]
let ``test discriminated unions``() =
let pattern = MultiPrimitive(
[
MultiPrimitive(
[
MultiPrimitive(
[
Square((10.,10.), 10., 45.);
Circle((3.,7.), 3.);
Circle((7.,7.), 3.);
Square((5.,2.), 3., 45.);
]);
Square((10.,10.), 10., 45.);
Circle((3.,7.), 3.);
Circle((7.,7.), 3.);
Square((5.,2.), 3., 45.);
]);
Square((10.,10.), 10., 45.);
Circle((3.,7.), 3.);
Circle((7.,7.), 3.);
Square((5.,2.), 3., 45.);
])
let r = pattern.Length
我試圖使用延續的辦法有以下:
let rec calcLength x f =
match x with
| Circle (_,r) -> f() + System.Math.PI * r * 2.
| Ellipse (_,r1,r2) -> f() + System.Math.PI * 2. * sqrt( (r1 * r1) + (r2 * r2)/2.)
| Square (_, w,_) -> f() + w * 4.
| MultiPrimitive [] -> f()
| MultiPrimitive (head::tail) -> calcLength head (fun() -> calcLength(MultiPrimitive tail) f)
calcLength x (fun() -> 0.)
但步進通過與調試器顯示堆棧增長,任何幫助將真的讚賞。
可能重複[什麼是尾遞歸?](http://stackoverflow.com/questions/33923/what-is-tail-recursion) – CoderDennis 2015-02-10 20:26:04
如果您使用的是Visual Studio,那麼默認情況下,在調試模式下禁用調用優化,爲您提供更好的堆棧跟蹤。嘗試在項目選項中啓用它。 – 2015-02-10 20:29:13
@TomasPetricek謝謝你,好貼士! – 2015-02-12 04:06:45