Use Functional Programming to Simplify Your Meteor Code

I just wanted to show the community a different way to program that has really helped cleanup my codebase and make it more simple. More experienced programmers will already know this but since OO programming is so prevalent I think it’s worth mentioning.

Example 1 - Simplify with partial application

(also a great example of how JS closures work)

We’ll create a function with the arguments we’d like to pass in then that function returns a new function. The inner function will have access to the outer function’s variables which allows us to pass in our component and still use the params and queryParams arguments in FlowRouter. Notice, render is getting called because we use the () to call and return the new function for FlowRouter.

// create a cleaner API by 'preloading' arguments for 'action'

function render(Comp, Layout = MainLayout) {

  return function action(params, queryParams) {
    ReactLayout.render(Layout, {
      content: <Comp store={store} />
    });
  };

}

FlowRouter.route('/about', {name: 'About Page', action: render(AboutPage) } );
FlowRouter.route('/login', {name: 'Login Page', action: render(LoginPage) } );

Instead of this:


FlowRouter.route('/about', {name: 'About Page', action: aboutActionFn } );

actionFn(params, queryParams) {
    ReactLayout.render(MainLayout, {
      content: <AboutPage store={store} />
    });
}

FlowRouter.route('/login', {name: 'Login Page', action: loginActionFn } );

loginActionFn(params, queryParams) {
    ReactLayout.render(MainLayout, {
      content: <LoginPage store={store} />
    });
}


### Using many simple functions instead of one complex one:

Take a common example… formatting a phone number to a normalized format. The imperative approach would be to make a single function with conditionals that does 4 different things at once. In larger examples this can be very complex. Also I realize one regex could replace this but that’s not the point for a simple example :wink:

Here’s one way to do it in a functional approach that’s similar to Unix pipes, sending one result to the next function:

cleanNum = pipe("(123) 456-7890")
  .removeSpaces()
  .removeParens()
  .removeDashes()
  .value()

// or without the piping helper you can unpack this from the middle to outward:

removeDashes(removeParens(removeSpaces("(123) 456-7890")))

#### code to do this with underscore: ``` // gives underscore's chain a better API pipe = _.chain;

removeDashes = function(str) {
return str.replace(/-/g, ‘’);
};

removeParens = function(str) {
return str.replace(/(|)/g, ‘’);
};

removeSpaces = function(str) {
return str.replace(/\s/g, ‘’);
};

// allow these to be chained with underscore

_.mixin({
removeSpaces: removeSpaces,
removeParens: removeParens,
removeDashes: removeDashes
});






Interested? Checkout these guides/ebooks for JavaScript

- 1 http://eloquentjavascript.net/1st_edition/chapter6.html
- 2 Free Ebook https://github.com/MostlyAdequate/mostly-adequate-guide
25 Likes

You could also do

_.compose(removeDashes, removeParens, removeSpaces)("(123) 456-7890")

Or if this is a combination that you are going to reuse :

var sanitizeNumber = _.compose(removeDashes, removeParens, removeSpaces);

where sanitizeNumber is a new function doing the three steps.

8 Likes

Nice :thumbsup: I can imagine using compose can really clean up the utils file!!

This approach is also great for filtering/manipulating collections. Say for example you need to fetch events for a calendar that shows one month at a time, function composition can be used to achieve this.

Example using Ramda:

/* Events is our collection */

// Fetch data (sub in for something like Events.find().fetch())
var events = [
  {_id: 1, title: 'Test 1', date: '24-05-2015'},
  {_id: 3, title: 'Test 3', date: '15-10-2015'},
  {_id: 4, title: 'Test 4', date: '13-08-2015'}
];

// Start and end of current month
let date = new Date();
let rawStart = new Date(date.getFullYear(), date.getMonth(), 1)  

const start = moment(rawStart).format('YYYY-MM-DD');
const end = moment(start).endOf('month').format('YYYY-MM-DD');


// parseDate :: [Object] -> [Object]
const parseDate = (arr) => {
  let reverse = R.compose(R.join('-'), R.reverse(), R.split('-')
  let newDate = (obj) => { obj.date = reverse(obj.date); return obj }
  return R.map(newDate, arr)
}

// isInMonth :: [Object] -> [Object]
const isInMonth = (arr) => {
  let match = (obj) => return obj.date >= start && ob.date <= end
  return R.filter(match, arr)
}

// Compose our utilities
const processEvents = compose(isInMonth, parseDate)

// Result!
let eventsThisMonth = processEvents(events) // [ { _id: 3, title: 'Test 3', date: '2015-10-15' } ]

Would love to keep this conversation going @SkinnyGeek1010 @vjau!

1 Like

@ryenbeatty Yea this is great!! How do you like Ramda? I almost switched to it but after working in Elixir and Elm on the weekends using the |> pipe operator has me hooked on that syntax inside of the nested function style.

Currently i’m using Lo-Dash and seamless-immutable and it’s been working rather well! Now using a constructor or class almost feels dirty :laughing: Seeing methods produce side effects and mutations makes me wince lol.

I would def. checkout this video, it’s really great. Dave talks about re-thinking programming as a set of transformations like in your example. https://www.youtube.com/watch?v=5hDVftaPQwY

Using Elixir on the weekends has really helped shape up my JavaScript for the better!

Actually you might be interested in this toy side project I made that transpiles F#/Elixir/Elm style |> pipes into a lodash chain.

https://github.com/AdamBrodzinski/pipes-js

Using your example it would be something like this (roughly, not sure if I copied it right):

const reverseDate = (oldObj) => {
  let newDate = oldObj.date |> reverse
  // copy with ES6 spread
  return {...oldObj, date: newDate}
}

// parseDate :: [Object] -> [Object]
const parseDate = (arr) => {
  return arr |> map reverseDate
}

// isInMonth :: [Object] -> [Object]
const isInMonth = (arr) => {
  return arr
  |> filter(obj => obj.date >= start && ob.date <= end)
}


eventsThisMonth = events
 |> parseDate
 |> isInMonth

//>> [ { _id: 3, title: 'Test 3', date: '2015-10-15' }

3 Likes

Oh awesome! I have taken a brief look at Elm but haven’t built anything in it, looks like a logical end-game for pursuing a function style when making web apps.

Ramda is great for these sorts of small utilities, it’s a really amazing toolkit, and serves as a good intro to functional JS.

I agree using constructors starts to feel wrong!

I’ll defs check out the video, still working out ways to make my JS more functional, especially when working with Meteor.

Example is neat too! Quite a bit less code :smile:

@SkinnyGeek1010 really like where you are getting at.

RethinkDB, Ramda, Elixir, Ractive.js, Elm, functional programming & immutability …how deep the rabbit hole goes?

One must choose. And considering everything, React may become the de-facto winner. Clojure might have made the move, Elm might be the end game but React will adopt the good practises from them and make it available to us in javaScript (even if its late). It will not be as elegant as clojure or Elm but at least it will be available to us.
Question is, whether using various combos like React + some-kind-of-Flux-in-Js ( instead of using the React-Flux combo ) rip any benefit for us?

Really liked Elm though

2 Likes

Haha, it goes much deeper :smile:

I think React may be the de-facto winner out of sheer popularity. They’re also slowly peeling off the OO clothing and moving toward function APIs (like 0.14 stateless comps) so it seems like it’ll get even better in the functional point of view.

I like Elm but the whole thing currently is too slow for me… I spend too much time futzing with things to get it to work and the Elm HTML is harder to visually parse. I do plan to dive deeper in that after Elixir land though!

I think that using React, Redux (for that Elm/ClojureScript single state tree), seamless-immutable, and Lo-Dash take you a really long way without getting too academic (like Haskell or Lisp).

Actually another side project i’m tinkering with is a new language that compiles to JS… RedScript 2.0. Basically a CoffeeScript that wraps all of those (minus React) all together. It’s more less a toy but slightly interesting:
https://github.com/AdamBrodzinski/RedScript

3 Likes

what I am thinking is…React is trying to rip the benefit of the functional programming and immutability. what is the best course of action for us meteor guys?

Getting the blaze up to work with react seems too much work. It will be like re-making a discourse clone in Meteor. Rather ride the React wave as @sashko put it. Although I vehemently disagreed previously, I understand the need of forward thinking (functional programming) and that implementing React is perhaps the best course. Am I right? Please confirm.

When I think about advocating Meteor to the ever growing number of javaScript programmers here in my country, I have much better time selling them it as a much better backend for React while they cower at the thought of using vanilla flux (Most of them want to use some sort of Js variant of Flux ).

So what do you think we should do?.. @SkinnyGeek1010

  • React+ Some sort of flux variant + Meteor ?
  • meteorflux packages
  • some sort of package like sideburns
  • React + Meteor

There is no point integrating Flux if it creates more problem than it solves. please advise

you mean use these with meteor?

1 Like

I think so. At best they’ll be able to match React but it’ll never be sustainable with the momentum React has. There’s a lot of people working on it. I also think the Blaze currently will not work well for a discourse clone because of the complexity (in my experience at least).

React while they cower at the thought of using vanilla flux (Most of them want to use some sort of Js variant of Flux ).

Flux is unnecessarily complex IMHO. Redux can be super simple and some examples add a lot of extras but you can do Redux in like 20 lines for everything. Redux is the way flux should have been and is the strong leader currently. Also another perk with Meteor is that you can use the Meteor mixin to load database data and just use Redux for local state (things that Session would normally be used for). This make things much more simple.

So what do you think we should do?.. @SkinnyGeek1010

Keep in mind i’m very biased but have also put in hundreds of hours with several flux libraries in Meteor and have been using it in 4 prod apps for several months.

  • React will help structure large/complex frontends
  • React will use more code than most Blaze examples (no worried im not playing code golf!)
  • Redux is the only way to go in a new app… doubly so if you’re into functional concepts
  • Sideburns means you’ll need to learn React and learn the quirks of sideburns, and learn how to translate React into Sideburns
  • Meteorflux might be good for Blaze but i’ve never used it

I would stick to using the Meteor React mixin for database data and use Redux for local state to replace Session for keeping track of local state (for things like form saving).

If you’re using Redux and React 0.14 you can use stateless components for almost everything and never need to use the class component (except for meteor data). For example:

// example tree of components

  PostsContainer       // *just* fetches data and renders `Posts` comp... adding data as props
     Posts             // stateless component that only takes props and renders each `Post` passing props
        PostItem       // another stateless comp that takes props
        PostItem
        PostItem

If one of them needs data from Redux you can use connect and a plain function to ‘wrap’ the component and pass Redux data as props.

There is no point integrating Flux if it creates more problem than it solves. please advise

The main problem flux (or redux) solves is how can I share this components state with a parent or sibling… without it you’re stuck. Also without flux you can get confused when passing props down more than 3 layers (for me at least). Flux helps you just connect to a store and get data.


you mean use these with meteor?

For sure! It’s made my life easier :smiley:

Here are some example repos:

React:

Flux/Redux (checkout Redux branch)

and seamless-immutable just drops right in via browserify or copy/paste source into a file.

4 Likes

@kaiyes oh also worth mentioning… going through the Redux example in the docs is a must. You have to actually code with the example… otherwise its hard to grok. The first example can be done in the console without any UI !

1 Like

awesome !! I will start using what you have said. I have been advised the same by someone minus the immutable bit & lo-dash. One last question! What is the integration status of React Native + Meteor right now ?

Still very separated. You can use the Node DDP adapter in React Native to get any realtime needs… although a bit verbose.

I opted to just use Meteor as a REST API because there wasnt’ a lot of realtime needs and also needed to support a native app as well as React Native app.

That being said it’s been a breeze compared to Cordova :smile:

1 Like

I remember getting into a heated discussion about two years ago with glasser, nmartin, avital, and the other core devs about functional programming and variable scoping. We were discussing memory leaks, and I was taking the stance of “embrace the functional programming that’s built into the language, and avoid memory leaks by simply not writing objects to the memory stack/heap.” It’s a little vindicating to see React becoming popular, and the approach I was advocating becoming widely adopted.

For what it’s worth, we use lots of functional programming in the data visualization layer using D3, and with Nightwatch as our testing framework (it’s got a functional programming API).

That being said, I do agree with @faceyspacey from the other thread that the whole ‘managing state’ thing seems a bit overblown and like a manufactured concern. A lot of the Flux/Redux architecture seems like it’s simply the result of people discovering The Rule of Three and reporting the results of basic refactoring. I suspect the Flux/Redux architecture would seem a lot more trivial if there were more validation testing and refactoring among the Meteor community. The general pattern arises even in Blaze code, and is a byproduct of the Javascript language, not necessarily the templating/UI layer.

3 Likes

Yea I remember that! It’s nice to see that the JS community is heading towards that way (and I think in general it’s getting more popular). It seems like React + Redux is the gateway drug for JavaScript FP :laughing:

Being a newer programmer, learning about FP was like an ‘ah-ha’ moment but this has been realized by experienced devs for quite some time :smiley:

I agree that the flux phenomenon is overblown, though sharing what React calls ‘state’ is hard to do without some kind of pattern (as a component can’t pass to it’s sibling). I think that’s where it started and then morphed into borrowed ideas as new buzz words.

However, the nice thing is that it’s getting people thinking about decoupling the views and not keeping transient state public and scattered about.

3 Likes

Immutability everywhere is an incredibly poor fit in a generational stop the world gc world. That’s one of the problems Erlang solves beautifully with gc per process, and also why modern vm’s cache strings internally as a pool of constants.

I once had the bright idea of eliminating bugs by refactoring all Vector3f objects to be immutable in an mmo. Spent a few days and a gallon of coffee on the 90k line codebase. The gc was able to keep up during testing with the 5-10 member test team.

Once I pushed the branch into production and a thousand users logged on, things were a bit different indeed. Lesson learned. Immutable nothing, pool all objects.

In terms of FP concepts, lambdas / closures are hot for sure. However I’m just not copacetic when it comes to recursion and pattern matching. A high level language shouldn’t end up looking like something Leonard Susskind would write on his blackboard.

1 Like

It depends on your definition of high level. A pool of objects === references === pointers you have to micro manage. I find working with values only, where you can replace a value by another without bothering about distant side effects, to be more high level.

@jacobin this is really interesting, thanks for sharing! These kind of things can be tough to figure out until it’s too late :smile: I don’t think Redux is technically immutable in the way where it copies the object… instead it just enforces not mutating regular data structures.

However, I was wondering what the perf. impact would be with seamless-immutable vs immutable.js… seamless-immutable only has dev time checks to prevent you from using mutation and then in prod is using mutable structures… unless you use merge to do the trie thing.

I’ve also been wondering if an es-lint check can be made to check against mutations… it would be interesting to just enforce this rather than making slower data structures.

What do you think of Erlang/Elixir pattern matching? The ones i’ve used so far is mainly to check if something in a pipeline has an 'ok' or 'error'.

I really do agree that when you try and get too clever with FP it makes things incredibly hard for new devs or coming back a year later.

After some Reagent training and few Redux demos, I think it is nice to use functional programming and I am trying re-wire my patterns in head. Use underscore to slowly switch my habbits from Coffeescript to more widely used library so people can better understand original form of my code.

And btw, this seems like really nice tutorial - loooong, but deep http://teropa.info/blog/2015/09/10/full-stack-redux-tutorial.html

3 Likes