我需要编写一个程序,将命令式代码转换为纯函数式。我并不担心I / O - 我有一些解决方案 - 但我确实需要处理堆对象和局部变量。
我想可以通过在每个函数调用中返回TheWorld
对象并返回,然后从那里进行优化,尝试从不使用它的函数中删除该参数等来完成。但是有没有更好的已知这样做的方式?
答案 0 :(得分:8)
正如SK-logic指出的那样,你可以用SSA形式代表你的命令式程序。
然而,您可以直接将命令式SSA表示转换为“行政范式”中的等效纯函数程序 - 一种受限制的函数式语言,基于Zadarnowski等人发布的算法< / p>
这两种语言由:
给出
请参阅:“A Functional Perspective on SSA Optimisation Algorithms”,它提供了将SSA表单中的程序自动转换为ANF的算法。
答案 1 :(得分:7)
有许多方法可以有效地进行这种翻译。首先,值得使用随后的CPS转换进行SSA转换:这样你就可以从带有变量和分支的命令式代码中获得一堆简单的相互递归函数。通过传递continuation参数而不是依赖于隐式堆栈语义,函数调用(甚至虚拟调用)也可以很容易地进行CPS编辑。
数组的处理方式与变量相同,在SSA转换之前,所有数组访问都应该用get
和update
函数调用替换,这应该具有隐式复制语义(但要小心)在这种情况下的别名)。结构相同。
只有在无法维护复制语义的情况下,您才需要拥有此TheWorld
对象,该对象应保留所有已分配的对象,并且每次修改其中一个时都应该进行复制。
答案 2 :(得分:1)
通过替换变量,可以将一系列命令式语句转换为单个算术表达式。在Prolog中,这可以通过replacing subterms完成:
:- use_module(prolog_vars_list).
:- set_prolog_flag(double_quotes, chars).
:- initialization(main).
main :-
To_solve = (Z=11,
Z=Z*2,
A=1+A,
A=A+2,
A = Z+1,
A = A * 2,
A=A+3+Z+P),
run_imperative(To_solve,B),
%print the input
writeln(To_solve),
%now print the output
writeln(B).
run_imperative(A,B) :- imperative_to_declarative(A,_=B).
imperative_to_declarative((A,B,C),D1) :-
imperative_to_declarative((B,C),D),imperative_to_declarative((A,D),D1).
imperative_to_declarative((A=A1,B=B1),(_=C)) :-
replace(A,A1,B1,C).
replace(Subterm0, Subterm, Term0, Term) :-
( Term0 == Subterm0 -> Term = Subterm
; var(Term0) -> Term = Term0
; Term0 =.. [F|Args0],
maplist(replace(Subterm0,Subterm), Args0, Args),
Term =.. [F|Args]
).
此程序转换后,可以使用partial evaluation进行简化。