Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have been interested in some of the concepts of functional programming lately. I have used OOP for some time now. I can see how I would build a fairly complex app in OOP. Each object would know how to do things that object does. Or anything it's parents class does as well. So I can simply tell Person().speak() to make the person talk.

But how do I do similar things in functional programming? I see how functions are first class items. But that function only does one specific thing. Would I simply have a say() method floating around and call it with an equivalent of Person() argument so I know what kind of thing is saying something?

So I can see the simple things, just how would I do the comparable of OOP and objects in functional programming, so I can modularize and organize my code base?

For reference, my primary experience with OOP is Python, PHP, and some C#. The languages that I am looking at that have functional features are Scala and Haskell. Though I am leaning towards Scala.

Basic Example (Python):

Animal(object):
    def say(self, what):
        print(what)

Dog(Animal):
    def say(self, what):
        super().say('dog barks: {0}'.format(what))

Cat(Animal):
    def say(self, what):
        super().say('cat meows: {0}'.format(what))

dog = Dog()
cat = Cat()
dog.say('ruff')
cat.say('purr')
share|improve this question
    
Scala is designed as OOP + FP, so you dont have to choose –  Karthik T Dec 19 '12 at 5:41
1  
Yes I am aware, but i am also wanting to know for intellectual reasons. I cannot find anything on the equivalent of object in functional languages.As for scala, i would still want to know when/where/how i should use functional over oop, but that IMHO is another question. –  skift Dec 19 '12 at 5:51
1  
"Particularly over-emphasized, IMO is the notion that we don't maintain state.": This is the wrong notion. It is not true that FP does not use state, rather FP handles state in a different way (e.g. monads in Haskell or unique types in Clean). –  Giorgio Dec 19 '12 at 7:05
1  
possible duplicate of How to organize functional programs –  Doc Brown Dec 19 '12 at 7:08
3  
possible duplicate of Functional Programming vs. OOP –  Caleb Dec 19 '12 at 9:00

6 Answers 6

What you are really asking about here is how to do Polymorphism in functional languages, i.e. how to create functions that behave differently based on their arguments.

Note the first argument to a function is typically equivalent to the "object" in OOP, but in functional languages you usually want to separate functions from data, so the "object" is likely to be a pure (immutable) data value.

Functional languages in general provide various options for achieving polymorphism:

  • Something like multimethods which call a different function based on examining the arguments provided. This can be done on the type of the first argument (which is effectively equal to the behaviour of most OOP languages), but could also be done on other attributes of the arguments.
  • Prototype / object-like data structures which contain first-class functions as members. So you could embed a "say" function inside your dog and cat data structures. Effectively you have made the code part of the data.
  • Pattern matching - where pattern matching logic is built into the function definition, and ensures different behaviours for different parameters. Common in Haskell.
  • Branching / conditions - equivalent to if / else clauses in OOP. Might not be highly extensible, but can still be appropriate in many cases when you have a limited set of possible values (e.g. was the function passed a number or a string or null?)

As an example, here's a Clojure implementation of your problem using multimethods:

;; define a multimethod, that dispatched on the ":type" keyword
(defmulti say :type)  

;; define specific methods for each possible value of :type. You can add more later
(defmethod say :cat [animal what] (println (str "Car purrs: " what)))
(defmethod say :dog [animal what] (println (str "Dog barks: " what)))
(defmethod say :default [animal what] (println (str "Unknown noise: " what)))

(say {:type :dog} "ruff")
=> Dog barks: ruff

(say {:type :ape} "ook")
=> Unknown noise: ook

Note that this behaviour doesn't require any explicit classes to be defined: regular maps work fine. The dispatch function (:type in this case) could be any arbitrary function of the arguments.

share|improve this answer
    
Not 100% clear, but enough to see where you are going. I could see this as the 'animal' code in a given file. Also the part on branching/conditions is good too. I had not considered that as the alternative to if/else. –  skift Dec 19 '12 at 8:12

In Haskell, the closest you have is "class". This class though not as same as the class in Java and C++ , will work for what you want in this case.

In your case this is how your code will look.

class Animal a where 
say :: String -> sound 

Then you can have individual data types adapting these methods.

instance Animal Dog where
say s = "bark " ++ s 

EDIT :- Before you can specialize say for Dog you need to tell the system that Dog is animal.

data Dog =  \--something here --\ (deriving animal)

EDIT :- For Wilq.
Now if you want to use say in a function say foo, you will have to tell haskell that foo can only work with Animal.

foo :: (Animal a) => a -> String -> String
foo a str = say a str 

now if you call foo with dog it will bark, if you call with cat it will meow.

main = do 
let d = dog (\--cstr parameters--\)
    c = cat  
in show $ foo d "Hello World"

You now can not have any other definition of function say. If say is called with anything not animal will cause compile error.

share|improve this answer
    
ill have to real a little more on haskell to understand thi fully, but i think i get the jist of it. im still curious though how this would line up with more a complex code base. –  skift Dec 19 '12 at 7:44
    
nitpick Animal should be capitalized –  jozefg Dec 20 '12 at 0:55
1  
How does the say function know that you call it on a Dog if it only takes a String? And isn't "deriving" only for some built-in classes? –  WilQu Dec 20 '12 at 12:43

This is not a direct answer, nor is it necessarily 100% accurate as I'm not a functional language expert. But in either case, I'll share with you my experience...

About a year ago I was in a similar boat as you. I've done C++ and C# and all of my designs were always very heavy on OOP. I've heard about FP languages, read some info online, flipped through F# book but still couldn't really grasp how can an FP language replace OOP or be useful in general as most examples I've seen were just too simple.

For me the "breakthrough" came when I decided to learn python. I downloaded python, then went to project euler homepage and just started doing one problem after another. Python is not necessarily an FP language and you can certainly create classes in it, but compared to C++/Java/C#, it does have a lot more of FP constructs, so when I started playing with it, I made a conscious decision not to define a class unless I absolutely had to.

What I found interesting about Python was how easy and natural it was to take functions and "stitch" them to create more complex functions and in the end your problem was still solved by calling a single function.

You pointed out that when coding you should follow single responsibility principle and that is absolutely correct. But just because function is responsible for a single task, doesn't mean it can only do the absolute bare minimum. In FP, you still have abstraction levels. So your higher-level functions can still do "one" thing but they can delegate to lower level functions to implement finer details of how that "one" thing is achieved.

The key with FP however is that you do not have side-effects. As long as you treat the application as simple data transformation with defined set of inputs and set of outputs, you can write FP code that would accomplish what you need. Obviously not every application will fit nicely into this mold, but once you start doing it, you'll be surprised how many applications do fit. And this is where I think Python, F# or Scala shine because they give you FP constructs but when you do need to remember your state and "introduce side-effects" you can always fall back on true and tried OOP techniques.

Since then, I've written a whole bunch of python code as utilities and other helper scripts for internal work and some of them scaled out fairly far but by remembering basic SOLID principles, most of that code still came out very maintainable and flexible. Just like in OOP your interface is a class and you move classes around as you refactor and/or add functionality, in FP you do exactly same thing with functions.

Last week I started coding in Java and since then, almost on daily basis I get reminded that when in OOP, I have to implement interfaces by declaring classes with methods that override functions, in some cases I could achieve the same thing in Python using a simple lambda expression, for example, 20-30 lines of code that I wrote to scan a directory, would've been 1-2 lines in Python and no classes.

FP themselves are higher level languages. In Python (sorry, my only FP experience) I could put together list comprehension inside another list comprehension with lambdas and other stuff thrown in and the whole thing would only be 3-4 lines of code. In C++, I could absolutely accomplish the same thing, but because C++ is lower-level, I would have to write much more code than 3-4 lines and as the number of lines increases, my SRP training would kick in and I would start thinking about how to split up code into smaller pieces (i.e. more functions). But in the interests of maintainability and hiding implementation details, I would put all those functions into the same class and make them private. And there you have it... I just created a class whereas in python I would have written "return (.... lambda x:.. ....)"

share|improve this answer
    
Yes it doesnt directly answer the question, but still a great response. when i write smaller scripts or packages in python, i dont always use classes either. many times just having it in a package format fits perfectly. especially if i do not need state. I also agree that list comprehensions are damn useful as well. Since reading up on FP, i have realized how much more powerful they can be. which has then led me to wanting to learn more about FP, compared to OOP. –  skift Dec 19 '12 at 8:02
    
Great answer. Speaks to everybody standing at the side of the funcctional pool but not sure whether to dip their toe in the water –  David Relihan Dec 25 '12 at 22:31

Functional languages use 2 constructs to achieve polymorphism:

  • First order functions
  • Generics

Creating polymorphic code with those is completely different than how OOP uses inheritance and virtual methods. While both of those might be available in your favorite OOP language (like C#), most functional languages (like Haskell) kick it up to eleven. It is rare to function to be non-generic and most functions have functions as parameters.

It is hard to explain like this and it will require lot of your time to learn this new way. But to do this, you need to completely forget OOP, because that's not how it works in functional world.

share|improve this answer
    
That is not really an answer to the question (IMHO the OP primarily wants to know "how to modularize and organize my code base comparable to OOP"). –  Doc Brown Dec 19 '12 at 7:30
1  
OOP is all about polymorphism. If you think OOP is about having functions tied to your data, then you know nothing about OOP. –  Euphoric Dec 19 '12 at 7:32
3  
polymorphism is just one aspect of OOP, and I think not the one the OP is really asking about. –  Doc Brown Dec 19 '12 at 7:34
1  
Polymorphism is key aspect of OOP. Everything else is there to support it. OOP without inheritance/virtual methods is almost exactly same as procedural programming. –  Euphoric Dec 19 '12 at 7:38
1  
You don't always need an interface. But they are highly useful when you do need them. And IMO another important part of OOP. As for modules go in Haskell, I think this is probably closest to OOP for functional languages, as far as code organization is concerned. At least from what I have read so far. I know they're still very different. –  skift Dec 19 '12 at 8:34

it really depends on what you want to accomplish.

if you just need a way to organize behaviour based on selective criteria, you can use e.g. a dictionary (hash-table) with function-objects. in python it could be something along the lines of:

def bark(what):
    print "barks: {0}".format(what) 

def meow(what):
    print "meows: {0}".format(what)

def climb(how):
    print "climbs: {0}".format(how)

if __name__ == "__main__":
    animals = {'dog': {'say': bark},
               'cat': {'say': meow,
                       'climb': climb}}
    animals['dog']['say']("ruff")
    animals['cat']['say']("purr")
    animals['cat']['climb']("well")

note however, that (a) there are no 'instances' of dog or cat and (b) you will have to keep track of the 'type' of your objects yourself.

like for example: pets = [['martin','dog','grrrh'], ['martha', 'cat', 'zzzz']]. then you could do a list comprehension like [animals[pet[1]]['say'](pet[2]) for pet in pets]

share|improve this answer

You could do something like this .. php

    function say($whostosay)
    {
        if($whostosay == 'cat')
        {
             return 'purr';
        }elseif($whostosay == 'dog'){
             return 'bark';
        }else{
             //do something with errors....
        }
     }

     function speak($whostosay)
     {
          return $whostosay .'\'s '.say($whostosay);
     }
     echo speak('cat');
     >>>cat's purr
     echo speak('dog');
     >>>dogs's bark
share|improve this answer
    
I haven't given any negative votes. But my guess is that it is because this approach is neither functional not object oriented. –  Manoj R Dec 19 '12 at 13:20
    
But the concept conveyed is close to the pattern matching used in functional programming, i.e. $whostosay becomes the object type that determines what gets executed. The above can be modified to additionally accept another parameter $whattosay so that a type that supports it (e.g. 'human') can make use of it. –  syockit Nov 14 '13 at 17:20

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.