2016-01-31 5 views
10

Voll Faulheit hat gewesen repeatedly demonstrated zu cause space leaks.Warum ist Vollfaulheit eine Standardoptimierung?

Warum ist die volle Faulheit von -O an? Ich bin nicht von der Argumentation in SPJs The Implementation of Functional Programming Languages überzeugt. Die Forderung ist, dass in

f = \y -> y + sqrt 4 

sqrt 4 unnötig jedes Mal wiederholt wird f eingegeben wird, so sollten wir es außerhalb des Lambda schweben. Ich stimme dem zu, aber seit wir gesehen haben, welche Probleme diese Transformation im Großen verursacht, glaube ich nicht, dass es das wert ist. Es scheint mir, dass die Vorteile dieser Transformation einseitig erzielbar sind ** mit nur lokalen Code-Änderungen und Programmierern, die es von Hand implementieren möchten.

Können Sie mich sonst überzeugen? Ist full-laziness wirklich wirklich nützlich? Ich bin besonders überzeugt, wenn Sie Beispiele nennen können, die per Hand eine multilaterale Zusammenarbeit oder nicht-lokale Transformationen erfordern.

** im Gegensatz zu Optimierungen wie inlining und Strom-Fusion, die von Hand implementieren würde multilaterale Zusammenarbeit zwischen den Modulen und nicht-lokalem Code erfordert Änderungen

+1

Die 'Full-Faulheit'-Transformation hat eigentlich nichts mit der Bewertungsreihenfolge zu tun. –

Antwort

7

Es gibt zumindest einen gemeinsamen Fall, in dem volle Faulheit „sicher“ und eine Optimierung .

g :: Int -> Int 
g z = f (z+1) 
    where f 0 = 0 
     f y = 1 + f (y-1) 

Das bedeutet wirklich g = \z -> let {f = ...} in f (z+1) und auf diese Weise zusammengestellt, wird vor dem Aufruf es einen Verschluss für f zuordnen. Offensichtlich das ist dumm, und der Compiler sollte das Programm in

g_f 0 = 0 
g_f y = 1 + g_f (y-1) 
g z = g_f (z+1) 

verwandeln, wo keine Zuordnung erforderlich ist g_f zu nennen. Glücklicherweise macht die volle Faultransformation genau das.

Offensichtlich Programmierer aus der Herstellung dieser lokalen Definitionen verzichten könnte, die auf die Argumente der Funktion der obersten Ebene hängen nicht, aber solche Definitionen sind in der Regel gut Stil angesehen ...

Ein weiteres Beispiel:

h :: [Int] -> [Int] 
h xs = map (+1) xs 

In diesem Fall können Sie einfach reduzieren, aber normalerweise können Sie nicht reduzieren. Und die Benennung der Funktion (+1) ist ziemlich hässlich.

+0

Danke für das Beispiel. Das gleiche würde gelten, wenn "f" ein "Int" wäre, insbesondere wenn es teuer ist. Ich dachte jedoch an eine weniger heftige Transformation: 'g = let {f = ...} in \ z -> f (z + 1)'. Dies würde immer noch als guter Stil angesehen werden, denke ich, auch wenn es syntaktisch nicht so gut zu Haskells "wo" passt. –

+0

Ihr zweites Beispiel, "h", ist überzeugender, denn "(+1)" zu benennen ist in der Tat ziemlich hässlich. Ich würde es als äquivalent zu SPJs Beispiel mit 'sqrt 4 'bewerten. Ich denke, meine Schlussfolgerung ist dann, dass "Vollfaulheit" dich durch tausend Schnitte vor dem Tod bewahrt. Man könnte im Prinzip optimierte Versionen von Hand herstellen, aber es wäre ineffizient, dies überall zu tun. –

Verwandte Themen