Vehicles on Mars autonomously self-regulate, plan, and navigate using software packaged up in millions of lines of C. Now, if hardware limitations were not a concern, what language would you choose to write the logic, decision-flow, and reasoning for an extraterrestrial robot?
火星上的车辆使用数百万行C中打包的软件自动进行自我调节,计划和导航。 现在,如果不考虑硬件限制,那么您会选择哪种语言来编写外星机器人的逻辑,决策流程和推理?
Some prefer the brevity of Python, while others appreciate the robustness of Rust, but picking a language for a project has deep consequences. Just ask any linguist:
有些人喜欢Python的简洁性,而另一些人则喜欢Rust的健壮性,但是为项目选择语言会带来深远的影响。 只需询问任何语言学家 :
"Language shapes the way we think, and determines what we can think about."
语言决定了我们的思考方式,并决定了我们可以考虑的内容。”
"The limits of my language mean the limits of my world."
“我语言的局限意味着我世界的局限。”
"A language that doesn’t affect the way you think about programming, is not worth knowing."
“不影响您对编程的思考方式的语言是不值得了解的。”
There's no one-size-fits-all when it comes to programming languages, so it's worth expanding our horizon by studying what's out there.
关于编程语言,没有万能的,所以值得研究现有内容,以扩大我们的视野。
Categorizing the thousands of programming languages that exist is no easy task, but software trends over the years have revealed two sovereign frameworks: imperative (object-oriented) and declarative (functional) languages.
对现有的数千种编程语言进行分类并不是一件容易的事,但是多年来的软件趋势已经揭示了两个主要框架:命令式(面向对象)和声明式(功能)语言。
Imperative: The programmer defines how to perform algorithms and how memory is accessed. Examples include C++, JavaScript, and Python.
当务之急 : 程序员定义了如何执行算法以及如何访问存储器。 示例包括C ++,JavaScript和Python。
Declarative: The programmer defines the composition of functions, and lets the run-time optimize algorithms. Examples include Haskell, Erlang, and OCaml.
陈述式 : 程序员定义函数的组成,并让运行时优化算法。 示例包括Haskell,Erlang和OCaml。
A classic way to describe the distinction between declarative and imperative programming is that declarative languages let the programmer describe what to do, whereas imperative languages let the programmer define how to do it.
描述声明和必要的程序之间的区别经典的方式是声明性语言让程序员描述做什么 ,而命令式语言让程序员定义如何做到这一点。
If we extend this idea to a third type of language that lets the programmer define why choices are made, then we have discovered task-oriented programming languages.
如果我们将这种想法扩展到第三种语言,这种语言可以让程序员定义为什么做出选择,那么我们已经发现了面向任务的编程语言。
Task-oriented: The programmer defines desired states, and lets the runtime resolve the composition of actions. Examples include DMPL, PDDL, and DTProbLog.
面向任务 : 程序员定义所需的状态,并让运行时解析动作的组成。 示例包括DMPL,PDDL和DTProbLog。
The figure below summarizes these paradigms with glorious details about how languages have influenced each other over the years. The types of languages are all over the place, and it all started less than a century ago!
下图总结了这些范例,并详细介绍了这些年来语言如何相互影响。 语言的类型无处不在,并且都始于不到一个世纪前!
Task-oriented languages bring a new perspective to the way we think about code. In this article, we'll cover exactly what the means.
面向任务的语言为我们思考代码的方式带来了新的视角。 在本文中,我们将确切介绍其含义。
The following section below distills what makes some languages so popular today (and why popularity may not be a good indicator for choosing one language over another).
以下部分摘录了今天使某些语言如此流行的原因(以及为什么流行可能不是选择一种语言而不是另一种语言的一个很好的指标)。
The subsequent section walks through implementing an algorithm in the different paradigms.
下一节将介绍如何在不同的范例中实现算法。
We then conclude with a discussion on what each paradigm does exceptionally well.
然后,我们讨论每种范例的出色表现。
为什么要坚持使用语言? (Why stick with a language?)
Of the thousands of programming languages out there, you may be wondering what sets your favorite language apart from a freshly minted one. Typically, what locks developers in is a combination of the following factors:
在成千上万种编程语言中,您可能想知道是什么让您最喜欢的语言与新鲜出炉的语言不同。 通常,锁定开发人员的是以下因素的组合:
APIs/frameworks: Sometimes you just really need to use a library that's not widely available in many languages. OpenCV, for example, is a computer vision library that pairs exceptionally well with C++ or Python, but has limited support for some other languages, such as Elixir.
API /框架:有时候,您实际上只需要使用在许多语言中都没有广泛使用的库即可。 例如,OpenCV是一种计算机视觉库,可与C ++或Python配对得很好,但对某些其他语言(例如Elixir)的支持有限。
Learning curve: Some languages take years of study to master, such as Haskell, whereas other languages like Python let you stumble upon desired behaviors through trial and error.
学习曲线:有些语言(例如Haskell)需要多年的学习才能掌握,而其他语言(例如Python)则允许您通过反复试验偶然发现所需的行为。
Documentation: Older languages, like C, typically have mature documentation due to years of refinement. However, newer languages may rapidly outgrow their original specs before they reach stability.
文档:由于经过多年的改进,较旧的语言(如C)通常具有成熟的文档。 但是,较新的语言在达到稳定之前可能会Swift超出其原始规格。
Community: Stack Overflow, for example, gives you the peace of mind that you're not alone in solving some of your hardest programming challenges. Newer languages may not have an established community, so sometimes you're on your own.
社区:例如,Stack Overflow使您放心,您并不孤单地解决一些最困难的编程挑战。 较新的语言可能没有建立的社区,因此有时您是一个人。
Performance: C/C++ are languages that compile to machine code and perform certain algorithms more efficiently than higher-level interpreted languages such as JavaScript.
性能: C / C ++是可编译为机器代码并比高级解释型语言(例如JavaScript)更有效地执行某些算法的语言。
Elegance: If you're truly a romantic, then the syntax and philosophy of the language may play a key factor in why you've chosen to stick with a language.
优雅:如果您确实是个浪漫主义者,那么该语言的语法和哲学可能会成为您选择坚持使用某种语言的关键因素。
Robustness: Type safety, informative error messages, and intuitive memory management are all aspects of languages that relieve the programmer from worrying about anything but the task at hand.
健壮性:类型安全,信息错误消息和直观的内存管理都是语言的所有方面,这些语言可以使程序员不必担心手头的任务。
Legacy: Sometimes the argument of "it's always been done that way" tends to be reason alone to keep up a tradition.
遗留问题:有时“总是以这种方式完成”的论点往往仅是保持传统的理由。
Indeed, imperative languages are no doubt the most popular in industry (see chart below), perhaps because those languages have successfully satisfied most of the above criteria. However, you've read up to this point in this article already, so I bet you're game to try something new.
确实,命令性语言无疑是业界最受欢迎的语言(请参见下表),这也许是因为这些语言已成功满足了上述大多数标准。 但是,您已经在本文中读到了这一点,所以我敢打赌,您正在尝试新的尝试。
We're about to dive into a couple concrete examples, so hold on tight, buckle your seat belts, and please keep your arms within the vehicle.
我们将深入探讨几个具体示例,因此请紧紧握紧安全带并扣紧安全带,然后将手臂保持在车内。
比较语言 (Comparing languages)
Suppose you'd like to write an algorithm for a Mars rover that intelligently sends back video recordings to mission control on Earth. There's no high speed fiber-optic connection between the planets, so the order in which videos are sent really matters.
假设您想编写一个火星探测器的算法,该算法可以智能地将视频记录发送回地球上的任务控制系统。 行星之间没有高速光纤连接,因此视频的发送顺序确实很重要。
The list of video recordings may be defined as follows:
录像列表可以定义如下:
Let's say mission control is only interested in retrieving videos that run shorter than 20 minutes, so you'd like to write out an algorithm that sequences videos accordingly. In the next few sections, we'll see how different language paradigms might implement this simple task.
假设任务控制仅对检索运行时间少于20分钟的视频感兴趣,因此您想编写一种算法来对视频进行相应的排序。 在接下来的几节中,我们将看到不同的语言范例如何实现此简单任务。
强制执行 (Imperative implementation)
If a for
loop through the videos
array is your first instinct, then you're thinking like an imperative programmer. For example, you may want to use an if
statement within the loop to selectively append videos that are shorter than 20 minutes to a queue, as shown below:
如果通过videos
数组for
循环是您的第一个本能,那么您就像在当急程序员一样。 例如,您可能想在循环中使用if
语句,以将少于20分钟的视频有选择地追加到队列中,如下所示:
The variables queue
and i
are declared with initial values of []
and 0
, respectively. Then the rest of the code specifies how to update the variables.
变量queue
和i
分别以[]
和0
初始值声明。 然后,其余代码指定如何更新变量。
功能实现 (Functional implementation)
Functional programmers smirk, and present us with an elegant one-liner:
函数式程序员会傻笑,并向我们展示一种优雅的单行代码:
Here, filter
is a function that reduces an array based on a predicate. The focus is no longer about how variables get updated through an algorithm, but instead about what data transformations need to occur to produce the desired result.
在此, filter
是一种基于谓词来简化数组的函数。 重点不再是如何通过算法更新变量,而是要发生什么数据转换才能产生所需的结果。
面向任务的实施 (Task-oriented implementation)
In task-oriented languages, you define the goal and possible actions. The goal, in our case, is to pick videos that are shorter than 20 minutes.
在面向任务的语言中,您可以定义目标和可能采取的措施。 在我们的案例中,目标是选择短于20分钟的视频。
One way to author goals is by listing situations in order of preference, such as [{minutes: 10}, {minutes: 40}]
, which declares that minutes == 10
is more favorable than minutes == 40
.
制定目标的一种方法是按优先顺序列出情况,例如[{minutes: 10}, {minutes: 40}]
,它声明minutes == 10
比minutes == 40
更有利。
The action is to select a video from the videos
list. We do so using the fork
statement, which is a generalized if
statement. Traditional if
statements execute the first satisfying entry condition, but fork
statements consider all satisfying entry-conditions, and choose the one that best characterizes our preferences by searching (for example depth-first search) forwards in time.
该操作是从videos
列表中选择一个视频。 我们使用fork
语句(这是广义的if
语句)来执行此操作。 传统的if
语句执行第一个满足条件的输入条件,但是fork
语句考虑所有满足条件的输入条件,并通过及时搜索(例如深度优先搜索)选择最能体现我们偏好的条件。
The programmer lists the candidate choices, and lets the run-time resolve the best possible path to take. That way, some of the cognitive-load of defining system behavior is offloaded from the programmer.
程序员列出了候选选项,然后让运行时解决可能的最佳选择。 这样,定义系统行为的一些认知负担就从程序员那里分担了。
The run-time of the language resolves forks by picking a candidate block that will increase the situation's utility. In this case, the run-time will select videos of shorter duration.
该语言的运行时通过选择一个候选块来解决派生问题,这将增加情况的实用性。 在这种情况下,运行时将选择持续时间较短的视频。
了解每个范例的力量 (Understanding the power of each paradigm)
Let's face it, in order for code to stay relevant, it needs to be continuously maintained. Refactoring, enhancing, and scaling can get a bit scary at times. That's why each of the three paradigms champion their own mechanisms for dealing with changing requirements.
让我们面对现实,为了使代码保持相关性,需要不断对其进行维护。 重构,增强和扩展有时会有些令人恐惧。 因此,这三种范式都拥护自己的机制来应对不断变化的需求。
Object-oriented design in imperative languages: Instead of directly accessing data, the programmer defines interfaces, which hide the implementation details of how the data changes. That way, you can plug and play these objects with new problems, without needing to overwhelm yourself with all the minor details.
命令式语言中的面向对象设计 :程序员定义了接口,而不是直接访问数据,这些接口隐藏了数据更改方式的实现细节。 这样,您可以插入并播放具有新问题的这些对象 ,而无需让所有次要细节不知所措。
Pure functions in functional languages: A pure function is slightly like a look-up table (like a dictionary or map). It guarantees that no matter how the software evolves, the pure function will not accidentally update variables beyond its scope. Chaining pure functions together creates more complex functions that remain pure, letting you refactor easily without worrying about global variables.
在功能性的语言纯功能 :纯函数是略微像查找表(如字典或地图)。 它保证无论软件如何发展,纯函数都不会意外地更新超出其范围的变量。 将纯函数链接在一起将创建更复杂的函数,这些函数保持纯函数,使您可以轻松进行重构,而不必担心全局变量。
Tasks in task-oriented languages: Tasks let you explain a desired behavior without needing to detail out a concrete plan. For example, defining what one may want for dinner is different from writing a recipe to outline the precise steps in the kitchen. The run-time of the language is responsible for assembling instructions that achieve the task, whereas the programmer is responsible for carefully defining the desirable states.
任务在任务型语言:任务让你解释一个期望的行为,而不需要进行详细具体的计划。 例如,定义一个人可能想要吃晚饭不同于编写食谱来概述厨房中的精确步骤。 语言的运行时负责汇编完成任务的指令,而程序员负责仔细定义所需的状态。
For instance, in our Mars rover example, let's say the requirements have changed: mission control now wants to only retrieve videos with anomalies. Consider how you would rewrite the imperative, functional, and task-oriented code.
例如,在我们的火星漫游车示例中,假设要求已更改:任务控制现在只希望检索出现异常的视频。 考虑如何重写命令性,功能性和面向任务的代码。
I'll let you think about the first two, but in task-oriented languages, simply change the goal to change program behavior:
我让您考虑一下前两个,但是在面向任务的语言中,只需更改目标即可更改程序行为:
As systems mature in complexity, task-oriented languages unveil powerful abstractions that allow programmers to scale and alter the behavior of their systems more efficiently. The programmer focuses on defining the why, whereas the run-time composes the how. This explicit decoupling of goals from actions helps alleviate software failure due to unforeseen edge-cases.
随着系统的复杂性日趋成熟,面向任务的语言揭示了强大的抽象概念,使程序员可以更有效地扩展和更改其系统行为。 程序员专注于定义why ,而运行时则编写how 。 目标与操作的明确脱钩有助于减轻由于意外情况导致的软件故障。
These task-oriented languages may one day be the de facto standard for authoring the behavior of video-game agents (NPCs), industrial robots, chat-bots, or any decision-making system. The technical maturity of programming language design hasn't even reached its adolescence – for example, compared to the history of the automobile, we haven't even made it to the Ford Model T. Now's the time for the adventurous to uncover new fundamental software principles.
这些面向任务的语言有一天可能成为创作视频游戏代理(NPC),工业机器人,聊天机器人或任何决策系统的行为的事实上的标准。 编程语言设计的技术成熟度甚至还没有达到青春期–例如,与汽车的历史相比,我们甚至还没有涉足福特T型车。现在正是冒险探索新的基础软件的时候原则。
If you would like to try out DMPL, join the W3C Conversational Interfaces Community Group, and follow @binroot for more announcements, news, and discussion.
如果您想试用DMPL ,请加入W3C对话界面社区小组,并关注@binroot以获取更多公告,新闻和讨论。