i am trying to learn F# functional programming but i have some issues translating some concepts from Javascript functional programming to F#. I have this code that enables me to compose a "pipeline" of functions in Javascript like this:
const compose = ((functions) => {
return ((input) => {
return functions.reduce((ack, func) => {
return func(ack);
}, input);
});
});
const addOne = ((input) => input + 1);
const addTwo = ((input) => input + 2);
const composedFunction = compose([addOne, addTwo]);
const result = composedFunction(2);
console.log(result);
Is it even possible to do this kind of composition in F#? How would i do it?
Assuming that the list of functions you need to compose is not known at compile time, you can use a fold to compose your list of functions.
In your answer I see you found a very close solution with reduce which is a special case of fold but it doesn't have an initial state so when the list is empty it fails.
Since we can't have compile guarantee that the list is not empty I highly recommend you for this scenario using a fold, having the id function as initial state:
let compose funcs = (fun x -> x |> List.fold (>>) id funcs)
We can apply eta reduction:
let compose funcs = List.fold (>>) id funcs
One more time:
let compose = List.fold (>>) id
Although with this last step you will run in the value restriction, but it might disappear with the rest of the code:
let addOne x = x + 1
let addTwo x = x + 2
let compose = List.fold (>>) id
let list = [addOne; addTwo]
let composed = compose list
let elist = []
let composed2 = compose elist
// test
let result = composed 1
let result2 = composed2 1
// val result : int = 4
// val result2 : int = 1
This code got me the solution that i wanted:
let addOne x = x + 1
let addTwo x = x + 2
let compose funcs =
(fun x -> x |> List.reduce (>>) funcs)
let list = [addOne; addTwo]
let composed = compose list
let result = composed 1
If you're composing a number of functions that is fixed at compile time you should use >> directly:
let addOne n = n + 1
let addTwo n = n + 2
let addThree = addOne >> addTwo
You say that you're just learning F#, so I'll risk stating the obvious here - this is how you compose functions in F#:
addOne >> addTwo
Functional programming in a statically-typed FP-first language like F# has a very different flavor than encoding the same approach in a language that is not geared to it (like JS or C#). Things that in those languages have to be encoded with dedicated functions, like partial application or function composition, are directly exposed in the language itself.
For instance, while you can express the same pattern of sequentially applying a collection of functions to a value in F#, you will find it both an overkill (because it can be replaced by a simple function composition) and less powerful compared to JS equivalent (because you can't compose functions with different types this way, e.g. you can't compose an int -> string and a string -> bool because list requires all elements to be the same type, something that JS doesn't care at all about).
In JS this pattern might be "the way" to do function composition - you need a function for it anyway, it might as well take a collection of them while you're at it, but translating it directly into F# is less useful than it seems. Case in point - I have maybe used it once or twice over many years of writing F#, and I can't say it was unavoidable. If you find yourself wanting to use this pattern over and over in F#, you might need to revisit how you're doing things.
Related
I want to make my JS code to be less repetitive with an organized look. But I don't know if calling a function from inside another function is a bad practice, like Global Variables.
I share a piece of the code here.
thanks.
function getEx() {
return document.getElementById('example')
}
function getExTwo() {
return document.getElementById("exampleTwo");
}
function getTheValue() {
let getExValue = getEx();
let getExTwoValue = getExTwo();
}
Calling a function from within another function is absolutely not bad coding. That's part of what functions are for, really -- breaking up logical processes into smaller pieces.
Here's an example of how this can work.
// Note: This is new ES6/ES7 syntax for writing JavaScript functions.
// I'm using it here because it's very terse.
const add = (a, b) => a + b;
const multiply = (a, b) => a * b;
const square = (a) => multiply(a, a);
const sumOfSquares = (arr) => {
let sum = 0;
arr.forEach(number => sum += square(number));
return sum;
};
In the (simplified) example above, we use different functions to break up the distinct logical pieces of the problem into smaller, more manageable problems. For example, to calculate the sum of the squares of the array [1, 10, 12], we want to be able to add things and we want to be able to square things, so it's a good idea to create functions for performing each of those steps. We might even want to use other functions within those functions (e.g. calling multiply from within square).
Now, is it possible to go overboard with creating new functions? Yes. Try to avoid writing multiple functions that are basically the same. But otherwise... go nuts!
Calling a function from within another function is not bad. It is a recommended way of reducing repetition by breaking your code into smaller pieces, each handling some specific logic.
Here is a simplified version of your code:
// ps: $ is not from jquery it is just a normal variable.
const $ = document.querySelector
const getValues = () => {
const firstVal = $('#example')
const secondVal = $('#exampleTwo')
}
Write a function that takes in a string of one or more words, and returns the same string, but with all five or more letter words reversed. Strings passed in will consist of only letters and spaces. Spaces will be included only when more than one word is present.
The code I wrote reverses the whole string. I believe it is something with the if statement, it is not catching words greater than 5. My thinking when writing the code is to first convert the string into an array of words, use a for loop to run through the arrays and find the words that are greater than 5, then reverse the words greater than 5. I have found similar problems and this is how far I got searching for help. I'm stuck, any help would be greatly appreciated! I am new to coding and learning Javascript.
function spinWords(backward){
var sentence = "";
var separate = backward.split("");
for (var i = separate.length - 1; i >= 0; i--){
if (separate[i].length >= 1){
sentence += separate[i].split("").reverse().join("");
}
else {
sentence += "" + separate[i];
}
}
return sentence;
}
spinWords("Hey fellow warriors");
You might find the logic a lot easier if you used a regular expression to match 5 or more word characters in a row, and use a replacer function to reverse them:
function spinWords(backward) {
return backward.replace(/\w{5,}/g, word => word.split('').reverse().join(''));
}
console.log(spinWords("Hey fellow warriors"));
To fix your code, you should split the input string (the variabla named backward) by a space, not by the empty string, to get an array of words, then iterate through that array (starting from the beginning, not at the end), checking for each word's length and concatenating with sentence:
function spinWords(backward) {
var sentence = "";
var separate = backward.split(" ");
for (var i = 0; i < separate.length; i++) {
if (sentence) sentence += ' ';
if (separate[i].length >= 5) {
sentence += separate[i].split("").reverse().join("");
} else {
sentence += separate[i];
}
}
return sentence;
}
console.log(spinWords("Hey fellow warriors"));
Below is a discussion about a possible way to approach this problem. It is not what I would likely do for a question as simple as this, but it demonstrates a mindset that makes it easier to solve many problems, and to reuse your work as you do so.
Breaking the problem down
You want to do several things here, so it might help to break the problem down into steps.
At the core, you want to reverse certain words. So why not write a function to do only that? It should be simple. Here is one version:
const reverseWord = word => word.split('').reverse().join('')
reverseWord('word') //=> 'drow'
But you only want to do this to words whose length is at least five. Rather than rewriting our existing function, we can use it to write the more complex one:
const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
reverseIfGte5('word') //=> 'word'
reverseIfGte5('supercalifragilisticexpialidocious')
//=> 'suoicodilaipxecitsiligarfilacrepus')
Note that here, we write reverseIfGte5 using reverseWord. So our reverseWord function is also available to be reused if we choose, but also so that each function is doing something simple.
We could now write spinWord in terms of this function, via
const spinWords = sentence => sentence.split(/\s+/).map(reverseIfGte5).join(' ')
spinWords('Hey fellow warriors') //=> 'Hey wollef sroirraw'
This does what's expected. And it might be a good place to stop. However...
Do only one thing per function
Our spinWords function above is responsible for two things:
finding the words in the sentence
applying our reversing function to each
Ideally, a function should be responsible for one thing an one thing only. (There is some judgment to be made in deciding how such responsibilities break down, of course.)
It might be useful to break this apart. We can do that in different ways. Here's a simple one:
const updateWords = wordFn => sentence => sentence.split(/\s+/).map(wordFn).join(' ')
const spinWords = updateWords(reverseIfGte5)
Now we have a reusable function, which we could use, for instance, with an obvious capitalizeFirstLetter function like this:
const titleCase = updateWords(capitalizeFirstLetter)
titleCase('Hey fellow warriors') //=> 'Hey Fellow Warriors')
Fixing bugs
Our code now looks like this:
const updateWords = wordFn => sentence => sentence.split(/\s+/).map(wordFn).join(' ')
const reverseWord = word => word.split('').reverse().join('')
const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
const spinWords = updateWords(reverseIfGte5)
These functions are ordered from the most likely to the least likely to be reusable.
Note that the total code here, when using such reusable functions, is a bit longer than this plain version:
const spinWords = sentence => sentence.split(/\s+/).map(
word => word.length >= 5 ? word.split('').reverse().join('') : word
).join(' ')
But our version has several advantages. Obviously, reusability is one. But another is that with the problem broken down into small pieces, if we find a problem, we know where look to for a solution.
And guess what, there is in fact a potential bug in this solution.
If we call this function with 'Hey fellow warriors', we return 'Hey wollef oirraw' instead of the expected 'Hey wollef sroirraw'. Our spacing is off.
Because this problem is broken down into distinct functions, there is no question about which function we need to change in order to fix this. Clearly it is the function responsible for pulling apart and putting back together the sentence, updateWords. There is one simple fix to this, changing from
const updateWords = wordFn => sentence => sentence.split(/\s+/).map(wordFn).join(' ')
to
const updateWords = wordFn => sentence => sentence.split(' ').map(wordFn).join(' ')
but we might be better off using a variant of the answer from CertainPerformance, and rewriting it like this:
const updateWords = wordFn => sentence => sentence.replace(/\w+/g, wordFn)
This fixes the bug and actually handles more cases than we could have originally. (Note that it now deals with punctuation characters as well):
spinWords('Hey, fellow warriors!') //=> 'Hey, wollef sroirraw!'
The important point is that in order to fix our bug, we were able to isolate the function responsible and change it without changing anything else.
Working code
This is what we have arrived at:
const updateWords = wordFn => sentence => sentence.replace(/\w+/g, wordFn)
const reverseWord = word => word.split('').reverse().join('')
const reverseIfGte5 = word => word.length >= 5 ? reverseWord(word) : word
const spinWords = updateWords(reverseIfGte5)
console.log(spinWords('Hey, fellow warriors!'))
We have broken the problem down into two fairly reusable functions (reverseWord and updateWords), and two very specific to our problem (reverseIfGte5 and spinWords.) Each has a well-defined responsibility, and they are easy to test in isolation.
Extending further
This is as far as I would likely go with such a function. But because my personal library often includes a function, when, which is already a generalization of one of these, sometimes I might prefer to build on that:
const when = (cond, then) => val => cond(val) ? then(val) : val
const reverseIfGte5 = when(word => word.length >= 5, reverseWord)
I created when because there are times when I want to use an altered version of my input if some condition is true about it and use it unaltered if the condition is false. That is exactly what reverseIfGte5 needs to do, so it's useful to build it on top of when.
This is how utility libraries are built. Several specific problems have obvious connections and more general solutions to them are written to handle them. If these such solutions are generic enough, they are candidates for inclusion in your personal library or your team's library. And if they are useful to a wider audience, they might get included in a general-purpose utility library.
I'm one of the authors of Ramda, a utility library for functional programming in JS, and this is exactly how it has been built.
I've been playing around with functional programming and some of the challenges set on websites like Codewars (in JavaScript). One challenge I undertook was to find the digital root of an input integer n (i.e. the sum of each of n's individual digits). I'd really like some help fixing it, but by using the functional paradigm, because I've already done this task by other means with OOP techniques. The code used follows:
const digitalRoot = n => {
let arr = n.toString().split('').map(x => parseInt(x, 10)), sum = 0;
for (let i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
};
I'm not sure why this doesn't work in most cases. It returns as follows, for example:
digitalRoot(15); //returns 15 instead of 6
digitalRoot(108); //returns 108 instead of 9
digitalRoot(20); //returns 20 instead of 2
However, in some instances it does work:
digitalRoot(16); //returns 7 as expected
digitalRoot(0); //returns 0 as expected
Could anyone explain to me what the issue with this is and how I might go about fixing it? I'm not sure if it's continuing to be treated as a string despite parseInt being used or what. Please let me know if converting to a string and then an array etc. are bad practice, and/or the wrong approach. Thanks a bunch in advance!
You should add the numbers together with reduce instead of using map, especially so if you're aiming to use "functional" javascript:
const rootNum = n =>
n.toString().split('').reduce((all, current)=>parseInt(current) + all, 0);
console.log(rootNum(1));
console.log(rootNum(20));
console.log(rootNum(440));
console.log(rootNum(1012340));
console.log(rootNum(1021394812));
A functional solution can be a recursive method. As long as n is not 0, get the last digit using the remainder operator (%), and remove it from the number by dividing by 10, and rounding the results down.
const digitalRoot = n =>
n && n % 10 + digitalRoot(Math.floor(n / 10));
console.log(digitalRoot(15));
console.log(digitalRoot(108));
console.log(digitalRoot(20));
console.log(digitalRoot(16));
console.log(digitalRoot(0));
In case anyone was interested, I came across a mathematical formula for this in the Java section of Stack Overflow, which would eliminate the need for any sort of looping or recursion, or calling other functions at all.
The resulting code is:
const digitalRoot = n => 1 + (n - 1) % 9;
This relies on the mathematical properties of numbers, as discussed here.
I have a large data collection that I frequently query by first applying a filter to it. I want to cache and reuse the results of the different filter functions I use because this part can be expensive. Here's a rough simulation of this:
const a = x => x + 1;
const b = x => x + 2;
const m = _.memoize(
f => (console.log('filtering data'), f(314159)),
f => String(f)
);
console.log(m(a));
console.log(m(b));
console.log(m(a));
console.log(m(b));
Here "a" and "b" would be the filter functions I want to use and "m" is acting on the same data each time.
How do I specify the key for the _.memoize function?
The above works but I'm using the string representation of the function which feels wrong. Is there a better way?
I'm worried this isn't safe when minification is applied. In my actual code, the "memoize" part is in one ES6 module, the "a" and "b" parts are in another module and the calls to "m" are in several different modules which import the "a" and "b" function. Will the string representation be stable across modules like this? Is converting to the string representation fast?
The only alternative I can think of is to create a string -> function dictionary so you would do calls like m("a") but JavaScript linters won't pick up if the name is wrong.
The above works but I'm using the string representation of the function which feels wrong.
Indeed.
I'm worried this isn't safe when minification is applied.
No, minification is not the problem. Different functions get minified to different code.
The problem is closures:
const addTo = x => y => x + y
const a = addTo(1),
b = addTo(2);
console.log(String(a) === String(b));
You can only reliably compare functions by their object identity. The best way would probably be to update Lodash to use an ES6 WeakMap that doesn't require any stringification.
As long as such is not available, you can use
const id = Symbol("function identity");
let count = 0;
function toMemoizeKey(fn) {
return fn[id] || (fn[id] = ++count);
}
During the Math classes we learned how to define new operators. For example:
(ℝ, ∘), x ∘ y = x + 2y
This defines ∘ law. For any real numbers x and y, x ∘ y is x + 2y.
Example: 2 ∘ 2 = 2 + 4 = 6.
Is possible to define operators like this in JavaScript? I know that a function would do the job:
function foo (x, y) { return x + 2 * y; }
but I would like to have the following syntax:
var y = 2 ∘ 2; // returns 6
instead of this:
var y = foo(2, 2);
Which is the closest solution to this question?
The short answer is no. ECMAScript (the standard JS is based on) does not support operator overloading.
As an aside, in ECMAScript 7, you'll be able to overload a subset of the standard operators when designing custom value types. Here is a slide deck by language creator and Mozilla CTO Brendan Eich about the subject. This won't allow arbitary operators, however, and the overloaded meaning will only be applied to value types. <- haha that ended up not happening.
It is possible to use third party tools like sweet.js to add custom operators though that'd require an extra compilation step.
I've answered with a solution from outside JavaScript using esprima - this is changing JavaScript and extending it, it's not native.
Given the somewhat new tagged template literals feature that was added in ES6 one can create custom DSLs to handle embedded expressions such as these including different algebraic symbols.
ex. (run in stackblitz)
function math(strings, x, y) {
// NOTE: Naive approach as demonstration
const operator = strings[1].replace(/\s/gi, "");
if (operator == "∘") {
return x + 2 * y;
}
else if (operator == "^") {
return Math.pow(x, y);
}
else {
return `Unknown operator '${operator}'`;
}
}
console.log(math`${2} ∘ ${2}`)
Note that since tagged template literals don't necessarily return strings as results they can return more complex intermediate AST like structures to build up an expression that can then be further refined and then interpreted while keeping close to the domain specific language at hand. I haven't found any existing library that does this yet for Javascript but it should be an interesting and quite approachable endeavor from what it appears from what I know of tagged template literals and usage in such places as lit-html.
No. You can't do that in JS.
The closest you can have IMO is to implement your own object which has a chainable interface, aka "fluent" syntax. That way you can operate as if you were speaking out in sequence.
var eq = new YourEquationObject();
// Then operate like 1 - 2 * 3
eq.add(1).sub(2).mul(3);
Details are up to you though. Just giving out an idea.
No. JavaScript does not support operator overloading . but you can make a class method for doing this
var mathClass = function(value){
this.value = value;
}
mathClass.prototype.toLaw = function(){
return 2 * this.value;
}
var y = new mathClass(2)
2 + y.toLaw(); //2 + 2 * y
You can add pseudo-operators via methods on Number.prototype:
Object.defineProperty(Number.prototype, 'myOp', {
value: function(that) {
return this + 2 * that;
}
});
Then all of this syntax will work
alert( (2).myOp(2) )
alert( 2 .myOp(2) )
alert( 2..myOp(2) )
alert( 2.0.myOp(2) )
2.myOp(2) does not work because the period is treated as a decimal point
Read the comments below the answer.
Apparently you can't. Here is something close :
function exec(input) {
return Function(
'return ' + input.replace(/∘( *[\d.]+)/g, '+ 2 * $1') + ';'
)();
}
exec('2 ∘ 2'); // 6
Set of compiled to JS languages support custom operators.
I would highlight ReasonML (ocaml-syntax-readable-by-js-folks) and Bucklescript (ocaml-to-js-compiler) which makes custom operators look neat:
For example an operator to concatenate strings can look like:
let (>|<) = (list, seperator) => Belt.List.reduce(list, "", (a, b) => a ++ seperator ++ b);
which can then be used like:
[Styles.button, Media.Classes.atLeastTablet] >|< " "
The downside of all this is the fact it has to be written in such compiled-to-js language, and it comes with lots of pros and cons, but usually those languages have the appeal of tons of nice syntactic sugar you don't get in js/ts
The slightly longer then the short one is that Yes you can, but its a bit more involved then what you did in Math class
To extend the language with new constructs you can use a transformer like http://esprima.org/ or any of the others. You need to define your syntax, write the parser to parse your statement and finally add the actual code to do the math parts. When these parts is in place you have made a new language that works just as javascript but with the added support of the ∘ operator.
Its really not that hard to add new syntax, here is facebooks example how they add => arrow function syntax
https://github.com/facebook/jstransform/blob/master/visitors/es6-arrow-function-visitors.js
I was asking this question too, and here's my answer:
function myCustomOperation(string){
var res = String.fromCharCode(9762);
var thing = string.replace(/☢/g," + 10 + ");
thing=thing.replace(/☣/g," * 2 + ");
thing=thing.replace(/☠/g," / 3 * ");
return [eval(thing),string+" = "+eval(thing)];
};
var thing = myCustomOperation("
3 ☠ 4
");
document.write(thing[1]);
There are several tools, compilers, or language extensions providing such a possibility, and even using emojis and other stuff, that are uncommon in JavaScript itself. sweet.js is the closest one I can remember, and also another JavaScript compiled tool might be useful.