DEV Community

Discussion on: Why I love learning functional programming

Collapse
 
pentacular profile image
pentacular

What does expressing an eagerly evaluated imperative operation in a functional style have to do with being declarative programming?

Thread Thread
 
savagepixie profile image
SavagePixie • Edited

Maybe you should look up a quick definition of declarative programming.

The difference between imperative and declarative is not in the operations you use but in the constructs. The example is declarative rather than imperative because the logic is expressed without an explicit control flow.

Thread Thread
 
pentacular profile image
pentacular

a.b(c).d(e) has no explicit flow control?

What an interesting idea ...

It looks very explicitly defined by the semantics of ecmascript to me.

But perhaps I'm missing something -- could you explain more about how a.b(c).d(e), etc, has no explicit flow control?

Thread Thread
 
savagepixie profile image
SavagePixie • Edited

Certainly. If we oversimplify it, in computer science control flow refers to statements such as ifs or fors.

As you can see, in a.b(c).d(e) there are no such statements. So there is no explicit imperative structure to control the flow of execution. There is only one execution branch explicitly stated.

By contrast, something like the following code would have explicit control flow:


if (a) {
  for (let i = 0; i < 12; i++) b(i)
} else {
  switch (c) {
    case 2:
      d(e)
      break;
    ...
  }
}

As you can see, the difference is that there are control flow starements to control the flow of execution. If you look at Wikipedia's page for control flow it even lists the control flow structures that exist.

Thread Thread
 
pentacular profile image
pentacular

Let us note that a.b(c).d(e) is a chain of explicit procedure calls.

Are you saying that procedures calls don't affect flow control?

This is a novel concept to me, and I look forward to reading your explanation of how this works. :)

Thread Thread
 
savagepixie profile image
SavagePixie • Edited

Are you saying that procedures calls don't affect flow control?

No, I'm saying that list.filter(isEven).map(double) has no explicit control flow statements. The key here is the difference between implicit and explicit.

If you want to use the expression "control flow" in a different way than the standard definition in CS, be my guest. Just don't get surprised that everyone else means something different.

Also, a.b(c).d(e) is nothing but a bunch of letters and punctuation marks. Discussing whether that's declarative or not is like discussing whether a = 12 is declarative. The example was using filter with a predicate and map rather than using explicit control flow statements. If you want to talk code, give me a real example. a.b(c).d(e) could just be anything in any context, so there's little point in discussing that.

Thread Thread
 
pentacular profile image
pentacular

Let's start with list.filter(isEven).

In javascript, this is not a bunch of letters and punctuation marks, it is a method invocation.

Now, let's take a look at the Wikipedia page you referred to on flow control.

Subroutine
The terminology for subroutines varies; they may alternatively be known as routines, procedures, functions (especially if they return results) or methods (especially if they belong to classes or type classes).

Unsurprisingly, method calls are included as flow control operations.

This is unsurprising, since method calls transfer flow control to somewhere else -- the method being called.

So, list.filter(isEven) is an explicit flow control operation.

Now, if we can agree on that basic point, I suggest you go back and re-read what I've written so far, with that understanding in mind.

Thread Thread
 
savagepixie profile image
SavagePixie • Edited

I have actually re-read everything you've written so far, and I'm starting to wonder if we're even talking about the same sort of stuff. So perhaps you might explain what you understand as declarative programming?

As a response to your previous comment, my take is this: list.filter(isEven).map(double) does not have an explicit description of its control flow. A runtime or compiler might run them one after the other or might lump them together in one iteration. It can do that because the construct itself is not describing step by step how the code should be evaluated. It is just describing what should happen to the data. The specifics of how (e.g. one iteration over the list or two) are left to the language's implementation. A piece of code doesn't become imperative programming, simply because there is one single primitive, especially when said primitive is a subroutine.

Also, this is an aside and not that important, but it's control flow, not flow control. Flow control refers to the management of data transmission rate between a sender and a receiver.

Thread Thread
 
pentacular profile image
pentacular

Then your conclusion is that wrapping anything in a procedure makes it declarative, making declarative code equivalent to procedural abstraction.

Being able to rearrange how list.filter(isEven).map(double) executes doesn't mean that the control flow is not explicit.

Let's rephrase your argument to be about for loops, and see that it holds true to the same degree.

"A for loop does not have an explicit description of its control flow. A runtime or compiler might run them one after the other or might lump them together in one iteration. It can do that because the construct itself is not describing step by step how the code should be evaluated. It is just describing what should happen to the data."

This claim is incorrect for a couple of reasons.

  1. If we understand the effects of a piece of code, regardless of how it is expressed, we can replace that piece of code with another piece of code which has the same effects. This is the basis of optimizing compilation.

  2. In javascript, list.filter(isEven).map(double) describes method calls. It is describing step by step how the code should be evaluated. It is not making declarations about how the data should be changed. In some other language this might not be the case, but we're talking about javascript.

"A piece of code doesn't become imperative programming, simply because there is one single primitive, especially when said primitive is a subroutine."

Perhaps not, but your argument hinges on "explicit control flow operations", which clearly include procedure calls.

Is your claim that "a piece of code becomes declarative, simply because it is wrapped in a procedure"? :)

Regarding flow control -- we were talking of transfer of control over the control flow, control flow is a flow, and so we can refer to this as flow control -- English is flexible, and writing out control flow control is awkward.

Thread Thread
 
savagepixie profile image
SavagePixie

No, sorry, you can't change my argument and then make a rebuttal for that. That is called a strawman and is not an honest way to engage in a discussion.

Thread Thread
 
pentacular profile image
pentacular

Which part did I change?