本文是对函数式编程范式的系列文章从而拉开了与以下延续一个。

介绍

在JavaScript中,函数只是对象。因此,可以构造函数,作为参数传递,从函数返回或分配给变量。因此,JavaScript具有一流的功能。更准确地说,JavaScript支持以下内容:

  • 高阶函数参数
  • 产生高阶函数
  • 嵌套函数
  • 匿名功能
  • 关闭
  • 部分申请(ECMAScript 5)

通过函数表示数据

我们S是任何元素的集合abc...(例如,桌子上的书本或欧几里得平面的点),并让S'是这些元素的任意子集(例如,桌子上的书本绿色或点半径1的圆心以欧几里德平面的原点为中心)。

所述特征函数 S'(x)的一组S'是其中任一相关联的功能truefalse与每个元件xS

  1. S'(x) = true if x is in S'
  2. S'(x) = false if x is not in S'

让我们S成为桌子上的一套书,让我们S'成为桌上的绿色书籍。设ab是两个绿色的书,让cd是在表中的两个红本本。然后:

  1. S'(a) = S'(b) = true
  2. S'(c) = S'(d) = false

S是集的欧几里德平面中的点,并且让S'在半径为1的在欧几里得平面(0,0)的原点为中心的圆的组的点的(单位圆)。让ab在单位圆的两点,并让c并且d是在欧几里得平面的原点为中心的半径2的圆的两点。然后:

  1. S'(a) = S'(b) = true
  2. S'(c) = S'(d) = false

因此,任何集合S'总是可以由其特征函数表示。一个函数,它将一个元素作为参数,true如果该元素在S'false则返回,否则返回。换句话说,可以通过JavaScript中的函数表示集合(抽象数据类型)。

  1. function set() { }

在接下来的部分中,我们将看到如何通过JavaScript以函数方式表示集合代数中的一些基本集合,然后我们将在集合上定义泛型二进制运算。然后,我们将在欧几里德平面的子集上对数字应用这些操作。集合是抽象数据结构,数字的子集和欧几里得平面的子集是抽象数据结构的表示,最后二元操作是适用于抽象数据结构的任何表示的通用逻辑。

JavaScript环境

要运行网站源码,您需要一个JavaScript引擎。有很多JavaScript引擎可用。在本节中,我将逐步介绍如何使用Ubuntu 16.04中的V8 JavaScript引擎来设置JavaScript环境。V8是一个用C ++编写的开源JavaScript引擎,用于谷歌Chrome,Node.js和V8.NET。设置也可以在Windows和macOS上完成。

  1. 获取V8源代码并编译它:

    我通过在终端中运行以下命令,在Ubuntu 16.04上成功安装并执行了d8。

    1. sudo apt-get install git
    2. mkdir ~/js
    3. cd ~/js
    4. git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git depot_tools
    5. export PATH=~/js/depot_tools:"$PATH"
    6. fetch v8
    7. cd v8
    8. make native
    9. ~/js/v8/out/native/d8

    从git存储库下载V8源代码需要一些时间,具体取决于Internet连接速度。编译V8源代码也需要一些时间,具体取决于硬件配置,但在等待必要的时间后,一切正常。

  2. 我们可以编写第一个JavaScript代码:

    要在控制台中加载JavaScript文件,可以按如下方式执行:

    1. load('set.numbers.demo.js')

本节通过JavaScript介绍集合代数中一些基本集的表示。

空集

E是空集和Empty它的特色功能。在集合的代数中,E是没有元素的唯一集合。因此,Empty可以定义如下:

  1. Empty(x) = false if x is in E
  2. Empty(x) = false if x is not in E

因此,EJavaScript中的表示可以定义如下:

  1. empty = function() {return function(){return false}}

在集合的代数中,Empty表示如下:

因此,运行以下代码:

  1. print('\nEmpty set:')
  2. print('Is 7 in {}? ' + empty()(7))

给出以下结果:

全部设定

我们S是一组和S'是的子集S,它包含所有要素,All特色功能。在集合的代数中,S'是包含所有元素的完整集合。因此,All可以这样定义:

  1. All(x) = true if x is in S

因此,S'JavaScript中的表示可以定义如下:

  1. all = function() {return function(){return true}}

在集合的代数中,All表示如下:

因此,运行以下代码:

  1. print('\nSet All:')
  2. print('Is 7 in integers set? ' + all()(7))

给出以下结果:

单身套装

我们E是辛格尔顿集和Singleton它的特色功能。在集合的代数中,E也称为单位集合,或者1元组是具有恰好一个元素的集合e。因此,Singleton可以定义如下:

  1. Singleton(x) = true if x is e
  2. Singleton(x) = false if x is not e

因此,EJavaScript中的表示可以定义如下:

  1. singleton = function(x) {return function(y){return x === y}}

因此,运行以下代码:

  1. print('\nSingleton set:')
  2. print('Is 7 in the singleton set {0}? ' + singleton(0)(7))
  3. print('Is 7 in the singleton set {7}? ' + singleton(7)(7))

给出以下结果:

其他套装

本节介绍整数集的子集。

偶数

我们E是一组连号,并且Even它的特色功能。在数学中,偶数是一个2的倍数。因此,Even可以定义如下:

  1. Even(x) = true if x is a multiple of 2
  2. Even(x) = false if x is not a multiple of 2

因此,EJavaScript中的表示可以定义如下:

  1. even = function(x){return x%2 === 0}

因此,运行以下代码:

  1. print('\nEven numbers set:')
  2. print('Is 99 in even numbers set? ' + even(99))
  3. print('Is 998 in even numbers set? ' + even(998))

给出以下结果:

奇数

我们E是一组奇数的和Odd它的特色功能。在数学中,奇数是一个不是2的倍数的数字。因此,Odd可以定义如下:

  1. Odd(x) = true if x is not a multiple of 2
  2. Odd(x) = false if x is a multiple of 2

因此,EJavaScript中的表示可以定义如下:

  1. odd = function(x){return x%2 === 1}

因此,运行以下代码:

  1. print('\nOdd numbers set:')
  2. print('Is 99 in odd numbers set? ' + odd(99))
  3. print('Is 998 in odd numbers set? ' + odd(998))

给出以下结果:

倍数为3

我们E是一组3的倍数和MultipleOfThree它的特色功能。在数学中,3的倍数是可被3整除的数。因此,MultipleOfThree可以定义如下:

  1. MultipleOfThree(x) = true if x is divisible by 3
  2. MultipleOfThree(x) = false if x is not divisible by 3

因此,EJavaScript中的表示可以定义如下:

  1. multipleOfThree = function(x){return x%3 === 0}

因此,运行以下代码:

  1. print('\nMultiples of 3 set:')
  2. print('Is 99 in multiples of 3 set? ' + multipleOfThree(99))
  3. print('Is 998 in multiples of 3 set? ' + multipleOfThree(998))

给出以下结果:

倍数为5

我们E是集合5的倍数和MultipleOfFive它的特色功能。在数学中,5的倍数是可被5整除的数。因此,MultipleOfFive可以定义如下:

  1. MultipleOfFive(x) = true if x is divisible by 5
  2. MultipleOfFive(x) = false if x is not divisible by 5

因此,EJavaScript中的表示可以定义如下:

  1. multipleOfFive = function(x){return x%5 === 0}

因此,运行以下代码:

  1. print('\nMultiples of 5 set:')
  2. print('Is 15 in multiples of 5 set? ' + multipleOfFive(15))
  3. print('Is 998 in multiples of 5 set? ' + multipleOfFive(998))

给出以下结果:

质数

很久以前,当我玩Project Euler问题时,我不得不解决以下问题:

  1. By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13,
  2. we can see that the 6th prime is 13.
  3. What is the 10 001st prime number?

为了解决这个问题,我首先必须编写一个快速算法来检查给定的数字是否为素数。编写算法后,我编写了一个迭代算法,迭代遍历素数,直到找到10 001 st素数。

我们E是集合素数的和Prime它的特色功能。在数学中,素数是大于1的自然数,除了1和自身之外没有正除数。因此,Prime可以定义如下:

  1. Prime(x) = true if x is prime
  2. Prime(x) = false if x is not prime

因此,EJavaScript中的表示可以定义如下:

  1. prime = function(x){
  2. if(x===1) return false
  3. if(x<4) return true
  4. if(x%2===0) return false
  5. if(x<9) return true
  6. if(x%3===0) return false
  7. var sqrt = Math.sqrt(x)
  8. for(var i = 5; i <= sqrt; i+=6){
  9. if(x%i===0) return false
  10. if(x%(i+2)===0) return false
  11. }
  12. return true
  13. }

因此,运行下面的代码来解决我们的问题:

  1. print('\nPrimes set:')
  2. print('Is 2 in primes set? ' + prime(2))
  3. print('Is 4 in primes set? ' + prime(4))
  4. print('The 10 001st prime number is ' + getPrime(10001))

其中getPrime定义如下:

  1. getPrime = function(p){
  2. var count = 0;
  3. for(var i = 1; ; i++){
  4. if(prime(i)) count++
  5. if(count === p){
  6. return i
  7. break
  8. }
  9. }
  10. }

给出以下结果:

二元操作

本节介绍了从给定集合和操作集合构造新集合的几个基本操作。下面是集合代数中的维恩图。

联盟

让我们EF两套。该联合EF,记为E U F是一组其是成员的所有元素EF

让我们Union结合工会。因此,Union可以在JavaScript中按如下方式实现操作:

  1. union = function(e, f){return function(x){ return e(x) || f(x)}}

运行以下代码:

  1. print('\nUnion:')
  2. print('Is 7 in the union of Even and Odd Integers Set? ' + union(even,odd)(7))

给出以下结果:

路口

让我们EF两套。的交叉点EF,记为E n F是一组这两者都是成员的所有元素的EF

让我们Intersection进行交叉操作。因此,Intersection可以在JavaScript中按如下方式实现操作:

  1. intersection = function(e, f){return function(x){ return e(x) && f(x)}}

运行以下代码:

  1. print('\nIntersection:')
  2. multiplesOfThreeAndFive = intersection(multipleOfThree, multipleOfFive)
  3. print('Is 15 a multiple of 3 and 5? ' + multiplesOfThreeAndFive(15))
  4. print('Is 10 a multiple of 3 and 5? ' + multiplesOfThreeAndFive(10))

给出以下结果:

笛卡尔积

让我们EF两套。的笛卡儿积EF,由表示E × F是该组所有有序对(e, f),使得e是其成员Ef是其成员F

让我们CartesianProduct进行笛卡尔积运算。因此,CartesianProduct可以在JavaScript中按如下方式实现操作:

  1. cartesianProduct = function(e, f){return function(x, y){ return e(x) && f(y)}}

运行以下代码:

  1. print('\nCartesian Product:')
  2. cp = cartesianProduct(multipleOfThree,multipleOfFive)
  3. print('Is (9, 15) in MultipleOfThree x MultipleOfFive? ' + cp(9, 15))

给出以下结果:

补语

让我们EF两套。的相对补FE,由表示E \ F是一组其是成员的所有元件的E但不是成员F

让我们Complement进行相对补充操作。因此,Complement可以在JavaScript中按如下方式实现操作:

  1. complement = function(e, f){return function(x){ return e(x) && !f(x)}}

运行以下代码:

  1. print('\nComplement:')
  2. c = complement(multipleOfThree, multipleOfFive)
  3. print('Is 15 in MultipleOfThree \\ MultipleOfFive set? '+ c(15))
  4. print('Is 9 in MultipleOfThree \\ MultipleOfFive set? '+ c(9))

给出以下结果:

对称差异

让我们EF两套。的对称差EF,记为E delta F是一组其是的任成员的所有元素的EF,但不是在相交EF

让我们SymmetricDifference进行对称差分运算。因此,SymmetricDifference可以在JavaScript中以两种方式实现该操作。一个简单的方法是使用union和补充操作如下:

  1. symmetricDifferenceWithoutXor = function(e, f){ return function(x)
  2. { return union(complement(e,f), complement(f, e))(x)}}

另一种方法是使用XOR二进制操作如下:

  1. symmetricDifferenceWithXor = function(e, f){return function(x)
  2. { return (e(x) ^ f(x)) === 1 ? true : false}}

运行以下代码:

  1. print('\nSymmetricDifference without XOR:')
  2. sdWithoutXor = symmetricDifferenceWithoutXor(prime, even)
  3. print('Is 2 in the symetric difference of prime and even Sets? ' + sdWithoutXor(2))
  4. print('Is 4 in the symetric difference of prime and even Sets? ' + sdWithoutXor(4))
  5. print('Is 7 in the symetric difference of prime and even Sets? ' + sdWithoutXor(7))
  6.  
  7. print('\nSymmetricDifference with XOR:')
  8. sdWithXor = symmetricDifferenceWithXor(prime, even)
  9. print('Is 2 in the symetric difference of prime and even Sets? ', sdWithXor(2))
  10. print('Is 4 in the symetric difference of prime and even Sets? ', sdWithXor(4))
  11. print('Is 7 in the symetric difference of prime and even Sets? ', sdWithXor(7))

给出以下结果:

其他行动

本节介绍集合上其他有用的二进制操作。

包含

Contains是检查元素是否在集合中的操作。此操作是一个函数,它将元素作为参数,true如果元素在集合中则返回,false否则返回。

因此,此操作在JavaScript中定义如下:

  1. contains = function(e, x){return e(x)}

因此,运行以下代码:

  1. print('\nContains:')
  2. print('Is 7 in the singleton {0}? ' + contains(singleton(0), 7))
  3. print('Is 7 in the singleton {7}? ' + contains(singleton(7), 7))

给出以下结果:

让我们Add将一个元素添加到集合中的操作。此操作是一个函数,它将元素作为参数并将其添加到集合中。

因此,此操作在JavaScript中定义如下:

  1. add = function(e, y){return function(x){ return x === y || e(x)}}

因此,运行以下代码:

  1. print('\nAdd:')
  2. print('Is 7 in {0, 7}? ' + add(singleton(0),7)(7))
  3. print('Is 0 in {1, 0}? ' + add(singleton(1),0)(0))
  4. print('Is 7 in {19, 0}? ' + add(singleton(19),0)(7))

给出以下结果:

去掉

Remove是从集合中删除元素的操作。此操作是一个函数,它将元素作为参数并将其从集合中删除。

因此,此操作在JavaScript中定义如下:

  1. remove = function(e, y){return function(x){ return x !== y && e(x)}}

因此,运行以下代码:

  1. print('\nRemove:')
  2. print('Is 7 in {}? ' + remove(singleton(0), 0)(7))
  3. print('Is 0 in {}? ' + remove(singleton(7), 7)(0))

给出以下结果:

对于那些想要更进一步的人

您可以通过函数式编程看到我们可以轻松地在JavaScript中使用集合代数。在前面的部分中,显示了最基本的定义。但是,如果你想进一步,你可以考虑:

  • 关系集
  • 抽象代数,如幺半群,群,场,环,K-矢量空间等
  • 包含 - 排除原则
  • 罗素的悖论
  • 康托尔的悖论
  • 双向量空间
  • 定理和推论

欧几里得飞机

在上一节中,集合的基本概念是在JavaScript中实现的。在本节中,我们将练习在平面点集(欧几里德平面)上实现的概念。

绘制磁盘

磁盘是由圆圈限定的平面的子集。有两种类型的磁盘。封闭的磁盘是包含构成其边界的圆的点的磁盘,而打开的磁盘是不包含构成其边界的圆的点的磁盘。

在本节中,我们将成立Characterstic功能的的封闭盘和HTML5绘制。

要设置Charactertic函数,首先需要一个计算平面中两点之间欧氏距离的函数。该功能实现如下:

  1. function distance(p1, p2){
  2. return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2))
  3. }

其中point定义如下:

  1. point = function(x,y){
  2. this.x = x
  3. this.y = y
  4. }

这个公式是基于毕达哥拉斯定理。

其中c欧几里德距离(p1.X - p2.X)²(p1.Y - p2.Y)²

我们Disk特色功能的封闭盘。在集合的代数中,实数集中的闭合磁盘的定义如下:

其中ab是中心和R半径的坐标。

因此,DiskJavaScript中的实现如下:

  1. disk = function(center, radius){return function(p){ return distance(p, center) <= radius}}

为了查看集合,我决定实现一个draw欧几里得平面中绘制集合的函数。我选择了HTML5,因此使用了canvas元素进行绘制。

因此,我通过该方法建立了下面说明的欧几里德平面draw

下面是飞机的实施。

  1. /*
  2. * Plane
  3. *
  4. */
  5. plane = function(width, height) {
  6.  
  7. /**
  8. * Plane width in pixels
  9. *
  10. */
  11. this.width = width
  12.  
  13. /**
  14. * Plane height in pixels
  15. *
  16. */
  17. this.height = height
  18.  
  19. /*
  20. * Draws a generic set
  21. *
  22. */
  23. this.draw = function (set, canvasId){
  24. var canvas = document.getElementById(canvasId)
  25. canvas.width = this.width
  26. canvas.height = this.height
  27. var context = canvas.getContext('2d'),
  28. semiWidth = this.width/2, semiHeight = this.height/2,
  29. xMin = -semiWidth, xMax = semiWidth,
  30. yMin = -semiHeight, yMax = semiHeight
  31. for(var x = 0; x < this.width; x++){
  32. var xp = xMin + x * (xMax - xMin) / this.width
  33. for(var y = 0; y < this.height; y++) {
  34. var yp = yMax - y * (yMax - yMin) / this.height
  35. if(set(new point(xp, yp))) context.fillRect(x, y, 1, 1)
  36. }
  37. }
  38. }
  39. }

在该draw方法中,创建canvas具有与欧几里德平面容器相同的宽度和相同高度的a 。然后(x,y)canvas如果属于的是黑点,则每个像素点都被替换为黑点setxMinxMaxyMinyMax 是在的图中所示的边界值欧几里得平面的上方。

运行以下代码:

  1. euclideanPlane = new plane(200, 200)
  2. euclideanPlane.draw(disk(new point(0, 0), 50), 'disk')

这里diskid帆布:

  1. <canvas id="disk">Your browser does not support HTML5 canvas.</canvas>

给出以下结果:

绘制水平和垂直半平面

水平垂直半平面或者是两个子集到其中的平面将欧几里德空间。甲水平半平面或者是两个子集到其中的平面垂直通过与所述的线划分的欧几里得空间的Y轴如上面的图中。甲垂直半平面或者是两个子集到其中的平面通过管线垂直与划分欧几里得空间的X轴

在本节中,我们将设置水平垂直半平面的特征函数,在HTML5中绘制它们,看看如果我们将它们与磁盘子集组合,我们可以做些什么。

我们HorizontalHalfPlane特色功能一的水平半平面。HorizontalHalfPlaneJavaScript中的实现如下:

  1. horizontalHalfPlane = function(y, isLowerThan){return function(p)
  2. { return isLowerThan ? p.y <= y : p.y >= y}}

因此,运行以下代码:

  1. euclideanPlane.draw(horizontalHalfPlane(0, true), 'hhp')

这里hhpid帆布:

  1. <canvas id="hhp">Your browser does not support HTML5 canvas.</canvas>

给出以下结果:

我们VerticalHalfPlane特色功能一的垂直半平面。VerticalHalfPlaneJavaScript中的实现如下:

  1. verticalHalfPlane = function(x, isLowerThan){return function(p) { return isLowerThan ? p.x <= x : p.x >= x}}

因此,运行以下代码:

  1. euclideanPlane.draw(verticalHalfPlane(0, false), 'vhp')

这里vhpid帆布

  1. <canvas id="vhd">Your browser does not support HTML5 canvas.</canvas>

给出以下源码结果:

在本文的第一部分中,我们在集合上设置了基本的二进制操作。因此,通过组合a disk和a 的交集half-plane,我们可以绘制半盘子集。

因此,运行以下示例:

  1. euclideanPlane.draw(intersection(disk(new point(0, 0), 50), verticalHalfPlane(0, false)), 'hd')

这里hdid帆布:

  1. <canvas id="hd">Your browser does not support HTML5 canvas.</canvas>

给出以下结果:

功能

本节介绍欧几里德平面上的集合的函数。

翻译

我们translatePoint是翻译在平面上的点的功能。在欧几里德几何中,translatePoint是一个将给定点在指定方向上移动恒定距离的函数。因此,JavaScript中的实现如下:

  1. translatePoint = function(deltax, deltay){return function(p)
  2. { return new point(p.x + deltax, p.y + deltay)}}

其中(deltax, deltay)是翻译的常量向量。

我们translate是转化平面中的设定功能。这个函数在JavaScript中简单地实现如下:

  1. translate = function(e, deltax, deltay){return function(p)
  2. { return e(translatePoint(-deltax, -deltay)(p))}}

translatedeltax第一欧几里德维度中的delta距离作为参数,其是deltay第二欧几里德维度中的delta距离。如果点P(x,y)在集合S中被平移,则其坐标将变为(x',y')=(x + delatx,y + deltay)。因此,点(X ' - delatx,Y' - DELTAY)将始终属于集合小号。在集合代数中,translate称为同构,换句话说,所有翻译的集合形成翻译组T,其与空间本身同构。这解释了该功能的主要逻辑。

因此,运行以下代码:

  1. var deltay = 0
  2. setInterval(function(){
  3. deltay = deltay <= euclideanPlane.height ? deltay + 20 : 0
  4. euclideanPlane.draw(translate(disk(new point(0, -50), 50), 0, deltay) , 'ep_op')
  5. }, 1000)

这里ep_opid帆布:

  1. <canvas id="ep_op">Your browser does not support HTML5 canvas.</canvas>

给出以下结果:

位似

scalePoint是发送的任何点的功能中号到另一点Ñ使得段SN是在同一行作为SM,而是由一个因子缩放拉姆达。在集的代数中,Scale表述如下:

因此,JavaScript中的实现如下:

  1. scalePoint = function(lambdax, lambday, deltax, deltay)
  2. {return function(p){ return new point(lambdax * p.x + deltax, lambday * p.y + deltay)}}

其中(deltax, deltay)是平移的常数向量,(lambdax, lambday)是lambda向量。

让我们scale在计划中的集合上应用同一性的功能。这个函数在JavaScript中简单地实现如下:

  1. scale = function(e, lambdax, lambday, deltax, deltay)
  2. {return function(p){ return e(scalePoint(1/lambdax, 1/lambday,
  3. -deltax/lambdax, -deltay/lambday)(p))}}

scaledeltax第一欧几里德维度中的Δ距离作为参数,该第一欧几里德维度deltay是第二欧几里德维度中的Δ距离,并且(lambdax, lambday)是恒定因子向量λ。如果点P(x,y)scale在集合S中变换,则其坐标将变为(x',y')=(lambdax * x + delatx,lambday * y + deltay)。因此,点((x'- delatx)/ lambdax,(y' - deltay)/ lambday)将始终属于集合S,当然,如果lambda不同于向量0。在集合的代数中,scale称为同构,换句话说,所有同态的集合形成Homothety组H,与空间本身\ {0}同构。这解释了该功能的主要逻辑。

因此,运行以下代码:

  1. var deltay = 0, lambday = 0.05
  2. setInterval(function(){
  3. deltay = deltay <= euclideanPlane.height ? deltay + 20 : 0
  4. lambday = deltay <= euclideanPlane.height ? lambday + 0.05 : 0.05
  5. euclideanPlane.draw(scale(disk(new point(0, -50), 50), 1, lambday, 0, deltay), 'ep_op')
  6. }, 1000)

给出以下结果:

旋转

我们rotatePoint是用旋转的角度2θ位置的点的功能。在矩阵代数中,rotatePoint表述如下:

其中(x',y')是旋转后点的坐标,x'y'的公式如下:

这个公式的演示非常简单。看看这个轮换。

以下是演示:

因此,JavaScript中的实现如下:

  1. rotatePoint = function(theta){ return function(p)
  2. { return new point(p.x*Math.cos(theta)-p.y*Math.sin(theta),
  3. p.x*Math.sin(theta)+p.y*Math.cos(theta))}}

我们rotate是在与角度theta平面一套适用的旋转功能。这个函数在JavaScript中简单地实现如下。

  1. rotate = function(e, theta){ return function(p){return e(rotatePoint(-theta)(p))}}

rotate是一个作为参数的函数,theta它是旋转的角度。如果点P(x,y)rotate在集合S中变换,那么它的坐标将变为(x',y')=(x * cos(theta) - y * sin(theta),x * sin( theta)+ y * cos(theta))。因此,点(X '* COS(THETA)+ Y' * SIN(THETA),Y '* COS(THETA) - X' * SIN(THETA))将永远属于一套小号。在集合的代数中,rotate称为同构,换句话说,所有旋转的集合形成旋转组R,其与空间本身同构。这解释了该功能的主要逻辑。

因此,运行以下代码:

  1. var theta = 0
  2. setInterval(function(){
  3. euclideanPlane.draw(rotate(horizontalHalfPlane(-90, true), theta), 'ep_op')
  4. theta = (theta + Math.PI/2)%(2*Math.PI)
  5. }, 1000)

给出以下结果:

对于那些想要更进一步的人

很简单,不是吗?对于那些想要更进一步的人,你可以探索这些:

  • 椭圆
  • 三维欧氏空间
  • Ellipsoide
  • 抛物面
  • 双曲面
  • 球谐波
  • Superellipsoid
  • 妊神星
  • 同形体
  • Focaloid

分形

分形是具有通常超过其拓扑维度并且可能落在整数之间的分形维数的集合。例如,Mandelbrot集是由一系列复数二次多项式定义的分形:

  1. Pc(z) = z^2 + c

哪里c是复杂的。所述曼德尔布罗分形被定义为所有点的集合c,使得上述序列不逃逸到无穷远。在集合的代数中,这表达如下:

Fractals(抽象数据类型)总是可以在JavaScript中表示如下:

  1. function fractal() {}

复数和绘图

为了能够绘制分形,我需要操纵复数。因此,我创建了complex以下类:

  1. complex = function(r, i){
  2. this.x = r
  3. this.y = i
  4. }
  5.  
  6. complex.prototype.toString = function(){
  7. return this.x + ' + i * ' + this.y
  8. }
  9.  
  10. complex.prototype.abs = function(){
  11. return Math.sqrt(this.x*this.x+this.y*this.y)
  12. }
  13.  
  14. complex.add = function(z1, z2){
  15. return new complex(z1.x+z2.x, z1.y+z2.y)
  16. }
  17.  
  18. complex.substract = function(z1, z2){
  19. return new complex(z1.x-z2.x, z1.y-z2.y)
  20. }
  21.  
  22. complex.multiply = function(z1, z2){
  23. return new complex(z1.x*z2.x - z1.y * z2.y, z1.x * z2.y+ z1.y * z2.x)
  24. }
  25.  
  26. complex.zero = new complex(0, 0)

Mandelbrot分形

我创建了一个Mandelbrot Fractal(抽象数据类型表示)P(z) = z^2 + c,可在下面找到。

  1. mandelbrot = function(c, z){return complex.add(complex.multiply(z, z), c)}

为了能够绘制复数,我创建了一个complexPlane类。以下是JavaScript中的实现。

  1. /*
  2. * Plane
  3. *
  4. */
  5. complexPlane = function(width, height, real_min, real_max,
  6. imaginary_min, imaginary_max, boundary, fractalIterationsPerPixel, canvasId) {
  7.  
  8. /**
  9. * Plane width in pixels
  10. *
  11. */
  12. this.width = width
  13.  
  14. /**
  15. * Plane height in pixels
  16. *
  17. */
  18. this.height = height
  19.  
  20. /**
  21. * Real axis minimum value
  22. *
  23. */
  24. this.real_min = real_min
  25.  
  26. /**
  27. * Real axis maximum value
  28. *
  29. */
  30. this.real_max = real_max
  31.  
  32. /**
  33. * Imaginary axis minimum value
  34. *
  35. */
  36. this.imaginary_min = imaginary_min
  37.  
  38. /**
  39. * Imaginary axis maximum value
  40. *
  41. */
  42. this.imaginary_max = imaginary_max
  43.  
  44. /**
  45. * Boudary
  46. *
  47. */
  48. this.boundary = boundary
  49.  
  50. /**
  51. * Number of Zn iterations per pixel
  52. *
  53. */
  54. this.fractalIterationsPerPixel = fractalIterationsPerPixel
  55.  
  56. /**
  57. * Canvas Identifier
  58. *
  59. */
  60. this.canvasId = canvasId
  61.  
  62. /*
  63. * Draws a fractal
  64. *
  65. */
  66. this.draw = function (fractal){
  67. var canvas = document.getElementById(this.canvasId)
  68. canvas.width = this.width
  69. canvas.height = this.height
  70. var context = canvas.getContext('2d')
  71. context.fillStyle = 'yellow'
  72. for(var x = 0; x < this.width; x++){
  73. var xp = this.real_min + x * (this.real_max - this.real_min) / this.width
  74. for(var y = 0; y < this.height; y++) {
  75. var yp = this.imaginary_max - y *
  76. (this.imaginary_max - this.imaginary_min) / this.height
  77. var c = new complex(xp, yp)
  78. var z = complex.zero
  79. for(var k=0; k< this.fractalIterationsPerPixel;k++) z = fractal(c, z)
  80. if(z.abs() < this.boundary) context.fillRect(x, y, 1, 1)
  81. }
  82. }
  83. }
  84.  
  85. /*
  86. * Displays 'Please wait...' at the center of the canvas
  87. *
  88. */
  89. this.pleaseWait = function(){
  90. var canvas = document.getElementById(this.canvasId)
  91. canvas.width = this.width
  92. canvas.height = this.height
  93. var context = canvas.getContext('2d')
  94. context.fillStyle = 'yellow'
  95. context.fillText('Please wait...', this.width/2 - 30, this.height/2)
  96. }
  97. }

因此,运行以下代码:

  1. complexPlane = new complexPlane(300, 300, -1.5, 1.5, -1.5, 1.5, 1.5, 20, 'fractal')
  2.  
  3. mandelbrot = function(c, z){return complex.add(complex.multiply(z, z), c)}
  4.  
  5. complexPlane.pleaseWait()
  6.  
  7. setTimeout(function(){ complexPlane.draw(mandelbrot) }, 500)

这里fractalid帆布:

  1. <canvas id="fractal">Your browser does not support HTML5 canvas.</canvas>

给出以下结果:

通过代数,数字,欧几里得平面和分形讨论JavaScript中的函数式编程的更多相关文章

  1. this,this,再次讨论javascript中的this,超全面

    至于js中this这个东西,好多淫解释过了,看起来好高端的样子,不造你看懂了木有? 先引用比较高端的,“汤姆大叔“ 的,yes this 好了,下面加上鄙人比较挫的解释 论点: this 不是变量,不 ...

  2. JavaScript从初见到热恋之深度讨论JavaScript中的面向对象。

    JavaScript中的面向对象.面向对象的三个基本特征:封装.继承.多态. 1.封装 js的封装如下 定义Person类 function Person(name,age,sex) { this.n ...

  3. 再次讨论javascript 中的this

    原文: http://www.jb51.net/article/77519.htm 核心总结: 1.不论函数在哪里被调用,只要没有指定调用方,则this都指向window.指定了调用方,就指向调用方. ...

  4. JavaScript中的面向对象的讨论(转)

    前言 今天,WEB2.0时代的到来,给了JavaScript又一次大展身手的机会.Web2.0借助JavaScript技术,使得客户端的Web体验更加丰富多彩,同时JavaScript面对的问题域也变 ...

  5. 算法-找出与目标数字相同的digit组成的整数中比该数字大的数集中的最小数字

    题目: 给出1个正整数,找到用与这个数字相同的digit组成的整数中比这个数字大的数集中的最小数字.比如:12352874 的结果是 12354278 分析: 这道题目的考虑目标是数组的查找与排序. ...

  6. 3.键盘输入10个数,放到数组中,(1)去除该数组中大于10的数 (2)将该数组中的数字写入到本地文件number.txt中

    package cn.it.text; import java.io.FileWriter; import java.io.IOException; import java.util.Scanner; ...

  7. javascript中的数字玩法,颠覆你的眼睛

    1.JavaScript中的数字中有一些很奇葩的现象. 在Chrome控制台中可以自己做一下实验: 1 === 1.0 ; //true 习惯了强类型语言,如java,c,OC看到这个结论还是有点小迷 ...

  8. javaScript中Number数字类型方法入门

    前言 Number和Math都属于JavaScript中的内置对象,Number数字类型作为基础数据类型,我们在开发过程中会经常用到,包括数字精度的格式化,还有字符串转换成数字等操作. Number数 ...

  9. JavaScript中有关数字的精确计算

    问题这样的: 37.5*5.5=206.08 (JS算出来是这样的一个结果,我四舍五入取两位小数) ,我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.08499999999998 怎么会 ...

随机推荐

  1. 在UWP 将BitmapImage转换为 WriteableBitmap

    原文: How to convert BitmapImage to WriteableBitmap in Universal application for windows 10? 您可以直接从文件将 ...

  2. asp.net 验证正则表达式 精心整理

    asp.net 验证正则表达式 整数或者小数:^[0-9]+\.{0,1}[0-9]{0,2}$只能输入数字:"^[0-9]*$".只能输入n位的数字:"^\d{n}$& ...

  3. Windows XP 每次开机都自动检测硬盘 解决办法(可以用HDDRegenerate修复坏道)

    Windows XP,每次开机都自动检测硬盘,之前正常关机,没有任何非法操作.Windows XP,每次开机都自动检测硬盘,之前正常关机,没有任何非法操作. 1.和硬盘的分区格式有关,FAT32格式在 ...

  4. QT字符编码转换,可用于中文内码传输

    串口.TCP.UDP传输中文字符时,先将字符串转内码.客户端接收到数据后,将内码转为字符串就OK了 QByteArray CommonFunction::strToInterCode(constQSt ...

  5. VCL比MFC好在哪里

    作者:刘国华链接:https://www.zhihu.com/question/35218485/answer/118472021来源:知乎著作权归作者所有,转载请联系作者获得授权. 从使用感受而言, ...

  6. Hadoop集群(第4期)VSFTP安装配置

    1.VSFTP简介 VSFTP是一个基于GPL发布的类Unix系统上使用的FTP服务器软件,它的全称是Very Secure FTP 从此名称可以看出来,编制者的初衷是代码的安全. 安全性是编写VSF ...

  7. oracle11g安装时出现程序未找到文件解决办法

    在安装的最后可能会出现如下问题 解决办法如下 将win64_11gR2_database_2of2中的\win64_11gR2_database_2of2\database\stage\Compone ...

  8. F4帮助

    在INITIALIZATION之后添加 AT SELECTION-SCREEN ON VALUE-REQUEST FOR s_month-low 事件,s_month-low为要添加的搜索帮助. 下面 ...

  9. Centos7离线安装mysql8

    linux版本:Centois7 mysql版本:5.7 一.安装 1.下载mysql离线安装包 下载地址:https://dev.mysql.com/downloads/mysql/ 选择如下: [ ...

  10. CTF练习资源大全集

    练习CTF清单/永久CTF清单 以下列出了一些长期运行的CTF实践站点和工具或CTF.谢谢,RSnake用于启动这是基于的原始版本.如果您有任何更正或建议,请随时通过dot com tld在域psif ...