十分钟了解 18 个冷门编程概念

开发
本文介绍了 18 个比较冷门的编程概念,并通过示例代码帮助读者理解这些概念,同时强调了它们在编程实践中的重要性。这些概念虽然不为人所知,但对提升编码技能和思维方式具有重要意义。

作为开发者,我们需要不断学习新的术语、技术和最佳实践。但是,如果有人告诉你还有许多你甚至不知道的概念,而且这些概念可能会改变你编码和思考的方式,你会怎么想?无论你是初学者还是经验丰富的开发者,这 18 个冷门概念都将帮助你提升水平。本文就会带你深入了解这些概念,示例代码将基于 JS 和 Python。

1. Thunk:善用拖延症

你有过把事情拖到最后一刻才做的经历吗?thunk 正是如此,它将函数的执行推迟到绝对必要的时候。

想象一下,有一项计算成本很高的任务,但暂时不确定是否需要计算结果。与其提前计算,不如用 thunk 将其封装起来。

const thunk = () => 5 + 10;
console.log(thunk()); // 只在调用时进行计算
  • 1.
  • 2.

2. Monad(单子):代码的安全网

Monad 就像是函数的安全网,帮你实现链式操作并处理意外行为(如错误或空值),而不会导致整个程序崩溃。如果你正在处理异步数据,可能已经在不知不觉中用到了 monad!

new Promise((resolve) => resolve(5))
    .then(value => console.log(value)) // 输出: 5
  • 1.
  • 2.

Monad 看起来很神秘,但可以把它们想象成沿着管道安全传递数据的容器。

3. Closure(闭包):代码记忆

试想一下,如果过去的自己能给未来的自己留下一段回忆会怎么样,这正是 closure(闭包)的作用,它允许函数 "记住" 变量创建时候的上下文。

def counter():
    count = 0

    def _():
        nonlocal count
        count += 1
        return count
    return _

increment = counter()
print(increment())
print(increment())
print(increment())

#1
#2
#3
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

4. Memoization:让我们提高效率,好吗?

有没有反复问同一个问题的经历?很烦人吧?计算机也是这么想的。Memoization 通过存储结果解决了这个问题,这样就不必重复进行昂贵的计算。

def fib(n, memo={}):
    if n in memo:
        return memo[n]
    if n < 2:
        return n
    memo[n] = fib(n - 1, memo) + fib(n - 2, memo)
    return memo[n]

fib(100)

#354224848179261915075
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

5. Continuation:未来掌握在自己手中

continuation 就像在代码中按下 "暂停" 键,并将稍后执行下一步,这是许多异步系统背后的秘诀。

function asyncTask(callback) {
    setTimeout(() => {
        console.log("Task complete");
        callback();
    }, 1000);
}
asyncTask(() => console.log("Next step"));
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

1 秒后,箭头内的代码 () => { console.log("Task complete"); callback(); } 将被执行。

处理过异步编程吗?写过最后的回调函数吧?它就是一个 continuation,是将在未来发生的事情!

6. Idempotence(幂等性):无论做多少次,结果都和第一次一样

在编程过程中,有些操作无论执行多少次,其行为方式都是一样的。这就是幂等性 -- 无论调用 API 一次还是 100 次,结果都是一样的。

GET /user/123  HTTP/1.1
  • 1.

如果一直调用 GET /user/123,得到的永远是同一个用户。API 的世界依赖于这一原则,它让一切都具有可预测性和安全性。

7. Quine(奎因):自我复制的程序

quine 是一种聪明的代码,能输出自己的源代码,就像照镜子时看到……嗯,代码正盯着你看。

s = 's = {!r}; print(s.format(s))'; print(s.format(s))

#输出 => s = 's = {!r}; print(s.format(s))'; print(s.format(s))
  • 1.
  • 2.
  • 3.

8. Zipper:超级结构化导航

在不造成混乱的情况下浏览和修改数据结构是一件棘手的事情,直到出现了 zipper,它可以帮助我们高效遍历和修改结构(如树),而不会破坏原有结构。

class Zipper:
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def move_left(self):
        return Zipper(self.left[:-1], [self.left[-1]] + self.right)

    def move_right(self):
        return Zipper(self.left + [self.right[0]], self.right[1:])
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

Zipper 是复杂数据结构的导航指南针。

9. Functor(函子):友好的映射

functor 是一种可以映射函数的东西,可以在不接触容器本身的情况下,对容器中的每个数据进行转换。它不仅仅是函数式编程,更具备强大的组合能力。

numbers = [1, 2, 3]
squared = list(map(lambda x: x ** 2, numbers))
print(squared)  # [1, 4, 9]
  • 1.
  • 2.
  • 3.

Python 中的 list 是函数,允许我们在不改变原始结构的情况下进行映射操作。

10. Tail Call Optimization(尾调用优化):不会造成栈溢出的无限递归

尾调用优化(TCO)让我们在编写递归函数时不必担心内存不足。如果函数的最后一个操作是调用自身,TCO 可以重复使用当前函数的栈帧。

def factorial(n, acc=1):
    if n == 0:
        return acc
    return factorial(n - 1, acc * n)
  • 1.
  • 2.
  • 3.
  • 4.

注:以上示例只显示了 TCO 的结构,但请记住 Python 本身并不支持 TCO。

11. Currying(柯里化):请一次只做一件事!

柯里化将一个接受多个参数的函数分解成一系列函数,每个函数只有一个参数。

def add(x):
    def inner(y):
        return x + y
    return inner

add_five = add(5)
print(add_five(3))  # 8
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

柯里化是获得灵活性的关键 -- 想要应用部分参数?柯里化可以做到。

还可以基于 partial 进行函数柯里化。

from functools import partial

def adder(a, b):
    return a + b

two_adder = partial(adder, 2)
two_adder(10)

#12
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

12. Spectre & Meltdown:困扰你的 CPU

你可能听说过 Spectre 和 Meltdown 这两个震惊世界的臭名昭著的漏洞,它们利用了现代处理器优化性能的方式,泄露了敏感数据。

if (untrusted_input < array_size) {
    temp = array[untrusted_input * 512];
}
  • 1.
  • 2.
  • 3.

单纯追求速度可能会让事情更糟,投机取巧的执行可能会加快代码的执行,但有时泄露的信息会超出我们的想象!

13. Homomorphism(同态):保留结构

Homomorphism(同态)是个花哨的词,指在两个代数系统之间保留结构的函数。在数学中是很重要的概念,但在编程中转换数据时也很重要。(最重要的函数式编程概念之一)

numbers = [1, 2, 3, 4]
def square(x):
    return x * x
squared_numbers = list(map(square, numbers))
print(squared_numbers)  

# Output: [1, 4, 9, 16]
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

14. Lazy Evaluation(惰性求值):只在需要时

惰性求值会将表达式的求值延迟到需要时才进行,对于提高大型数据集或计算程序的性能非常有用。

def lazy_range(n):
    i = 0
    while i < n:
        yield i
        i += 1

for num in lazy_range(5):
    print(num)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

生成器只在需要时才计算数值,从而节省了内存和处理时间。

thunk 和惰性求值生成器 😫 有何区别?

  • 惰性求值是一种延迟求值表达式的策略,直到实际需要时才进行计算。它可以避免不必要的计算,从而帮助优化性能,尤其是在使用无限数据结构或处理昂贵的操作时。
  • Thunk 是一种用于实现惰性求值的特定技术,本质上是一个没有参数的函数,封装了计算或表达式,计算会被延迟到 Thunk 被明确调用时执行。

15. Canonicalization(规格化):将数据标准化

Canonicalization(规格化)是将数据转换为标准或规范化形式的过程,通常用于数据库和 URL,以确保一致性。

http://example.com
https://example.com
http://www.example.com
  • 1.
  • 2.
  • 3.

规格化可确保所有版本都指向一个唯一首选版本。

16. Side Effect(副作用):超出预期

当函数或表达式修改了其本地环境之外的某些状态时,就会产生副作用,例如改变全局变量、I/O 操作或修改输入参数。

def add_to_list(value, lst=[]):
    lst.append(value)
    return lst

print(add_to_list(1))  # [1]
print(add_to_list(2))  # [1, 2] (unexpected!)
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

本例中的函数修改了默认参数,导致了意想不到的副作用。

17. Hoisting:将声明移至顶部

在 JavaScript 中,hoisting 会在编译阶段将变量和函数声明移到其作用域的顶部。

console.log(x);  // 未定义
  var x = 5;
  • 1.
  • 2.

即使 x 是在 console.log 之后声明,JavaScript 也会将声明提升到顶部,使 x 在定义之前就可以访问。

18. Monoid(单态):以一致的方式组合数据

monoid (单态)是一种代数结构,具有二元运算和一个标识元素,允许以关联方式组合数据。

result = ''.join(['a', 'b', 'c'])
print(result)  # 'abc'
  • 1.
  • 2.

这里的字符串连接构成了一个以 '' 为标识元素、以 + 为二进制运算的单元。

结论

这些高级编程术语初看起来可能很深奥,但理解了它们可以极大改进编写代码的方法。无论是优化性能、安全性还是可读性,这些概念可以是强大的工具,帮助我们以优雅的方式解决复杂问题。

责任编辑:赵宁宁 来源: DeepNoMind
相关推荐

2024-06-19 09:58:29

2024-05-13 09:28:43

Flink SQL大数据

2023-07-15 18:26:51

LinuxABI

2024-11-07 16:09:53

2015-11-06 11:03:36

2021-07-29 08:57:23

ViteReact模块

2020-12-17 06:48:21

SQLkafkaMySQL

2009-11-03 11:01:45

VB.NET远程事件

2024-12-13 15:29:57

SpringSpringBeanJava

2024-10-08 11:12:12

2019-04-01 14:59:56

负载均衡服务器网络

2016-01-04 11:18:00

KubernetesKubernetes概容器技术

2024-10-06 12:50:25

2020-12-09 16:41:22

LinuxIT开发

2021-09-07 09:40:20

Spark大数据引擎

2022-06-16 07:31:41

Web组件封装HTML 标签

2023-04-12 11:18:51

甘特图前端

2024-01-29 00:20:00

GolangGo代码

2015-09-06 09:22:24

框架搭建快速高效app

2012-07-10 01:22:32

PythonPython教程
点赞
收藏

51CTO技术栈公众号