一览函数式编程

文章目录

    • 一、 什么是函数式编程
      • 1.1 编程范式
        • 1.1.1 命令式编程(Imperative Programming)范式
        • 1.1.2 声明式编程(Declarative Programming)范式
        • 1.1.3 函数式编程(Functional Programming)范式
        • 1.1.4 面向对象编程(Object-Oriented Programming)范式
        • 1.1.5 元编程(Metaprogramming)范式
      • 1.2 数学函数
      • 1.3 函数是一等公民(Functions are first-class citizens)
        • 1.3.1 函数可以被赋值给变量或者数据结构中的元素
        • 1.3.2 函数可以作为参数传递给其他函数
        • 1.3.3 函数可以作为其他函数的返回值
        • 1.3.4 函数可以在运行时动态创建和定义
      • 1.4 不可变性(immutability)和无副作用
    • 二、函数式编程的基础
      • 2.1 纯函数(pure function)
      • 2.2 闭包(closure)
      • 2.3 Lambda
      • 2.4 高阶函数
      • 2.5 偏函数(Partial)
      • 2.6 柯里化(Currying)
        • 柯里化转换
        • 优势
    • 三、函数式编程的进阶
      • 3.1 函数组合(composition)
      • 3.2 Pipeline
      • 3.3 PointFree
      • 3.4 惰性求值(Lazy evaluation)
      • 3.5 尾递归(Tail recursion)
      • 3.6 MapReduce
        • 3.6.1 多线程
    • 四、总结
      • 4.1 优缺点
        • 4.1.1 优点
        • 4.1.2 缺点

一、 什么是函数式编程

函数式编程是一种编程范式,它将计算视为数学函数的求值过程。在函数式编程中,函数是一等公民,可以像其他值一样被传递、组合和操作。函数式编程强调不可变性和无副作用,即函数的执行不会改变程序状态或外部环境。这使得函数式编程更容易进行推理和测试,并且可以更好地支持并发和并行计算。

1.1 编程范式

编程范式是一种编程思想或方法,它定义了如何组织和结构化计算机程序。不同的编程范式有不同的方法和规则,以解决不同类型的问题。
同一门语言,同一个问题,来看一下不同的范式,会写出什么样的代码

问题:计算一个整数数组中所有元素的平均值。

1.1.1 命令式编程(Imperative Programming)范式

命令式编程范式是一种基于语句的编程范式,它通过一系列指令来改变程序状态。在命令式编程中,程序员需要指定每个步骤的操作,以便计算出所需的结果。

img

1.1.2 声明式编程(Declarative Programming)范式

声明式编程范式是一种基于表达式的编程范式,它通过表达式来描述计算机程序的行为。在声明式编程中,程序员只需要描述所需的结果,而不需要指定每个步骤的操作。

img

1.1.3 函数式编程(Functional Programming)范式

函数式编程范式是一种基于函数的编程范式,它将计算机程序视为一系列函数的组合。在函数式编程中,程序员只需要定义函数的输入和输出,而不需要指定每个步骤的操作。

img

1.1.4 面向对象编程(Object-Oriented Programming)范式

面向对象编程范式是一种基于对象的编程范式,它将计算机程序视为一组相互作用的对象。在面向对象编程中,程序员定义对象的属性和方法,并使用这些对象来执行计算机程序的操作。

img

1.1.5 元编程(Metaprogramming)范式

元编程范式是一种编程范式,它允许程序员在运行时创建、修改和操作程序的结构和行为。元编程范式的目的是使程序更加灵活和可扩展,因为它允许程序在运行时自我修改和适应。

img

1.2 数学函数

假设有一个数学函数 f(x) = x^2,它将一个数 x 映射到它的平方。在函数式编程中,我们可以定义一个函数 square(x),它也将一个数 x 映射到它的平方。这个函数可以用如下的方式定义:

img

这个函数与数学中的函数 f(x) = x^2 有很多相似之处。它们都将一个输入映射到一个输出,而且输出只取决于输入,不会受到外部状态的影响。在函数式编程中,我们也可以将这个函数作为另一个函数的参数,或者将它的输出作为另一个函数的输入,这也是函数式编程中常见的操作。

另外,函数式编程中的函数也具有不可变性和纯函数性质。这意味着函数的输出只取决于输入,不会受到外部状态的影响。例如,如果我们调用 square(2) 函数,它的输出始终为 4,不会受到任何外部状态的影响。这与数学中的函数也有很多相似之处,因为数学中的函数的输出也只取决于输入,不会受到外部环境的影响。

1.3 函数是一等公民(Functions are first-class citizens)

是指在编程语言中,函数可以像其他数据类型一样被传递、赋值、作为参数和返回值使用。
具体来说,函数作为一等公民具有以下特点:

1.3.1 函数可以被赋值给变量或者数据结构中的元素

img

1.3.2 函数可以作为参数传递给其他函数

img

1.3.3 函数可以作为其他函数的返回值

img

1.3.4 函数可以在运行时动态创建和定义

img

1.4 不可变性(immutability)和无副作用

不可变性是指在程序执行过程中,某个对象的状态不会发生改变。在函数式编程中,不可变性是一个重要的概念,因为它可以避免副作用和竞态条件等问题。在不可变性的约束下,函数的执行结果只取决于输入参数,而不会受到外部环境的影响。这使得函数更容易进行推理和测试,并且可以更好地支持并发和并行计算。在实现不可变性时,可以使用一些技术,例如使用不可变数据结构、避免共享可变状态、使用纯函数等。

img

反之

img

带来的问题

  1. 副作用:在使用可变性的情况下,我们直接修改了sum_of_numbers变量的值,这可能会导致副作用。副作用是指函数或程序对外部环境产生的影响,例如修改全局变量、打印输出等。副作用可能会使程序更难以理解和调试,因为它们使程序的行为不可预测。
  2. 竞态条件:如果在计算平均值的过程中,有其他线程或进程也在修改sum_of_numbers变量的值,那么可能会导致计算结果不正确。竞态条件是指多个线程或进程同时访问共享资源时,由于访问顺序不确定,导致程序的行为不可预测。
  3. 可读性和可维护性:如果我们在程序的其他地方也使用了sum_of_numbers变量,那么可能会导致代码的可读性和可维护性下降。因为我们不知道sum_of_numbers变量的值是在哪里修改的,也不知道它的值是否正确。

因此,使用可变性来计算平均值可能会带来一些问题。相比之下,使用不可变性可以避免这些问题,使程序更容易理解和调试。

二、函数式编程的基础

2.1 纯函数(pure function)

纯函数是指在相同的输入下,总是返回相同的输出,并且没有任何副作用的函数。具体来说,纯函数满足以下两个条件:

  1. 相同的输入总是返回相同的输出。
  2. 函数执行过程中没有对外部环境产生任何影响,也就是没有副作用。

纯函数的好处在于它们更容易进行测试和调试,因为它们的行为是可预测的。此外,纯函数还可以更容易地进行并行化和优化,因为它们不依赖于外部状态。
例如,下面是一个纯函数的例子:

img

这个函数总是返回相同的输出,而且没有任何副作用。无论何时调用它,它都只是简单地将两个数字相加并返回结果。

Question:这是一个纯函数吗?

img

2.2 闭包(closure)

闭包是指一个函数和它所引用的外部变量的组合。在函数式编程中,闭包通常用于创建高阶函数,这些函数可以接受其他函数作为参数或返回函数作为结果。
闭包可以捕获外部变量的状态,并在函数调用之间保留它。这使得闭包可以实现一些有趣的功能,如记忆化和延迟计算。
例如,以下代码创建了一个闭包,它返回一个函数,该函数可以访问外部变量x:

img

在这个例子中,createAdder函数返回一个函数,该函数可以访问外部变量x。我们可以使用createAdder(5)创建一个新的函数add5,它将5添加到它的参数中。由于add5是一个闭包,它可以记住x的值,并在每次调用时使用它。

2.3 Lambda

Lambda是一种匿名函数,它可以在需要时被创建和调用,而不需要给它们命名。在JavaScript中,Lambda函数可以使用箭头函数语法来定义。

img

2.4 高阶函数

高阶函数是指能够接收一个或多个函数作为参数,并且/或者返回一个新函数的函数。函数是一等公民,因此函数可以像其他值一样被传递和操作。高阶函数是利用这种特性来实现更加灵活和抽象的编程方式。
以下是一些JavaScript中的高阶函数示例:

  1. **Array.prototype.map():**接收一个函数作为参数,该函数将应用于数组中的每个元素,并返回一个新数组,其中包含每个元素应用该函数的结果。

img

  1. **Array.prototype.filter():**接收一个函数作为参数,该函数将应用于数组中的每个元素,并返回一个新数组,其中包含满足该函数条件的元素。

    img

  2. **Array.prototype.reduce():**接收一个函数作为参数,该函数将应用于数组中的每个元素,并返回一个累加器的值。

    img

  3. 使用多个函数作为参数

img

2.5 偏函数(Partial)

偏函数是指将一个多参数函数转化为一个只有部分参数的函数,即固定函数的一些参数,使得这个新函数只需要传入剩余的参数即可完成调用。这样做的好处是可以简化函数的调用,减少重复代码的编写,提高代码的可读性和可维护性。

img

2.6 柯里化(Currying)

柯里化是一种函数式编程技术,它将一个接受多个参数的函数转换为一系列只接受单个参数的函数。这些单参数函数可以被组合在一起,以便在后续的计算中使用。
例如,假设有一个接受两个参数的函数 add(x, y),我们可以使用柯里化将其转换为一系列只接受一个参数的函数:

img

现在,我们可以使用这些单参数函数来进行计算:

img

这里,我们首先使用 add(1) 创建了一个新的函数 add_1,它只接受一个参数 y,并将其与 1 相加。然后,我们使用 add(2) 创建了另一个新的函数 add_2,它也只接受一个参数 y,并将其与 2 相加。最后,我们使用这些新函数来计算 add_1(3) 和 add_2(3),得到了正确的结果。
柯里化可以使代码更加简洁和可读,同时也可以提高代码的复用性和灵活性。

柯里化转换

下面是一个使用 JavaScript 实现柯里化的函数:

img

这个函数接受一个函数 fn 作为参数,并返回一个新的函数 curried,这个新函数可以接受任意数量的参数,并将它们逐步累积起来,直到收集到足够的参数后再调用原始函数 fn。
具体来说,当 curried 函数接收到的参数数量大于或等于 fn 函数的参数数量时,它会直接调用 fn 函数,并将收集到的参数传递给它。否则,它会返回一个新的函数,这个新函数可以接受更多的参数,并将它们与之前收集到的参数合并起来,然后递归调用 curried 函数,直到收集到足够的参数后再调用 fn 函数。
下面是一个使用 curry 函数实现柯里化的例子:

img

在这个例子中,我们定义了一个接受三个参数的函数 add(x, y, z),然后使用 curry 函数将它转换为一个柯里化函数 curriedAdd。最后,我们使用 curriedAdd 函数来计算 add(1, 2, 3),add(1, 2, 3),add(1, 2, 3) 和 add(1, 2, 3),得到了正确的结果。

优势
  1. 延迟执行:柯里化可以将一个函数的执行延迟到后续的计算中,这样可以避免不必要的计算和资源浪费。例如,在上面的例子中,我们可以先使用 add(1) 和 add(2) 创建两个新函数,然后在需要计算时再传递参数,这样可以避免重复计算和资源浪费。

  2. 函数组合:柯里化可以将多个函数组合在一起,以便在后续的计算中使用。例如,我们可以将多个只接受单个参数的函数组合在一起,形成一个新的函数,这个新函数可以接受多个参数,并将它们依次传递给这些单参数函数,从而得到最终的结果。

    img

柯里化是将一个接受多个参数的函数转换为一系列只接受单个参数的函数,这些单参数函数可以被组合在一起,以便在后续的计算中使用。柯里化的目的是为了提高代码的复用性和灵活性,使得代码更加简洁、可读和灵活。
偏函数是将一个接受多个参数的函数转换为一个接受部分参数的函数,这个部分参数是在转换时就已经确定的。偏函数的目的是为了简化函数调用,避免重复传递相同的参数,提高代码的可读性和可维护性。

三、函数式编程的进阶

3.1 函数组合(composition)

函数组合是一种将多个函数组合在一起以形成新函数的技术,可以帮助我们更好地组织和重用代码。
在函数组合中,我们将一个函数的输出作为另一个函数的输入,以此类推,直到我们得到最终的输出。这种方法可以让我们将多个简单的函数组合成一个更复杂的函数,从而使代码更加模块化和可读性更高。
例如,假设我们有两个函数 f(x) 和 g(x),我们可以将它们组合成一个新函数 h(x) = f(g(x))。这个新函数 h(x) 将先应用 g(x),然后将其结果传递给 f(x)。
函数组合还可以用于构建管道,其中每个函数都是前一个函数的输出。这种方法可以让我们轻松地将多个函数链接在一起,以便在数据流中进行转换和处理。

img

3.2 Pipeline

pipeline 是一种将多个函数组合在一起,形成一个数据处理流程的编程模式。它的核心思想是将数据从一个函数传递到另一个函数,每个函数都对数据进行一些操作,最终得到最终结果。
在函数式编程 pipeline 中,通常会使用一些高阶函数,如 map、filter、reduce 等,来对数据进行处理。这些函数可以接受一个函数作为参数,并将其应用于数据中的每个元素。
下面是一个简单的函数式编程 pipeline 的示例:

img

3.3 PointFree

函数式编程中的 pointfree 是一种编程风格,它的核心思想是尽可能地避免使用命名参数,而是通过组合函数来实现代码的复用和简化。
在 pointfree 风格中,函数的定义不会显式地引用它的参数,而是通过组合其他函数来实现其功能。这种风格的优点在于可以使代码更加简洁、可读性更高,并且可以更容易地进行代码重构和测试。

JavaScript

img

Scala

img

Go

img

3.4 惰性求值(Lazy evaluation)

惰性求值是一种计算策略,它只在需要时才计算表达式的值。这意味着,如果一个表达式的值从未被使用,那么它将永远不会被计算。相反,它只有在需要时才会被计算,这可以节省计算资源和提高程序的效率。
在函数式编程语言中,函数可以作为参数传递给其他函数,也可以从其他函数中返回。惰性求值可以使这些函数更加灵活和高效。只在需要时才计算表达式的值,可以提高程序的效率和灵活性。

img

在这个例子中,lazyAdd 函数返回一个函数,这个函数会在需要时才计算 a + b 的值。当我们调用 lazyAdd(2, 3) 时,它并不会立即计算 2 + 3 的值,而是返回一个函数。当我们调用这个函数时,它才会计算 2 + 3 的值并返回。
这种方式可以避免不必要的计算,提高程序的效率。例如,如果我们有一个很大的数组,我们可以使用惰性求值来避免不必要的遍历:

img

在这个例子中,lazyFilter 函数返回一个生成器函数,这个函数会在需要时才遍历数组并返回符合条件的元素。当我们调用 lazyFilter(arr, x => x % 2 === 0) 时,它并不会立即遍历数组,而是返回一个生成器函数。当我们使用 for…of 循环遍历这个生成器函数时,它才会遍历数组并返回符合条件的元素。这种方式可以避免不必要的遍历,提高程序的效率。

3.5 尾递归(Tail recursion)

递归

img

在这个实现中,递归调用发生在函数的中间,每次递归调用都需要等待下一层递归的返回值才能继续执行。这种形式的递归可能会导致栈溢出等问题,因为每次递归调用都会在栈中创建一个新的帧,如果递归层数太多,就会导致栈溢出。
尾递归
指一个函数在调用自身之后,不再有其他操作需要执行,直接返回结果。这种形式的递归可以被优化为迭代,从而避免栈溢出等问题。
在尾递归中,递归调用发生在函数的最后一步,而且递归调用的返回值直接被当前函数返回,不再进行其他操作。这种形式的递归可以被编译器或解释器优化为迭代,从而避免栈溢出等问题。
例如,下面是一个阶乘函数的尾递归实现:

img

在这个实现中,递归调用发生在函数的最后一步,而且递归调用的返回值直接被当前函数返回,不再进行其他操作。这种形式的递归可以被优化为迭代,从而避免栈溢出等问题。

3.6 MapReduce

在函数式编程中,Map和Reduce是两个常用的高阶函数。Map函数接受一个函数和一个列表作为输入,将该函数应用于列表中的每个元素,并返回一个新的列表。Reduce函数接受一个函数和一个列表作为输入,将该函数应用于列表中的每个元素,并返回一个单一的值。
在MapReduce中,Map函数将数据集分成小块,并将每个块映射到一个键值对。Reduce函数将相同键的所有值组合在一起,并将它们合并成一个单一的值。这个过程可以在分布式计算环境中并行执行,从而加快处理速度。

img

3.6.1 多线程

img

四、总结

4.1 优缺点

4.1.1 优点
  1. 简洁性:函数式编程通常比命令式编程更简洁,因为它们不需要维护状态或副作用。这使得代码更容易理解和维护。
  2. 可读性:函数式编程通常更容易阅读,因为它们的代码更加模块化和组合化。这使得代码更容易理解和修改。
  3. 可扩展性:函数式编程通常更容易扩展,因为它们的代码更加模块化和组合化。这使得代码更容易重用和修改。
  4. 可靠性:函数式编程通常更可靠,因为它们不依赖于共享状态或副作用。这使得代码更容易测试和调试。
  5. 并行性:函数式编程通常更容易并行化,因为它们的代码不依赖于共享状态或副作用。这使得代码更容易利用多核处理器和分布式系统。
4.1.2 缺点
  1. 性能:函数式编程通常比命令式编程更慢,因为它们需要更多的内存和计算资源来处理数据。这使得函数式编程不适合处理大规模数据或高性能应用程序。
  2. 学习曲线:函数式编程通常比命令式编程更难学习,因为它们需要更多的数学和抽象思维。这使得函数式编程不适合初学者或非技术人员。
  3. 可读性:函数式编程通常比命令式编程更难阅读,因为它们的代码更加抽象和符号化。这使得函数式编程不适合所有人,特别是那些不熟悉函数式编程的人。
  4. 可维护性:函数式编程通常比命令式编程更难维护,因为它们的代码更加抽象和符号化。这使得函数式编程不适合所有人,特别是那些不熟悉函数式编程的人。
  5. 工具支持:函数式编程通常比命令式编程缺乏工具支持,因为它们需要更多的数学和抽象思维。这使得函数式编程不适合所有人,特别是那些需要使用工具来提高生产力的人。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/7955.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(1day)致远M3 log 敏感信息泄露漏洞(Session)复现

前言 系统学习web漏洞挖掘以及项目实战也有一段时间了,发现在漏洞挖掘过程中难免会碰到一些历史漏洞,来帮助自己或是提高自己挖洞和及时发现漏洞效率,于是开始创建这个专栏,对第一时间发现的1day以及历史漏洞进行复现,来让自己更加熟悉漏洞类型以及历史漏洞,方便自己在后续的项…

商家制作微信小程序有什么好处?微信小程序的制作有哪些步骤和流程

微信小程序全面指南 微信小程序是微信生态系统中一项革命性的功能,为希望与庞大的微信用户群体互动的企业提供了独特的融合便捷性和功能性的体验。本全面指南深入探讨了微信小程序的世界,强调了其重要性、工作原理以及实际用例,特别是针对企…

开发组合php+mysql 人才招聘小程序源码搭建 招聘平台系统源码+详细图文搭建部署教程

随着互联网的快速发展,传统的招聘方式已经不能满足企业和求职者的需求。为了提高招聘效率,降低招聘成本,越来越多的人开始关注人才招聘小程序、在线招聘平台。分享一个人才招聘小程序源码及搭建,让招聘更加高效便捷。系统是运营级…

windows安装ElasticSearch以及踩坑

1.下载 elasticsearch地址:Past Releases of Elastic Stack Software | Elastichttps://www.elastic.co/cn/downloads/past-releases#elasticsearch IK分析器地址:infinilabs/analysis-ik: 🚌 The IK Analysis plugin integrates Lucene IK…

VS2022快捷键修改

VS2022快捷键修改 VS2022快捷键修改 VS2022快捷键修改

c++笔记——概述运算符重载——解析运算符重载的难点

前言:运算符重载是面向对象的一个重要的知识点。我们都知道内置类型可以进行一般的运算符的运算。但是如果是一个自定义类型, 这些运算符就无法使用了。那么为了解决这个问题, 我们的祖师爷就在c中添加了运算符重载的概念。 本篇主要通过实例的实现来讲述…

网络网络层之(4)IPv4协议

网络网络层之(1)IPv4协议 Author: Once Day Date: 2024年4月4日 一位热衷于Linux学习和开发的菜鸟,试图谱写一场冒险之旅,也许终点只是一场白日梦… 漫漫长路,有人对你微笑过嘛… 全系列文档可参考专栏:通信网络技术_Once-Day的…

《QT实用小工具·五十九》随机图形验证码,带有一些可人的交互与动画

1、概述 源码放在文章末尾 该项目实现了可交互的动画验证码控件,趣味性十足: 字符变换动画 噪音动画 可拖动交互 项目demo演示如下所示: 项目部分代码如下所示: #ifndef CAPTCHAMOVABLELABEL_H #define CAPTCHAMOVABLELABEL…

VMware虚拟机提示内存不足

VMware虚拟机,k8s集群搭建内存不足的问题 疑问:我的电脑是8G8G双通道的内存,当我在搭建k8s集群时给master-2G内存,node1-3G内存,node2-3G内存; 当依次打开虚拟机到node2时VM提示“物理内存不足,…

【busybox记录】【shell指令】cut

目录 内容来源: 【GUN】【cut】指令介绍 【busybox】【cut】指令介绍 【linux】【cut】指令介绍 使用示例: 关于参数的特殊说明: 打印行中选定部分 - 输出每行的第n-m个字节 打印行中选定部分 - 输出每行的第n-m个字符 打印行中选定…

【论文阅读】Fuzz4All: Universal Fuzzing with Large Language Models

文章目录 摘要一、介绍二、Fuzz4All的方法2.1、自动提示2.1.1、自动提示算法2.1.2、自动提示的例子2.1.3、与现有自动提示技术的比较 2.2、fuzzing循环2.2.1、模糊循环算法2.2.2、Oracle 三、实验设计3.1、实现3.2、被测系统和baseline3.3、实验设置以及评估指标 四、结果分析4…

每日OJ题_贪心算法三③_力扣45. 跳跃游戏 II(dp解法+贪心解法)

目录 力扣45. 跳跃游戏 II 解析代码1_动态规划 解析代码2_贪心 力扣45. 跳跃游戏 II 45. 跳跃游戏 II 难度 中等 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。 每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 num…

ws注入js逆向调用函数

这里需要选择一个文件夹 随便 紫色为修改保存 记得ctrls保存 注入代码如下 (function() {var ws new WebSocket("ws://127.0.0.1:8080")ws.onmessage function(evt) {console.log("收到消息:" evt.data);if (evt.data "exit") {…

PHPStudy Apache或者MySQL启动以后自动停止

问题 phpstudy小皮面板中的Apache或MySQL启动以后自动停止 正在启动——已启动——已停止 总结:最主要的原因:端口冲突 端口冲突了,已经有其他程序占用了80、3306端口。 也就是说你的电脑上已经有了一个Apache、MySQL并且正在运行。 解决方案…

C++ list 介绍

&#x1f308;一、认识list这个模版 ist是一个模版&#xff0c;需要结合一个具体的数据类型作为模版参数&#xff0c; 即list < T > <T> <T>&#xff0c;才能成为一个类类型。list是双向循环链表&#xff0c;是序列容器&#xff0c;允许在序列中的任何位置进…

DNS域名解析服务的部署及优化方案

实验要求: 1.配置2台服务器要求如下&#xff1a; a&#xff09;服务器1&#xff1a; 主机名&#xff1a;dns-master.timinglee.org ip地址&#xff1a; 172.25.254.100 配置好软件仓库 b&#xff09;服务器2&#xff1a; 主机名&#xff1a;dns-slave.timinglee.org ip地址&am…

MySQL数据库练习——视图

schooldb库——utf8字符集——utf8_general_ci排序规则 先创建库&#xff0c;再去使用下列的DDL语句。 DDL CREATE TABLE student (id int(11) NOT NULL AUTO_INCREMENT COMMENT 学号,createDate datetime DEFAULT NULL COMMENT 创建时间,modifyDate datetime DEFAULT NULL …

使用 GPT-4-turbo+Streamlit+wiki+calculator构建Math Agents应用【Step by Step】

&#x1f496; Brief&#xff1a;大家好&#xff0c;我是Zeeland。Tags: 大模型创业、LangChain Top Contributor、算法工程师、Promptulate founder、Python开发者。&#x1f4dd; CSDN主页&#xff1a;Zeeland&#x1f525;&#x1f4e3; 个人说明书&#xff1a;Zeeland&…

机器人系统ros2-开发实践07-将机器人的状态广播到 tf2(Python)

上个教程将静态坐标系广播到 tf2&#xff0c;基于这个基础原理这个教程将演示机器人的点位状态发布到tf2 1. 写入广播节点 我们首先创建源文件。转到learning_tf2_py我们在上一教程中创建的包。在src/learning_tf2_py/learning_tf2_py目录中输入以下命令来下载示例广播示例代码…

双ISP住宅IP有何优势?

双ISP住宅IP在当前的互联网环境中具有显著的优势&#xff0c;这些优势主要体现在网络连接的稳定性、安全性、速度以及业务适用范围等方面。以下是对双ISP住宅IP优势的详细分析&#xff1a; 第一点网络连接的稳定性&#xff0c;双ISP住宅IP使用两个不同的互联网服务提供商&…