Lambda the Ultimate

inactiveTopic Refactoring Functional Programs
started 7/10/2002; 4:02:14 AM - last post 7/18/2002; 3:02:16 AM
jon fernquest - Refactoring Functional Programs  blueArrow
7/10/2002; 4:02:14 AM (reads: 16659, responses: 19)
Refactoring Functional Programs
We might program in an exploratory way: first establishing the functionality we seek, and then refactoring into a more elegant form. We suspect that functional languages are particularly suited to this form of programming, because their clean semantic basis makes wholesale transformations more feasible than for a language in the C family, say.

The site contains a catalog of Haskell refactorings a case study in refactoring student "Semantic Tableaux" programs (propositional logic background here), a presentation, source code for the refactoring example, and a difference utility. Here's a rough distribution of refactorings in the catalog: types (7), function input arguments (4), case switches (2), monads (1), folds (1), set comprehensions (1), iteration/fixed point (1). Refactoring might be a useful tool in getting people to adopt functional languages in .NET, SML.NET and F#, when they have a comparative advantage over the languages that everyone is familiar with: Java, C++, and C#.


Posted to functional by jon fernquest on 7/10/02; 6:20:12 AM

Ehud Lamm - Re: Refactoring Functional Programs  blueArrow
7/10/2002; 10:30:10 AM (reads: 13941, responses: 0)
I find this work quite interesting. I always found refactoring to be closely related to OOP. Well, the classic refactorings obviously are. Looking at refactoring in the context of functional programming is interesting for the same reason patterns in dynamic languages are interesting. They help us see the role of the programming paradigm/language more clearly.

Notice that the refactorings here are more "low level" than the classic OOP refactorings.

jon fernquest - Re: Refactoring Functional Programs  blueArrow
7/11/2002; 4:41:37 AM (reads: 13914, responses: 0)
I know it doesn't really exist yet, but a catalog of cross-paradigm refactorings from OO+imperative to OO+functional (e.g. OCAML, F#, SML.NET) qould help people to rewrite parts of their .NET code into functional programming languages. Java + XSLT seems to be the only really common instance of functional + OO programming out there right now. The pros and cons behind multi-language programming are outlined pretty well here.

Charles Simonyi's famous paper The Death Of Computer Languages, The Birth Of Intentional Programming (1995) argues that computer languages should looked upon as sets of features that you should be able to freely choose from and mix. As in evolution, powerful features will survive, the weak will perish. As for syntax? He also argues that the least common denominator, abstract syntax tree's (AST) should be used. When I saw JavaML I immediately thought DOM = AST, but using XML for AST's is no doubt too slow. When I read his paper I kept thinking of all the tools in EOPL. Also, you should be able to express any language in s-expressions and give them the full power of Scheme hygienic macros. (Note: I saw some references to something called "Classic Java" in some of the PLT Scheme papers that looked like Java in s-expressions, but I couldn't find anything on it. Anyone?) The paper "From Competition to Amalgamation of Different Programming Paradigms" by Sergei G. Maslov from Google Multi-Paradigm Programming seems to be making a similar point to Simonyi's.

ANyone know of any weblogs out there in this vein?

Cheers,

Jon Fernquest

Programming Examples Weblog: http://www.geocities.com/bayinnaung/progexamplesworld.html

James Hague - Re: Refactoring Functional Programs  blueArrow
7/11/2002; 8:38:25 AM (reads: 13898, responses: 0)
Twenty years ago, program transformation (Darlington, et al) was considered one of the primary benefits of functional programming. And now it's back...with a new name :)

(I know, I know, they're not quite the same thing, but it is interesting nonetheless.)

Martin Bravenboer - Re: Refactoring Functional Programs  blueArrow
7/11/2002; 1:01:31 PM (reads: 13886, responses: 0)

Interesting topic! Jon Fernquest posted some interesting remarks on ASTs and XML.

I think you shouldn't judge XML on its verbose syntax or on the existing DOM implementations. XML is just about regular tree languages and regular tree grammars. Abstract Syntax Trees are also just about regular tree languages and grammars.

Stratego is in fact all about abstract syntax trees that can be exchanged between transformation components. The trees are exchanged in the fast and compact ATerm format. This ATerm format is howerver almost equivalent to XML as I discusses in this presentation. In this presentation I discuss some upcoming tools to map XML to ATerms and vice-versa.

So in my opinion XML is just a (verbose) serialization format of regular trees. ASTs are regular tree languages so the exchange of ASTs between components in XML format makes some sence. In fact this is just what web-services are all about: exchange of data in regular trees instead of in some concrete-syntax. This model has been used by the component of XT for some time and is quite succesful.

Stratego requires a signature of the data structures it is transforming. This signature is just a regular tree grammar. XML languages can also be described by regular tree grammars, for example in RELAX NG. The various XML schema language have been compared in the model of the regular tree languages.

At the program transformation Wiki there is a page on ProgramRefactoring. The refactoring of functional programs is also mentioned over there. Please contribute if you find interesting resources!

Wouter van Oortmerssen - Re: Refactoring Functional Programs  blueArrow
7/12/2002; 4:55:11 AM (reads: 13862, responses: 3)
Refactoring is a very fundamental activity, searching for the "normal form" of code, and surely is not related to any particular language paradigm.

What seems to have more of an influence on its effectiveness is syntactical/declaration structure, for example refactoring in C/C++ is excessively hard because function/method declaration are often duplicated atleast 2 times (.c, .h), unlike Java etc.

The non-functional language which probably is most refactor-friendly is probably Forth (in its purest form), as there you can abstract out (or inline) arbitrary code snippets by just cutting them out.

Ehud Lamm - Re: Refactoring Functional Programs  blueArrow
7/12/2002; 7:25:59 AM (reads: 13898, responses: 2)
Refactoring is a very fundamental activity, searching for the "normal form" of code, and surely is not related to any particular language paradigm.

I wouldn't accept this statement even if you tried to justify it. As presented, I only find the use of the word surely as a weak attempt of argument from authority.

I don't think that the phrase "normal form" of programs has any intrinsic meaning. Since many refactorings deal with software design, I don't see how they can be unrelated to the programming paradigm.

And to prove refactorings are language related, just take a look at the Replace Recursion with Iteration refactoring. A Scheme programmer reading this is even likely to understand the term iteration as specifying a form of recursion.

Maybe it would help if we would call refactorings design heuristics which is exactly what they are.

andrew cooke - Re: Refactoring Functional Programs  blueArrow
7/12/2002; 7:40:49 AM (reads: 13955, responses: 1)
Since the poster himself gave an example of how refactoring depends on language I think you could have assumed that "related" was an error - perhaps he meant "restricted".

Maybe it would help if we would call refactorings design heuristics which is exactly what they are.

Shouldn't that be Re-design heuristics?

Ehud Lamm - Re: Refactoring Functional Programs  blueArrow
7/12/2002; 7:46:45 AM (reads: 14010, responses: 0)
Yeah, it would be even more accurate to call them local redesign heuristics.

jon fernquest - Re: Refactoring Functional Programs  blueArrow
7/13/2002; 9:46:04 AM (reads: 13807, responses: 0)
> Refactoring is a very fundamental activity, searching for the "normal form" of code,
> and surely is not related to any particular language paradigm.

The ways you can write a program in a functional language without state or in an object-oriented language without higher-order functions must certainly be different from the ways you could write a program in a language like OCAML. that has both.

The term "Normal Form" is misleading here because this term does have an exact meaning in lambda calculus and functional programming. In refactoring the definitions are quite loose like what follows:

Extreme Normal Form Defined: All the code is tested. The code passes all the tests. No one on the team can think of code in the system that they could remove or simplify without reducing the feature set. You never have to go more than one place to change one thing. Refactoring Presentation in Powerpoint

The same feature set could be implemented using different paradigms or different mixes of paradigms.

I believe "simplify" above means "simple to read and understand." So refactoring might be "local redesign heuristics that make code more readable and easier to understand." Fowler's book always struck me as the programming equivalent of "Strunk and White," a style guide for writing.

But efficiency seems to dominate most analysis of functional programs, example: Oleg's Analysis of Tree Folds. One way of writing tree folds involved the inefficient creation of many closures. After Oleg's analysis there certainly doesn't seem to be much room to refactor and increase readability.

Code smells or ways of writing functional code that is not simple and easy to understand might also be a nice addition to a refactoring catalog.

Wouter van Oortmerssen - Re: Refactoring Functional Programs  blueArrow
7/15/2002; 3:45:42 AM (reads: 13771, responses: 1)
I don't think that the phrase "normal form" of programs has any intrinsic meaning.

normal form is exactly the meaning I intended... I know what it means in a programming language context (I have implemented quite a few functional/logic/rewriting languages), and I think it applies to code itself and many other structures in general too.

Maybe you define "refactoring" as a set of specific transformations which improve code in some way, many of which are defined in terms of language features which would seem to indicate a particular language paradigm. To me, refactoring is the act of removing redundancy from code or any other structure, making sure everything is said OnceAndOnlyOnce. It applies equally to any language, what particular language features you use to achieve it is irrelevant.

Maybe it would help if we would call refactorings design heuristics which is exactly what they are.

I think that complicates the issue and misses out on what's important about refactoring.

Ehud Lamm - Re: Refactoring Functional Programs  blueArrow
7/15/2002; 8:39:16 AM (reads: 13821, responses: 0)
I am still not sure I understand what you mean by normal form of code. Can you perhaps explain how your opinion is related to the refactorings catalog? To me most of them are not simple mechanical rules that can be applied blindly to give you a normal form.

I still claim that if your definiton of normal form includes the term classes and you have refactorings that talk about things like packages than you are talking at the level of the programming language/paradigm.

Perhaps you can help me understand your point of view if you would show me an example. Maybe the normal form for a program that prints the sum of prime numbers less than a 100?

jon fernquest - Re: Refactoring Functional Programs  blueArrow
7/16/2002; 4:07:33 AM (reads: 13750, responses: 0)
>To me, refactoring is the act of removing
>redundancy from code or any other structure,
>making sure everything is said OnceAndOnlyOnce.
>It applies equally to any language, what
>particular language features you use to achieve
> it is irrelevant.

Is redundcancy the sole objective in refactoring. Is there one unique way to remove redundancy?

If the code was badly structured, hard to read and maintain, but non-redundant then everything would be ok?

It seems that there are multiple objectives to be achieved in refactoring and some of these are captured in Code Smels. I don't think that "simple" means merely "non-redundant" .

(Note: The prose equivalent of redundant code would be an author who keeps repeating himself, something that Strunk and White (or other writing style guides) warn against.)

The very page you site OnceAndOnlyOnce implies that redundancy is not the sole factor in refactoring:

If you are aware of CodeSmells, and duplicate code is one of the strongest, and you react accordingly, your systems will get simpler (My emphasis)

I respect your experience, but I don't respect the rhetorical trick "appeal to experience" that many of the refactoring community uses, like the following quote:

Highly experienced and knowledgeable developers have a "feel" for good design. Having reached a state of "UnconsciousCompetence," where they routinely practice good design without thinking about it too much, they find that they can look at a design or the code and immediately get a "feel" for its quality, without getting bogged down in extensive "logically detailed arguments". (Code Smells)

No matter how experienced someone is they still should be able to explain the basis of their beliefs.

Wouter van Oortmerssen - Re: Refactoring Functional Programs  blueArrow
7/16/2002; 6:52:58 AM (reads: 13769, responses: 1)
I am still not sure I understand what you mean by normal form of code. Can you perhaps explain how your opinion is related to the refactorings catalog?

The page you mention is simply a list of possible transformations without indication when which one should be applied. For example Extract Method and Inline Method are each others opposites, they are both useful in particular situations, and when to apply which requires human insight (which is guided by non-redundancy, simplicity, readability, maybe others). A human repeatedly applies refactoring rules onto his data (the code) until none apply any more... reaching normal form. To me (and others) this is very similar to the classic meaning of normal form, sorry if I violated any strict definitions.

I still claim that if your definiton of normal form includes the term classes

No idea where you get this from, I have never mentioned classes, and to me they are orthogonal to refactoring.

Perhaps you can help me understand your point of view if you would show me an example. Maybe the normal form for a program that prints the sum of prime numbers less than a 100?

I guess my use of the term "normal form" made you assume there is a mechanical way to achieve it, or even a single possible normal form for any given bit of code. I wish there was! (imagine all those large amounts of code automatically cleaned up and made maintainable again... that be wonderful). for simple examples there probably are absolute normal forms, i.e.:

Button a = new Button("ok", 80, 20); a.resize(R_ABSOLUTE); form.add(a, L_BOTTOM); Button b = new Button("maybe", 80, 20); b.resize(R_ABSOLUTE); form.add(b, L_BOTTOM); Button c = new Button("cancel", 80, 20); c.resize(R_ABSOLUTE); form.add(c, L_BOTTOM);

is clearly redundant, and this isn't:

void addButton(String name) { Button a = new Button(name, 80, 20); a.resize(R_ABSOLUTE); form.add(a, L_BOTTOM); };

addButton("ok"); addButton("maybe"); addButton("cancel");

i.e. there is no less-redundant way of writing it.

Is redundcancy the sole objective in refactoring.

No, but I would argue it is the single most important one. There are others, but they often interfere.

Is there one unique way to remove redundancy?

Would be cool if there was... it is an interesting topic to think about. Some things that stand in the way: there is a point of diminishing returns when refactoring smaller amount of code, for example abtracting multiple occurrences of x*2 into a function, even though it is strictly redundant, probably only obfuscates. Second, there is not always a single way to reduce redundancy, one abtraction may reduce refactoring opportunities elsewhere. Third, programming language abstraction features are often inadequate to cope with any kind of redundancy elimation, especially of abtractions requiring delayed arguments (i.e. like smalltalk blocks, or lazy evaluation).

If you are aware of CodeSmells, and duplicate code is one of the strongest, and you react accordingly, your systems will get simpler (My emphasis)

It is my personal experience that a lot of types of "smelly code", or a lot of refactorings boil down to removing redundancy in one way or another. Maybe I suffer from seeing all the evil in the (IT-) world through redundancy glasses :)

I respect your experience, but I don't respect the rhetorical trick "appeal to experience"

I don't see where I try to come across as a design god.

Wouter van Oortmerssen - Re: Refactoring Functional Programs  blueArrow
7/16/2002; 6:58:07 AM (reads: 13739, responses: 0)
whoops, seems the "code" tag didn't work as expected. Hope you can read it.

Ehud Lamm - Re: Refactoring Functional Programs  blueArrow
7/17/2002; 5:08:09 AM (reads: 13807, responses: 0)
The page you mention is simply a list of possible transformations without indication when which one should be applied

Well, this is a catalog of refactorings, from a site called refactoring.com maintained by the guy who wrote the Refactoring book. So for my purposes this is what refactoring means.

This is also the place things like the reference to classes, packages etc. are from.

Wouter van Oortmerssen - Re: Refactoring Functional Programs  blueArrow
7/17/2002; 6:36:06 AM (reads: 13736, responses: 1)
refactoring is a very general principle, existing way before someone wrote a book about it with a rather self-important sounding title and snatched the domain name.

Don't get me wrong, it is an important book which is well worth reading by anyone. But I don't see the need to stop and think/discuss beyond what is written in it.

Wouter van Oortmerssen - Re: Refactoring Functional Programs  blueArrow
7/17/2002; 6:36:45 AM (reads: 13721, responses: 0)
stop and -> stop to

Ehud Lamm - Re: Refactoring Functional Programs  blueArrow
7/17/2002; 6:43:43 AM (reads: 13770, responses: 0)
As long as we all know what it is that we are talking about...

jon fernquest - Re: Refactoring Functional Programs  blueArrow
7/18/2002; 3:02:16 AM (reads: 13702, responses: 0)
Thank you very much for the detailed answers.

"OnceAndOnlyOnce" does seem to be the essence of re-use, putting redundant code into one place where it can be used over and over again.

Also in Martin Fowler's original book chapter 12 "Big Refactorings: Convert Procedural Design to Objects" sure seemed to me like refactoring that crossed programming paradigm boundaries.

In this example in a Java program with a procedural or imperative design (imperative programming paradigm) is refactored into a program that uses objects (object-oriented paradigm). (Can't find any online examples of this "big refactoring". Anyone?)

The book A Functional Pattern System for Object-Oriented Design is worth reading for seeing how the functional paradigm can be emulated in object-oriented Eiffel, one way to refactor an OO program into a more functional one.