Learning Functional Programming by Building an Analog Clock

Hi everyone,

I’m building a very basic analog clock in plain JS. My purpose with it is to learn about how to subdivide functions into smaller functions and pipe them together in a functional style.

I’m finding it very confusing. Particularly when it comes to answering the following questions:

  • How can I pipe functions together effectively without having my code look like an incomprehensible mess.
  • Is there a strategy for coding in this way that could help me organize my thinking so I don’t lose my mind? (I feel like I am).
    • i.e.: My current thinking is going something like this: “functionA needs to call funcB, which in terms needs the input from funcC and funcD, which in turn needs the input from…” So I feel like I can’t keep things straight.

Here is the codepen of what I have so far.

I’m not looking for someone to create the functions for me, but for recommendations as to how to mentally organize to:

  • know which functions I need to create, and
  • group functions into different levels of abstraction, so I can manage them easily.

If anybody is willing to give me a hand to understand this I’d really appreciate it! :slight_smile:

I apologize if my question is a bit all over the place too. I’m so confused I am finding it hard to even write a clear question.

Hi @johnsciutto,

By the way you are describing your problems it seems that you are following at the moment an event-driven[0][1] and bottom-up approach[2].

I understand that you want to write the analog clock in a functional style, one way to do it is:

  current state -> next state 

That can be read as:

  • state = all the information that is needed to be shared between functions (context)
  • current state and next state = are arguments
  • -> = is a function

An example:

Cheers and happy coding :slight_smile:

NOTES:

[0] Event-driven programming - Wikipedia

In computer programming, event-driven programming is a programming paradigm in which the flow of the program is determined by events such as user actions (mouse clicks, key presses), sensor outputs, or messages from other programs or threads. Event-driven programming is the dominant paradigm used in graphical user interfaces and other applications (e.g., JavaScript web applications) that are centered on performing certain actions in response to user input. This is also true of programming for device drivers (e.g., P in USB device driver stacks).

[1] Event-driven programming - Wikipedia

The design of those programs which rely on event-action model has been criticised, and it has been suggested that the event-action model leads programmers to create error-prone, difficult to extend and excessively complex application code. Table-driven state machines have been advocated as a viable alternative. On the other hand, table-driven state machines themselves suffer from significant weaknesses including state explosion phenomena. A solution for this is to use Petri nets.

[2] Bottom-up approach:

Bottom-up approach:
  • In a bottom-up approach the problem analysis starts at the lowest level possible

  • Individual parts of the system are implemented

  • This parts are then linked to form larger components

  • This process continues till all system components are implemented.

Bottom-up approach common patterns

When using the bottom-up approach, there are some patterns that we can identify:

  • Most of the programs follows the event-action paradigm:

    • Users supplies an event and

    • A sequence of actions is executed in response to that event

  • Event-handlers will execute functions in response to an event

  • Elements of the user interface may respond to an event in different ways, depending on the context

  • if-else statements are used to determine the context and which functions are executed

  • Event-handlers must use information shared between user interface objects

  • To share information the following options are used:

    • Explicit global variables

    • A value contained in an user interface object

    • Other attribute of an object

Calculator example (Bottom-up)
class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentVal: "0",
      prevVal: "0",
      formula: "",
      currentSign: "pos",
      lastClicked: ""
    };
    // ....
  }

  initialize() {
    this.setState({
      currentVal: "0",
      prevVal: "0",
      formula: "",
      currentSign: "pos",
      lastClicked: "",
      evaluated: false
    });
  }

  handleDecimal() {
    if (this.state.evaluated === true) {
     // ... 
    } else if (
      !this.state.currentVal.includes(".") &&
      !this.state.currentVal.includes("Limit")
    ) {
     // ...
      if (this.state.currentVal.length > 21) {
     // ...
      } else if (
        endsWithOperator.test(this.state.formula) ||
        (this.state.currentVal === "0" && this.state.formula === "")
      ) {
      // ...
      } else {
      // ...
      }
    }
   }
    
  handleEvaluate() {
    if (!this.state.currentVal.includes("Limit")) {
    //   ...
        expression = expression.replace(/x/g, "*").replace(/‑/g, "-");

     while (endsWithOperator.test(expression)) {
        expression = expression.slice(0, -1);
      }
    // ...
    }
  }

  handleOperators(e) {
    if (!this.state.currentVal.includes("Limit")) {
      // ...
      if (evaluated) {
      // ...
      } else if (!endsWithOperator.test(formula)) {
      // ...
      } else if (!endsWithNegativeSign.test(formula)) {
      // ...
      } else if (value !== "‑") {
      // ...
      }
    }
  }

  handleNumbers(e) {
    if (!this.state.currentVal.includes("Limit")) {
     // ...
      if (currentVal.length > 21) {
     // ... 
      } else if (evaluated) {
     // ...
      } else {
     // ...
    }
   }
  }

}
2 Likes

Hi @Diego_Perez,

Thank you so much! :grinning:

You’ve given me a lot to research and study. I didn’t even know the terms “bottom-up approach” and “event-driven programming”. Now that I have that, I can run with it and do more research on what other approaches and programming styles there are.

Is there a course or resource you could recommend to study more about different approaches to creating applications?

Thank you again!

1 Like

Hi @johnsciutto,

I didn’t even know the terms “bottom-up approach” and “event-driven programming”.

The term “bottom-up approach” is from a book of 1999[0], I think that the first time I heard about it was in an interview to Jamie Zawinski[1] or in the documentary “Code Rush”(2000)[2]. So, at least in that period (pre-2000’s) was used.

Is there a course or resource you could recommend to study more about different approaches to creating applications?

I think that this question can have 2 possible answers (general and specific):

In general, I think that the course “How To Design Programs” [3] [4] is a really (really) good introduction to problem solving. This is a personal opinion, but I think this course is infinitely better than memorizing Computer Science algorithms or solving algorithms(puzzles), because in the beginning is more important to learn how to solve a problem in a systematic way than getting the right answer (an answer that pass all the tests).

The course “Programming Paradigms (CS107)”[5] and the book “Concepts, Techniques, and Models of Computer Programming”[6] are really good for learn the theory behind programming, but you can spend years learning from both and I am not really sure if you will get something that you can use in a ‘real project’. The same goes for SICP[7]

There is a book called “Exercises in Programming Style” I haven’t read it but the github repository[8] seems interesting.

In specific, I think that it will be better to focus in Computer Science papers, “case study”[9], and JS frameworks:

I don’t know if you are interested, but I am currently writing a project that follows the event-state-action and imperative/procedual(?) paradigms using: finite state machines, state-transition tables and diagrams (quite far from functional programming).

An example:

  • The state transition table:
  *GREEN  time YELLOW entry: setstyledomgreen 
   YELLOW time RED    entry: setstyledomyellow 
   RED    time GREEN  entry: setstyledomred
  • The state machine and diagram:

  • Youtube channel:

I also have a youtube channel where I am currently uploading videos of my progress writing the project, my plan is also upload videos with comments about the code (something like a code review) and video tutorials to learn how to use the project.

https://www.youtube.com/playlist?list=PLEJxzxnNnYoXP-eOjedQJbmV7t82hHrTD

Cheers and happy coding :slight_smile:

NOTES:

[0] Constructing the User Interface with Statecharts, Ian Horrocks.

This book provides a practical guide to constructing real user interfaces for real projects. It is primarily written for practising software engineers, but will also be invaluable to students wishing to gain an insight into user interface construction.

[1] Jamie Zawinski - Wikipedia

… is an American computer programmer with contributions to the free software projects Mozilla and XEmacs, and early versions of the Netscape Navigator web browser.

[2] Code Rush - Wikipedia

Code Rush is a 2000 documentary following the lives of a group of Netscape engineers in Silicon Valley. It covers Netscape’s last year as an independent company, from their announcement of the Mozilla open source project until their acquisition by AOL. It particularly focuses on the last-minute rush to make the Mozilla source code ready for release by the deadline of March 31, 1998, and the impact on the engineers’ lives and families as they attempt to save the company from ruin.

[3] 35C3 - How to teach programming to your loved ones

Enabling students over example-driven teaching

Teaching beginners how to program is often hard. We love building programs, and seeing our loved ones struggle with this is painful. Showing them how to copy-paste a few example programs and change a few parameters is easy, but bridging from there to building substantial programs is a different game entirely. This talk is about how to teach programming successfully, through comprehensible design recipes, which anyone can follow, using languages and tools designed for beginners. This approach is probably different from how you learned how to program, or how you’re used to teaching. It is more effective, however, as it teaches more material successfully to a broader spectrum of people. It is also more enjoyable.

The talk is based on many years of research by the Program by Design, DeinProgramm, and Bootstrap educational projects, as well as over 30 years of personal teaching experience in school, university and industrial contexts. A word of warning: The resulting approach is radically different from most teaching approaches used in universities and schools. In particular, it avoids teaching purely through examples and expecting students to develop the skills to arrive at the solutions on their own.

Instead, it eaches explicit methodology that enables students to solve problems of surprising complexity on their own*, whether they are 11 or 55, whether in a classroom, a training facility, or your home. Extensive documentation, material, and software to support this methodology is available for free.
Mike Sperber

[4] How to Design Programs:

How to Design Programs, Second Edition (book)
How to Design Programs, Second Edition

Systematic Programming Design (video course)
https://www.youtube.com/channel/UC7dEjIUwSxSNcW4PqNRQW8w

  • The idea is simple, you can write programs in a systematic way:

[5] Programming Paradigms (CS107)

https://www.youtube.com/playlist?list=PL9D558D49CA734A02

[6] Concepts, Techniques, and Models of Computer Programming (By Peter Van Roy and Seif Haridi)
Concepts, Techniques, and Models of Computer Programming

[7] Structure and Interpretation of Computer Programs:

Structure and Interpretation of Computer Programs, Comparison Edition

[8] Exercises in Programming Style

GitHub - crista/exercises-in-programming-style: Comprehensive collection of programming styles using a simple computational task, term frequency

[9] Case study

Case study - Wikipedia

… a case study is a research method involving an up-close, in-depth, and detailed examination of a particular case.

4 Likes

@Diego_Perez,

Wow! Thank you so much! I’m going to have a feast with all the material you’ve shared!

I can’t thank you enough man!

I’m following your channel on YouTube :slight_smile: . I look forward to checking out your videos.

Thank you again!

Happy coding!

1 Like

I just wanted to point out this is one of the highest quality posts I’ve ever seen on this forum.

Goodjob!

2 Likes

Just a slightly different few points to add to @Diego_Perez resources

You’re trying to abstract this before you’ve got something working. Note that immediately trying to abstract just so that you can pipe functions together looks like a sign you’re trying to overabstract things. Piping is very easy to do, but you need to write a function to do it, and you need to follow a specific set of rules about what and how functions should be used in the pipe. JavaScript is neither statically nor strongly typed, not everything is an expression, and functions don’t work like ML-style languages (Haskell, OCaml, SML etc) where they always take one and only one argument. All the abstractions need to be written, they aren’t baked into the language. Be very wary of just trying to write “functional” code for the sake of it (same applies to any paradigm), it may just end up being cargo culting

You’ve also picked something that doesn’t lend itself completely to a functional style. It relies on time and relies on the DOM, and cannot be side-effect free. Note that to avoid drift you have to check the system time here (setInterval on its own won’t work)

All that being said, you can do this fine using functional techniques, ish. But in the small, not really as the overarching structure – it has to be quite imperative.

There aren’t many different ways to approach this, imo basic skeleton would be:

  • a recursive function that runs the clock, calling itself to update the time (something built on requestAnimationFrame would be perfect)
  • a function that takes the current time and renders something to the DOM/adjusts some DOM or CSS values. Imo rendering to the DOM is not a great idea; adjusting CSS transforms is much easier and more performant (and using SVG rather than HTML is also easier). Canvas is another good option.

Then you just start it up and the clock does its thing: the loop loops, calling the render function each tick

This can be changed to something more robust. For example, passing time as an argument to the loop function, producing a delta against the current time inside the function, and only adjusting the hour/min/sec hands if necessary, then passing the current time to the recursive call. This is where you can possibly use functional techniques.

2 Likes

Thank you @DanCouper!

I clearly have a lot to learn. Exciting stuff!

I’ll be referencing your answer and doing some reading/studying about it. I feel like as I am know, I’m only able to understand 60% of how to do the things you mentioned.

Thank you for helping me get to the next level!

1 Like

This is a scary amount of information for the app whose task is to show the current time :laughing:

I’ll try to sum up in fewer possible words. It’s not possible to implement purely functional programming here, as modifying DOM element is the side effect and wrapping this modification in function will not make it functional programming I’m afraid. Practically speaking it means that your function chain will have to end up with .forEach() method that will implement this “non-functional” side effect.

Your code is not very functional, in fact it’s very hard-coded and your choice of objects (over arrays) makes things a bit more complicated. In contrast arrays are perfect structure for “vanilla” functional programming. So if you, let’s say start like this:

const getCurrentTime = () => {
  const date = new Date();
  return [
    date.getHours(),
    date.getMinutes(),
    date.getSeconds(),
  ];
};

It will make things a bit easier in my point of view, as you will get access to (most functional method ever) .map() allowing you to map current time to ratios which in turn will do that “dirty” .forEach() updating hands :slight_smile:

Good luck!

1 Like

Adding a bit further (and being complete picky moron), I’m not sure about .getHours() / .getMinutes() / .getSeconds() strategy to begin with, as this means at 11:59 hour hand will still point to 11. I’m not sure this is correct - every hour hour hand will do these crazy jumps

1 Like

Thank you for your kind words @bradtaniguchi :smile:

Thanks :smile:

Cheer and happy coding :slightly_smiling_face:

1 Like

I know, right?! It made me go :thinking: … “maybe I’m doing things wrong” :stuck_out_tongue_closed_eyes:.

Thank you @snigo for your comments and suggestions. I will try to implement what you suggested and see how I do!

Thanks!