【函数式编程】什么是函数式编程? C语言为何不是函数式语言?

article/2025/10/25 21:55:22

什么是函数式编程? C语言为何不是函数式语言?

函数式语言有两个主要的特点:1. 函数是“头等公民”。2. 数据的“immutability”(不变;永恒性;不变性;). 操作的“无副作用”,
这规避了‘锁’。
函数式编程的函数是指数学上的函数:给定输入固定的输出,没有副作用。任何语言都可以用函数式的风格,
只是难易不同罢了。
比如有函数 y = f(x). 和 函数 x = g(z); 可以组成复合函数 y=f(g(z));

对于第二个问题,C为何不是函数式语言?

因为这种效果在C里面不能实现: y=f(g(z));

int f(int x) { print x;}             ===== y = f(x)
int g(int z) {return z;}             ===== x = g(z)
int f1(int (*g)(int)) { print g(z);} ===== y = f1(g(z))


从上面的函数定义可以看到,当函数f(x)的参数定义为int时,便不能将函数g(z)作为形参传递给它。(函数指针与int参数类型不匹配)
反过来看函数f1()也不能接受int作为参数了。

于是,C达不到数学上函数的那种效果。

而在clojure里面却可以。

(defn f [x] (print x))    ======= y = f(x)
(defn g [z] z)            ======= t = g(z)



这时,(f (g 3)) 和 (f 3) 的结果是一样的,达到了数学上的效果。
再者,C也不具有函数式语言的特点2.

常见的函数式语言有哪些?

coljure、scala、Haskell。

为什么如python/javascrip这些语言不是函数式语言呢,因为他们不具备函数式语言的特点2.
————————————————
原文链接:https://blog.csdn.net/lx1848/article/details/77619881

 

毫无干货的带你理解什么是函数式编程

 

世界模型

如果让你搭建一个模型来描述这个世界你会怎么做?

面向对象

面向对象之父Alan Kay给我们带来了一种抽象化世界的方法。

一切事物皆对象,通过面向对象的方式,将现实世界的事物抽象成对象,现实世界中的关系抽象成类、继承,帮助人们实现对现实世界的抽象与数字建模。

因此我们有了面向对象式的编程式范。

函数式

这里本来应该引入《范畴论》的概念,不过在这里引入似乎会把事情搞的更复杂,所以先不去理会它,直接看结果。

世界就是由事物和事物之间的关系构成的

下面是一个空无一物的世界:

 

image.png

世界中有一个a:

image.png

 

世界中有了事物ab,还有他们之间的关系f,即使他们之间没关系也可以用f来表示,只不过f等于null

image.png

 

我们的世界更加丰富了:

image.png

如果我们继续这样画下去我们可以画出一个足够复杂的世界。不过到这里已经足够了。

  • 把关系f作用到a上可以得到b
  • 把关系g作用到b上可以得到c
  • 把关系h作用到a上可以得到c
  • 其中h = g.f

让我们再次进行抽象,抽取他们的共性部分。

 

image.png

所以我们得到了一个结构:a表示事物,f表示关系。把f作用到a上我们就可以得到b

image.png

 

要知道一切真理都是包含在特定的上下文中的(除了这一句)。所以我们的事物a也应该包含在上下文中它才是真正的a,所以我们得到的b也是上下文中的b

image.png

(这张图看起来像是a是印在盒子上的而不是在盒子内部,不要在意这些细节它是在盒子里的)
我们来用一个算式来验证一下模型计算1+2+4的值:

image.png

 

我们再来一个用户登录的模型,用户名和密码长度都大于0的时候才可以登录:

image.png

 

上面的做法和直接写语句有什么不同?

- (BOOL)canLoginUserName:(NSString *)username password:(NSString *)password{if (username.length > 0 && password.length > 0) {}else{}
}

拆分方式不同,图中拆分成了:

  • username和它的关系length>0,得到结果YES
  • password和它的关系length>0,得到结果YES
  • 两个YES和它的关系&&,得到结果YES

结论:

  • 如果你把世界拆分成,对象你就得到了面向对象
  • 如果你把世界拆分成事物事物之间的关系你就得到了函数式

好了道友们,看到这里你可以怀着愉快的心情关上电脑,闭上眼睛,深呼吸,思考一下如何按照事物事物之间的关系的方式来拆分世界,你就已经掌握了函数式编程的思想。

简单对比

  • 面向对象的世界里我们是把事物抽象成对象,然后通过封装继承多态来演示他们之间的关系。
  • 函数式的世界里把世界抽象成事物事物之间的关系,用这种方式实现世界的模型。

面向对象的编程更有人情味一些更社会化。比如你想要买一辆汽车,想要托人帮忙砍价。恰好你同学的朋友的大表哥的二嫂子在4s店工作。你就需要:

import "同学"
import "朋友"
import "大表哥"
import "二嫂子"

然后再调用二嫂子.砍价();

函数式编程则更“冰冷”一些,像是工厂里的流水线不停的运转,只要你放入材料就可以在出口处拿到产品。而且它对外部环境没有依赖,只需要将流水线搬走就可以在任何地方生产。不需要找同学的朋友的大表哥的二嫂子来帮忙了。


整理了几篇干货资料,有兴趣的道友可以看看:

  • 函数式编程入门教程

  • ReactiveCocoa v2.5 源码解析 之 架构总览

  • JS 函数式编程指南

  • Functor、Applicative 和 Monad

  • 函数编程中 functor 和 monad的形象解释

  • 理解范畴论中单子需要的最小知识集

  • 函子与单子--从范畴论到编程


http://chatgpt.dhexx.cn/article/Z55lB9Yk.shtml

相关文章

MP2451 VOUT计算公式 表

MP2451 DC-DC管理芯片 手册就不贴出来了. 下面贴出需要用的电阻值和需要转换的电压

MP2451电路调试笔记

MP2451电路调试笔记 EN脚内部有一个8V的稳压管,因此电路中R5可不要,R2取124K接到VIN脚。C7取100nF ,C8要根据不同输出电压选取,3.3V输出时取值33pFC7、C8取值不对,纹波会很大

【MSP430单片机】MSP430G2553程序,MSP430G2553单片机教程,MSP430G2553实战演练

文章目录 开发环境板子介绍官网示例代码下载MSP430普通IO口控制IO口外部中断MSP430时钟系统MSP430不精确延时之delay_msMSP430定时器_CCR0溢出中断MSP430定时器_定时器计数溢出中断MSP430定时器_PWM波形产生MSP430串口_收发9600波特率115200 波特率 MSP430ADCMSP430 Flash读写 …

LPC4357JET256/LPC4337FET256/LPC4337JET256 32位MCU 204MHz 1MB

【详情】LPC4300系列微控制器(MCU)拥有全世界首款非对称双核数字信号控制器体系结构,配有ARM Cortex-M4和Cortex-M0处理器。这些NXP Cortex-M4 MCU配有Cortex-M0协处理器,优势在于,可在单一体系结构、开发环境中,开发数字信号处理…

STM32MP157驱动开发——Linux I2C驱动

相关文章:正点原子教程第四十章——Linux I2C驱动实验 0.前言 为了简化笔记的编写以及降低工作量,本节开始相关的基础知识部分通过引入原子哥的教材链接来完成,有兴趣的可以进入学习。   上一节学完 RGB LCD 本来想直接学习 RGB 转 HDMI 实…

SPI转can芯片mcp2515

开发环境 CPU:RK3399 ARCH: aarch64 KERNEL:Linux4.4 OS:ubuntu18.04 mcp2515芯片相关信息 CAN、SPI接口控制电路图 修改设备树文件 文件路径:kernel/arm64/boot/dts/rockchip/rk3399.dts 增加spi节点,具体增加那…

MSP432 TFTLCD ILI9481 软件SPI

下面是我用的LCD屏的图片 CS : PF1 RS : PF2 RST: PF3 MOSI: PL4 SCK: PL5 代码: SPI.h #ifndef _SPI_…

MPC5744P-SPI

1.结构 5744的SPI模块支持全双工三线同步传输,可运行在主机或从机模式,分别含有深度为5的FIFO发送和接收缓存区。其结构如下图。SPI配置允许模块发送和接收串行数据,同时也支持带FIFO缓存区的的进行扩展队列操作的数据传输。模块接收和发送的…

SPI协议、MCP2515裸机驱动详解----主流SPI总线接口原理

最近看到一个介绍SPI接口原理的帖子,看完觉得甚好。特来分析给大家一起学习。 SPI概述 Serial Peripheral interface 通用串行外围设备接口 是Motorola首先在其MC68HCXX系列处理器上定义的。SPI接口主要应用在 EEPROM,FLASH,实时时钟&#…

MP2451 使能脚电阻判断

MP2451使能脚(EN)内部接一个稳压管,防止EN所接电压过大。 EN输入的电压范围:从PDF文档中找到EN的开启电压和最高电压。 Enable up Threshold 1.4-1.7 因为计算时需要考虑其极端现象,所以开启电压的临界电压选择最高,1.7v。最高…

CSM3416SF兼容MP2451,MCP16301HT-E,LT1933ES6,AOZ1282CI

CSM3416SF是一颗高耐压DC-DC降压芯片,宽电压范围输入,完美兼容MP2451,MCP16301HT-E,LT1933ES6,AOZ1282CI,助力智能电表市场,赋能车库门驱动系统。

S32K144开发笔记5 - SPI驱动MCP2515

1、接线图 PTB13 — INT 接收数据中断引脚 PTB14 — CLK 时钟 PTB15 — MISO 接收 PTB16 — MOSI 发送 PTB17 — CSN 片选 2、软件SPI 2.1、GPIO口配置 鼠标放在如下位置右击选择Pin Functional Properities,进入引脚属性配置 PTB13引脚配置如下: PT…

nRF52笔记(26)QSPI接口液晶显示屏

1 平台条件 硬件:nrf52840 软件:sdk17.0 2 QSPI概述 QSPI 外设支持使用 SPI 与外部闪存设备进行通信 此处列出了 QSPI 外设的主要特性: • 单/双/四通道 SPI 输入/输出 • 2–32 MHz 可配置时钟频率 • 从/到外部闪存的单字读/写访问 • …

MPC5744-LINFlexD

目录 一、基本介绍1.功能2.时钟源3.外设控制器4.中断向量5.基地址 二、寄存器介绍1.LIN控制寄存器1 LINFlexD_LINCR12.LIN中断使能寄存器LINFlexD_LINIER3.LIN状态寄存器LINFlexD_LINSR4.LIN错误状态寄存器LINFlexD_LINESR5.UART控制寄存器LINFlexD_UARTCR6.UART状态寄存器LINF…

MP2456的芯片的学习

本章将讲述MP2456的特征、性能、参数、应用电路、以及使用时的注意事项。小白总结,如有错误,请大神指教。 目录 一、MP2456的特征 二、MP2456的性能和参数 四、MP2456使用时的注意事项 五、名词解释 一、MP2456的特征 (1)MP…

硬件电路-MP2451组成的电压反转/极性反转电路设计

板上要集成一个18V供电的模拟信号处理电路,包括线圈驱动、小信号拾取、滤波、二级放大等部分。因此,需要板上提供18V电源。正负电压需要分开控制,因为正电压需要兼作485传感器供电,此时关闭负电压部分节省耗电以及保护模拟端。 b…

MP2451的应用电路

电阻R32和电阻R23是怎么实现的电压,FB口的输出是0.8V。 正确的计算应该是: 0.8/10*(1027)这样就是输出的电压。 SS14是大电流二极管,可以用5819完全替代。还有续流二极管。 SS14是40V的耐压,SS12是20V的耐压。 8050可以替代BC8…

MP2451问题记录

数据手册 https://pan.baidu.com/s/1ggJs0y3 MP2451应用电路如下图 在我自己的应用电路中R1120K,R224k 问题一、 电源输出0.42V V(FB)手册中应等于0.8V,但在测试中发现该引脚电压仅为0.07V 0.07 * (12024) / 24 0.42V 判断是芯片损坏 问题二、FB引脚输…

MP2451的BUCK电路

5V的稳压模块经常会用得到,普通的AMS1117-5.0虽然电压输出非常稳定,但是只适合低压降,小电流的场合。笔者曾经用AMS1117-5.0把8.4V稳压到5V,电流160mA(8.4V端),芯片一会儿就非常烫手了,即使并联…

MP2451使用注意事项

MP2451使用注意事项 MP2451是一个高速2M的高效的降压芯片,提供0.6A的电流输出,输入电压范围3.3V-36V可调,有关闭芯片引脚,关闭电流3uA,用起来还不错,分享一下经验,如下原理图已经制成了板子&am…