Skip to content

mattgrande/coder-camp-june-17-2017

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

What is this?

These are my crib notes for the talk I'm giving at Hamilton's CoderCamp, June 14, 2017 at Phesant Plucker.

Intro

  • Ramda is a functional programming framework for JavaScript
  • It focuses on small, composable, reusable functions, and encourages a point-free style
  • Features:
    • Higer-order functions (functions that take another function as an input, OR return a function as the output)
    • Function-first, data last, API
    • Automatic currying
    • Function composition
    • Immutability
  • All internal code is ES3-compliant (works back to IE6)
  • No dependencies! https://github.com/ramda/ramda/blob/master/package.json#L55
  • So, let's talk about currying...

Ex 0 (Rogers)

  1. Change to a .map
  2. Require Ramda
  3. Use R.multiply(1.10, plans[i].price)
  4. Show auto-currying (R.multiply(1.10, plans[i].price) => R.multiply(1.10)(plans[i].price))
  5. Extract multiplyer
  6. Contrived example; Could do more, but let's jump ahead

Ex 1 (YouTube Views)

  1. Filter out only videos w/ views youtubeVideos = youtubeVideos.filter(video => 'views' in video);

  2. Map out the views of the videos youtubeVideos = youtubeVideos.map(video => video.views);

  3. 'Combine' these two steps

  4. const R = require('ramda')

  5. Use R.pipe:

     R.pipe(
         R.filter(...),
         R.map(...)
     )(youtubeVideos)
  • They accept the function as the first argument, and the thing that you want to applied as the second argument
  1. Change filter internal to R.has('views')
  2. Change map internal to R.prop('views')
  • Ramda encourages a 'point-free' style; Combine functions so you're dealing with the data less
  1. To make it point free, and the function only takes one argumetn, we can change it so that: const getViews = R.pipe...
  2. Show compose (reverse order)

Ex 2

  1. Break it up so it's one string of if/else statements
  •  NOTE: We want to make things as similar as possible to help with refactoring
    
  1. Bring in Ramda
  2. R.is(ErrorWithStatus, error); R.is(ValidationError, error)
  3. R.propEq('type', 'PaymentNotIncluded', error)
  4. But if error is null || undefined, R.propEq will fail, so add to the top:
if (!Boolean(error)) {
    return 500;
}
  1. R.test(/not found/i, error)
  2. R.always(true, error)
  3. Now all functions have the same last argument! This is very curry friendly!
  4. Convert to Cond expression:
     R.cond([
         [predicateFunction, transformationFunction],
         [R.always(true), errorToStatusCodeOrig]
     ])(error);
  • predicateFunction takes a value and returns true or false.
  • transformationFunction takes that same value and transforms it in some way
  • Goes from top to bottom
  1. [R.isNil, R.always(500)], [R.is(ErrorWithStatus), R.prop('status')], [R.is(ValidationError), R.always(400)], [R.propEq('type', 'PaymentNotIncluded'), R.always(402)], [R.test(/not found/i), R.always(404)], [R.always(true), R.always(500)]
  2. Now, get rid of the error from the function: const errorToStatusCode = R.cond...

Ex 3 (Albums / Lenses)

  1. const R = require('ramda')
  2. Build lenses for artist & name
  3. Compose the lenses together
  4. Refactor setArtist: 4a. return R.set(artistNameLens, artistName, album)
  5. Refactor addMetadata: 5a. return R.over(artistLens, R.merge(metadata), album)
  6. Refactor getArtist: 6a. return R.view(artistNameLens, album)
  7. Remove shallowClone
  8. Let Ramda build the functions! 8a. const setArtist = R.set(artistNameLens); 8b. const getArtist = R.view(artistNameLens);

What function should I use?

https://github.com/ramda/ramda/wiki/What-Function-Should-I-Use%3F

About

Refactoring with Ramda for Coder Camp (June 2017)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published