zoukankan      html  css  js  c++  java
  • 函数式编程基础(F#,JS)

      前面三篇是关于javascript的函数式特性:

    1. javascript之典型高阶函数
    2. javascript之典型高阶函数二
    3. javascript之Partial Application

      索性就把形式化方法从头复习一遍吧,顺便也温习下f#,并尝试使用javascript来表现一下,同时也会加入C#作为对比。关于f#,请阅读维基百科:F#

      为什么要学习函数式编程?原因有太多,每个人都有他们的说法。而对于我,因为当我第一次在C#中使用LINQ、使用Lambda时,感到非常惊讶,怎么会有这样的用法?但当时仅仅停留在使用的层面,没能理解为什么,或者是怎么做到的。直到学习了这门课程之后,我才真正明白。所以这就是原因,很简单。

    基础

      首先是基础部分,看一下如何定义类型。比如我们要定义名为"day"的类型。这个"day"可以是Monday,Tuesday,...,Sunday。下面呢,看看三个版本的定义,首先是F#:

    1 type day =
    2   | Monday
    3   | Tuesday
    4   | Wednesday
    5   | Thursday
    6   | Friday
    7   | Saturday
    8   | Sunday

      在F#中,type是定义类型的关键字,定义的构造函数的首字母必须大写如应该是"Monday"而不是"monday"。"|"后面的每一个值都是day类型的。第二个是javascript版本的:

     1 var day = function(name){
     2     this.name = name;   
     3 }
     4 var Monday = new day("Monday"),
     5     Tuesday = new day("Tuesday"),
     6     Wednesday = new day("Wednesday"),
     7     Thursday = new day("Thursday"),
     8     Friday = new day("Friday"),
     9     Saturday = new day("Saturday"),
    10     Sunday = new day("Sunday");

      在javascript中,day作为一个类,然后其他都是day的实例,跟F#比起来是有点麻烦。这应该是一种表现,有其它更好的方式还望高手告知。最后呢是我们最熟悉的C#啦:

    abstract class day
    {
    }
    class Monday:day
    {
    }
    class Tuesday:day
    {
    }
    class Wednesday:day
    {
    }
    class Thursday:day
    {
    }
    class Friday:day
    {
    }
    class Saturday:day
    {
    }
    class Sunday:day
    {
    }

      在C#代码里,使用了抽象类做类型,其他都从它继承。很明显的,在表达能力上F#最简洁。有了类型后,再定义一个使用此类型的函数:

    1 let next_weekday (d:day) : day =
    2   match d with
    3   | Monday -> Tuesday
    4   | Tuesday -> Wednesday
    5   | Wednesday -> Thursday
    6   | Thursday -> Friday
    7   | Friday -> Monday
    8   | Saturday -> Monday
    9   | Sunday -> Monday

      上面定义一名为"next_weekday"的函数,后边括号中接受一个参数"d","d:day"中冒号后边指的是类型,最后的" : day"表示函数的返回类型是day,"="后面很明显就是函数体啦。函数体中"Monday -> Tuesday"中的箭头右边表示返回值。所以这个函数就是下一个“工作日”,周一的下一个工作日是周二,那“箭头”是最自然、直接的表达方式,一目了然。再看看其它两个版本的:

     1 function next_weekday(d){
     2     switch(d.name){
     3     case "Monday": return new day("Tuesday");
     4     case "Tuesday": return new day("Wednesday");
     5     case "Wednesday": return new day("Thursday");
     6     case "Thursday": return new day("Friday");
     7     case "Friday": return new day("Monday");
     8     case "Saturday": return new day("Monday");
     9     case "Sunday": return new day("Monday");
    10     }
    11 }

      

    day next_weekday(day d)
    {
        switch(d.ToString())
        {
            case "Monday": return (new Tuesday());
            case "Tuesday": return (new Wednesday());
            case "Wednesday": return (new Thursday());
            case "Thursday": return (new Friday());
            case "Friday": return (new Monday());
            case "Saturday": return (new Monday());
            case "Sunday": return (new Monday());
            default:return null;
        }
    }

      这样定义完了函数,就可以先做一个单元测试。同样的先看F#的:

    printfn "%A\n" (next_weekday Friday)
    printfn "%A\n" (next_weekday (next_weekday Saturday))
    
    //结果:
    Monday
    Tuesday

      同样地,javascript与C#的测试:

    console.log(next_weekday(Friday));
    console.log(next_weekday(next_weekday(Saturday)));
    
    //结果:
    day {name: "Monday"}
    day {name: "Tuesday"} 

      

    1 Console.WriteLine(next_weekday(new Friday()));
    2 Console.WriteLine(next_weekday(next_weekday(new Saturday())));

    //结果:
    Monday
    Tuesday

      测试结果都是OK的啦。使用F#又是最简洁的哦。而且语义上面也是最直接的。不知道你是否会爱上F#,嘿嘿。再来定义一个类型,只有True和False的Boolean类型。大家都知道这个类型除了C语言没有,其他语言都内置了,现在我们就自己来实现一下:

    type bool =
      | True
      | False
    var bool = function(b){
        if(b==="True" || b==="False") this.name=b;
    }
    abstract class bools
    {
    }
    class True
    {
    }
    class False
    {
    }

      其中C#中bool为关键字,所以把它改成了bools。如果抛开逻辑,只看类型貌似没啥意义,根本体现不出布尔的特性,所以加上一些辅助函数把这些特性表现出来。他们别是:取反、或和与操作。

    let negb (b:bool) : bool = 
      match b with
      | True -> False
      | False -> True
    
    let andb (b1:bool) (b2:bool) : bool = 
      match b1 with 
      | True -> b2 
      | False -> False
    
    let orb (b1:bool) (b2:bool) : bool = 
      match b1 with 
      | True -> True
      | False -> b2
    function negb(b){
        if(b.name==="True") return new bool("False");
        if(b.name==="False") return new bool("True");
    }
    function andb(b1,b2){
        if(b1.name==="True") return b2;
        else return new bool("False");
    }
    function orb(b1,b2){
        if(b1.name==="True") return new bool("True");
        else return b2;
    }
    bools negb(bools b)
    {
        if(b.GetType().ToString()=="False")
            return new True();
        return new False();
    }
    bools andb(bools b1,bools b2)
    {
        if(b1.GetType().ToString()=="False")
            return new False();
        return b2;
    }
    bools orb(bools b1,bools b2)
    {
        if(b1.GetType().ToString()=="True")
            return new True();
        return b2;
    }

      测试和结果就不贴了,上面主要做了一些类型定义方面的工作。感觉javascript在实现的时候有点奇怪,各读者心理也明白这是弱点,也是优点!F#在做类型定义的时候非常直接,简洁。而C#主要就是通过结构体或类来做定义。还是F#更让人喜欢:)

  • 相关阅读:
    【java多线程】队列系统之说说队列Queue
    【传输协议】什么是CA证书
    5.1 javassist基本使用
    第四章 dubbo内核之aop源码解析
    第三章 dubbo内核之ioc源码解析
    2.2 dubbo-spi源码解析
    2.1 jdk-spi的实现原理
    第一章 第一个dubbo项目
    第零章 dubbo源码解析目录
    macOS Sierra10.12.5 显示允许任何来源
  • 原文地址:https://www.cnblogs.com/mike442144/p/2868774.html
Copyright © 2011-2022 走看看