Skip to content

davidgtonge/query-predicate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

78 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Query-Predicate

Re-write of underscore-query using ES6 and Ramda in an (extreme) point-free style.

This module exports a single createPredicate function. This function takes a mongo-like query and returns a predicate function. This function can then be used with R.filter or R.find, etc.

The module parses a wide variety of mongo queries - please see the tests for examples.

Documentation will be added shortly, but in the meantime check the Documentation for the query operators for underscore-query

Why Point Free

This is an experiment in how much of a non-trivial program can be written in a point-free manner. I wrote it partly to explore the ramda api and partly as a challenge.

Currently there are only 4 function declarations.

  • 3 are needed to allow recursion. While I probably could re-write the functions to use a y-combinator, I've not yet got round to it. The place that the recursion is used would make those particular functions a lot harder to reason about
  • 1 is needed to throw errors

I think when used well by people who are familiar with functional apis (such as Ramda), the style is very expressive. At a simple level a procedural for loop could be used for map or filter or reduce. By using map rather than a for loop, the intent of my program is easier to understand.

Here is an example of the journey from procedural to point free

Simple Procedural

function fn(input) {
  var output = []
  for (i = 0; i < input.length; i++) {
      output.push(input[i].key)
  }
  return output
}

Using Native Map

function fn(input) {
  return input.map(function(item) {
      return item.key
  })
}

Using FP Style Map

function fn(input){
  return map(function(item) {
    return item.key
  }, input)
}

Making Point free - part 1 (i.e. no arguments)

This works

var fn = R.map(function(item) {
  return item.key
})

Making Point free - part 2 - Using R.prop

var fn = R.map(R.prop("key"))

Using R.pluck

var fn = R.pluck("key")

Where doesn't it work

Some functions become a lot more verbose and less clear. For example:

function $mod(value, attr){
  return attr % value[0] === value[1]
}

becomes:

const $mod = R.converge(R.identical, [
  R.converge(R.modulo, [R.nthArg(1), R.compose(R.head, R.nthArg(0))]),
  R.compose(R.last, R.nthArg(0))
])

About

Generates predicate functions from Mongo queries

Resources

License

Stars

Watchers

Forks

Packages

No packages published