if - then - else syntax and cycles), arithmetic operators ( + , - , * , / ), comparison operators ( === , > , < , and m .d.), and logical operators ( && , || ,!). const multiply = (a, b) => a * b const addOne = x => x + 1 const square = x => x * x const operate = pipe( multiply, addOne, square ) operate(3, 4) // => ((3 * 4) + 1)^2 => (12 + 1)^2 => 13^2 => 169 multiply where we used the samopisnaya function, we can take advantage of the addOne add function to replace our addOne , and we can also write square using multiply . const square = x => multiply(x, x) const operate = pipe( multiply, add(1), square ) add(1) very similar to the increment operator ( ++ ), but the increment operator changes the variable so that it causes a mutation. As we learned from the first part , immobility is the basic principle of functional programming, so we don’t want to use ++ or its cousin -- .add(1) and subtract(1) to increase and decrease, but since these two operations are so common, Ramda provides inc and dec instead. const square = x => multiply(x, x) const operate = pipe( multiply, inc, square ) subtract is a replacement for the binary operator - , but we still have a unary operator - to negate the value. We can also use multiply(-1) , but Ramda provides the negate function to perform this task. const wasBornInCountry = person => person.birthCountry === OUR_COUNTRY const wasNaturalized = person => Boolean(person.naturalizationDate) const isOver18 = person => person.age >= 18 const isCitizen = either(wasBornInCountry, wasNaturalized) const isEligibleToVote = both(isOver18, isCitizen) === and >= in this case). As you can imagine now, Ramda also provides substitutes for all of this.=== and gte instead of >= . const wasBornInCountry = person => equals(person.birthCountry, OUR_COUNTRY) const wasNaturalized = person => Boolean(person.naturalizationDate) const isOver18 = person => gte(person.age, 18) const isCitizen = either(wasBornInCountry, wasNaturalized) const isEligibleToVote = both(isOver18, isCitizen) > , lt for < and lte for <=equals there are still identical ones to determine if two values ​​are references to the same space in memory.=== : checking that a string or array is empty ( str === '' or arr.length === 0 ) and checking whether a variable is null or undefined . Ramda provides convenient functions for both isEmpty and isNil .both and both functions in the places of the operators && and || . We also talked about complement for places with ! .wasBornInCountry , wasNaturalized and isOver18 all applied to the person object.&& , || and ! to different values. For sub-cases, the Ramda provides us with the functions and , or and not . I think as follows: and , or and not work with values, while both , both and complement work with functions.|| used to get default values. For example, we can write something like this: const lineWidth = settings.lineWidth || 80 0 is a valid parameter? Since 0 is a false value, we get a line value of 80.isNil function, which we have just learned about above, but Ramda again has a more logical option for us: defaultTo . const lineWidth = defaultTo(80, settings.lineWidth) defaultTo checks the second argument on isNil . If the check fails, it returns the resulting value, otherwise it returns the first argument passed to it.forever21 , which gets the year and returns the next. But, as we are told by her name, from the age of 21, he will remain in that meaning. const forever21 = age => age >= 21 ? 21 : age + 1 age >= 21 ) and the second branch ( age + 1 ) can both be written as functions of age . We can rewrite the first branch ( 21 ) as a constant function ( () => 21 ). Now we will have three functions that accept (or ignore) age .if...then..else or its shorter cousin, the ternary operator ( ?: . const forever21 = age => ifElse(gte(__, 21), () => 21, inc)(age) __ ). We can also use lte instead: const forever21 = age => ifElse(lte(21), () => 21, inc)(age) age ”. I'm going to stick with the placeholder version for the rest of the post, since I find it more readable and less confusing. const forever21 = age => ifElse(gte(__, 21), always(21), inc)(age) always(true) and always(false)alwaysDrivingAge . This function takes age and returns it if its value is gte 16. If it is less than 16, then it will return 16. This allows anyone to pretend that he controls age, even if it is not: const alwaysDrivingAge = age => ifElse(lt(__, 16), always(16), a => a)(age) a => a ) is another typical pattern in functional programming. This is known as “identity” ( I don’t know the exact translation of the term “identity function”, just choose this one - approx. Lane ). That is, it is a function that simply returns the argument that it received. const alwaysDrivingAge = age => ifElse(lt(__, 16), always(16), identity)(age) identity can take more than one argument, but always returns only the first one. If we want to return something else that is different from the first argument, for this, there is a more general function nthArg . This is a much less common situation than using identity .ifElse expression, in which one of the logical branches is the identity, is also a typical paternum, so Ramda provides us with more reduction methods.ifElse : const alwaysDrivingAge = age => when(lt(__, 16), always(16))(age) gte(__, 16) , we can use unless . const alwaysDrivingAge = age => unless(gte(__, 16), always(16))(age) switch or a chain of if...then...else expressions. const water = temperature => cond([ [equals(0), always('water freezes at 0°C')], [equals(100), always('water boils at 100°C')], [T, temp => `nothing special happens at ${temp}°C`] ])(temperature) cond in my code with Ramda, but I wrote similar Lisp code many years ago, so cond feels like an old friend.forever21 , drivingAge and water ) all accept the parameters, create a new function and then apply this function to the parameter.Source: https://habr.com/ru/post/349674/
All Articles