Skip to content

Instantly share code, notes, and snippets.

@crshmk
Last active January 2, 2023 08:44
Show Gist options
  • Save crshmk/3ec3ca5af3d8a39707caf06fd355cadc to your computer and use it in GitHub Desktop.
Save crshmk/3ec3ca5af3d8a39707caf06fd355cadc to your computer and use it in GitHub Desktop.
Some point-free string processing with curried utils
// let's create a util by composing common utils
import {
join,
map,
pipe,
reverse,
split,
tail,
toArray,
toLower,
toUpper,
toWords,
ucFirst
} from 'utils'
//[ "nodnol", "dnalgne"] -> ["london", "england"]
const reverseEach = pipe(
map(toArray),
map(reverse),
map(join(''))
)
const makeCity = pipe(
toLower,
toWords,
reverse,
reverseEach,
map(ucFirst),
join(', ')
)
const makeCities = map(makeCity)
export default makeCitites
// devs will rarely, if ever, look at this file
export const join = by => xs => xs.join(by)
export const map = fn => xs => xs.map(fn)
export function pipe() {
const fns = Array.prototype.slice.call(arguments)
return seed =>
fns.reduce((acc, fn) => fn(acc), seed)
}
export const reverse = xs => xs.reverse()
export const split = by => x => x.split(by)
export const tail = xs => xs.slice(1)
export const toArray = split('')
export const toLower = x => x.toLowerCase()
export const toUpper = x => x.toUpperCase()
export const toWords = split(' ')
export const ucFirst = xs => xs[0].toUpperCase() + tail(xs)
@crshmk
Copy link
Author

crshmk commented Jan 2, 2023

let's use our util in a component file

import makeCities from './makeCities'

const cities = ["dNalGne noDNoL", "EcNarf SIrap"]

makeCities(cities)
// ["London, England","Paris, France"]

@crshmk
Copy link
Author

crshmk commented Jan 2, 2023

Currying and function composition allow you to abstract away common processing and create clean, robust, declarative routines. Although these patterns may be unfamiliar to some, a little study of functional programming makes this code extremely clear.

Utils are composable, pure functions. They are abstracted away and rarely touched. Ideally, they are autocurried.

In this example, the team has agreed on the use of common utils. Its api is understood, and its code is rarely read. The developer composes these common utils to create (and test) a makeCities function. A component file simply imports the makeCities function and uses it in a couple lines.

There is no need for verbose type declarations, as the type is implicit in each small, pure function. In fact, type declarations diminish code quality here, as they would severely reduce readability.

The code is easily read, tested, maintained, and extended. The senior dev understands that following reads as

const makeCity = pipe(
// lower case a string
    toLower,
// split a string by space; create an array of strings from a string
    toWords,
// reverse an array 
    reverse,
// for each item in an array of strings, reverse the chars (the developer created this in the same file)
    reverseEach,
// for each item in an array of strings, uppercase the first char
    map(ucFirst),
// join an array of strings with a comma 
    join(', ')
)

We can write our own utils, but it's probably best to use more popular ones.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment