Design Patterns and Functional programming

This is a discussion on Design Patterns and Functional programming within the Theory and Concepts forums in category; Daniel T. wrote: > Jon Harrop <jon @ ffconsultancy.com> wrote: >> [ FP example snipped ... ] > I have no clue what the above does, so I can't say. I have been > intrigued by functional languages for many years, but I have been unable > to wrap my head around their apparently stateless nature. My programming > problems have always involved state machines reacting to each other and > the user through time. > Can you recommend some good tutorials? I would be interested in, for > example, how one would program pong in OCaml or any functional ...

Go Back   Application Development Forum > Theory and Concepts

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #11  
Old 07-08-2007, 10:38 AM
S Perryman
Guest
 
Default Re: Design Patterns and Functional programming

Daniel T. wrote:

> Jon Harrop <jon@ffconsultancy.com> wrote:


>> [ FP example snipped ... ]


> I have no clue what the above does, so I can't say. I have been
> intrigued by functional languages for many years, but I have been unable
> to wrap my head around their apparently stateless nature. My programming
> problems have always involved state machines reacting to each other and
> the user through time.


> Can you recommend some good tutorials? I would be interested in, for
> example, how one would program pong in OCaml or any functional language.
> What language do you recommend I start with?


How about we start with something simple like writing a program to do stuff
with stacks (read numbers from IO, push onto the stack, write top to IO and
pop until stack empty etc) ??

You know how to do this with an imperative prog lang.
Which means you have terms of reference if/when the FP form starts to give
you conceptual problems. You can bridge to FP by using an intermediate form
(applicative programming) which is written in imperative prog langs almost
identically to FP.


Regards,
Steven Perryman
Reply With Quote
  #12  
Old 07-08-2007, 10:57 AM
Jon Harrop
Guest
 
Default Re: Design Patterns and Functional programming

Daniel T. wrote:
> I'm not sure what you are calling "lines" here to say the example below
> is "~9 lines long".


I'm writing in the style that the interactive top-level shows. So you write
an expression or definition after the "#" prompt and it prints the
definition or value and its type in response. For example:

# 1 + 2*3;;
- : int = 7

# let sqr x = x*x;;
val sqr : int -> int = <fun>

If you were writing the code I gave in a source code file, it would just be:

type t =
| ObjA of [`A | `B]
| ObjB of [`A | `B | `C]

let f = function
| ObjA (`A | `B) -> ObjA `B
| ObjB `A -> ObjB `B
| ObjB (`B | `C) -> ObjB `C

let x = function
| ObjA (`A | `B) -> ObjA `A
| ObjB (`A | `B | `C) -> ObjB `A

> The C++ version has only 4 executable lines...


I'm including the definitions. Also, I only defined the type "t" for
clarity: it can be completely inferred:

let f = function
| `ObjA (`A | `B) -> `ObjA `B
| `ObjB `A -> `ObjB `B
| `ObjB (`B | `C) -> `ObjB `C

let x = function
| `ObjA (`A | `B) -> `ObjA `A
| `ObjB (`A | `B | `C) -> `ObjB `A

> What is the functional equivalent in Scheme?


Good question. I've no idea but I'll have a play with it. :-)

>> # let rec ( +: ) f g = match f, g with
>> | Int n, Int m -> Int (n + m)
>> | Int 0, e | e, Int 0 -> e
>> | f, g -> Add(f, g);;
>> val ( +: ) : expr -> expr -> expr = <fun>
>> # let rec ( *: ) f g = match f, g with
>> | Int n, Int m -> Int (n * m)
>> | Int 0, e | e, Int 0 -> Int 0
>> | Int 1, e | e, Int 1 -> e
>> | f, g -> Mul(f, g);;
>> val ( *: ) : expr -> expr -> expr = <fun>
>>
>> How do you add that to the object oriented design?

>
> I have no clue what the above does, so I can't say.


You use the infix operators +: and *: to construct symbolic expressions:

a +: b
Int 3 *: c

but these operators simplify the expressions as they construct them:

Int 3 +: Int 4 -> Int 7

> I have been
> intrigued by functional languages for many years, but I have been unable
> to wrap my head around their apparently stateless nature. My programming
> problems have always involved state machines reacting to each other and
> the user through time.


Stateless programming is really very simple. Indeed, simplicity is its main
advantage. Stateless programming can also be very useful in OO languages
(i.e. const) although it is less common.

Whenever you update an immutable data structure you simply return a new data
structure. However, this does not require the whole data structure to be
copied. When you create the new data structure you can refer back to parts
of the previous data structure because you know they cannot change (they
are immutable).

For example, consider a type representing a binary tree:

type 'a t =
| Empty
| Node of 'a t * 'a * 'a t

You can write a function to insert an element into an ordered tree like
this:

let rec insert x = function
| Empty -> Node(Empty, x, Empty)
| Node(l, v, r) when x<v -> Node(insert x l, v, r)
| Node(l, v, r) when x=v -> Node(l, x, r)
| Node(l, v, r) -> Node(l, v, insert x r)

Note that inserting an element into the left subtree creates a new
node "Node(insert x l, v, r)" that refers to the whole of the old right
subtree. Consequently, the right subtree is not copied (you might call it a
shallow copy).

> Can you recommend some good tutorials?


http://www.ffconsultancy.com/product...roduction.html
http://www.ffconsultancy.com/ocaml/benefits
http://www.ffconsultancy.com/ocaml

> I would be interested in, for example, how one would program pong in OCaml
> or any functional language.


The above pages describe a variety of different uses, from Sudoku Solving to
real-time visualization using OpenGL.

> What language do you recommend I start with?


If you're using Linux or Mac OS X, I recommend OCaml:

http://caml.inria.fr

If you're using Windows, I recommend F#:

http://research.microsoft.com/fsharp

We also have lots of F# tutorials and articles:

http://www.ffconsultancy.com/product...roduction.html
http://www.ffconsultancy.com/dotnet/fsharp

--
Dr Jon D Harrop, Flying Frog Consultancy
The OCaml Journal
http://www.ffconsultancy.com/product...ournal/?usenet
Reply With Quote
  #13  
Old 07-08-2007, 11:32 AM
Daniel T.
Guest
 
Default Re: Design Patterns and Functional programming

S Perryman <q@q.net> wrote:
> Daniel T. wrote:
> > Jon Harrop <jon@ffconsultancy.com> wrote:


> > Can you recommend some good tutorials? I would be interested in, for
> > example, how one would program pong in OCaml or any functional language.
> > What language do you recommend I start with?

>
> How about we start with something simple like writing a program to do stuff
> with stacks (read numbers from IO, push onto the stack, write top to IO and
> pop until stack empty etc) ?


That isn't my world. In my world, things react when they detect changes
in their environment. At its most fundamental, I see state changing over
time. How is that handled in FP languages?

> You know how to do this with an imperative prog lang.


I know how to program Pong in an imperative programming language as
well. Pong is simple (at least in imperative programming languages,) is
there a reason that it is too complex an example in an FP language?

Here's something simpler than Pong, a ball bouncing. The user can hit a
key and if he hits the key just as the ball hits the ground, the
magnitude of the ball's vector increases.
Reply With Quote
  #14  
Old 07-08-2007, 11:39 AM
H. S. Lahman
Guest
 
Default Re: Design Patterns and Functional programming

Responding to Harrop...

>>>Is there any literature describing how object-oriented design patterns
>>>reinvent existing techniques like functional programming?

>>
>>They don't.

>
>
> Here are some examples:
>
> Function object => Closure
> Factory => Curried function
> Singleton => Value
> Command => Variant
> Iterator => Fold/Zipper
> Chain of Responsibility => Event
> Inversion of Control => Continuation passing style


As Perryman's response (and yours to him!) indicate, FPLs and OOPLs both
provide syntax that enable the implementation of design patterns. My
point was that the design patterns exist independently of the solution
paradigm. The mapping between OOPLs and, say, GoF design patterns is
just more direct because an OOA/D notation was used to express the
design patterns themselves.

>>Design patterns exist outside both functional and OO
>>The OO paradigm just makes expressing design patterns easier because it
>>already emphasizes problem space abstraction.

>
>
> You mean design patterns try to solve the problems that object orientation
> has with abstraction?


I mean that one needs to represent design patterns to communicate them.
Since patterns, by their nature, are about abstraction and
generalization, an OOA/D notation is naturally suited to representing
them _as concepts_.

OTOH, expressing design patterns in an OOA/D notation creates problems
when one tries to map them into a non-OO development context. So if one
wants to map design patterns into FPL syntax rather than OOPL syntax,
one would be better expressing the design patterns in a different notation.

>>Since the OO and functional paradigms are fundamentally incompatible,

>
>
> Given that some languages provide both OO and FP paradigms and several
> languages even compile functional programs into object oriented
> intermediate representations (F# targetting .NET and Scala targetting the
> JVM, for example), in what sense are these paradigms "incompatible"? Do you
> mean "complementary"?


The issue is methodological (i.e., the way that applications are
constructed). For example, collaboration in functional programming is
inherently hierarchical while in OO development it is peer-to-peer. (One
can make a strong case that the primary goal of the OO paradigm is to
eliminate the hierarchical structure inherent in functional
decomposition and procedural message passing.) Thus OOPL procedures will
be designed differently than FPL procedures.

[Providing mapping between representations is an issue for MDA. In
theory any representation can be mapped into any other provided both
representations have a rigorous semantic model and the subject matter is
the same.]

>
> <snip exmple>
>
> You can see that the object oriented approach requires twice as much code.


As a general rule OO applications will be more verbose than either
functional or procedural applications. There are trade-offs in every
aspect of software development and that applies to overall paradigms as
well. Size and performance are trade-offs that the OO paradigm chooses
to make versus maintainability.

>>one would need a different representation of design to express design
>>patterns in a form that is unambiguously mappable to FPLs. At present
>>there does not seem to be a body of literature for functional
>>programming that provides the sort of design methodologies that the
>>OOA/D literature provides.

>
>
> Yes, there are certainly a lot more books discussing problems with
> abstraction in the context of object orientation.


Ah, I see where this is going. I am not going to get into a religious
discussion of OOPLs vs. FPLs. Ta-ta.


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info@pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH



Reply With Quote
  #15  
Old 07-08-2007, 11:58 AM
Daniel T.
Guest
 
Default Re: Design Patterns and Functional programming

Jon Harrop <jon@ffconsultancy.com> wrote:

> > Can you recommend some good tutorials?

>
> http://www.ffconsultancy.com/product...roduction.html
> http://www.ffconsultancy.com/ocaml/benefits
> http://www.ffconsultancy.com/ocaml
>
> > I would be interested in, for example, how one would program pong in OCaml
> > or any functional language.

>
> The above pages describe a variety of different uses, from Sudoku Solving to
> real-time visualization using OpenGL.


I'm downloading and building OCaml now, in the mean time...
How about an alarm clock example? Or simply a program that prints a '.'
on the screen every second?

How are such things done in a stateless environment?
Reply With Quote
  #16  
Old 07-08-2007, 01:02 PM
gpuchtel
Guest
 
Default Re: Design Patterns and Functional programming

On Jul 6, 11:48 am, Jon Harrop <j...@ffconsultancy.com> wrote:
> Is there any literature describing how object-oriented design patterns
> reinvent existing techniques like functional programming?
>
> --
> Dr Jon D Harrop, Flying Frog Consultancy
> The OCaml Journalhttp://www.ffconsultancy.com/products/ocaml_journal/?usenet


In 'Gulliver's Travels', "that all true believers break their eggs at
the convenient end." -- Jonathan Swift


Reply With Quote
  #17  
Old 07-08-2007, 01:05 PM
Jon Harrop
Guest
 
Default Re: Design Patterns and Functional programming

Dmitry A. Kazakov wrote:
>> How do you add that to the object oriented design?

>
> No problem actually. You first derive from abstract expression an abstract
> infix operation (that is - two arguments one result) and then specialize
> it to concrete operation.


Could you post working code for that design, please?

> BTW, in a real compiler you won't have them in the form you have proposed.


Most compilers written in Standard ML, Haskell or OCaml use this form.
Indeed, this carries through to machine code generation as the machine
itself doesn't implement n-ary addition.

> Think about optimizations made later during code generation. You would
> really wish to factorize infix commutative operators like a+b+c+d out into
> Sum(a,b,c,d). The number of arguments becomes variable.


If you wanted to do that then it is easy enough. Replace the binary Add
constructor with:

| Sum of expr * expr list

I don't think there is any point though.

> How do you add precedence to your design?


Precedence is implemented the same way in the functional and OO styles. For
programmatic construction, it is inherited from the use of infix operators.
For parsing, use yacc and specify the operator precedences.

> Association order?


Add clauses to rotate the abstract syntax tree as it is constructed:

| Add(f, Add(g, h)) -> f +: g +: h

| Mul(f, Mul(g, h)) -> f *: g *: h

> Association checks? [this is when x and y or z is illegal without
> brackets]


That is a check in the parser. Nothing to do with functional vs OO designs.

> What about types and types matching?


Type constructors handle run-time types. The pattern matches handle
deconstruction of boxes values (type matching). If you want static typing
then you must design and implement a static type checker in OCaml/SML/F#.
In Haskell, you can embed the static type system of a domain specific
language in Haskell's own type system and get it to do the static type
checking for you (Google for "GADTs"). The same can be done in C++ using
template metaprogramming. This is not related to functional vs OO style.

> Reasonable error diagnostic and recovery?


This is mostly automated by the "scrap your boilerplate" techniques in
Haskell and OCaml. This is not related to functional vs OO style.

> Array aggregates?


Add a constructor to the expr type:

# type expr =
| Int of int
| Array of expr array
| Add of expr * expr
| Mul of expr * expr;;

> Literals?


Add a rule to the grammar with an action that uses the Array constructor.

> Function calls?


See the complete interpreter in this post for a working example.

> Keyed parameter association? Defaulted parameters?


Implementation dependent: what semantics would you like them to support?

> Do you honestly believe that a syntax + semantic analyzer can be 100 lines
> long?


I've attached a 49-line interpreter for a dynamically-typed purely
functional programming language.

> If not, then what about readability, maintainability, reuse etc?


In this context, all much better with a functional style. This family of
languages were designed for compiler writing...

> Object-oriented only means that the tree and its nodes are considered
> objects of some types.


Yes. An object oriented approach can be quite devastating to readability and
maintainability, as I'm sure you'll agree if you try implementing this
simple functionality in an entirely OO style.

The following is a complete term-level interpreter for a dynamically-typed
functional programming language that supports higher-order functions and
currying:

open Camlp4.PreCast;;

let expr = Gram.Entry.mk "expr";;
EXTEND Gram
expr:
[ "prog" NONA
[ "if"; p = expr; "then"; t = expr; "else"; f = expr -> `If(p, t, f)
| "let"; "rec"; f = LIDENT; x = LIDENT; "="; body = expr; "in"; rest =
expr ->
`LetRec(f, x, body, rest) ]
| "equal" LEFTA
[ e1 = expr; "="; e2 = expr -> `Equal(e1, e2) ]
| "sum" LEFTA
[ e1 = expr; "+"; e2 = expr -> `Add(e1, e2)
| e1 = expr; "-"; e2 = expr -> `Add(e1, `Mul(`Int(-1), e2)) ]
| "product" LEFTA
[ e1 = expr; "*"; e2 = expr -> `Mul(e1, e2) ]
| "apply" LEFTA
[ e1 = expr; e2 = expr -> `Apply(e1, e2) ]
| "simple" NONA
[ v = LIDENT -> `Var(v)
| n = INT -> `Int(int_of_string n)
| "("; e = expr; ")" -> e ] ];
END;;

(* Evaluator *)
let int = function `Int n -> n | _ -> invalid_arg "int";;
let bool = function `Bool b -> b | _ -> invalid_arg "bool";;

let rec eval vars = function
| `Apply(func, arg) -> apply (eval vars func) (eval vars arg)
| `Add(e1, e2) -> `Int (int(eval vars e1) + int(eval vars e2))
| `Mul(e1, e2) -> `Int (int(eval vars e1) * int(eval vars e2))
| `Equal(e1, e2) -> `Bool (eval vars e1 = eval vars e2)
| `If(p, t, f) -> eval vars (if bool (eval vars p) then t else f)
| `Int i -> `Int i
| `LetRec(var, arg, body, rest) ->
let rec vars' = (var, `Closure(arg, vars', body)) :: vars in
eval vars' rest
| `Var s -> List.assoc s vars
and apply func arg = match func with
| `Closure(var, vars, body) -> eval ((var, arg) :: vars) body
| _ -> invalid_arg "Attempt to apply a non-function value";;

(* Top level *)
let string_of_value = function
| `Int n -> string_of_int n
| `Bool true -> "true"
| `Bool false -> "false"
| `Closure _ -> "<fun>";;

let () =
let program = Gram.parse expr Loc.ghost (Stream.of_channel stdin) in
let vars = ["true", `Bool true; "false", `Bool false] in
print_endline(string_of_value(eval vars program));;

This can interpret the following program, for example:

let rec fib n =
if n=0 then 0 else
if n=1 then 1 else
fib(n - 1) + fib(n - 2) in
fib 35

What would the equivalent be in an object oriented design?

--
Dr Jon D Harrop, Flying Frog Consultancy
The OCaml Journal
http://www.ffconsultancy.com/product...ournal/?usenet
Reply With Quote
  #18  
Old 07-08-2007, 01:36 PM
Jon Harrop
Guest
 
Default Re: Design Patterns and Functional programming

Dmitry A. Kazakov wrote:
>> How do you add that to the object oriented design?

>
> No problem actually. You first derive from abstract expression an abstract
> infix operation (that is - two arguments one result) and then specialize
> it to concrete operation.


Could you post working code for that design, please?

> BTW, in a real compiler you won't have them in the form you have proposed.


Most compilers written in Standard ML, Haskell or OCaml use this form.
Indeed, this carries through to machine code generation as the machine
itself doesn't implement n-ary addition.

> Think about optimizations made later during code generation. You would
> really wish to factorize infix commutative operators like a+b+c+d out into
> Sum(a,b,c,d). The number of arguments becomes variable.


If you wanted to do that then it is easy enough. Replace the binary Add
constructor with:

| Sum of expr * expr list

I don't think there is any point though.

> How do you add precedence to your design?


Precedence is implemented the same way in the functional and OO styles. For
programmatic construction, it is inherited from the use of infix operators.
For parsing, use yacc and specify the operator precedences.

> Association order?


Add clauses to rotate the abstract syntax tree as it is constructed:

| Add(f, Add(g, h)) -> f +: g +: h

| Mul(f, Mul(g, h)) -> f *: g *: h

> Association checks? [this is when x and y or z is illegal without
> brackets]


That is a check in the parser. Nothing to do with functional vs OO designs.

> What about types and types matching?


Type constructors handle run-time types. The pattern matches handle
deconstruction of boxes values (type matching). If you want static typing
then you must design and implement a static type checker in OCaml/SML/F#.
In Haskell, you can embed the static type system of a domain specific
language in Haskell's own type system and get it to do the static type
checking for you (Google for "GADTs"). The same can be done in C++ using
template metaprogramming. This is not related to functional vs OO style.

> Reasonable error diagnostic and recovery?


This is mostly automated by the "scrap your boilerplate" techniques in
Haskell and OCaml. This is not related to functional vs OO style.

> Array aggregates?


Add a constructor to the expr type:

# type expr =
| Int of int
| Array of expr array
| Add of expr * expr
| Mul of expr * expr;;

> Literals?


Add a rule to the grammar with an action that uses the Array constructor.

> Function calls?


See the complete interpreter in this post for a working example.

> Keyed parameter association? Defaulted parameters?


Implementation dependent: what semantics would you like them to support?

> Do you honestly believe that a syntax + semantic analyzer can be 100 lines
> long?


I've attached a 49-line interpreter for a dynamically-typed purely
functional programming language.

> If not, then what about readability, maintainability, reuse etc?


In this context, all much better with a functional style. This family of
languages were designed for compiler writing...

> Object-oriented only means that the tree and its nodes are considered
> objects of some types.


Yes. An object oriented approach can be quite devastating to readability and
maintainability, as I'm sure you'll agree if you try implementing this
simple functionality in an entirely OO style.

The following is a complete term-level interpreter for a dynamically-typed
functional programming language that supports higher-order functions and
currying:

open Camlp4.PreCast;;

let expr = Gram.Entry.mk "expr";;
EXTEND Gram
expr:
[ "prog" NONA
[ "if"; p = expr; "then"; t = expr; "else"; f = expr -> `If(p, t, f)
| "let"; "rec"; f = LIDENT; x = LIDENT; "="; body = expr; "in"; rest =
expr ->
`LetRec(f, x, body, rest) ]
| "equal" LEFTA
[ e1 = expr; "="; e2 = expr -> `Equal(e1, e2) ]
| "sum" LEFTA
[ e1 = expr; "+"; e2 = expr -> `Add(e1, e2)
| e1 = expr; "-"; e2 = expr -> `Add(e1, `Mul(`Int(-1), e2)) ]
| "product" LEFTA
[ e1 = expr; "*"; e2 = expr -> `Mul(e1, e2) ]
| "apply" LEFTA
[ e1 = expr; e2 = expr -> `Apply(e1, e2) ]
| "simple" NONA
[ v = LIDENT -> `Var(v)
| n = INT -> `Int(int_of_string n)
| "("; e = expr; ")" -> e ] ];
END;;

(* Evaluator *)
let int = function `Int n -> n | _ -> invalid_arg "int";;
let bool = function `Bool b -> b | _ -> invalid_arg "bool";;

let rec eval vars = function
| `Apply(func, arg) -> apply (eval vars func) (eval vars arg)
| `Add(e1, e2) -> `Int (int(eval vars e1) + int(eval vars e2))
| `Mul(e1, e2) -> `Int (int(eval vars e1) * int(eval vars e2))
| `Equal(e1, e2) -> `Bool (eval vars e1 = eval vars e2)
| `If(p, t, f) -> eval vars (if bool (eval vars p) then t else f)
| `Int i -> `Int i
| `LetRec(var, arg, body, rest) ->
let rec vars' = (var, `Closure(arg, vars', body)) :: vars in
eval vars' rest
| `Var s -> List.assoc s vars
and apply func arg = match func with
| `Closure(var, vars, body) -> eval ((var, arg) :: vars) body
| _ -> invalid_arg "Attempt to apply a non-function value";;

(* Top level *)
let string_of_value = function
| `Int n -> string_of_int n
| `Bool true -> "true"
| `Bool false -> "false"
| `Closure _ -> "<fun>";;

let () =
let program = Gram.parse expr Loc.ghost (Stream.of_channel stdin) in
let vars = ["true", `Bool true; "false", `Bool false] in
print_endline(string_of_value(eval vars program));;

This can interpret the following program, for example:

let rec fib n =
if n=0 then 0 else
if n=1 then 1 else
fib(n - 1) + fib(n - 2) in
fib 35

What would the equivalent be in an object oriented design?

--
Dr Jon D Harrop, Flying Frog Consultancy
The OCaml Journal
http://www.ffconsultancy.com/product...ournal/?usenet
Reply With Quote
  #19  
Old 07-08-2007, 02:26 PM
Jon Harrop
Guest
 
Default Re: Design Patterns and Functional programming

Daniel T. wrote:
> That isn't my world. In my world, things react when they detect changes
> in their environment. At its most fundamental, I see state changing over
> time. How is that handled in FP languages?


Consider integrating the dynamics of accelerating particles over time. In an
imperative style, you define the position "x" and velocity "dx" to be
mutable and then alter them in-place when updating a particle:

# type particle = {mutable x: float; mutable dx: float};;
# let update g dt p =
p.x <- p.x +. dt *. p.dx;
p.dx <- p.dx +. dt *. g;;
val update : float -> float -> particle -> unit = <fun>

For example, updating an array of particles in place:

# let state = [|{x=0.; dx=1.}; {x=0.; dx=2.}|];;
val state : particle array = [|{x = 0.; dx = 1.}; {x = 0.; dx = 2.}|]
# Array.iter (update 0.1 0.001) state;;
- : unit = ()
# state;;
- : particle array = [|{x = 0.001; dx = 1.0001}; {x = 0.002; dx = 2.0001}|]

To avoid mutation, you simply return a new state rather than mutating the
existing state:

# type particle = {x: float; dx: float};;
type particle = { x : float; dx : float; }
# let update g dt p =
{x = p.x +. dt *. p.dx;
dx = p.dx +. dt *. g};;
val update : float -> float -> particle -> particle = <fun>

Now you "map" the update function over an array of particles to create a new
array of particles:

# let state = [|{x=0.; dx=1.}; {x=0.; dx=2.}|];;
val state : particle array = [|{x = 0.; dx = 1.}; {x = 0.; dx = 2.}|]
# Array.map (update 0.1 0.001) state;;
- : particle array = [|{x = 0.001; dx = 1.0001}; {x = 0.002; dx = 2.0001}|]

> I know how to program Pong in an imperative programming language as
> well. Pong is simple (at least in imperative programming languages,) is
> there a reason that it is too complex an example in an FP language?


Pong is probably best implemented in an imperative style (note that OCaml is
also an imperative language, as the above example showed). For slightly
more complicated examples (even a Sudoku solver) the back end of a GUI
application can be written very elegantly in a purely functional style
(without mutation). I would still use mutation in the front-end though.

> Here's something simpler than Pong, a ball bouncing. The user can hit a
> key and if he hits the key just as the ball hits the ground, the
> magnitude of the ball's vector increases.


Here is an OCaml program that simulates the dynamics of dozens of rigid
balls in real time and visualizes the result using OpenGL, in <400 lines of
code:

http://www.ffconsultancy.com/ocaml/balls?co

I just wrote a complete GUI Sudoku Solver in ~100 lines of code for an OCaml
Journal article...

--
Dr Jon D Harrop, Flying Frog Consultancy
The OCaml Journal
http://www.ffconsultancy.com/product...ournal/?usenet
Reply With Quote
  #20  
Old 07-08-2007, 02:28 PM
Patrick May
Guest
 
Default Re: Design Patterns and Functional programming

"H. S. Lahman" <h.lahman@verizon.net> writes:
> Responding to Harrop...
>> Function object => Closure
>> Factory => Curried function
>> Singleton => Value
>> Command => Variant
>> Iterator => Fold/Zipper
>> Chain of Responsibility => Event
>> Inversion of Control => Continuation passing style

>
> As Perryman's response (and yours to him!) indicate, FPLs and OOPLs
> both provide syntax that enable the implementation of design
> patterns. My point was that the design patterns exist independently
> of the solution paradigm.


Peter Norvig noted almost 10 years ago that 16 of the 23 patterns
in the GoF book are "invisible or simpler" in Lisp
(http://norvig.com/design-patterns). This suggests that, rather than
existing independently of the solution domain, many design patterns
are actually standardized workarounds for limitations in the language
used for implementation.

Paul Graham touches on this in his essay "Revenge of the Nerds":

"When I see patterns in my programs, I consider it a sign of
trouble. The shape of a program should reflect only the problem
it needs to solve. Any other regularity in the code is a sign,
to me at least, that I'm using abstractions that aren't powerful
enough -- often that I'm generating by hand the expansions of
some macro that I need to write."

(http://www.paulgraham.com/icad.html)

I find this argument compelling. Many patterns are symptoms of a
problem, not aspects of a solution.

Regards,

Patrick

------------------------------------------------------------------------
S P Engineering, Inc. | Large scale, mission-critical, distributed OO
| systems design and implementation.
pjm@spe.com | (C++, Java, Common Lisp, Jini, middleware, SOA)
Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 01:27 AM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.