DEV Community

Cover image for If - procedural, functional, object-oriented
stereobooster
stereobooster

Posted on • Originally published at stereobooster.com on

If - procedural, functional, object-oriented

Let's talk about the if statement. A lot of people view it as the corner-stone of programming, for example, whenever I discuss the question if CSS is a programming language or not (it is) somebody would say: "CSS doesn't have if statement so it can't be considered as PL". I don't know where this idea comes from. if statement is one of the many control flow structures, like goto, jump, exceptions, loops, etc.

Procedural

I guess the most known form of if is it's "procedural" or structured form:

if (condition) {
  thenAction();
} else {
  elseAction();
}

By "procedural" I mean the type of imperative programming, but more organized than just Von Neumann machine. (Imperative style of programming is when you give direct instructions to the machine do step 1, step 2, etc.)

Instead of the precise definition, I will give examples:

  • Most imperative languages: assembly (machine code), Fortran.
  • Less imperative languages, so-called "procedural" or structured): Algol, Pascal (I guess Go as well).

Functional

To impelemnt if in functional style we need to restrict ourselves to functions only:

// Implementation:
const True = (x) => (y) => x;
const False = (x) => (y) => y;
const If = (condition, thenAction, elseAction) => {
  const action = condition(thenAction)(elseAction);
  return action();
}
// Usage:
If(condition, thenAction, elseAction);

This idea is a direct translation of Church Encoded True, False in lambda calculus:

True = λx.λy.x
False = λx.λy.y

Object-oriented

To impelemnt if in functional style we need to restrict ourselves to objects only:

// Implementation:
class TrueClass {
  Then(callBack) {
    callBack.call()
    return this
  }
  Else(callBack) {
    return this
  }
}
class FalseClass {
  Then(callBack){
    return this
  }
  Else(callBack){
    callBack.call()
    return this
  }
}
const True = new TrueClass();
const False = new FalseClass();
// Usage:
// const condition = True or False
condition.Then(thenAction).Else(elseAction)

Conclusions

In practice, a lot of OOP and FP languages use procedural-style if (you can get away without it).

The reason I presented those examples is to show "pure" FP and OOP implementations so you could compare them. For the full picture, I need to mention that OOP example is SmallTalk style, and SmallTalk took some inspiration from Scheme, which in turn uses ideas from lambda calculus ¯\_(ツ)_/¯. Some people would argue definition of "pure" OOP as SmallTalk, let's leave it for another article.

Photo by Tom Parsons on Unsplash

Top comments (9)

Collapse
 
bugmagnet profile image
Bruce Axtens

I think you forgot one. I'm not sure what to call it. Perhaps "calculated". The language is this case is tbas, a dialect of BASIC.

DEF FNC(n)
    dim sum = 0
    dim i
    if n > 1 then
        for i = 2 to (n \ 2)
            sum = sum - (i * (n %% i = 0))
        next
    end if
    let FNC = sum
FNEND

Inside that for/next there's an if hidden away in the calculation.

Many dialects of BASIC do not have a boolean type but rather use the values 0 and -1 to signify false and true.

In the equation above the n %% i = 0 takes n modulus i and tests the result against 0. If true, -1 otherwise 0. The next level up in the formula therefore multiplies i by either -1 or 0 resulting in either -(i) or zero. The next level up subtracts a negative or subtracts a zero. According to standard number theory, subtracting a minus value is the same as adding a positive.

Were one to use if/then here it would convert

sum = sum - (i * (n %% i = 0))

to

if n %% i = 0 then
    sum = sum + i
end if

In tbas's case, the formulaic approach is faster than the if/then. YMMV.

Collapse
 
stereobooster profile image
stereobooster

To be fair I didn't try to least them all (if it's even possible, how to guarantee the exhaustiveness of list). Nice to have more examples

Collapse
 
yaser profile image
Yaser Al-Najjar

Thanks for the article.

Sometimes I think inside myself, how come new programmers (esp. bootcampers) ignore such information just cuz they're fixated on one lang that "does the job" for them 😕

Collapse
 
stereobooster profile image
stereobooster • Edited

I can try to answer your question.

Would you be happy to learn Lisp? (I guess that average answer would be no)

But Lisp is very powerful for learning because it overcomes "tyranny of syntax" (when people focus on syntax instead of the actual meaning, when they can't unsee the syntax).

I didn't start from learning Lisp. I learn it now, by implementing Lisp interpreter. And I realize how much-overcomplicated solutions I dealt with through my career. How much confusing explanations I saw, because people don't understand what they talk about (I did it myself, I thought I knew something. I was wrong).

PS I'm not using Lisp for work and doubt I will use it professionally. I use it as a learning vessel.

Collapse
 
yaser profile image
Yaser Al-Najjar

Exactly, I hardly know people who love the idea of mere learning rather than "doing their job".

I would say it's really a deep personal philosophy more onto: do I really wanna know what I'm doing or not?

I took Lisp and Haskell in my uni, wasn't happy about learning it till I saw the potential of understanding what actually functional means.

Collapse
 
dalmo profile image
Dalmo Mendonça

Very interesting but, could you... Uhh... ELI3?

Can you show some examples of using the fp and oo definitions?

Collapse
 
stereobooster profile image
stereobooster • Edited
  1. those are just educational examples, most of the time people would use "procedural" form
  2. there is no native support for it in JS so it's just imitation. We will need some function which will convert from native boolean to ours booleans
// Implementation:
const True = (x) => (y) => x;
const False = (x) => (y) => y;
const If = (condition, thenAction, elseAction) => {
  const action = condition(thenAction)(elseAction);
  return action();
}
// Usage:
const convertNativeBoolean = (b) => b === true ? True : False;
const condition = convertNativeBoolean(Math.random() > 0.5);
const result = If(condition, () => "More" , () => "Less");
console.log(result);
// Implementation:
class TrueClass {
  Then(callBack) {
    callBack.call()
    return this
  }
  Else(callBack) {
    return this
  }
}
class FalseClass {
  Then(callBack){
    return this
  }
  Else(callBack){
    callBack.call()
    return this
  }
}
const True = new TrueClass();
const False = new FalseClass();
// Usage:
const convertNativeBoolean = (b) => b === true ? True : False;
const condition = convertNativeBoolean(Math.random() > 0.5);
condition.Then(() => console.log("More")).Else(() => console.log("Less"))

Or imagine any function which would return our predefined values True or False.

Collapse
 
dalmo profile image
Dalmo Mendonça

Awesome, thanks.

The conversion was the tricky part... looks obvious now that you showed it.

Thread Thread
 
stereobooster profile image
stereobooster • Edited

Yeah... They idea is to imagine language wehere instead of true/false (0/1) they use True/False (those which I provided). It is hard to wrap head around in JS. But I have series of posts about creating a language, in this language we can:

  • 1 - implement "procedural" if
  • 2 - remove "procedural" if and implement functional if

This should be more clear.