Ramda X
Ramda X is a super small API with only 10 most important methods for functional programming. Original Ramda library is too big and abstracts almost everything away from the JavaScript language. That's why Ramda X uses the most important methods and leaves everything as it is. All implemented methods are auto-curried!!!
Important: Data comes last!
Implemented API methods:
- I. curry()
- II. compose()
- III. map() -> works only on arrays
- IV. filter() -> works only on arrays
- V. prop() -> works only on objects
prop('name')({name: 'Dimitri', location: 'Berlin'})
- VI. propEq() -> works only on objects
propEq('location', 'Berlin')
- VII. reduce() -> works only on arrays
reduce(fn, null || 'acc value', {location: Berlin})
- VIII. Task() || Task.of(x) || Task.map(), Task.chain(), Task.ap() -> for lazy evaluation and isolation of side effects
- IX. Either.Right(x) || Either.Left(x) || Either.fromNullable(x) || Either.of(x) || Either.try(f) -> for branching
Methods on the waiting list:
- composeP() -> composition with Promises
- propNotEq() -> removing a an element from an array
Additional methods for debugging Ramda X
- trace() -> can be used to debug compose/pipe
trace('label')(value)
If you want the full suite, just use the original Ramda.
Algebraic Typologies
// Source: https://github.com/DrBoolean // FunctorBox//Box(10) // MonadBox// Box(false) // MonoidBox// Box('smallpox') // ApplicativeBox// Box(3) // TraversableBox// Right(Box(3)) // Natural transformation// Box(null)
When to use what? - Code that never fails!
const Task Either Box compose map fold chain ap fork trace = const fs = // we are using Task in order not to grab the state directly// by doing so we isolate the side-effects and make our app more safely // Use Task for side-effects: console.log, process.arg, http calls, db calls, read/write -> ASYNCHRONOUS CODEconst argv = const httpGet = const readFile = const file = // Use Eiter.try for JSON.parse/JSON.stringify -> SYNCHRONOUS CODEconst parse = Either const readFileSync = Either const result = result // Use Either.fromNullable when you are trying to get properties out of an object object.property const first = Either const name = const myName = const herName = myNameherName
Either.fromNullable - Code that never fails!
const Task Either prop compose trace map fold chain = const findColor = red: '#ff4444' green: '#36599' blue: '#fff68f' name const getColor = Eitherconst sliceBy = strconst upperCaseValue = strconst reportError = 'no color'const showResult = const sliceByTwo = const result = // 36599 // FF4444 // FFF68F // no color // no color // no color
ap && chain (Reigth/Left.chain || Right/Left.ap) - Code that never fails
const Task Either prop compose trace map fold chain = const fs = // Important: If you'll try to get a non-existing property out of the object, //the app would not return undefined it will return 3000 as default value of the error function, defined in showResult()const getProperty = Either const readFile = Eitherconst parseJSON = Eitherconst isPortAvailable = const parse = const showResult = const result = // 8888 // 3000
Currying with Types (Boxes & Either)
const Box = const add = x + yconst res = console//---------------------------------- // ----------------------------------const Task Either prop compose trace map fold chain ap = const $ = Either const getScreenSize = screen - headheight + footheight const result = console
ap - safe and concurent IO operations - Code that never fails
const Task Either prop compose trace map fold chain ap = const request = const url1 = 'https://jsonplaceholder.typicode.com/posts/4'const url2 = 'https://jsonplaceholder.typicode.com/posts/2' const e = 'error'const identity = xconst getTitle = Eitherconst getId = Either const reportHeader = `Report: compared to ` const reportId = `Report: compared to ` const parse = Either const httpGet = const res = // Report: eum et est occaecati compared to qui est esse // Report: 4 compared to 2
ap Redux - concurrent IO operations - Code that never fails
const Task Either prop compose trace map fold chain ap = const request = const update = msgtype === 'UPDATE' ? ...model report: msgpayload : msgtype === 'ERROR' ? ...model error: msgerror : model const dispatch = { let model = {} model = model console} const updateModelMsg = type: 'UPDATE' payload const updateModelErrorMsg = type: 'ERROR' error const url1 = 'https://jsonplaceholder.typicode.com/posts/4'const url2 = 'https://jsonplaceholder.typicode.com/posts/2' const e = const identity = xconst getTitle = Eitherconst getId = Either const reportHeader = `Report: compared to ` const reportId = `Report: compared to ` const parse = Either const httpGet = const res = // UPDATED MODEL { report: 'Report: 4 compared to 2' }// UPDATED MODEL { report: 'Report: eum et est occaecati compared to qui est esse' }
safe I/O Operations with Parsing - Code that never fails
const Task Either prop compose trace map fold chain ap fork = const fs = const readFile = const writeFile = const writeToConfigTwo = const parse = Eitherconst stringify = Either const getProperty = Task const eitherToTask = e const error = consoleconst success = console const transformation =
Traversable with Lists
const Task = const fs = const readFile = const List = { return xs } const files = files``´ ### Example ```jsconst { map, prop, compose, trace } = require('ramda-x') const users = [ { name: 'Dimitri', isAdmin: true }, { name: 'John', isAdmin: true }, { name: 'Mike', isAdmin: false }] const names = map(prop('name'), users)console.log(names) // [ 'Dimitri', 'John', 'Mike' ] const message = { Records: [ { name: 'Dimitri', isAdmin: true }, { name: 'John', isAdmin: true }, { name: 'Mike', isAdmin: false } ]} const extractNamesFromMessage = compose( map(prop('name')), trace('AFTER PLUCK'), prop('Records')) console.log(extractNamesFromMessage(message))// AFTER PLUCK: [// {// "name": "Dimitri",// "isAdmin": true// },// {// "name": "John",// "isAdmin": true// },// {// "name": "Mike",// "isAdmin": false// }// ]//[ 'Dimitri', 'John', 'Mike' ] const filterNamesFromMessage = compose( filter(propEq('name', 'Dimitri')), prop('Records')) console.log(filterNamesFromMessage(message))// [ { name: 'Dimitri', isAdmin: true } ]
Task - Lazy Evaluation / Isolation of Side Effects
const Task = // pure functionconst readFile = // pure functionconst writeFile = // pure functionconst app = // impure function with side effectsapp
Lifting a value into a type
const f = x const res = Taskres // hello!!! Either // hello!!!
Try/Catch Examples
const Either = const fs = const tryCatch = { try return Either catch e return Either } const getPort = const res =
Try with Either.try(f)
const parse = Either const eitherToTask = e const findPost = const main = Task id
Either - Instead of If/Else + Composition
const fromNullable = x !== null ? Either : Either // You can also import Either.fromNullable() and use it instead of fromNullable()const findColor = const result =
Either - Instead of If/Else + Composition
const Task Either prop compose trace map fold chain = const fromNullable Right Left = Either const dispatch = consoleconst getItem = const someAction2 = data const toUpperCase = str const someAction3 = data const prepeareAction = const prepareNewAction = // comes from the err function -> the application runs without exiting // TypeError: Cannot read property 'item' of null
Some other examples
const fromNullable = x !== null ? Either : Either const tryCatch = { try return Either catch e return Either } // imperative codeconst openSite = { if current_user return else return } // declarative codeconst openSite = { } // imperative codeconst getPrefs = { if userpremium return else return defaultPrefs } // declarative codeconst getPrefs = userpremium ? : // imperative codeconst streetName = { const address = useraddress if address const street = addressstreet if street return streetname return 'no street!'} // declarative codeconst streetName = // imperative codeconst concatUniq = { const found = ys0 return found ? ys : ys} // declarative codeconst concatUniq = // imperative codeconst wrapExamples = { if examplepreviewPath try examplepreview = fs catch e return example} const readFile = // declarative codeconst wrapExamples = { } // imperative codeconst parseDbUrl = { try const c = JSON ifcurl return curl catche return null } // declarative codeconst parseDbUrl = { }