I often have the following code at the end of my functional pipelines
1 | function doSomething() { |
The last function assign
does nothing but assigns the returned list to a local variable items
.
The new ES6 syntax help a little, but still requires a functional expression
1 | function doSomething() { |
Can we eliminate the functional expression and the argument name list
?
I would love to be able to use something like this (function assign
is curried)
1 | var assign(variableName, value) { ... } |
Because function assign
declares 2 arguments (target variable name and value), and is curried,
the expression assign('items')
returns a function that only expects value
to complete its work.
Can we write this function? It is a dynamic expression, thus using eval
is necessary. A first implementation
certainly is simple enough.
1 | var R = require('ramda'); |
We have the function assign
right inside our scope with the variable items
. When the eval
executes,
it uses the scope around it to evaluate variable references, thus it finds the correct items
variable.
This is unlike evaluating the code dynamically using new Function(code)
approach, which only evaluates
in the global scope.
Ok, this is working, I would like to reuse assign
, maybe even mix it into the
Ramda library. This is where we run into troubles
1 | var R = require('ramda'); |
The evaluated assignment expression marked // 1
is no longer written in the same scope as the variable items
.
The JavaScript language despite its dynamic nature and flexibility only uses lexical scope - the source
around the place where the function is written, not where it is evaluated. There is no way to force eval
to
use the runtime or call-site scope. That would be amazing, but would break closures
and make the evaluation impossible to predict.
Can we find a work around? Our problem is that we are trying to overwrite the variable reference, not its value. The only way we could this is by passing and object and overwriting a property inside of it.
1 | var R = require('ramda'); |
This works again. What if we don't want to use a function from a large library to do currying?
Well, we could use plain Function.prototype.bind
to do partial application
in JavaScript.
1 | function assign(object, property, value) { |
Short and sweet, but we can shorten this even more (by exactly 18 characters). Notice that the function
assign
puts the value into a passed object, while assign.bind
sets the context of the assign
.
We can write instead the following
1 | function assign(property, value) { |
I believe this is the only time I found using the keyword this
helpful.
Here is a practical application: grabbing something in the unit tests. For example, it gets tiresome to
write beforeEach
callback just to assign a value to a variable
1 | describe('a mocha spec', function () { |
If we have the assign
from above we can make a shortcut
1 | describe('assign in a mocha spec', function () { |
Typically, the shortcut is more complicated and would be a promise or a function call, something like
1 | function assign(property, value) { |
This assignment can handle the async unit test setup.