Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Programming Examples: Declarative, Imperative, Functional, Etc.

by aaron_baugher (Deacon)
on Jul 25, 2012 at 13:32 UTC ( #983655=perlquestion: print w/ replies, xml ) Need Help??
aaron_baugher has asked for the wisdom of the Perl Monks concerning the following question:

I've been reading lately about different programming styles: declarative, imperative, procedural, functional, and object oriented, among others. I'm having trouble seeing the distinctions between them and getting a grasp of the differences. The comparisons I've found so far aren't much help: this Wikipedia page on imperative_programming, for instance, includes these statements:

  • Procedural programming is imperative programming in which...
  • Procedural programming could be considered as a step towards declarative programming.
  • Declarative programming is a non-imperative style of programming...

So....procedural programming is imperative, but it's also a step towards declarative, which is not imperative.... My head hurts.

I understand some of the concepts, like how purely functional programming doesn't allow side effects, and I understand how objects work. But with these other terms, there seems to be a lot of overlap, and I'm starting to suspect that a certain amount of semantic nit-picking is being done to fill Computer Science textbooks.

So, finally to my question: Does anyone know of a comparison of programming styles that uses Perl for examples? Do any of the Perl books out there include such a thing? I'm picturing a simple task like a random number guesser (pick a number between 1-10, and it tells you whether you guessed right or not) written in the different styles. There would be an OO version, a functional version, a procedural version, and so on, all performing the same task, so it would be easy to see the differences. I assume Perl can be written in any of these ways, though it may lend itself more to some than others.

If nothing like that exists, I think it'd make a good meditation. I'd write it myself, but I don't understand the subject well enough yet. I'm not even sure what style I program in!

Aaron B.
Available for small or large Perl jobs; see my home node.

Comment on Programming Examples: Declarative, Imperative, Functional, Etc.
Re: Programming Examples: Declarative, Imperative, Functional, Etc.
by MidLifeXis (Prior) on Jul 25, 2012 at 13:50 UTC

    Some languages lend themselves better to some styles of programming. Which is a reason why it is occasionally suggested to learn things like java, lisp, and so on. Techniques learned in each of these may then be able to be applied in other languages.

    --MidLifeXis

Re: Programming Examples: Declarative, Imperative, Functional, Etc.
by tobyink (Abbot) on Jul 25, 2012 at 14:05 UTC

    Programming styles are like beard styles. People give names to different styles, but there's a lot of overlap and grey areas between them, and some styles simply defy categorisation.

    One of the nice things about Perl is that it pretty much allows you to take your pick. You can choose a programming style that is appropriate to the task at hand.

    Here's a brief rundown of the styles you mentioned...

    declarative programming

    A big umbrella term.

    If you use SQL, then you already do this. In a declarative programming style you describe the results that you want, but not how to get there. When you're writing SQL, you don't describe what order to do cross-table joins in; you don't tell the engine which indexes to consult; you just tell it what data you want, and the SQL engine figures out the best way to get it.

    There's a programming language called Prolog which is beloved of computer science departments worldwide but little used outside academia which is a declarative logic programming language. You tell it facts like lives(John, London) and based_at(GlaxoSmithKline, London) and ask it queries like potentialEmployer(John, ?) at it will do all the inferencing and searching and stuff.

    Logical programming like Prolog is pretty much the only fully declarative programming style. Most other programming styles tend to mix declarative and imperative aspects. As I said, this is big umbrella term.

    imperative programming

    The other umbrella.

    Anything that isn't declarative can be categorised as imperative. The word "imperative" comes from the Latin "impero" meaning "I command". It's the same place we get "emperor" from, and that's quite apt. You're the emperor. You give the computer little orders to do and it does them one at a time and reports back.

    This is quite imperative:

    my $x = 4; my $y = 3; my $z = $x * $y; say $z;

    Now we'll get to the other programming styles which are somewhere between.

    procedural programming

    Procedural programming is imperative programming where you're allowed to write reusable subs/functions. Pretty much every imperative programming language allows you to write these now, so it's almost a synonym for imperative programming.

    functional programming

    In functional programming you compose your program of short functions. All code is within a function. All variables are scoped to the function. Whatsmore, within a function, you cannot modify any variables.

    Sounds like quite a restriction, doesn't it? But actually you can get most stuff done pretty elegantly. And the restrictions add up to create a situation which is very good for running computations in parallel.

    Haskell is a good example of a functional programming language. The first Perl 6 implementation (Pugs) was written in Haskell.

    If you find yourself using, grep, map and the goodies from List::Util and List::MoreUtils a lot, then chances are you'd be very comfortable with functional programming.

    Functional programming is generally considered to be quite a declarative style. If you're writing a grep or map in Perl, you probably don't really care about which order the iterations are evaluated in (though you often care what order the results are returned in), and you probably don't care whether they're evaluated in series or in parallel. That is, you're caring about the results not how they're calculated... declarative.

    Other paradigms common in functional programming include currying and more generally first-class functions (i.e. functions which are a datatype in their own right and can be passed to other functions as parameters - this is very much possible in Perl).

    object-oriented programming

    In object oriented programming you create complex data structures known as objects to model the problem domain. Objects tend to have properties (e.g. an object representing a person might have a name and a date of birth as properties) and methods (i.e. things they can do).

    Most object-oriented programming languages these days are also class-oriented. This means that all objects have to be members of a specific class, which defines what methods and properties it may have. Java is the classic example of a class-oriented programming language.

    A notable example of a non class-oriented, but object-oriented programming language is Javascript which uses prototypes to provide sort of templates for the construction of new objects.

    Big questions in object oriented programming are whether languages should support single or multiple inheritance; and whether objects should be mutable or not. (Immutable objects bring aspects of functional programming to OO.)

    Object oriented programming is kinda declarative, but the methods are usually defined quite procedurally. Of course, the principle of encapsulation says that we must ignore how the methods are internally implemented. Pay no attention to that man behind the curtain! Therefore by implication, object oriented programming is completely declarative. :-)

    Object-oriented programming is quite commonly done in Perl these days, particularly class-oriented programming because Perl makes that so easy. Other non-class-based OO can usually be pulled off in Perl too, but some are harder than others.

    Moose gives you a really good framework for class-based and role-based OO in Perl.

    Quite often people will categorise languages into these different styles, but it's really a mistake to do so. It is a oft-quoted witticism that you can write FORTRAN in any programming language. FORTRAN was (technically is) the quintessential imperative programming language. It did support function calls (i.e. procedural programming) but (I may be getting a little technical here) because these weren't implemented using a stack they were little more than syntactic sugar for GOTO.

    So what people mean is that it's possible to write in a horrible, nasty imperative style (yes, imperative programming is generally looked down upon) even in languages not thought of as imperative. For example in Java you can create a single class with a single method and code your entire program into that method. And although C is generally considered procedural, via careful naming conventions and calling conventions for functions, and good use of structs, you can program in quite an object-oriented style.

    Of course, sometimes your choice of language can make a particular style quite tricky and ugly. You have to jump through a lot of hoops to achieve anything even vaguely like first-class functions in Java, making many functional programming techniques difficult.

    OK, some practical examples. These are several different ways to sum a list of numbers...

    imperative
    use 5.010; my @numbers = qw(1 3 5 6 7 8); my $sum = 0; for my $num (@numbers) { $sum += $num; } say $sum;
    procedural
    use 5.010; my @numbers = qw(1 3 5 6 7 8); sub sum { my $sum = 0; for my $num (@_) { $sum += $num; } return $sum; } say sum(@numbers);
    functional
    use 5.010; my @numbers = qw(1 3 5 6 7 8); sub reduce (&@) { my ($code, $first, @rest) = @_; return $first unless @rest; return $code->( $first, reduce($code, @rest), ); } sub sum { return reduce { $_[0] + $_[1] } @_; } say sum @numbers;

    Which looks very complicated, but actually the reduce function is incredibly reusable for other tasks, and many programming languages will provide a reduce function out of the box. (Perl's List::Util module provides one and has been included in the Perl core since 5.8. I didn't use their one but wrote my own as an illustration.)

    Interesting thing to notice: of the examples here, this is the only one that doesn't contain a looping construct. (The recursive nature of reduce is used instead.)

    object-oriented
    use 5.010; use IO::Handle; my @numbers = qw(1 3 5 6 7 8); { package Sum; use Any::Moose; has total => (is => 'rw', isa => 'Num', default => 0); sub add { my ($self, $num) = @_; $self->total( $self->total + $num ); } } my $answer = Sum->new; $answer->add($_) for @numbers; STDOUT->say( $answer->total );

    Perl (more than any other language I've tried) gives you tremendous freedom to take your pick of programming style depending on the task at hand. Some new styles even seem to be developing within Perl that don't seem to exist elsewhere. (One I can think of appears to be the emerging habit of using Moose objects as memoization containers and lazy evaluators for complex procedures.)

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
      like beard styles... but there's a lot of ... grey areas
      Amen Brother.

      TJD

      Thanks very much for the detailed explanation and examples! I understand the differences much better now.

      I think part of my problem was that I assumed these were all different choices at the same level, when they aren't. Now I see declarative/imperative at one level, with procedural/functional/object-oriented at a higher level. In other words, your procedures/functions/objects may contain code that is imperative or declarative or (most likely) some mix of the two.

      I think the other problem was that I got hung up on the definition of declarative as (from the Wiki page), "describing what the program should accomplish, rather than describing how to go about accomplishing it." It seems to me that unless you're writing machine code at the lowest level, that's always the case to some extent. For instance, if I write:

      my $x = 3;

      I don't care how or where perl stores the value of $x, whether it stores it as a string or integer or floating point value, how many bytes it takes, or how it marks it as belonging to the current scope. I only care that when I write $x again, perl will replace it with 3, and that it will disappear at the appropriate time when the current scope ends. So although that seems like a straightforward imperative command, there's also a lot that's declarative about it.

      I can see the distinction between that and purely declarative commands, though, so maybe I'm just being too picky.

      I've been working through Higher Order Perl and Paul Graham's On Lisp, both of which get into functional programming, and it looks excellent. It's just plain harder than the other methods, though, at least for me. Maybe that's because my background was heavily imperative: BASIC 7.0, then 8502 and Z80 machine language and assembly, then shell, some C, and then to Perl. I suppose had I started with something like Lisp, it would come more naturally. I think it's worth struggling through the learning curve, though.

      Aaron B.
      Available for small or large Perl jobs; see my home node.

Re: Programming Examples: Declarative, Imperative, Functional, Etc.
by choroba (Abbot) on Jul 25, 2012 at 15:30 UTC

      Thank you, those examples are very helpful. Now I'm wondering what category "chaining" of commands falls into, like this sort of thing in jQuery:

      $('#tag').first.parent.parent.addClass('new');

      Is that just functional programming written backwards?

      Aaron B.
      Available for small or large Perl jobs; see my home node.

Re: Programming Examples: Declarative, Imperative, Functional, Etc.
by Anonymous Monk on Jul 26, 2012 at 02:01 UTC
    A good example of declarative programming is ... the spreadsheet. It is not a strict example but it does give the flavor of the idea: you're telling the system about, shall we say, "the goals," and letting the programming language fill in the details of how to get there. Procedural programming, on the other hand, gives you the ability to tell the computer precisely what you want it to do from one nanosecond to the next but really nothing at all about the problem being solved.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://983655]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (8)
As of 2014-09-22 19:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (198 votes), past polls