software-strategy-book/Ch2-3-SoftwareLanguage.tex

283 lines
39 KiB
TeX
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

世界离不开计算,描述计算离不开程序设计语言。不同的程序设计语言描述不同的计算模式,比如,命令式语言描述以状态的变换作为计算的模式,函数式语言描述以函数作为计算的模式,逻辑语言描述以证明作为计算的模式,而量子语言则描述量子计算的模式。在第\ref{book1-PL}章,我们对众多的程序设计语言进行了比较并回顾了程序设计语言的发展历史,从中我们可以看到,新的程序设计语言的出现通常是为了应对新的计算模式、新兴应用、或者新兴硬件和计算平台的需要。
“软件定义一切”本质上是可编程思想扩张到整个社会和物理世界,是一种以软件实现分层抽象的方式来驾驭复杂性的方法论。随着人机物融合的发展,计算的泛在化成为必然,程序设计语言向下需要对物理世界进行抽象并提供处理物理世界的接口,向上需要能够处理不同场景的多范式的应用编程。泛在计算中不断涌现出的新的计算模式、新的计算平台和新的应用问题给程序设计语言的定义和实现带来了新的机遇和挑战。
首先,新的计算模式需要新的程序设计语言。随着不断涌现的新的计算模式,如适合于抽象描述机器学习的概率计算、神经网络计算、大数据计算、保护隐私的计算等,我们需要新的语言定义和实现技术,快速开发各种各样新的程序设计语言,支持各类新型计算模式。
第二新的硬件和计算平台需要新的语言实现技术。新的硬件如GPU、非易失性内存等和新的计算平台如云、网构等不断涌现。除了设计新的程序设计语言我们还需要研究新的编译技术以生成适合于新的硬件和体系结构的高效代码。
第三,新的应用问题需要新的程序设计语言来高效地解决。随着社会的发展,我们会遇到各种各样的新的复杂的应用问题,除了利用既有程序设计语言开发新的软件之外,我们还可以通过设计更好的程序设计语言来解决这些问题。新型语言不单单提供了描述解决该问题本身的一个方法,而且可以提供解决一类相似问题的方便而可信的一般途径。程序设计语言技术提供给我们解决类似问题的方便而可信的途径。
第四,程序设计语言的发展需要健在的语言生态。程序设计语言的生态,包括支撑环境、集成开发环境、扩展功能支持库、第三方功能模块、帮助文档和知识库、技术交流社区、资源下载网站、教程和培训等。程序设计语言生态的繁荣决定了程序设计语言的繁荣。
在这一章里,我们将从计算的泛在和多样性,计算平台,软件的复杂性和安全性,以及软件的生产效率等几个方面来讨论新时代软件设计语言与支撑环境方面的挑战,列出重要的研究内容,并阐述展示程序设计语言及支撑环境方面的研究趋势。
\section{重大挑战问题}
程序设计语言的挑战问题集中于如何建立、描述和实现抽象。具体来说,其挑战表现在两个方面。首先,在抽象建立和描述方面,主要表现在如何通过对领域和应用问题的抽象,开发有效的领域特定语言(§1.1)、支持多范式程序设计(§1.2),特别是加强大数据时代语言对数据处理的支持(§1.3)。其次,在抽象的实现方面,主要表现在如何开发人机物融合的泛在混合系统的编译技术(§1.4)和构建程序语言的安全性保障机制(§1.5)。
\subsection{面向泛在计算的语言的定制}
随着泛在计算的普及,一方面,专用化的计算设备和运行平台需要软件具备面向不同专用硬件和平台的高效定制能力;另一方面,泛在服务软件需要提供各种特定的编程抽象,支持面向人机物融合的最终用户编程。在泛在计算的环境下,程序员的概念也不断泛化——未来越来越多的人,甚至那些缺乏足够计算机专业知识的领域专家,需要对专用化的设备或特定领域的问题进行程序设计。这就需要我们开发各式各样的领域特定语言。面向泛在的计算为领域特定语言的定义和实现带来了新的挑战。
\begin{itemize}
\item 特定领域语言一般是轻量的,是通用语言的特例。在通用语言的实现已经存在的前提下,我们可以用通用语言的方式来定义和实现领域特定语言。然而,这种方式不仅增加了开发的难度,而且也不经济。我们需要一种高效的特定语言的定义和实现方法。一个想法是设计并实现一种通用语言作为特定语言定义和实现的基础,但是什么样的通用语言适合于定义和实现各类特定领域语言是一个必须解决的问题。
\item 对于通用语言,我们已经开发了不少很有用的程序分析、优化、调试、测试方法。对于特定领域语言,我们需要利用这些方法。尽管我们可以用通用语言来实现某种特定领域语言,但是如何能够将这些一般性的方法系统化地映射到特定语言的实现上是一个挑战。比如,假设我们在通用语言上实现了一个测试方法,但是通用语言上的测试结果对于特定领域语言的用户而言是不能理解的。我们只有将通用语言上的测试例子和结果映射到特定语言程序上,特定领域语言的用户才能理解。
\item 在设计特定领域语言时存在的一个选择是应该设计一个小而精的语言还是设计一个大而全面的语言Schema语言的设计者之一的Guy Steele认为既不应该建立一种小语言也不应该建立一种大语言而需要设计一种可以成长的语言。语言设计应该是增长式的——语言必须从小开始能够随着用户集的增长而增长。例如我们可以比较APL语言和Lisp语言APL不允许用户以“流畅”的方式向该语言添加新的原语premitive)这使得用户难以扩展该语言在Lisp中用户可以定义与语言基元保持一致的单词它使语言用户可以轻松扩展语言并共享代码。为此在设计语言时我们面临的挑战是如何保证其具有一定的韧性支持新的语言构造和特性可以被无缝接入其中同时在语言演化过程中也能保证遗留系统被无障碍地执行。
\end{itemize}
\subsection{多范式程序设计的语言支持}
主流程序设计语言支持不同的程序设计范式。从程序设计语言的角度出发,一方面,需要设计与程序设计语言相适应的程序设计范式或者程序设计模型,以获取程序可读性、模块性、抽象性和性能上的平衡。另一方面,需要提供技术手段,根据程序员能力或者开发任务自动选择或者推荐程序设计范式,提升程序员程序设计效率。然而随着解决的问题越来越复杂,我们需要研究支持多范式的程序设计语言,以及对多范式语言的高效实现机制。特别是,我们面对下面一些挑战。
首先,如何将描述函数计算最直接的函数式程序设计融合到其它语言中是多范式语言设计的一个挑战。函数式程序设计 (Hu, 2015)用函数来抽象计算它的高阶函数和计算的透明性的两个重要特征一方面使函数式语言适用于大数据处理、人工智能等领域但是另一方面也使它不容易与其它语言共用。尽管已有不少关于研究和系统讨论如何融合逻辑语言与函数式语言融合面向目标式语言和函数式语言不少通用程序设计语言C++和Java、Kotlin等也开始支持函数式程序设计但是现在还没有一个公认的计算模型来系统地支持这种融合的设计和实现。如何将函数式语言的高阶函数和计算透明性有效而便捷地扩展至通用程序设计语言及支撑环境以支持函数式程序设计或混合程序设计成为一个值得关注的挑战问题。
其次,无缝融合并发程序设计是多范式语言设计和实现的另一个挑战。目前已经存在很多并发程序设计模型,它们指定了系统中的线程/进程如何通过协作来完成分配给它们的作业——不同的并发模型采用不同的方式拆分任务,线程/进程间的协作和交互方式也不相同。为此需要建立与特定程序设计语言相适应的一组并发模型更好支持程序员设计与实现并发任务。此外传统的并发思维是在单个处理器上使用分时方式或是时间片模型来执行多个任务。如今的并发场景则正好相反是将一个逻辑上的任务放在多个处理器或者多核上执行。因此程序设计语言需要提供足够的机制来分解任务。然而基于目前并发API比如线程、线程池、监视等编写并发程序依然很困难还需要更多关于程序设计语言及实现方面的努力。例如可以由编译器甚至执行引擎识别出程序中可并发的任务以便多核计算机可以将其安全地并发执行。
\subsection{大数据处理的程序语言支持}
当今时代是大数据的时代。全球的数据在不断地增多依赖这些数据对各行各业进行优化是当今社会的发展趋势。大数据呈现出体量巨大数据类型多样数据增长速度快和数据价值密度低的4V特征这就意味着要利用好数据中的价值我们必须依赖于程序以自动化地管理和分析数据从而给程序设计语言带来了一系列全新挑战。
首先,大数据的一个特点是数据类型多样,但不同的人和不同的场合需要的数据是不一样的,这就意味着我们常常需要对数据按不同方式进行组织。数据自主性和数据互操作性给程序语言的设计带来挑战。一方面,当我们按照某一种特定格式获取到数据的时候,需要把数据转换成其他格式保存和展示。另一方面,当我们修改了其中一份数据的时候,需要保证其它保存的数据和展示的视图都能对应修改。如果用传统程序设计语言编写这样的数据同步程序有两方面的问题:(1) 重复的编码工作量大:对于两种数据的同步一般需要编写两份转换程序,但这两份转换程序很多部分是重复的。(2) 很容易出现错误:两份转换程序容易写得不一致。因此,需要新的程序设计语言来处理此类数据管理需求。
其次大数据具有体量巨大、数据增长快的特点。这就意味着要对海量的大数据进行分析不但人工无法完成小型计算机系统通常也无法完成。要完成海量的数据分析往往需要包含多个CPU的大型机系统或者由多个中小型计算机联网形成的集群系统。但是用普通程序设计语言编写这类集群系统上的大数据处理程序非常复杂因为程序员必须处理并行任务分解、多CPU/计算机调度、进程/线程同步等一系列问题。需要新的程序设计语言来降低大数据处理程序的编写难度。尽管MapReduce, Pregel等面向大数据处理的并行计算模型已经提出但是基于这些模型的程序语言要么接近于模型、用户难以使用要么用户容易写但是缺少优化方法、运行效率低。需要新的程序设计语言来解决此类数据计算需求。
最后,大数据具有价值密度低的特点,这就意味着如果要发挥大数据的作用,需要采用合适的方式对数据进行统计。有效的统计方法往往需要我们针对数据的特点构建统计模型,然后根据统计模型对数据进行统计。比如,现在流行的神经网络需要用户首先给出网络结构,然后根据数据确定网络中参数数值。而基于统计学的概率图方法需要先确定随机变量的分布和随机变量之间的依赖关系,然后基于数据确定随机变量的后验分布。这些统计模型的编写较为复杂,同时给定模型之后的统计算法也比较复杂,因此,需要有新的程序设计语言来支持这类模型的描述(如概率编程等)、验证和测试。
\subsection{面向人机物融合的混合编译}
编译器是程序设计语言的重要支撑环境,其负责将一种语言(通常为高级语言)所书写的程序变换成另一种语言(通常为低级语言)程序。编译器的另一个主要功能是对程序进行优化,提升软件的性能。现代软件系统呈现人机物融合的泛在混合特性,对编译技术也带来新的挑战。
首先编译器需要能够快速对应不断出现的专用处理器。摩尔定律的逐渐失效以及大数据处理深度学习等新应用需求的出现正助推计算机行业从通用计算机系统转向一个青睐专用微处理器和专用存储系统等专用硬件的时代。这种转变需要我们研究新的更有效的编译技术。当一个新的硬件出现之后首先应该对专用硬件进行抽象定义一个底层使用该硬件的领域特定语言DSL然后扩充现有的语言为之提供一个高层次的界面以便用户描述专用硬件上的计算最后定义如何将高层次的程序翻译到底层的DSL。为了支持这个过程我们需要研究自动编译技术——我们预测未来的编译器能够在SMT等求解器的帮助下自动生成能在专用处理器上运行的的目标程序通过重写策略对目标程序自动优化且保证编译过程的正确性和代码质量。
其次,编译器需要能够高效地处理混合系统。现在的软件系统越来越复杂,形成了一个混合的系统,需要既能处理离散的又能处理连续的计算,既能处理决定性(逻辑式)的又能处理概率性的计算,既针对命令式的又针对函数式的程序设计语言,既可静态类型检查又可以动态确认程序满足的性质。为了开发这样的复杂的软件系统,混合语言以及相应编译技术变得非常重要。此外,复杂软件系统可能由不同程序设计语言书写的程序组成。对不同程序设计语言所书写的程序进行高效混合编译,也是一个值得关注的研究问题。
\subsection{程序设计语言的安全性保障}
程序设计语言的安全性,体现在两个方面:程序设计语言自身的安全性设计与其支撑环境(如库、编译器、解释器、运行时等)的安全性保障。程序设计语言的设计者和实现者都在不遗余力的提升程序设计语言的安全性。当前,程序设计语言的安全性方面,还存在以下的重大挑战问题。
首先需要建立语言安全性和灵活性、复杂性之间的平衡。程序设计语言的安全性主要体现为程序设计模型中一组机制保障程序员写出安全的程序。例如C++支持的RAII资源获取即初始化通过栈语义保证对象析构函数的自动调用解决了内存泄漏问题类型系统使代码仅能访问被授权可以访问的内存位置脸书公司推出的智能合约语言Move语言不支持动态分配和循环递归依赖等Blackshear2019等。然而语言安全性的提升意味着程序设计灵活性的下降、支撑环境复杂性的提升。为此在设计一门程序设计语言的同时需要定义一组通用的或领域/环境相关的安全机制,包括是否支持指针、自动垃圾回收、异常处理,是否支持强类型检查和中间码验证等,一方面允许程序设计人员编写出既功能强大又足够安全的程序,另一方面在静态编译或者动态执行时实现程序的安全性检查。
其次需要提供充分保障支撑环境可靠性、安全性的分析、测试和验证等技术手段。编译器、虚拟机和执行引擎的代码复杂其中潜伏着包含缺陷或者安全漏洞。如何提升编译器、虚拟机和执行引擎的安全性是一个重要的问题。当前已经出现了经过验证的编译器例如CompCert。此外已经出现了一批针对编译器和虚拟机的测试和安全分析工作例如CSmith、EMI等。尽管如此对编译器包括优化算法及虚拟机等安全性分析、测试、验证工作还面临很多问题我们仍需要能够充分保障编译器、虚拟机和执行引擎的安全性的分析、测试和验证技术手段。例如不可能枚举出一个语言的所有程序实例以对支撑环境进行穷尽测试相反需要提供一套策略协助选择或者自动生成具有代表性的程序实例以高效测试支撑环境的健壮性。特别是针对支撑环境进行广泛测试针对各类编译技术和算法如优化算法和垃圾回收算法进行正确性验证及验证应用程序接口的正确性仍然是这个方向上的难点问题。此外在程序设计语言动态演化过程中需要提供足够的技术手段保障语言新特性和支撑环境新功能可以被可靠地、安全地加入至既有语言和支撑环境中。
\tikzstyle{every node}=[draw=black,thick,anchor=west]
\tikzstyle{selected}=[draw=red,fill=red!30]
\tikzstyle{optional}=[dashed,fill=gray!50]
\begin{figure}
\begin{tikzpicture}[%
grow via three points={one child at (0.5,-0.65) and
two children at (0.5,-0.65) and (0.5,-1.3)},
edge from parent path={(\tikzparentnode.south) |- (\tikzchildnode.west)}]
\node{程序设计语言主要研究内容}
child {node{语言设计}
child {node {传统语言设计}
child {node {类型系统}}
child {node {语言定义}}
child {node {内存模型}}
}
child [missing] {}
child [missing] {}
child [missing] {}
child {node {新型语言设计}
child {node {泛在计算}
child {node {\it 软件定义网络的程序设计语言}}
child {node {软件定义内存的程序设计语言}}
child {node {\it 离散和连续混成系统的语言}}
child {node {\it 支持共享内存模型的并发程序设计}}
}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child {node {大数据处理}
child {node {\it 面向数据管理统计的程序设计语言}}
}
child [missing] {}
child {node {人机物融合}
child {node {\it 支持最终用户编程的程序设计语言}}
}
child [missing] {}
child {node {多范式程序设计}
child {node {\it 多范式和领域特定的程序设计语言}}
}
child [missing] {}
}
}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child {node {语言实现和支撑环境}
child {node {编译器设计与实现}}
child {node {程序分析与验证}}
child {node {程序综合与精化}}
child {node {\it 程序设计开发环境}}
child {node {\it 离散和连续混成系统的语言支撑工具}}
}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child [missing] {}
child {node {语言生态}
child {node {\it 程序设计框架和库}}
child {node {\it 特定领域语言的元编程和开发环境}}
child {node {\it 程序设计语言的生态及其演化规律}}
}
;
% child {node {E}
% child {node {``value''}}
% };
\end{tikzpicture}
\caption{程序设计语言主要研究内容\label{fig:ProgrammingLanguages}}
\end{figure}
\section{主要研究内容}
为了应对上述重大挑战,需要在多方面开展研究。首先,为了支持泛在计算(§2.1.1)、大数据处理(§2.1.3)、和人机物融合(§2.1.4)等多种新型应用场景,需要研究面向不同领域的编程语言,包括面向数据管理统计的程序设计语言(§2.2.2)、面向软件定义网络的程序设计语言(§2.2.3)、支持最终用户编程的程序设计语言(§2.2.6)。其次,为了设计面向泛在计算的语言(§2.1.1)和实现多范式程序设计支持(§2.1.2),需要研究多范式和领域特定的程序设计语言(§2.2.1)、离散和连续混成系统的语言和工具(§2.2.4)以及支持共享内存模型的并发程序设计(§2.2.5)。最后,为了支持新语言所带来的开发环境和生态的变化,我们需要研究程序设计框架和程序设计开发环境(§2.2.7)、特定领域语言的元编程和开发环境(§2.2.8)、程序设计语言的生态及其演化规律(§2.2.9)。
\subsection{多范式和领域特定的程序设计语言}
主流程序设计语言都支持多种程序设计范式。一方面需要研究如何设计程序设计语言所支持的范式乃至于库、编程框架等,以助于程序员更便捷地编写大型应用。另一方面,需要研究如何根据程序员能力或者开发任务自动选择或者推荐程序设计范式,以提升程序员程序设计效率。此外,也需要对多范式程序设计语言的支撑环境(含编译、编译时和运行时优化、内存管理、多线程处理、垃圾回收等)及其程序分析、验证技术进行研究——在一门程序设计语言中引入新的程序设计范式,往往需要很多工业界和学术界的努力,避免支撑环境的复杂性、分析及验证技术难度的急剧上升。
随着专用处理器等硬件的不断出现以及各种特定应用领域软件开发的需求领域特定语言的开发变得非常重要。领域特定语言既向下提供特定平台的编程模型也向上提供具体应用场景的需求描述方法。尽管我们可以使用一般的程序语言的设计方法和编译技术但是这样开发效率低。我们应该开发在通用语言的基础上实现领域特定语言的技术。主要研究内容包括1如何在用户的DSL上来表示运行时和编译时的错误2如何自动生成测试用例直接测试DSL程序3如何将深度嵌入和浅嵌入的领域特定语言的定义方法结合起来。
\subsection{面向数据管理统计的程序设计语言}
数据在我们的生活中无处不在。在一个医疗保健系统中,医院、药房、患者都有各自的数据,为了保护隐私,这些数据没有被集中统一管理,而是以一种非中心的方式分散在不同的系统中。如何安全地共享和交换信息从而实现非中心数据的互操作成为现代社会亟需解决的一个重要问题。为了解决这个问题,需要将非中心数据的互操作问题分解为(1)局部的隐私控制问题、(2)全局的数据同步问题、(3)联系局部和全局的软件体系结构问题。每个问题的解决都需要我们设计好的程序设计语言,从而实现一个高可信且可扩展的非中心数据的互操作系统。目前,研究人员提出的双向变换语言(Czarnecki,2009)能够保证两种数据的一致性,为部分解决数据的互操作提供一个好的解决方案,值得进一步深入研究。
解决数据统计问题的途径是设计程序设计语言来编写统计模型。目前的统计模型语言主要包括两类。一类是支持神经网络编写的语言代表语言包括TensorFlow(Abadi, 2016)、PyTorch(Paszke, 2017)等。神经网络要求构造出一个网络结构同时网络上的所有运算都要是能求导的。神经网络的程序设计语言通过限定程序中的运算必须是由可求导的操作构成来保证网络是可以求导的并利用微积分中的求导算法自动求导来完成网络的训练。此外神经网络语言通常包括大数据分析语言的功能可以将运算分配到多个CPU或者多台计算机上应对大数据程序的运算量要求。另一类是概率程序设计语言代表语言包括Stan (Carpenter, 2017)、PyMC (Patil, 2010)等。概率程序设计语言主要用于编写一个概率模型,包括随机变量、随机变量的分布和相互关系等,允许程序员指定一些模型上的观察值,通过贝叶斯统计来对模型其他部分的随机变量计算后验分布。概率程序设计语言通常提供一系列分析算法和采样算法用于求解和近似求解模型,同时部分语言也提供并行计算能力,以支持用于在大型机/集群系统上快速求解。
\subsection{面向软件定义网络的程序设计语言}
传统网络设施的网络协议都固定在芯片中一旦制造出来就不可能支持新的网络协议。为了解决这个问题软件定义的网络设备把控制器制作成可以程序设计的开关电路允许通过软件控制开关来实现不同的协议。最基础的软件定义网络程序设计语言是Openflow(McKeown, 2008)该语言用于直接控制网络硬件中的开关。由于直接程序设计控制开关较为困难研究人员又进一步提出了高层的程序设计语言其代表语言为NetKat语言(Anderson, 2014)和P4语言(Bosshart, 2014)NetKat语言主要从控制角度看待网络协议允许程序员采用类似普通函数语言的方式来声明函数和函数的组合然后该语言的编译器负责将这种高层声明转换成Openflow上的开关控制P4语言主要从数据角度看待网络协议通过数据格式和对应数据项上的操作来描述网络协议。然而程序设计人员在编写应用的时候仍需要使用一组与新型硬件相关的库函数这极大程度地影响了既有系统在新型硬件上的运行或者迁移。这里值得关注的研究内容包括1定义高层次的、具有更强表达能力的网络定义语言2通过修改底层支撑环境包含操作系统、编译器、执行引擎、库等支持既有系统在编译或者执行过程中主动支持新型硬件的使用。
\subsection{离散和连续混成系统的语言和工具}
混成系统是由离散和连续的多个子系统组合而成的混合模型。尽管近年来已有很多处理混成系统的语言和系统工具每个语言和工具对环境做出不同的假设导致混成系统难以在不同的语言和工具之间共享信息。因此需要解决混合系统中各个子系统的一致性问题从而最大限度地利用现有的语言和工具。主要研究内容包括1审阅和比较现有混成系统语言和工具的语义、表达能力和数学机制发掘它们的差异2设计一种语义感知的交换格式便于描述不同语言间的语义变换交叉语义3设计一个描述混成系统的统一的描述语言并开发相应的实现和验证技术。
\subsection{支持共享内存模型的并发程序设计}
由于处理器和编译器对程序的优化大多数处理器和程序设计语言如C++或Java无法提供理想化的顺序一致性sequential consistency内存模型。近年来对内存一致性模型的形式化定义成为研究的热点包括对处理器如x86、Arm、Power等和并发程序设计语言如C++和Java等的内存模型的设计与实现等。然而现有程序设计语言的内存模型仍然存在较多问题。Java和C++的内存模型仍然过于复杂且允许程序产生违背直观的行为特别是跟程序逻辑完全无关的行为即所谓的out-of-thin-air行为简写为OOTA。因此这些内存模型还有待改进。另一方面经典的并发验证逻辑和既有分析、测试、验证工具无法直接应用于弱内存模型程序我们需要新的理论和工具支持。针对以上不足我们需要解决以下问题1改良现有的程序设计语言中的内存模型避免内存模型中的OOTA行为2基于改良后的内存模型给出新型的并发程序验证、分析、测试的技术保证弱内存模型下的并发程序编译及执行的正确性。
\subsection{支持最终用户编程的程序设计语言}
最终用户程序设计主要涉及两条研究路线。一条路线是从教育的角度出发把现有程序设计语言中的概念用更简单直观的图形化方式表达出来使得没有学过程序设计的人也能很快熟悉和掌握。这其中的代表语言就是Scratch(Resnick, 2009)。Scratch采用类似程序流程图的方式表达顺序、选择、循环等概念使得没有接受过计算机教育的儿童和老人也可以通过简单拖动鼠标就能完成想要的程序。目前Scratch已经广泛用于儿童教育中用于培养儿童的计算思维。此外一些智能家居和智能机器人设备也引入了类似的语言来进行简单的程序设计。为此在设计此类语言的时候需要设计一组被最终用户所能接受和使用的语言构造并由相关支撑环境实现将用户设计的程序“编译”为可以被具体执行的程序。另一方面这类面向最终用户的程序设计语言一般都比较简单。且最终用户在程序设计时经常出错。如何能提升此类程序设计语言的表达及容错能力将成为一个值得研究的问题。
最终用户程序设计的另一条路线是针对特定领域让用户用最自然的方式表达需求同时用程序综合的方式来完成程序的构造。这方面的一个典型例子是Excel。Excel从2017起引入了基于样例的程序合成方法(Polozov, 2015)该方法允许用户对于一列或一行单元格中的几个数据提供计算结果的样例然后Excel自动根据样例推测出用户想要撰写的程序并自动填充其它单元格数据。然而上述基于样例的程序合成方法并不适合很多应用场景。我们需要研究更多适用于不同应用场景和不同用户级别的需求表达方式以及将这些需求转换成程序的方法。
最终用户程序设计的一个重要应用领域是应对面向人机物融合的大趋势为最终用户提供控制网络上设备的编程方式。目前在这个方向上已经有一些典型的应用包括为智能家居的物联网设备编程。比如IFTTT采用了IF语句作为基础编程单元主要表达不同条件满足的时候设备应该采用的动作。很多主流的智能家居企业比如小米、华为都采用了这种编程模型。但目前编程模型的能力还有较大局限性一些需求无法完全表达同时在程序变得比较复杂的时候基于IFTTT的编程方式也容易带来预期之外的交互引起较难调试的问题。
\subsection{程序设计框架和程序设计开发环境}
程序设计语言与编程环境、程序设计框架、程序设计工具需要协同发展。近几十年来程序设计的努力主要体现在框架及工具等方面。例如.NET Framework里有超过一万个类及十万个方法现有的编译器和解释器之间的界限越来越模糊。类似的现在的IDE包含了无数强大的功能例如语法提示重构调试器等。上述程序设计框架、工具等支撑着高层语言的普及和使用。因此需要设计与开发与程序设计语言相匹配的程序设计框架和程序设计环境支撑多范式程序设计并集成程序搜索、推荐、自动修复等功能以支持程序员轻易地开发出更强大的应用。
\subsection{特定领域语言的元编程和开发环境}
程序设计语言方面另一个研究内容是构建支持特定领域语言的定义和实现的开发环境。这个环境需支持高效而正确地设计和实现众多的领域特定语言抓住不同领域的计算特征便于领域专家使用。同时为了高效组合不同领域的计算特征需要构建“面向语言”的程序设计环境。面向语言的程序设计明确鼓励开发人员构建自己的领域特定语言或者将具有特定领域概念的现有语言作为方法的一部分进行扩展。利用这个环境程序员在软件开发时不是只使用一种语言而是使用最适合每项任务的语言然后把它们有机组合在一起。例如MPS (Meta Programming System) 等语言工作台是面向语言方法的重要组成部分。使用MPS可以为任何新语言定义编辑器使得领域特定语言的使用更简便。即使是不熟悉传统程序设计的领域专家也可以在MPS中使用领域特定语言。
\subsection{程序设计语言的生态及其演化规律}
程序设计语言的流行与发展,离不开其生态的繁荣与发展。生态,包括支撑环境、集成开发环境、扩展功能支持库、第三方功能模块、帮助文档和知识库、技术交流社区、资源下载网站、教程和培训等,提供了对程序设计语言更广泛的支持。然而,针对程序设计语言生态的研究还不多。仍需要对程序设计语言生态进行大量研究,研究如何定义/描述一个程序设计语言及其生态系统,以及研究如何将一个既有项目从一个语言生态迁移至另一个语言生态等。此外,需要分析生态系统的利益相关者及生态中蕴含的海量知识/数据等,以更好发现程序设计语言与生态、利益相关者的伴生、共同演化与发展的规律。
由于工业界、研究者的努力程序设计语言将处于持续演化中主要演化方向是使语言变得更简单、更完善、更强大、更安全、更易学和使用。然而仍需要进一步探索程序设计语言的演化规律理解、分析并利用程序设计语言演化的驱动力探索可能的演化方向推动程序设计语言进一步发展。首先需要归纳、总结程序设计语言中出现的、程序设计人员更主动采纳的新特性、新机制。例如如何设计一系列“语法糖”帮助程序设计人员更便捷地书写程序如何从语言角度设计模板使得模板的编写变得更简单和容易理解如何使程序员更容易使用容器和算法且更容易组合算法等如何通过语言来简化异步程序的编写等。此外程序设计语言的演化也会导致支撑环境性能的提升。例如利用模块以加快编译速度利用反射以提供强大的编译期AST元数据查询能力利用即时编译JIT编译器以省下了解释器的开销等等。这里语言的演化更需要得到编程支撑环境方面的支持。
\section{本章小结}
如果说软件是社会的基础,那么程序设计语言就是软件的核心。泛在计算促使我们设计各式各样的满足某种性质的领域特定程序设计语言,研究语言随着时间和环境的改变而变化的演化和生长机制,并开发一个全新的“基于语言”的软件设计方法和支撑环境。在这一章里,我们指出了新时代程序设计语言的几个挑战性问题,有些问题并不是新的,但是它们被赋予新的内涵。作为参考,我们也列出了一些重要的研究内容,希望能够通过这些具体研究来迎接这些挑战。
\section*{参考文献}
[1] Kreutz D, Ramos F M V, Esteves Verissimo P, et al. Software-Defined Networking: A Comprehensive Survey. Proceedings of the IEEE, 2014, 103(1):10-13.
[2] Thereska, E., Ballani, H., O'Shea, G., Karagiannis, T., Rowstron, A., Talpey, T., ... \& Zhu, T. (2013, November). IOFlow: a software-defined storage architecture. Proceedings of the Twenty-Fourth ACM Symposium on Operating Systems Principles (pp. 182-196). ACM.
[3] Ouyang J, Chu C W, Szmanda C R, et al. Programmable polymer thin film and non-volatile memory device[J]. Nature materials, 2004, 3(12): 918
[4] Jain S, Kumar A, Mandal S, et al. B4: Experience with a globally-deployed software defined WAN. ACM SIGCOMM Computer Communication Review. ACM, 2013, 43(4): 3-14.
[5] McKeown N, Anderson T, Balakrishnan H, et al. OpenFlow: enabling innovation in campus networks. ACM SIGCOMM Computer Communication Review, 2008, 38(2): 69-74.
[6] Czarnecki K, Foster J N, Hu Z, et al. Bidirectional transformations: A cross-discipline perspective. International Conference on Theory and Practice of Model Transformations. Springer, Berlin, Heidelberg, 2009: 260-283.
[7] Shvachko K, Kuang H, Radia S, et al. The hadoop distributed file systemMSST. 2010, 10: 1-10.
[8] Hu Z, Hughes J, Wang M. How functional programming mattered, National Science Review, Oxford Journal, 2015, 2(3):349-270.
[9] Zaharia M, Chowdhury M, Franklin M J, et al. Spark: Cluster computing with working sets. HotCloud, 2010, 10(10-10): 95.
[10] Kyrola A, Blelloch G, Guestrin C. GraphChi: Large-Scale Graph Computation on Just a PC, Presented as part of the 10th USENIX Symposium on Operating Systems Design and Implementation (OSDI 12). 2012: 31-46.
[11] Abadi M, Barham P, Chen J, et al. Tensorflow: A system for large-scale machine learning, 12th USENIX
Symposium on Operating Systems Design and Implementation (OSDI 16). 2016: 265-283.
[12] Paszke A, Gross S, Chintala S, et al. Automatic differentiation in pytorch. 2017.
[13] Carpenter B, Gelman A, Hoffman M D, et al. Stan: A probabilistic programming language. Journal of statistical software, 2017, 76(1).
[14] Patil A, Huard D, Fonnesbeck C J. PyMC: Bayesian stochastic modelling in Python. Journal of statistical software, 2010, 35(4): 1.
[15] Anderson C J, Foster N, Guha A, et al. NetKAT: Semantic foundations for networks. Acm sigplan notices, 2014, 49(1): 113-126.
[16] Bosshart P, Daly D, Gibb G, et al. P4: Programming protocol-independent packet processors. ACM SIGCOMM Computer Communication Review, 2014, 44(3): 87-95.
[17] Resnick M, Maloney J, Monroy-Hernández A, et al. Scratch: Programming for all. Commun. ACM, 2009, 52(11): 60-67.
[18] Polozov O, Gulwani S. FlashMeta: A framework for inductive program synthesis. ACM SIGPLAN Notices. ACM, 2015, 50(10): 107-126.
[19] Yuting Chen, Ting Su, Chengnian Sun, Zhendong Su, Jianjun Zhao: Coverage-directed differential testing of JVM implementations. PLDI 2016: 85-99
[20] Junjie Wang, Bihuan Chen, Lei Wei, Yang Liu: Skyfire: Data-Driven Seed Generation for Fuzzing. IEEE Symposium on Security and Privacy 2017: 579-594
[21] Xuejun Yang, Yang Chen, Eric Eide, John Regehr: Finding and understanding bugs in C compilers. PLDI 2011: 283-294
[22] Vu Le, Mehrdad Afshari, Zhendong Su: Compiler validation via equivalence modulo inputs. PLDI 2014: 216-226
[23] Junjie Chen, Yanwei Bai, Dan Hao, Yingfei Xiong, Hongyu Zhang, Bing Xie: Learning to prioritize test programs for compiler testing. ICSE 2017: 700-711
[24] Rody Kersten, Kasper Søe Luckow, Corina S. Pasareanu: POSTER: AFL-based Fuzzing for Java with Kelinci. ACM Conference on Computer and Communications Security 2017: 2511-2513
[25] Zeyu Sun, Qihao Zhu, Lili Mou, Yingfei Xiong, Ge Li, Lu Zhang: A Grammar-Based Structural CNN Decoder for Code Generation. CoRR abs/1811.06837 (2018)
[26] Sam Blackshear, Evan Cheng, David L. Dill, Victor Gao, Ben Maurer, Todd Nowacki, Alistair Pott, Shaz Qadeer, Rain, Dario Russi, Stephane Sezer, Tim Zakian, Runtian Zhou: Move: A Language With Programmable Resources. https://developers.libra.org/docs/assets/papers/libra-move-a-language-with-programmable-resources.pdf (2019)