js用函数实现输出100以内与7有关的数_函数式编程初探

开始

964bb12cc77b1559b724b645c6cccabc.png
来源:见水印(Hux黄玄)

当时看不懂,然后黏糊糊学长 @GooeyNyan 细心的讲了很久hhh

第一种方法是迭代,偏向命令式,也就是写一条条指令让计算机执行动作

每一步都有一个确定的结果,然后计算可以在每一步都可以暂停中断,也可以从任意部分再启动

第二种是用递归,偏向声明式,形成(a+b+c+d+...+0)这样的运算

更关心逻辑产生的过程.通过过程产生想要的结果
const sum1 = list => 
  list.length === 0
    ? 0
    : list[0] + sum1(list.slice(1))

const sum2 = list => list.reduce((acc,x) => acc + x)

这是求幂的例子

const pow1 = (base,count) =>
  count === 0
    ? 1
    : base * pow1(base,count-1)

const pow2 = (base,count) => {
  let result = 1;
  for(let i = 0;i<count;i++){
    result *= base;
  }
  return result;
}

因为要一次一次算*base,糊糊学长还做了优化

当count是2的倍数的时候,可以直接平方

const square = x => x*x;
const pow1 = (base, count) =>
  count === 0 
    ? 1
    : count % 2 === 0 
      ? square(pow1(base, count / 2))
      : base * pow1(base, count - 1) 
const pow2 = (base, count) => {
  let result = 1;
  let i = count;
  const iter = (j,res) => {
    j === 0
      ? res
      : j % 2 === 0
        ? iter(j/2,square(res))
        : iter(j-1,res * base)
  }
  return iter(i,result);
}

不可变(Immutable)

函数式推崇不可变,或者说是没有变量这个概念

  • 增加一点空间损耗 -> 换来可读性
const arr = [1,2,3];

arr.push(4) //normal

const brr = [...arr,4]; //better

不可变数据带来的提升:

React中的props和state是不可变的,这样能检测出前一个state和后一个是否相等,减少不必要的重绘


性能问题

justjavac:JavaScript 函数式编程存在性能问题么?在这个问题里面,for循环还是比一些遍历方法快的

随着JS引擎优化做的越来越好,遍历方法甚至已经比for循环还快,既提升了性能,可读性也变高了

f2c6ab2de1945c33f09363bd52f03242.png

e5a13cd8f30f309a34f15172d3ac41d7.png

纯函数

函数式编程的核心是借助形式化数学描述逻辑 -> lambda运算

纯函数: 无副作用,并且输入相同的时候,输出始终保持一致

const arr = [1,2,3,4,5,6,7];
arr.slice(0,3); //[1,2,3]
arr.slice(0,3); //[1,2,3]

arr.splice(0,3) //[1,2,3]
arr.splice(0,3) //[4,5,6]
arr.splice(0,3) //[7]

显而易见,slice()是纯函数,splice()不是纯函数

纯函数带来的好处: 可以仅仅关注函数本身,不用担心外部因素的问题

const add = x => x+10;

let a = 10;
const adda = x => x+a;
const addv = x => x+v;

比如这里的add是纯函数,我不用担心程序会因为a不同而改变,但是这样写死了10,程序的拓展性会变差


解决方案:柯里化

"预加载"的函数,传递较少的参数,得到一个已经记住了这些参数的新函数 -> 达到缓存计算

const add = x => y => x+y;

let add2 = add(2);
let add10 = add2(10); //12

组合

柯里化带来的问题,容易写出f(g(h(x)))这样的函数

const compose = (f,g) => (x => f(g(x)));

有了组合,就可以随意的拼接代码

const first = arr => arr[0];
const reverse = arr => arr.reverse();
const last = compose(reverse,first);
last([1,2,3,4,5]); //5

实现一个Compose

compose 函数 | ScriptOJ​scriptoj.mangojuice.top
const compose = (...funcs) => (data) => funcs.reverse().reduce((data,func) => func(data),data)

高阶函数的组合

  1. 之前写的OASIS小程序里面,也涉及过一点

数组的遍历方法代替loop和if,可能会增加一点可读性

// 项目管理员
let adminBrr = that.data.projectmembers
  .filter(x => Number(x.clearance) >= 1)
  .map(y => ({
    adminName: y.realName,
    adminEmail: y.email,
    uid: y.uid
  }));

//过滤空值
let filterArr = this.data.dateArr
  .filter(items => typeof items.day === "number")
  .map(item => {
    item.select = false;
  });

2. "乔波的招新题"

用(JAVA)JavaScript写出不显示定义变量的情况下,计算1~100中不能被3整除的数的平方和
[...Array(100).keys()]
  .map(x => (x + 1) ** 2)
  .filter(x => x % 3 !== 0)
  .reduce((x, y) => x + y);
import java.util.stream.IntStream;
class Main{
  public static void main(String[] args){
    System.out.println(IntStream.range(0,101).filter(x -> x%3 != 0).map(x -> x*x).sum());
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值