ISWIM(“If you See What I Mean”的首字母缩写),是的一种抽象的计算机编程语言或编程语言家族,它由Peter J. Landin设计,并描述在他1966年于ACM通讯发表的文章《The Next 700 Programming Languages》之中[1]。
| 编程范型 | 函数式, 指令式 |
|---|---|
| 設計者 | Peter J. Landin |
| 发行时间 | 1966年 |
| 作用域 | 词法 |
| 受影响于 | |
| ALGOL 60, Lisp | |
| 影響語言 | |
| PAL, SASL, ML, NPL, Lucid, Haskell | |
尽管没有实现,它被证明为在编程语言开发中非常有影响力的语言,特别是对于函数式编程语言,比如SASL、ML、NPL、Haskell和它们的后继者,还有数据流程编程语言如Lucid。
概述
编辑ISWIM是具有函数式核心的指令式编程语言,它构成自加了语法糖的叫做“应用表达式”(AE)的扩展λ演算,并增加了强力控制机制即对应J算子的程序点算子pp[2]。ISWIM的操作语义,可以使用Landin的SECD抽象机来定义,并且使用了传值调用,从而具有及早求值的求值策略[3]。
ISWIM基于了λ演算,从而具有高阶函数和词法作用域变量。ISWIM的目标之一,就是要看起来更像数学表示,所以在定义结构之时,放弃了ALGOL的语句括号begin……end,转而采用了越位规则和基于缩进的作用域。
没有进行过直接实现ISWIM的尝试,但是Arthur Evans的PAL[4],和John C. Reynolds的Gedanken[5],获取了Landin的多数概念,包括强力的控制转移运算,这两者都是动态类型语言。Robin Milner的ML,可以被认为等价于没有J算子,而有类型推论的ISWIM。
从ISWIM衍生出的另一条路线,是去掉指令式特征如J算子并加以单赋值限制,从而成为纯函数式语言并进一步切换为惰性求值[6]。这条路线导致了SASL、Hope、KRC、Miranda、Haskell、Clean。
语法
编辑ISWIM程序基于了一个单一表达式,它由where或let子句、条件表达式和函数定义所限定。ISWIM在表示法上的特色,是与CPL一起,最早使用了局部定义子句L where x = M let x = M; L,尤其是let子句适合表达ALGOL 60的嵌套的块结构而为后继者语言所承袭:
| AE | 逻辑ISWIM | |
|---|---|---|
{λf.f(b+2c)+f(2b-c)}
[λx.x(x+a)]
{λ(f,b,c).f(b+2c)+f(2b-c)}
[λx.x(x+a),
u/(u+1),
v/(v+1)]
{λf.f(6)}
[Yλf.λn.if(n=0)(1,nf(n-1))]
{λ(f,g).f(g(a))+g(f(b))}
[Yλ(f,g).
(λx.F(f,g,x),λx.G(f,g,x))]
{λg.g({λf.f}[λx.ax²+bx+c],
u/(u+1),
v/(v+1))}
[λ(f,p,q).f(p+2q,2p-q)]
{λx.xy(x+y)}
[{λy.a²+a√y}
[a²+b²]]
{λ(a,b,f).
{λ(g,h).
{λk.X}
[λ(u,v).λx.K]}
[Yλ(g,h).
(λx.G,λ(y,z).H)]}
[A,B,λ(x,y).F]
|
f(b+2c)+f(2b-c)
where f(x) = x(x+a)
f(b+2c)+f(2b-c)
where f(x) = x(x+a)
and b = u/(u+1)
and c = v/(v+1)
f(6)
where rec f(n) = (n=0)→1; nf(n-1)
f(g(a))+g(f(b))
where rec f(x) = F(f,g,x)
and g(x) = G(f,g,x)
g(f where f(x) = ax²+bx+c,
u/(u+1),
v/(v+1))
where g(f,p,q) = f(p+2q,2p-q)
xy(x+y)
where x = a²+a√y
where y = a²+b²
X
where k(u,v)(x) = K
where rec g(x) = G
and h(y,z) = H
where a = A
and b = B
and f(x,y) = F
|
let f(x) = x(x+a)
f(b+2c)+f(2b-c)
let f(x) = x(x+a)
and b = u/(u+1)
and c = v/(v+1)
f(b+2c)+f(2b-c)
let rec f(n) = (n=0)→1; nf(n-1)
f(6)
let rec f(x) = F(f,g,x)
and g(x) = G(f,g,x)
f(g(a))+g(f(b))
let g(f,p,q) = f(p+2q,2p-q)
g((let f(x) = ax²+bx+c; f),
u/(u+1),
v/(v+1))
let x =
let y = a²+b²; a²+a√y
xy(x+y)
let a = A
and b = B
and f(x,y) = F
let rec g(x) = G
and h(y,z) = H
let k(u,v)(x) = K
X
|
λ演算中的应用项(M N)及其关联的抽象项M := λx.L,在应用表达式中要一起表示为:{λM.(M N)}[λx.L],它对应的ISWIM表示为:M(N) where M(x) = L或let M(x) = L; M(N)。
ISWIM所基于的应用表达式,采用花括号包围算子,采用方括号包围运算元或运算元列表,它为了“同时”或“平行”定义而在λ和.之间扩展了标识符列表,列表用圆括号包围并在其中用逗号分隔元素。应用表达式为递归定义而采用了Y不动点组合子,采用λ().L表示无参数函数thunk。示例中处置下行函数参数的{λf.f}对应于I恒等组合子,此外还可能用到K常量组合子,和B复合组合子。
在ISWIM论文中首次出现了用来定义结构的代数数据类型定义,这是通过自然语言的either……or……和……and……描述完成的,但明确的表示出了当代函数式编程语言比如Standard ML中的“积之和”[7]:
| 抽象ISWIM | Standard ML |
|---|---|
an ( ) is either , and has a , which is an or a , in which case it has a , which is an , and a , which is an , or a , …… , or , …… , or a , …… , or , …… . |
datatype aexp
= SIMPLE of body
| COMBINATION of rator * rand
| CONDITIONAL ……
| ONE_ARMED ……
| LISTING ……
| BEET ……
and body = BODY of identifier
and rator = RATOR of aexp
and rand = RAND of aexp
|
这里的特有术语beet是对beta可归约式(beta redex)的简称,它代表了L where x = M或let x = M; L,这里的L称为主要子句,x = M称为支持(support)即辅助定义。
在ISWIM论文中,Landin将顶层的ISWIM构造称为amessage即消息,并示例了两个命令,特定的需求例如Print a+2b,和定义例如Def x = a+2b。
语义
编辑(D')规则:x = L and y = M and …… and z = N(x, y, ……, z) = (L, M, ……, N),它对应于Standard ML中的模式匹配。(I')规则:f(x) = Lf = (g where g(x) = L),它对应于Standard ML中的fun f x = Lval f = fn x => L。(I')规则还有更一般性的柯里化形式,形如f(a, b, c)(x, y) = Lf(a, b, c) = (g where g(x, y) = L)。
(I)规则:(f where f(x) = L) ML where x = M,这里的f where f(x) = L对应于Standard ML中此前将fn x => L绑定到变量时所生成的闭包。(β')规则:(x = L) where y = Mx = (L where y = M)。(β)规则:L where x = MSubst L,它对应于λ演算中的β-归约,即用M代换L中出现的所有适合的x。(Y)规则:rec x = Lx = (L where rec x = L),这里的rec对应于λ演算中的Y不动点算子。
下面以阶乘函数的应用为例,它用到了(I')、(Y)、(β)和(I)等价规则:
设C = (n=0)→1; nf(n-1)、G = (g where g(n) = C)并且F = (G where rec f = G)
| |||||
f(6) where rec f(n) = (n=0)→1; nf(n-1)
|
let rec f(n) = ((n=0)→1; nf(n-1)); f(6)
| ||||
f(6) where rec f(n) = C |
let rec f(n) = C; f(6)
| ||||
f(6) where rec f = (g where g(n) = C)
|
let rec f = (let g(n) = C; g); f(6)
| ||||
f(6) where rec f = G
|
let rec f = G; f(6)
| ||||
f(6) where f = (G where rec f = G)
|
let f = (let rec f = G; G); f(6)
| ||||
f(6) where f = F
|
let f = F; f(6)
| ||||
F(6)
|
F(6)
| ||||
(G where rec f = G)(6)
|
(let rec f = G; G)(6)
| ||||
(G where f = (G where rec f = G))(6)
|
(let f = (let rec f = G; G); G)(6)
| ||||
(G where f = F)(6)
|
(let f = F; G)(6)
| ||||
((g where g(n) = C) where f = F)(6)
|
(let f = F; (let g(n) = C; g))(6)
| ||||
((g where g(n) = (n=0)→1; nf(n-1)) where f = F)(6)
|
(let f = F; (let g(n) = ((n=0)→1; nf(n-1)); g))(6)
| ||||
(g where g(n) = (n=0)→1; nF(n-1))(6)
|
(let g(n) = ((n=0)→1; nF(n-1)); g)(6)
| ||||
((n=0)→1; nF(n-1)) where n = 6
|
let n = 6; ((n=0)→1; nF(n-1))
| ||||
6(F(5))
|
6(F(5))
| ||||
| ⋮ | ⋮ | ||||
6(5(4(3(2(1(F(0)))))))
|
6(5(4(3(2(1(F(0)))))))
| ||||
通过运用(I')、(β')、(D')和(Y)等价规则,ISWIM确使任何定义都能被标准化,即表达为lhs = rhs的绑定形式,等式的两侧分别为:左手侧(lhs)的确切的一个约束变量,右手侧(rhs)的它所对应的主体(body)。通过反向运用等价规则,ISWIM可在这个例子中恢复出等式的左手侧为rec f(n)形式的表达式:
6(F(5))
|
6(F(5))
| ||||
6(f(5) where f = F)
|
6(let f = F; f(5))
| ||||
6(f(5) where f = (G where rec f = G))
|
6(let f = (let rec f = G; G); f(5))
| ||||
6(f(5) where rec f = G)
|
6(let rec f = G; f(5))
| ||||
6(f(5) where rec f = (g where g(n) = C))
|
6(let rec f = (let g(n) = C; g); f(5))
| ||||
6(f(5) where rec f(n) = C)
|
6(let rec f(n) = C; f(5))
| ||||
6(f(5) where rec f(n) = (n=0)→1; nf(n-1))
|
6(let rec f(n) = ((n=0)→1; nf(n-1)); f(5))
|
执行
编辑对应用表达式(AE)进行机器求值的SECD抽象机将状态变迁规则定义为状态变换函数Transform(S,E,C,D):
| 初始状态 | 变换状态 | |||||||
|---|---|---|---|---|---|---|---|---|
| S | E | C | D | S | E | C | D | |
| s | e | combination(rator,rand)::c | d | s | e | rand::rator::ap::c | d | |
| s | e | λexp(v,L)::c | d | s | e | closure((e,v),[L])::c | d | |
| s | e | identifier(x)::c | d | locate(position(e,x),e)::s | e | c | d | |
| S | E | C | D | S | E | C | D | |
|---|---|---|---|---|---|---|---|---|
| f::x::s | e | ap::c | d | f(x)::s | e | c | d | |
| x::s | e | closure((e',v),[L])::ap::c | d | [] | (v,x)::e' | [L] | (s,e,c,d) | |
| x::s | e | [] | (s',e',c',d') | x::s' | e' | c' | d' | |
这里的[]是空列表,它在ISWIM中表示为nullist,在应用表达式中表示为()。这里的::是列表构造的中缀构造子,x::L cons(x,L) prefix(x)(L)。
在Landin的规定中,取得标识符X有关于环境E所指称的值的函数为:val(E)(X) = location(E*)(X)(E*),其中的E*指示与环境E对应的名值对的列表,这里将这个取值函数表示为locate(position(e,x),e),即定位在环境e中占据位置position(e,x)的常量x并取得它的原始值。
在Landin的规定中,设v = bv(X)且L = body(X),从λ表达式X所在的环境E派生出在其中求值L的新环境的函数为:derive(assoc(v,x))(E),这里假定环境E已经实现为特定LISP共享结构即元素为有序对的可持久性单向链表,从而将这个派生函数直接用代数数据类型的元组和递归数据类型的列表的特定算子来表示。
J算子的应用形式f = J(λX.L)称为“程序点”,它将函数F = λX.L变换成程序闭包。J算子对应的状态变换函数为:
| 初始状态 | 变换状态 | |||||||
|---|---|---|---|---|---|---|---|---|
| S | E | C | D | S | E | C | D | |
| s | e | F::J::ap::c | d | s | e | program-closure(F,d)::c | d | |
| x::s | e | program-closure(F,(s',e',c',d'))::ap::c | d | F::x::s' | e' | ap::c' | d' | |
程序点在ISWIM中表示为pp f(X) = L。
扩展
编辑应用表达式扩展了的赋值器(assigner) ,其应用形式为lhs rhs,则称为指令式应用表达式(IAE)。ALGOL 60中传名调用所关联起来的形式参数和实际参数,具有等价关系,它们的状态内位置属于同一个等价类故而称为共享,在直接计算机表示中每个等价类对应一个地址。赋值器重置lhs确定的状态内位置以及同它共享的所有的状态内位置,并在堆栈S上留下nullist作为结果。执行指令式应用表达式的抽象机的状态变换函数为:
| 初始状态 | 变换状态 | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| S | E | C | D | 共享 | S | E | C | D | 共享 | |
| s | e | combination(rator,rand)::c | d | s | e | rand::rator::ap::c | d | |||
| s | e | λexp(v,L)::c | d | s | e | closure((e,v),[L])::c | d | |||
| s | e | ()::identifier(p)::ap::c | d | s | e | parameter(p)::c | d | |||
| s | e | assigner(lhs,rhs)::c | d | s | e | rhs::lhs::assign::c | d | |||
| S | E | C | D | 共享 | S | E | C | D | 共享 | |
|---|---|---|---|---|---|---|---|---|---|---|
| s | e | identifier(x)::c | d | locate(l)::s | e | c | d | l=(position(e,x),e) | ||
| s | e | parameter(p)::c | d | locate(l)::s | e | c | d | l=locate(position(e,p),e) | ||
| r::x::s | e | assign::c | d | l | reset(l,x)::s | e | c | d | ||
| f::x::s | e | ap::c | d | l | f(x)::s | e | c | d | ||
| f::x::s | e | ap::c | d | f(x)::s | e | c | d | |||
| S | E | C | D | 共享 | S | E | C | D | 共享 | |
|---|---|---|---|---|---|---|---|---|---|---|
| r::s | e | closure((e',p),[L])::ap::c | d | l | [] | (p,l)::e' | [L] | (s,e,c,d) | ||
| x::s | e | closure((e',v),[L])::ap::c | d | [] | (v,x)::e' | [L] | (s,e,c,d) | |||
| x::s | e | [] | (s',e',c',d') | l | x::s' | e' | c' | d' | l | |
| x::s | e | [] | (s',e',c',d') | x::s' | e' | c' | d' | |||
这里的l表示左值,传递左值的所有的状态内位置position(e,p)共享同一个地址(position(e,x),e)。为了执行扩展了J算子的具有赋值器的指令式应用表达式,所细化的SECD抽象机叫做共享机器。
Landin将Y不动点算子表示为指令式应用表达示式:Y(F) ≡ {λz.{λz′.2nd(z⇐z′,z)}[F(z)]}[separate(nullist)],它对应的ISWIM表示为:
Y(F) let z = separate(nullist); let z' = F(z); 2nd(z z',z)
separate(x)函数同I恒等组合子一样取用右值x,从而避免了后续的赋值变更这个处在外层的非局部值。它的用途典型的对应于ALGOL 60中声明形式参数为传值调用,例如let x = separate(x()); L,形式参数对应的实际参数是在某个外层中声明的局部标识符,它采用separate函数初始化比如let x = separate(0.0)。separate函数对应的状态变换函数为:
| 初始状态 | 变换状态 | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| S | E | C | D | 共享 | S | E | C | D | 共享 | |
| s | e | separate::ap::λexp(v,L)::c | d | s | e | local-closure((e,v),[L])::c | d | |||
| S | E | C | D | 共享 | S | E | C | D | 共享 | |
|---|---|---|---|---|---|---|---|---|---|---|
| x::s | e | local-closure((e',v),[L])::ap::c | d | l | [] | (v,x)::e' | [L] | (s,e,c,d) | ||
| x::s | e | local-closure((e',v),[L])::ap::c | d | [] | (v,x)::e' | [L] | (s,e,c,d) | |||
Landin规定了赋值且保全命令assignandhold,它采用守卫命令处置指令式编程语言如ALGOL 60的原始数据类型:
assignandhold(x)(y) let x = (real(y)→float(x); integer(y)→entier(x+0.5); Boolean(y)→(Boolean(x)→x)); 2nd(y x,x)。
引用
编辑- ^ Landin, P. J. The Next 700 Programming Languages (PDF). Communications of the ACM (Association for Computing Machinery). March 1966, 9 (3): 157–165 [2021-08-28]. S2CID 13409665. doi:10.1145/365230.365257. (原始内容 (PDF)存档于2022-03-23).
- ^ Landin, P.J. A Generalization of Jumps and Labels (PDF). 1965 [2026-03-04]. (原始内容存档 (PDF)于2025-12-28).
Thielecke, H. An Introduction to Landin's "A Generalization of Jumps and Labels". Higher-Order and Symbolic Computation. December 1998, 11 (2): 117–123. S2CID 1562780. doi:10.1023/A:1010060315625. - ^ Gordon Plotkin. Call-by-Name, Call-by Value and the Lambda Calculus (PDF) (报告). 1975 [2020-04-26]. (原始内容 (PDF)存档于2020-02-01).
We are going to define ISWIM without letrec, without any syntactic sugar and without any imperative features. Abstract syntax will also ignored. Its set of programs is just the set of closed terms, …… given some infinite set of variables and a set of constants. ……
To complete the definition of the programming language, we will specify the evaluation function Evalv: Programs Programs. This is defined relative to an interpretation of the constants, given by a function:
Constapply: Constants × Constants Closed Values.
Constapply will give the δ-rules for λv, …… . By making a few alterations we could have allowed the range of Constapply to be Closed Terms. ……
The official definition of Evalv now requires the SECD machine. It should be remarked that this is too tedious to work with directly and so we will give an equivalent definition of Evalv immediately afterwards, prove it equivalent and from then on use only the simpler one. ……
A suitable λv calculus is obtained by simply restricting the β rule in the λK-βδ calculus induced by Constapply. - ^ Arthur Evans. PAL: a language designed for teaching programming linguistics. Proceedings ACM National Conference. ACM National Conference. Association for Computing Machinery. 1968 [2026-04-07]. (原始内容存档于2024-10-08).
- ^ John C. Reynolds. GEDANKEN: a simple typeless language which permits functional data structures and co-routines (PDF) (报告). Argonne National Laboratory. September 1969 [2021-09-09]. (原始内容 (PDF)存档于2021-09-09).
John C. Reynolds. Definitional interpreters for higher-order programming languages. ACM '72: Proceedings of the ACM annual conference - Volume. August 1972 [2022-11-19]. doi:10.1145/800194.805852. (原始内容存档于2022-11-27). - ^ Ivanović, Mirjana; Budimac, Zoran. A definition of an ISWIM-like language via Scheme. ACM SIGPLAN Notices. April 1993, 28 (4): 29–38 [2026-04-01]. S2CID 14379260. doi:10.1145/152739.152743. (原始内容存档于2024-04-21).
- ^ Turner, D. A., Some History of Functional Programming Languages (PDF), Lecture Notes in Computer Science 7829, Berlin, Heidelberg: Springer Berlin Heidelberg: 1–20, 2013 [2024-01-28], ISBN 978-3-642-40446-7, doi:10.1007/978-3-642-40447-4_1, (原始内容存档 (PDF)于2020-04-15),
The ISWIM paper also has the first appearance of algebraic type definitions used to define structures. This is done in words, but the sum-of-products idea is clearly there.