热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

程序设计语言中的语法糖

语法糖是什么呢?按我现在的理解,如果一门语言没有某个语法,照样可以通过其它更通用的方式来表达某种语义。这种语法的引入,只不过是让表达语义更方便了。那么这个语法,就叫语法糖。Scheme中有两个关键

语法糖是什么呢?按我现在的理解,如果一门语言没有某个语法,照样可以通过其它更通用的方式来表达某种语义。这种语法的引入,只不过是 让表达语义更方便了。那么这个语法,就叫语法糖。

Scheme 中有两个关键字 lambda, let ,我目前的理解是,他们就是语法糖。

lambda

lambda 用来定义一个匿名函数。有时候,一个函数我们只在一个地方用一次,完全没必要给它定义一个名字,这时候,我们就用 lambda 定义 一个匿名函数。

如果没有 lambda ,那么我们定义函数时,会使用下面这种方式:

(define (pi-sum a b)
(define (pi-term x)
(/ 1.0 (* x (+ x 2))))
(define (pi-next x)
(+ x 4))
(sum pi-term a pi-next b))

其中像 pi-term 和 pi-next 这样的小函数,完全可以通过 lambda 定义一个匿名函数。

(define (pi-sum a b)
(sum
(lambda (x) (/ 1.0 (* x (+ x 2))))
a
(lambda (x) (+ x 4))
b))

let

let 用来定义局部变量,其实没有局部变量,我们也可以表达相应的语义,只不过有了 let ,定义起来更方便了。由于之前没有函数式语言 编程的经验,完全不知道没有局部变量要怎么办,所以还是看一个例子。

计算

f(x,y) = x(1+xy)^2 + y(1-y) + (1+xy)(1-y)

我们可以通过

a = 1 + xy
b = 1 - y
f(x, y) = xa^2 + yb + ab

来定义这个函数,这里面的 a, b 就相当于局部变量,那么在没有局部变量语法的情况下,我们怎么定义这个函数呢?

办法就是定义一个内部函数,将形式参数设定为 a, b,然后将 1 + xy 和 1-y 作为实际参数传递进去:

(define (f x y)
(define (f-helper a b)
(+ (* x (square a))
(* y b)
(* a b)))
(f-helper (+ 1 (* x y))
(- 1 y)))

而如果引入 let 这个语法糖后,定义起来就变得直观,容易多了:

(define (f x y)
(let ((a (+ 1 (* x y)))
(b (- 1 y)))
(+ (* x (square a))
(* y b)
(* a b))))

从这里可以看出,let 作用域内分两部分,一部分定义局部变量,另一部分是函数体。

通过对 SICP 这部分的学习,我明白了,什么是本质上的东西,什么是语法糖。本质上的东西是对函数及求值方式的定义,他们形式简单,功能强大, 大部分语义都可以通过这些定义出来。只是为了方便,我们引入了语法糖,来更容易地表达语义。

关于 lambda 这个词的来源,书中也有介绍,这是历史原因,源于 Alonzo Church 的 lambda 演算。lambda 演算为研究函数定义, 函数应用提供了坚实的数学基础。我还隐约记得在程序设计语言课上,老师教我们用 lambda 演算定义自然数,加法等运算法则,true/false, if/else 等等。你可以看出,这些本质的东西,可以表达非常非常多的东西,功能异常强大。

注:这是我学习 SICP 后的总结与思考,例子也都来自于此书。


推荐阅读
  • 如何精通编程语言:全面指南与实用技巧
    如何精通编程语言:全面指南与实用技巧 ... [详细]
  • Python与R语言在功能和应用场景上各有优势。尽管R语言在统计分析和数据可视化方面具有更强的专业性,但Python作为一种通用编程语言,适用于更广泛的领域,包括Web开发、自动化脚本和机器学习等。对于初学者而言,Python的学习曲线更为平缓,上手更加容易。此外,Python拥有庞大的社区支持和丰富的第三方库,使其在实际应用中更具灵活性和扩展性。 ... [详细]
  • 本文介绍了进程的基本概念及其在操作系统中的重要性,探讨了进程与程序的区别,以及如何通过多进程实现并发和并行。文章还详细讲解了Python中的multiprocessing模块,包括Process类的使用方法、进程间的同步与异步调用、阻塞与非阻塞操作,并通过实例演示了进程池的应用。 ... [详细]
  • 本文详细记录了一位Java程序员在Lazada的面试经历,涵盖同步机制、JVM调优、Redis应用、线程池配置、Spring框架特性等多个技术点,以及高级面试中的设计问题和解决方案。 ... [详细]
  • 为帮助编程爱好者更好地掌握Python和Go语言的核心技能,我们特别提供两本精选图书的免费赠阅机会。《易懂的Python算法指南》适合所有希望提高算法理解能力的读者,《Go语言编程从入门到精通》则面向对Go语言感兴趣的初学者及有一定基础的开发者。 ... [详细]
  • RabbitMQ 核心组件解析
    本文详细介绍了RabbitMQ的核心概念,包括其基本原理、应用场景及关键组件,如消息、生产者、消费者、信道、交换机、路由键和虚拟主机等。 ... [详细]
  • 本文介绍了基于Java的在线办公工作流系统的毕业设计方案,涵盖了MyBatis框架的应用、源代码分析、调试与部署流程、数据库设计以及相关论文撰写指导。 ... [详细]
  • 本文探讨了在不同场景下如何高效且安全地存储Token,包括使用定时器刷新、数据库存储等方法,并针对个人开发者与第三方服务平台的不同需求提供了具体建议。 ... [详细]
  • Web开发实践:创建连连看小游戏
    本文详细介绍了如何在Web环境中开发一款连连看小游戏,适合初学者和技术爱好者参考。通过本文,您将了解游戏的基本结构、连线算法以及实现方法。 ... [详细]
  • 本文深入解析了WCF Binding模型中的绑定元素,详细介绍了信道、信道管理器、信道监听器和信道工厂的概念与作用。从对象创建的角度来看,信道管理器负责信道的生成。具体而言,客户端的信道通过信道工厂进行实例化,而服务端则通过信道监听器来接收请求。文章还探讨了这些组件之间的交互机制及其在WCF通信中的重要性。 ... [详细]
  • POJ 2482 星空中的星星:利用线段树与扫描线算法解决
    在《POJ 2482 星空中的星星》问题中,通过运用线段树和扫描线算法,可以高效地解决星星在窗口内的计数问题。该方法不仅能够快速处理大规模数据,还能确保时间复杂度的最优性,适用于各种复杂的星空模拟场景。 ... [详细]
  • 计算机视觉领域介绍 | 自然语言驱动的跨模态行人重识别前沿技术综述(上篇)
    本文介绍了计算机视觉领域的最新进展,特别是自然语言驱动的跨模态行人重识别技术。上篇内容详细探讨了该领域的基础理论、关键技术及当前的研究热点,为读者提供了全面的概述。 ... [详细]
  • 在本文中,我们将为 HelloWorld 项目添加视图组件,以确保控制器返回的视图路径能够正确映射到指定页面。这一步骤将为后续的测试和开发奠定基础。首先,我们将介绍如何配置视图解析器,以便 SpringMVC 能够识别并渲染相应的视图文件。 ... [详细]
  • 比特币的成功为区块链技术构建了可信货币的基石,标志着区块链1.0时代的到来。以太坊通过引入智能合约,极大地推动了去中心化应用的开发和普及,开启了区块链2.0时代。本文深入探讨了侧链技术在提升区块链扩展性方面的潜力和应用,分析了其在提高交易速度、降低成本和增强安全性等方面的优势,并讨论了当前面临的技术挑战和未来的发展方向。 ... [详细]
  • 本文详细介绍了如何在 EasyUI 框架中实现 DataGrid 组件的分页功能,包括配置方法和常见问题的解决方案。 ... [详细]
author-avatar
负能量包子玻璃包各负磁场宣泄区
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有