符号与机器(一):符号:抽象、语义

#Technomous #PL

符号常常比发明它们的数学家更能推广。-F.克莱因

前言

一个语言系统就是一个符号系统,其中不同符号的组合便是语言表达式。符号的出现增加了人们的思维能力,正是基于符号表达才使得逻辑推演得以达成。

抽象

数学在已有符号上抽象出简单接口,以表示不同的形式。比如数学中的求和符号正是由希腊字母演化而来:

Σi=1nxix1+x2+x3+sumx_{i}from{i=1}to{n}

软件开发中的接口设计和算法实现时同样可以去联想数学中那些好的抽象,来确保整个系统的可扩展性。

然而,虽然数学中用简单的记号表现复杂的事物,但是一旦符号越来越多,各立山头,而不是一个统一的形式化系统,数学、物理中的符号抽象和表达经常让人不知所以,导致语义混乱。

语义

数学中令人误解的函数语义。

我们经常用

y=x22x+1

(1-1)

表示 y 是 x 的函数。但是,如果我们令

f(x)=x22x+1g(x)=x2

(1-2)

那么可能是 y = f(x),也可能是 y = g(x-1),那么这个时候 y 实际上是 x-1 的函数。

为什么会出现这种混淆?

  1. 因为传统的函数表达方式(1-1)中没有显式给出函数的自变量,即使是后面两种表达方法(1-2)也是把函数体和自变量的说明分开了,这种表达方式依然有问题。
  2. 传统数学中对函数的定义和调用不加严格区分。那么 x22x+1 既可以看成是函数 f(x) 的定义,又可以看成是函数 g(x) 对变量 x-1 的调用。而定义和调用在概念上有很大区别,传统函数表示方法很难表达清楚这种函数结构层次上的表达,更不用说多变量函数以及泛函了。:(

λ 演算--严格的函数运算

丘奇等数学家给出了解决方法:λ 演算。基本定义形式如下,

λ<变量>.<表达式>

用这种方法定义的函数叫 λ表达式。λx.x22x+1 就是一个 λ表达式,其中显式地指出了 x 是变量。

当将这个 λ表达式定义应用于具体的变量值时,需要用一对括号把表达式括起来,比如,

(λx.x22x+1)1

应用过程是把变量值赋值给表达式中的 x,并去掉 λ<变量>,过程如下,

(λx.x22x+1)1=121+1=0

看到这里是不是熟悉了很多,这其实就对应着程序语言中的函数定义,参数传递,函数调用。函数式编程语言 Lisp 表达的也正是这种形式。

如果有多个变量呢?应该按照固定的顺序排列和传递,比如,

λx.λy.x+y

调用过程如下,

((λx.λy.2x+y)1)2=(λy.2+y)2=4

其中,x = 1,y = 2,也就是说计算顺序是固定的,从里层到外层一层层归约,如果改变变量的次序也会影响函数应用中的返回值,比如,

((λy.λx.2x+y)1)2=(λx.2x+1)2=5

这便是语义。

这里也可以看到就是,函数的返回值也可以是一个函数,这样不同函数的层次问题也解决了,也就是传统数学中的高阶函数、泛函的表示。在函数式编程语言中函数是一等公民与此也是一致的。

λ 演算之所以被程序语言学家如此推崇,正是因为 λ 演算系统的构建过程就是一个程序语言从无到有的构建过程,整个系统中任何一个复杂的 λ 表达式都是由:λ 抽象、应用和括号,粘合在一起的:)

下面给出一个 Scheme 语言对数学中求和函数定义和调用形式,来结束吧。

;define
(define sum
	(lambda (L)
		(cond
			((eqv? L '()) 0)
			(else (+ (car L) (sum (cdr L)))))))

;call
(sum '(1 2 3))

结尾

这是符号系统文章的第一篇,如果你对文章有意见或建议请留言。
禁止转载。

许愿

希望一切都会好起来吧。

下一篇符号和机器(二):符号,计算抽象