函数式编程 - 快速指南


函数式编程 - 简介

函数式编程语言是专门为处理符号计算和列表处理应用程序而设计的。函数式编程基于数学函数。一些流行的函数式编程语言包括:Lisp、Python、Erlang、Haskell、Clojure 等。

函数式编程语言分为两组,即 -

  • 纯函数式语言- 这些类型的函数式语言仅支持函数式范例。例如 - 哈斯克尔。

  • 不纯的函数式语言- 这些类型的函数式语言支持函数式范例和命令式编程。例如 - LISP。

函数式编程——特点

函数式编程最突出的特点如下:

  • 函数式编程语言是根据数学函数的概念设计的,它使用条件表达式和递归来执行计算。

  • 函数式编程支持高阶函数惰性求值功能。

  • 函数式编程语言不支持循环语句等流程控制以及 If-Else 和 Switch 语句等条件语句。他们直接使用函数和函数调用。

  • 与 OOP 一样,函数式编程语言支持抽象、封装、继承和多态性等流行概念。

函数式编程 – 优点

函数式编程具有以下优点 -

  • 无错误代码- 函数式编程不支持状态,因此没有副作用结果,我们可以编写无错误代码。

  • 高效的并行编程- 函数式编程语言没有可变状态,因此不存在状态更改问题。人们可以对“函数”进行编程,使其与“指令”并行工作。此类代码支持轻松的可重用性和可测试性。

  • 效率- 功能程序由可以同时运行的独立单元组成。因此,此类程序更加高效。

  • 支持嵌套函数- 函数式编程支持嵌套函数。

  • 惰性求值- 函数式编程支持惰性函数结构,如惰性列表、惰性映射等。

函数式编程的缺点是需要很大的内存空间。由于它没有状态,因此每次执行操作都需要创建新对象。

函数式编程用于必须对同一组数据执行许多不同操作的情况。

  • Lisp 用于人工智能应用,如机器学习、语言处理、语音和视觉建模等。

  • 嵌入式 Lisp 解释器为 Emacs 等某些系统添加了可编程性。

函数式编程与面向对象编程

下表强调了函数式编程和面向对象编程之间的主要区别 -

函数式编程 面向对象编程
使用不可变数据。 使用可变数据。
遵循声明式编程模型。 遵循命令式编程模型。
重点是:“你在做什么” 重点是“你做得怎么样”
支持并行编程 不适合并行编程
其功能无副作用 其方法会产生严重的副作用。
流程控制是使用函数调用和带有递归的函数调用来完成的 流程控制是使用循环和条件语句完成的。
它使用“递归”概念来迭代集合数据。 它使用“循环”概念来迭代集合数据。例如:Java 中的 For-each 循环
语句的执行顺序并不那么重要。 语句的执行顺序非常重要。
支持“数据抽象”和“Behave抽象”。 仅支持“数据抽象”。

程序代码的效率

编程代码的效率与算法效率和执行速度成正比。良好的效率确保更高的性能。

影响程序效率的因素包括 -

  • 机器速度
  • 编译速度
  • 操作系统
  • 选择正确的编程语言
  • 程序中数据的组织方式
  • 用于解决问题的算法

可以通过执行以下任务来提高编程语言的效率 -

  • 通过删除不必要的代码或进行冗余处理的代码。

  • 通过利用最佳内存和非易失性存储

  • 在适用的情况下使用可重复使用的组件。

  • 通过在程序的所有层使用错误和异常处理。

  • 通过创建确保数据完整性和一致性的编程代码。

  • 通过开发符合设计逻辑和流程的程序代码。

高效的编程代码可以尽可能减少资源消耗和完成时间,同时对操作环境造成的风险最小。

功能概述

在编程术语中,函数是执行特定任务的语句块。函数接受数据、处理数据并返回结果。编写函数主要是为了支持可重用性的概念。函数一旦编写完毕,就可以轻松调用,而不必一次又一次地编写相同的代码。

不同的函数语言使用不同的语法来编写函数。

编写函数的先决条件

在编写函数之前,程序员必须了解以下几点 -

  • 程序员应该知道函数的用途。

  • 程序员应该知道该函数的算法。

  • 程序员应该知道函数数据变量及其目标。

  • 用户调用的程序员应该知道函数的数据。

函数的流程控制

当一个函数被“调用”时,程序“转移”控制权来执行该函数,其“控制流程”如下 -

  • 程序到达包含“函数调用”的语句。

  • 执行函数内的第一行。

  • 函数内部的所有语句都是从上到下执行的。

  • 当函数成功执行时,控制返回到它开始的语句。

  • 函数计算和返回的任何数据都用于代替原始代码行中的函数。

函数的语法

函数的一般语法如下所示 -

returnType functionName(type1 argument1, type2 argument2, . . . ) {     
   // function body 
} 

在 C++ 中定义函数

让我们通过一个例子来了解如何在面向对象的编程语言 C++ 中定义函数。以下代码具有一个将两个数字相加并提供其结果作为输出的函数。

#include <stdio.h> 

int addNum(int a, int b);     // function prototype  

int main() {    
   int sum; 
   sum = addNum(5,6);         // function call 
   printf("sum = %d",sum); 
   return 0; 
}  
int addNum (int a,int b) {    // function definition      
   int result; 
   result = a + b; 
   return result;             // return statement 
} 

它将产生以下输出 -

Sum = 11

在 Erlang 中定义函数

让我们看看如何在 Erlang(一种函数式编程语言)中定义相同的函数。

-module(helloworld).  
-export([add/2,start/0]).   

add(A,B) ->
   C = A + B,  
   io:fwrite("~w~n",[C]).  
start() ->  
   add(5,6). 

它将产生以下输出 -

11

函数原型

函数原型是函数的声明,包括返回类型、函数名称和参数列表。它类似于没有函数体的函数定义。

例如- 有些编程语言支持函数原型,有些则不支持。

在 C++ 中,我们可以像这样创建函数“sum”的函数原型 -

int sum(int a, int b) 

注意- Python、Erlang 等编程语言不支持函数原型,我们需要声明完整的函数。

函数原型有什么用?

函数原型是编译器在调用函数时使用的。编译器使用它来确保正确的返回类型、传入正确的参数列表以及它们的返回类型是正确的。

函数签名

函数签名类似于函数原型,其中参数数量、参数数据类型和出现顺序应该相似。例如 -

void Sum(int a, int b, int c);         // function 1  
void Sum(float a, float b, float c);   // function 2  
void Sum(float a, float b, float c);   // function 3 

Function1 和 Function2 具有不同的签名。Function2 和 Function3 具有相同的签名。

注意- 我们将在后续章节中讨论的函数重载和函数重写基于函数签名的概念。

  • 当一个类具有多个名称相同但签名不同的函数时,函数重载是可能的。

  • 当派生类函数与其基类具有相同的名称和签名时,函数重写是可能的。

函数式编程 - 函数类型

函数有两种类型 -

  • 预定义函数
  • 用户定义函数

在本章中,我们将详细讨论函数。

预定义函数

这些函数内置于语言中以执行操作并存储在标准函数库中。

例如- C++ 中的“Strcat”和 Haskell 中的“concat”用于附加两个字符串,C++ 中的“strlen”和 Python 中的“len”用于计算字符串长度。

C++中打印字符串长度的程序

以下程序展示了如何使用 C++ 打印字符串的长度 -

#include <iostream> 
#include <string.h> 
#include <stdio.h> 
using namespace std;  

int main() {     
   char str[20] = "Hello World"; 
   int len; 
   len = strlen(str); 
   cout<<"String length is: "<<len; 
   return 0; 
} 

它将产生以下输出 -

String length is: 11

Python中打印字符串长度的程序

以下程序展示了如何使用 Python(一种函数式编程语言)打印字符串的长度 -

str = "Hello World"; 
print("String length is: ", len(str)) 

它将产生以下输出 -

('String length is: ', 11)

用户定义函数

用户定义的函数由用户定义来执行特定的任务。有四种不同的模式来定义函数 -

  • 无参数且无返回值的函数
  • 没有参数但有返回值的函数
  • 有参数但无返回值的函数
  • 带参数和返回值的函数

无参数且无返回值的函数

下面的程序展示了如何在C++中定义一个没有参数且没有返回值的函数-

#include <iostream> 
using namespace std; 

void function1() { 
   cout <<"Hello World"; 
}  
int main() { 
   function1(); 
   return 0; 
} 

它将产生以下输出 -

Hello World 

以下程序展示了如何在Python中定义类似的函数(无参数且无返回值)-

def function1():    
   print ("Hello World") 
    
function1() 

它将产生以下输出 -

Hello World 

没有参数但有返回值的函数

以下程序展示了如何在C++中定义一个不带参数但有返回值的函数-

#include <iostream> 
using namespace std; 
string function1() { 
   return("Hello World"); 
}  

int main() { 
   cout<<function1(); 
   return 0; 
}

它将产生以下输出 -

Hello World 

以下程序展示了如何在Python中定义类似的函数(不带参数,但有返回值):

def function1(): 
   return "Hello World" 
res = function1() 
print(res) 

它将产生以下输出 -

Hello World 

有参数但无返回值的函数

以下程序展示了如何在C++中定义带参数但不带返回值的函数-

#include <iostream> 
using namespace std; 
void function1(int x, int y) {    
   int c; 
   c = x+y;  
   cout<<"Sum is: "<<c; 
}  

int main() { 
   function1(4,5); 
   return 0; 
}

它将产生以下输出 -

Sum is: 9 

以下程序展示了如何在Python中定义类似的函数-

def function1(x,y): 
   c = x + y 
   print("Sum is:",c) 
function1(4,5)

它将产生以下输出 -

('Sum is:', 9)

带参数和返回值的函数

以下程序展示了如何在 C++ 中定义一个不带参数但有返回值的函数 -

#include <iostream> 
using namespace std; 
int function1(int x, int y) {    
   int c; 
   c = x + y;  
   return c;    
} 

int main() {  
   int res; 
   res = function1(4,5); 
   cout<<"Sum is: "<<res; 
   return 0; 
}

它将产生以下输出 -

Sum is: 9 

以下程序展示了如何在Python中定义类似的函数(带有参数和返回值) -

def function1(x,y): 
   c = x + y 
   return c  

res = function1(4,5) 
print("Sum is ",res) 

它将产生以下输出 -

('Sum is ', 9)

函数式编程 - 按值调用

定义函数后,我们需要将参数传递给它以获得所需的输出。大多数编程语言支持按值调用按引用调用方法将参数传递给函数。

在本章中,我们将学习“按值调用”在面向对象编程语言(如 C++)和函数式编程语言(如 Python)中的工作原理。

在按值调用方法中,原始值无法更改。当我们将参数传递给函数时,它由函数参数本地存储在堆栈内存中。因此,这些值仅在函数内部更改,不会对函数外部产生影响。

C++ 中的按值调用

以下程序显示了 C++ 中按值调用的工作原理 -

#include <iostream> 
using namespace std; 

void swap(int a, int b) {    
   int temp; 
   temp = a; 
   a = b; 
   b = temp; 
   cout<<"\n"<<"value of a inside the function: "<<a; 
   cout<<"\n"<<"value of b inside the function: "<<b; 
}  
int main() {     
   int a = 50, b = 70;   
   cout<<"value of a before sending to function: "<<a; 
   cout<<"\n"<<"value of b before sending to function: "<<b; 
   swap(a, b);  // passing value to function 
   cout<<"\n"<<"value of a after sending to function: "<<a; 
   cout<<"\n"<<"value of b after sending to function: "<<b; 
   return 0;   
}  

它将产生以下输出 -

value of a before sending to function:  50 
value of b before sending to function:  70 
value of a inside the function:  70 
value of b inside the function:  50 
value of a after sending to function:  50 
value of b after sending to function:  70 

Python 中的按值调用

以下程序显示了 Python 中按值调用的工作原理 -

def swap(a,b): 
   t = a; 
   a = b; 
   b = t; 
   print "value of a inside the function: :",a 
   print "value of b inside the function: ",b 

# Now we can call the swap function 
a = 50 
b = 75 
print "value of a before sending to function: ",a 
print "value of b before sending to function: ",b 
swap(a,b) 
print "value of a after sending to function: ", a 
print "value of b after sending to function: ",b 

它将产生以下输出 -

value of a before sending to function:  50 
value of b before sending to function:  75 
value of a inside the function: : 75 
value of b inside the function:  50 
value of a after sending to function:  50 
value of b after sending to function:  75 

函数式编程 - 通过引用调用

在按引用调用中,原始值发生了变化,因为我们传递了参数的引用地址。实际参数和形式参数共享相同的地址空间,因此函数内部值的任何更改都会反映在函数内部和外部。

C++ 中的引用调用

以下程序显示了 C++ 中按值调用的工作原理 -

#include <iostream> 
using namespace std; 

void swap(int *a, int *b) {    
   int temp; 
   temp = *a; 
   *a = *b; 
   *b = temp; 
   cout<<"\n"<<"value of a inside the function: "<<*a; 
   cout<<"\n"<<"value of b inside the function: "<<*b; 
}  
int main() {     
   int a = 50, b = 75;   
   cout<<"\n"<<"value of a before sending to function: "<<a; 
   cout<<"\n"<<"value of b before sending to function: "<<b; 
   swap(&a, &b);  // passing value to function 
   cout<<"\n"<<"value of a after sending to function: "<<a; 
   cout<<"\n"<<"value of b after sending to function: "<<b; 
   return 0;   
}

它将产生以下输出 -

value of a before sending to function:  50 
value of b before sending to function:  75 
value of a inside the function:  75 
value of b inside the function: 50 
value of a after sending to function:  75 
value of b after sending to function:  50 

Python 中的引用调用

以下程序显示了 Python 中按值调用的工作原理 -

def swap(a,b): 
   t = a; 
   a = b; 
   b = t; 
   print "value of a inside the function: :",a 
   print "value of b inside the function: ",b 
   return(a,b) 
    
# Now we can call swap function 
a = 50 
b =75 
print "value of a before sending to function: ",a 
print "value of b before sending to function: ",b 
x = swap(a,b) 
print "value of a after sending to function: ", x[0] 
print "value of b after sending to function: ",x[1] 

它将产生以下输出 -

value of a before sending to function:  50 
value of b before sending to function:  75 
value of a inside the function:  75 
value of b inside the function:  50 
value of a after sending to function:  75 
value of b after sending to function:  50  

函数重载

当我们有多个具有相同名称但参数不同的函数时,它们被称为重载。该技术用于增强程序的可读性。

有两种方法可以重载函数,即 -

  • 具有不同数量的参数
  • 具有不同的参数类型

当我们必须使用不同数量或类型的参数执行一项操作时,通常会进行函数重载。

C++ 中的函数重载

以下示例显示了如何在 C++ 中完成函数重载,C++ 是一种面向对象的编程语言 -

#include <iostream> 
using namespace std;  
void addnum(int,int); 
void addnum(int,int,int); 

int main() {     
   addnum (5,5); 
   addnum (5,2,8); 
   return 0; 
} 

void addnum (int x, int y) {     
   cout<<"Integer number: "<<x+y<<endl; 
} 

void addnum (int x, int y, int z) {     
   cout<<"Float number: "<<x+y+z<<endl; 
}

它将产生以下输出 -

Integer number: 10 
Float number: 15 

Erlang 中的函数重载

以下示例展示了如何在 Erlang(一种函数式编程语言)中执行函数重载 -

-module(helloworld).  
-export([addnum/2,addnum/3,start/0]).   

addnum(X,Y) ->  
   Z = X+Y,  
   io:fwrite("~w~n",[Z]).  
    
addnum(X,Y,Z) ->  
   A = X+Y+Z,  
   io:fwrite("~w~n",[A]).  
  
start() ->
   addnum(5,5),     addnum(5,2,8). 

它将产生以下输出 -

10 
15 

函数重写

当基类和派生类具有完全相同的名称、相同的返回类型和相同的参数列表的成员函数时,则称为函数重写。

使用 C++ 重写函数

以下示例显示了如何在 C++ 中完成函数重写,C++ 是一种面向对象的编程语言 -

#include <iostream> 
using namespace std;  

class A {  
   public: 
   void display() {   
      cout<<"Base class"; 
   } 
}; 

class B:public A {  
   public: 
   void display() {   
      cout<<"Derived Class"; 
   } 
}; 

int main() {  
   B obj; 
   obj.display(); 
   return 0;  
}

它将产生以下输出

Derived Class 

使用 Python 重写函数

以下示例展示了如何在 Python(一种函数式编程语言)中执行函数重写 -

class A(object): 
   def disp(self): 
      print "Base Class"  
class B(A): 
   def disp(self): 
      print "Derived Class"  
x = A() 
y = B()  
x.disp() 
y.disp() 

它将产生以下输出 -

Base Class 
Derived Class 

函数式编程 - 递归

调用自身的函数称为递归函数,这种技术称为递归。递归指令将继续执行,直到另一条指令阻止它为止。

C++ 中的递归

以下示例显示了 C++ 中递归的工作原理,C++ 是一种面向对象的编程语言 -

#include <stdio.h> 
long int fact(int n);  

int main() { 
   int n; 
   printf("Enter a positive integer: "); 
   scanf("%d", &n); 
   printf("Factorial of %d = %ld", n, fact(n)); 
   return 0; 
} 
long int fact(int n) { 
   if (n >= 1) 
      return n*fact(n-1); 
   else 
      return 1; 
} 

它将产生以下输出

Enter a positive integer: 5 
Factorial of 5 = 120 

Python 中的递归

以下示例显示了 Python(一种函数式编程语言)中递归的工作原理 -

def fact(n): 
   if n == 1: 
      return n 
   else: 
      return n* fact (n-1)  

# accepts input from user 
num = int(input("Enter a number: "))  
# check whether number is positive or not 

if num < 0: 
   print("Sorry, factorial does not exist for negative numbers") 
else: 
   print("The factorial of " + str(num) +  " is " + str(fact(num))) 

它将产生以下输出 -

Enter a number: 6
The factorial of 6 is 720   

高阶函数

高阶函数 (HOF) 是至少满足以下条件之一的函数 -

  • 接受一个或多个函数作为参数
  • 返回一个函数作为其结果

PHP 中的 HOF

以下示例展示了如何在 PHP(一种面向对象的编程语言)中编写高阶函数 -

<?php  
$twice = function($f, $v) { 
   return $f($f($v)); 
};  

$f = function($v) { 
   return $v + 3; 
}; 

echo($twice($f, 7));

它将产生以下输出 -

13

Python 中的 HOF

以下示例展示了如何在Python(一种面向对象的编程语言)中编写高阶函数 -

def twice(function): 
   return lambda x: function(function(x))  
def f(x): 
   return x + 3 
g = twice(f)
print g(7)      

它将产生以下输出 -

13

函数式编程 - 数据类型

数据类型定义了对象可以具有的值的类型以及可以对其执行哪些操作。数据类型在使用之前应先声明。不同的编程语言支持不同的数据类型。例如,

  • C支持char、int、float、long等。
  • Python支持字符串、列表、元组等。

从广义上讲,有三种类型的数据类型 -

  • 基本数据类型- 这些是程序员直接使用的预定义数据类型,用于根据要求仅存储一个值,即整数类型、字符类型或浮点类型。例如 - int、char、float 等。

  • 派生数据类型- 这些数据类型是使用内置数据类型派生的,这些数据类型是由程序员设计的,用于根据其要求存储相同类型的多个值。例如 - 数组、指针、函数、列表等。

  • 用户定义的数据类型- 这些数据类型是使用内置数据类型派生的,这些数据类型被包装到单个数据类型中,以根据要求存储相同类型或不同类型或两者的多个值。例如 - 类、结构等。

C++ 支持的数据类型

下表列出了 C++ 支持的数据类型 -

数据类型 尺寸 范围
字符 1字节 -128 至 127 或 0 至 255
无符号字符 1字节 0 至 255
签名字符 1字节 -128 至 127
整数 4字节 -2147483648 至 2147483647
无符号整数 4字节 0 至 4294967295
有符号整数 4字节 -2147483648 至 2147483647
短整型 2字节 -32768至32767
无符号短整型 2字节 0 至 65,535
有符号短整型 2字节 -32768至32767
长整型 4字节 -2,147,483,648 至 2,147,483,647
有符号长整型 4字节 -2,147,483,648 至 2,147,483,647
无符号长整型 4字节 0 至 4,294,967,295
漂浮 4字节 +/- 3.4e +/- 38(~7 位数字)
双倍的 8字节 +/- 1.7e +/- 308(~15 位)
长双 8字节 +/- 1.7e +/- 308(~15 位)

Java支持的数据类型

Java 支持以下数据类型 -

数据类型 尺寸 范围
字节 1字节 -128 至 127
字符 2字节 0 至 65,536
短的 2字节 -32,7688 至 32,767
整数 4字节 -2,147,483,648 至 2,147,483,647
长的 8字节 -9,223,372,036,854,775,808 至 9,223,372,036,854,775,807
漂浮 4字节 -2147483648 至 2147483647
双倍的 8字节 +9.223*1018
布尔值 1 位 对或错

Erlang 支持的数据类型

在本节中,我们将讨论 Erlang(一种函数式编程语言)支持的数据类型。

数字

Erlang 支持两种类型的数字文字,即整型浮点型。看一下下面的示例,它展示了如何添加两个整数值 -

-module(helloworld).
-export([start/0]). 
start() -> 
   io:fwrite("~w",[5+4]). 

它将产生以下输出 -

9

Atomics

Atomics是一个其值无法更改的字符串它必须以小写字母开头,并且可以包含任何字母数字字符和特殊字符。当Atomics包含特殊字符时,应将其括在单引号 (') 内。看一下下面的例子可以更好地理解。

-module(helloworld). 
-export([start/0]). 

start()-> 
   io:fwrite(monday). 

它将产生以下输出 -

monday

注意- 尝试将Atomics更改为大写“M”的“Monday”。程序会产生错误。

布尔值

此数据类型用于将结果显示为truefalse。看一下下面的例子。它展示了如何比较两个整数。

-module(helloworld). 
-export([start/0]). 

start() -> 
   io:fwrite(5 =< 9). 

它将产生以下输出 -

true

位串

位串用于存储非类型化内存区域。看一下下面的例子。它展示了如何将位串的 2 位转换为列表。

-module(helloworld). 
-export([start/0]). 

start() -> 
   Bin2 = <<15,25>>, 
   P = binary_to_list(Bin2), 
   io:fwrite("~w",[P]). 

它将产生以下输出 -

[15,25]

元组

元组是具有固定数量项的复合数据类型。元组的每一项称为一个元素。元素的数量就是元组的大小。以下示例演示如何定义 5 个术语的元组并打印其大小。

-module(helloworld).  
-export([start/0]).  

start() ->  
   K = {abc,50,pqr,60,{xyz,75}} ,  
   io:fwrite("~w",[tuple_size(K)]). 

它将产生以下输出 -

5 

地图

映射是一种复合数据类型,具有可变数量的键值关联。映射中的每个键值关联称为关联对。该对的部分称为elements。关联对的数量被称为地图的大小。以下示例演示如何定义 3 个映射的映射并打印其大小。

-module(helloworld).  
-export([start/0]).  
 
start() ->  
   Map1 = #{name => 'abc',age => 40, gender => 'M'},  
   io:fwrite("~w",[map_size(Map1)]). 

它将产生以下输出 -

3 

列表

列表是一种具有可变数量术语的复合数据类型。列表中的每个术语称为一个元素。元素的数量称为列表的长度。以下示例演示如何定义包含 5 个项目的列表并打印其大小。

-module(helloworld).  
-export([start/0]).  

start() ->  
   List1 = [10,15,20,25,30] ,  
   io:fwrite("~w",[length(List1)]). 

它将产生以下输出 -

5 

注意- Erlang 中未定义“String”数据类型。

函数式编程-多态性

就编程而言,多态意味着多次重用单个代码。更具体地说,它是程序根据对象的数据类型或类以不同方式处理对象的能力。

多态性有两种类型 -

  • 编译时多态性- 这种类型的多态性可以使用方法重载来实现。

  • 运行时多态性- 这种类型的多态性可以使用方法重写和虚函数来实现。

多态性的优点

多态性具有以下优点 -

  • 它帮助程序员重用代码,即一旦编写、测试和实现的类可以根据需要重用。节省大量时间。

  • 单个变量可用于存储多种数据类型。

  • 易于调试代码。

多态数据类型

多态数据类型可以使用仅存储字节地址的通用指针来实现,而不存储在该内存地址处的数据类型。例如,

function1(void *p, void *q) 

其中pq是通用指针,可以保存int、float(或任何其他)值作为参数。

C++ 中的多态函数

下面的程序展示了如何在 C++(一种面向对象的编程语言)中使用多态函数。

#include <iostream> 
Using namespace std: 

class A {  
   public: 
   void show() {    
      cout << "A class method is called/n"; 
   } 
}; 

class B:public A { 
   public: 
   void show() {   
      cout << "B class method is called/n"; 
   } 
};  

int main() {   
   A x;        // Base class object 
   B y;        // Derived class object 
   x.show();   // A class method is called 
   y.show();   // B class method is called 
   return 0; 
} 

它将产生以下输出 -

A class method is called 
B class method is called 

Python 中的多态函数

以下程序展示了如何在Python(一种函数式编程语言)中使用多态函数。

class A(object): 
   def show(self): 
      print "A class method is called" 
  
class B(A): 
   def show(self): 
      print "B class method is called" 
  
def checkmethod(clasmethod): 
   clasmethod.show()  

AObj = A() 
BObj = B() 
  
checkmethod(AObj) 
checkmethod(BObj) 

它将产生以下输出 -

A class method is called 
B class method is called 

函数式编程 - 字符串

字符串是一组包含空格的字符我们可以说它是一个以 NULL 字符('\0')结尾的一维字符数组。字符串也可以被视为一个预定义的类,大多数编程语言都支持它,例如 C、C++、Java、PHP、Erlang、Haskell、Lisp 等。

下图显示了字符串“Tutorial”在内存中的外观。

弦乐

在 C++ 中创建字符串

以下程序是一个示例,显示如何在 C++(一种面向对象的编程语言)中创建字符串。

#include <iostream> 
using namespace std; 

int main () {    
   char greeting[20] = {'H', 'o', 'l', 'i', 'd', 'a', 'y', '\0'}; 
   cout << "Today is: "; 
   cout << greeting << endl; 
   return 0; 
} 

它将产生以下输出 -

Today is: Holiday 

Erlang 中的字符串

以下程序是一个示例,展示了如何在 Erlang(一种函数式编程语言)中创建字符串。

-module(helloworld).  
-export([start/0]).   
start() -> 
   Str = "Today is: Holiday",  
   io:fwrite("~p~n",[Str]). 

它将产生以下输出 -

"Today is: Holiday" 

C++ 中的字符串操作

不同的编程语言支持不同的字符串方法。下表显示了 C++ 支持的一些预定义字符串方法。

编号 方法及说明
1

结构体(s1,s2)

它将字符串 s2 复制到字符串 s1

2

Strcat(s1,s2)

它将字符串 s2 添加到 s1 的末尾

3

斯特伦(s1)

它提供了字符串 s1 的长度

4

Strcmp(s1,s2)

当字符串 s1 和 s2 相同时返回 0

5

Strchr(s1,ch)

它返回一个指向字符串 s1 中第一次出现字符 ch 的指针

6

strstr(s1,s2)

它返回一个指向字符串 s1 中第一次出现字符串 s2 的指针

以下程序显示了如何在 C++ 中使用上述方法 -

#include <iostream> 
#include <cstring> 
using namespace std; 

int main () {   
   char str1[20] = "Today is "; 
   char str2[20] = "Monday"; 
   char str3[20]; 
   int  len ;  
   strcpy( str3, str1); // copy str1 into str3 
   cout << "strcpy( str3, str1) : " << str3 << endl;  

   strcat( str1, str2); // concatenates str1 and str2 
   cout << "strcat( str1, str2): " << str1 << endl;  

   len = strlen(str1);  // String length after concatenation 
   cout << "strlen(str1) : " << len << endl; 
   return 0; 
}    

它将产生以下输出 -

strcpy(str3, str1)   :  Today is 
strcat(str1, str2)   :  Today is Monday 
strlen(str1)         :  15 

Erlang 中的字符串操作

下表显示了 Erlang 支持的预定义字符串方法的列表。

编号 方法及说明
1

长度(s1)

返回给定字符串中的字符数。

2

等于(s1,s2)

当字符串 s1 和 s2 相等时返回 true,否则返回 false

3

连接(s1,s2)

它将字符串 s2 添加到字符串 s1 的末尾

4

字符串(s1,ch)

返回字符串 s1 中字符 ch 的索引位置

5

字符串 (s1,s2)

它返回字符串 s1 中 s2 的索引位置

6

substr(s1,s2,num)

该方法根据起始位置和距起始位置的字符数从字符串 s1 返回字符串 s2

7

to_lower(s1)

该方法返回小写字符串

下面的程序展示了如何在 Erlang 中使用上述方法。

-module(helloworld).  
-import(string,[concat/2]).  
-export([start/0]).  
   start() ->  
   S1 = "Today is ",  
   S2 = "Monday",  
   S3 = concat(S1,S2),  
   io:fwrite("~p~n",[S3]). 

它将产生以下输出 -

"Today is Monday" 

函数式编程 - 列表

列表是函数式编程语言中最通用的数据类型,用于存储相似数据项的集合。这个概念类似于面向对象编程中的数组。列表项可以写在方括号中,并用逗号分隔。将数据写入列表的方式因语言而异。

用 Java 创建数字列表的程序

列表不是 Java/C/C++ 中的数据类型,但我们有其他方法在 Java 中创建列表,即使用ArrayListLinkedList

以下示例展示了如何在 Java 中创建列表。在这里,我们使用链接列表方法来创建数字列表。

import java.util.*; 
import java.lang.*; 
import java.io.*;  

/* Name of the class has to be "Main" only if the class is public. */ 

public class HelloWorld { 
   public static void main (String[] args) throws java.lang.Exception { 
      List<String> listStrings = new LinkedList<String>(); 
      listStrings.add("1"); 
      listStrings.add("2"); 
      listStrings.add("3"); 
      listStrings.add("4"); 
      listStrings.add("5"); 
  
      System.out.println(listStrings); 
   } 
} 

它将产生以下输出 -

[1, 2, 3, 4, 5] 

在 Erlang 中创建数字列表的程序

-module(helloworld).  
-export([start/0]).   

start() ->  
   Lst = [1,2,3,4,5],  
   io:fwrite("~w~n",[Lst]). 

它将产生以下输出 -

[1 2 3 4 5]

Java 中的列表操作

在本节中,我们将讨论一些可以在 Java 中通过列表完成的操作。

将元素添加到列表中

方法 add(Object)、add(index, Object)、addAll() 用于将元素添加到列表中。例如,

ListStrings.add(3, “three”) 

从列表中删除元素

方法remove(index) 或removeobject() 用于从列表中删除元素。例如,

ListStrings.remove(3,”three”)

注意- 要从列表中删除所有元素,请使用clear()方法。

从列表中检索元素

get() 方法用于从列表中指定位置检索元素。getfirst() 和 getlast() 方法可以在 LinkedList 类中使用。例如,

String str = ListStrings.get(2) 

更新列表中的元素

set(index,element) 方法用于用指定元素更新指定索引处的元素。例如,

listStrings.set(2,”to”)

对列表中的元素进行排序

方法 collection.sort() 和 collection.reverse() 用于按升序或降序对列表进行排序。例如,

Collection.sort(listStrings) 

搜索列表中的元素

根据要求使用以下三种方法 -

如果列表包含指定元素,Boolean contains(Object)方法返回true ,否则返回false

int indexOf(Object)方法返回列表中指定元素第一次出现的索引,否则当未找到该元素时返回 -1。

int lastIndexOf(Object)返回列表中指定元素最后一次出现的索引,否则当未找到该元素时返回 -1。

Erlang 中的列表操作

在本节中,我们将讨论一些可以在 Erlang 中通过列表完成的操作。

添加两个列表

append(listfirst, listsecond) 方法用于通过添加两个列表来创建新列表。例如,

append(list1,list2)

删除元素

delete(element, listname) 方法用于从列表中删除指定元素并返回新列表。例如,

delete(5,list1) 

从列表中删除最后一个元素

droplast(listname) 方法用于删除列表中的最后一个元素并返回一个新列表。例如,

droplast(list1) 

搜索元素

member(element, listname) 方法用于在列表中搜索元素,如果找到则返回 true,否则返回 false。例如,

member(5,list1) 

获取最大值和最小值

max(listname) 和 min(listname) 方法用于查找列表中的最大值和最小值。例如,

max(list1) 

对列表元素进行排序

方法sort(listname)和reverse(listname)用于按升序或降序对列表进行排序。例如,

sort(list1) 

添加列表元素

sum(listname) 方法用于添加列表中的所有元素并返回它们的总和。例如,

sum(list1)

使用 Java 按升序和降序对列表进行排序

以下程序展示了如何使用 Java 按升序和降序对列表进行排序 -

import java.util.*; 
import java.lang.*; 
import java.io.*;  

public class SortList { 
   public static void main (String[] args) throws java.lang.Exception { 
      List<String> list1 = new ArrayList<String>(); 
      list1.add("5"); 
      list1.add("3"); 
      list1.add("1"); 
      list1.add("4"); 
      list1.add("2"); 
  
      System.out.println("list before sorting: " + list1); 
  
      Collections.sort(list1); 
  
      System.out.println("list in ascending order: " + list1); 
      Collections.reverse(list1); 
  
      System.out.println("list in dsending order: " + list1); 
   } 
} 

它将产生以下输出 -

list before sorting     : [5, 3, 1, 4, 2] 
list in ascending order : [1, 2, 3, 4, 5] 
list in dsending order  : [5, 4, 3, 2, 1] 

使用 Erlang 对列表进行升序排序

以下程序展示了如何使用 Erlang(一种函数式编程语言)按升序和降序对列表进行排序 -

-module(helloworld).  
-import(lists,[sort/1]).  
-export([start/0]).   

start() ->  
   List1 = [5,3,4,2,1],  
   io:fwrite("~p~n",[sort(List1)]), 

它将产生以下输出 -

[1,2,3,4,5] 

函数式编程 - 元组

元组是具有固定数量项的复合数据类型。元组中的每一项都称为一个元素。元素的数量就是元组的大小。

在 C# 中定义元组的程序

以下程序演示如何定义四个术语的元组并使用 C#(一种面向对象的编程语言)打印它们。

using System; 
public class Test { 
   public static void Main() { 
      var t1 = Tuple.Create(1, 2, 3, new Tuple<int, int>(4, 5));   
      Console.WriteLine("Tuple:" + t1);    
   } 
} 

它将产生以下输出 -

Tuple :(1, 2, 3, (4, 5)) 

在 Erlang 中定义元组的程序

下面的程序展示了如何定义一个由四个术语组成的元组并使用 Erlang(一种函数式编程语言)打印它们。

-module(helloworld).  
-export([start/0]).   

start() -> 
   P = {1,2,3,{4,5}} ,  
   io:fwrite("~w",[P]). 

它将产生以下输出 -

{1, 2, 3, {4, 5}} 

元组的优点

元组具有以下优点 -

  • 元组本质上是精细大小的,即我们不能向元组添加/删除元素。

  • 我们可以搜索元组中的任何元素。

  • 元组比列表更快,因为它们具有一组恒定的值。

  • 元组可以用作字典键,因为它们包含不可变的值,如字符串、数字等。

元组与列表

元组 列表
元组是不可变的,即我们无法更新它的数据。 列表是可变的,即我们可以更新它的数据。
元组中的元素可以是不同类型。 列表中的所有元素都具有相同的类型。
元组由元素周围的圆括号表示。 列表由元素周围的方括号表示。

元组操作

在本节中,我们将讨论可以对元组执行的一些操作。

检查插入的值是否是元组

is_tuple(tuplevalues)方法用于判断插入的值是否为元组。当插入的值是元组时,它返回true,否则返回false。例如,

-module(helloworld).  
-export([start/0]).  

start() ->  
   K = {abc,50,pqr,60,{xyz,75}} , io:fwrite("~w",[is_tuple(K)]). 

它将产生以下输出 -

True

将列表转换为元组

list_to_tuple(listvalues)方法将列表转换为元组。例如,

-module(helloworld).  
-export([start/0]).  

start() ->  
   io:fwrite("~w",[list_to_tuple([1,2,3,4,5])]). 

它将产生以下输出 -

{1, 2, 3, 4, 5} 

将元组转换为列表

tuple_to_list(tuplevalues)方法将指定的元组转换为列表格式。例如,

-module(helloworld).  
-export([start/0]).  

start() ->  
   io:fwrite("~w",[tuple_to_list({1,2,3,4,5})]). 

它将产生以下输出 -

[1, 2, 3, 4, 5] 

检查元组大小

tuple_size(tuplename)方法返回元组的大小。例如,

-module(helloworld).  
-export([start/0]).  

start() ->  
   K = {abc,50,pqr,60,{xyz,75}} ,  
   io:fwrite("~w",[tuple_size(K)]). 

它将产生以下输出 -

5

函数式编程 - 记录

记录是用于存储固定数量的元素的数据结构。类似于C语言中的结构体。在编译时,其表达式被转换为元组表达式。

如何创建记录?

关键字“record”用于创建由记录名称及其字段指定的记录。其语法如下 -

record(recodname, {field1, field2, . . fieldn})

将值插入记录的语法是 -

#recordname {fieldName1 = value1, fieldName2 = value2 .. fieldNamen = valuen}

使用 Erlang 创建记录的程序

在下面的示例中,我们创建了一条名为Student的记录,该记录具有两个字段,即snamesid

-module(helloworld).  
-export([start/0]).  
-record(student, {sname = "", sid}).   

start() ->  
   S = #student{sname = "Sachin",sid = 5}. 

使用 C++ 创建记录的程序

以下示例展示了如何使用 C++ 创建记录,C++ 是一种面向对象的编程语言 -

#include<iostream> 
#include<string>
using namespace std; 

class student {
   public: 
   string sname; 
   int sid; 
   15 
}; 

int main() {    
   student S;  
   S.sname = "Sachin"; 
   S.sid = 5; 
   return 0;  
} 

使用 Erlang 访问记录值的程序

以下程序显示了如何使用 Erlang(一种函数式编程语言)访问记录值 -

-module(helloworld).  
-export([start/0]).  
-record(student, {sname = "", sid}).   

start() ->  
   S = #student{sname = "Sachin",sid = 5},  
   io:fwrite("~p~n",[S#student.sid]),  
   io:fwrite("~p~n",[S#student.sname]). 

它将产生以下输出 -

5 
"Sachin"

使用 C++ 访问记录值的程序

以下程序展示了如何使用 C++ 访问记录值 -

#include<iostream> 
#include<string> 
using namespace std; 

class student {     
   public: 
   string sname; 
   int sid; 
}; 

int main()