关于编译器构造:您自己的编程语言是什么样的?

What would your own programming language look like?

您自己的(我假设是完美的)编程语言是什么样子的?举个小例子,解释一下你的新想法!

我对句法很感兴趣。


有点神秘,但这就是我想要的:

Legos!


乔恩说的对,"不同的任务适合不同的语言和范例。"然而,有一些考虑基本上独立于这个领域。这些大多与语法有关,但由于代码的阅读频率高于编写频率,所以我实际上认为语法很重要。

首先,许多语言都会出错,把语法从C.C.中去掉是完全随意的,实际上它的语法非常糟糕。我只举两个例子。

第一个是完全无争议的:分号是不必要的。采用下面的代码;语法完全不含糊,易于编译器分析。分号和显式行继续都不是必需的。

1
2
3
4
5
6
7
answer = 42
fraction = answer * 2 /
           (answer + 1)
Console.WriteLine(
   "Some funny number: {0}",
    fraction
)

这实际上与python非常相似,但更为宽松:fraction的定义跨越多行。这是合乎逻辑的,因为第一行尚未完成。

我要用C类语法挑选的另一个要点是它们的隐式变量声明。而不是明确宣布"我要宣布一个Foo类型的variable",他们都害羞地低语是"Foo var"。由于在大多数情况下,Foo甚至不是一个保留字,因此程序员在这里没有提供任何可视提示。我更喜欢vb的显式Dim var As Foo,甚至认为这里使用的关键字非常模糊。

(C++实际上使事情变得更糟,更糟的是,引入了许多几乎相同且通常含糊不清的语法,这意味着完全不同的事情,从变量初始化到函数声明)。

我的语言还需要静态输入。确实,动态类型有它的用途,但它们却非常罕见。即使是大多数"脚本语言"也不会真正需要它们。我认为这经常与隐式类型混淆,隐式类型有更多的用途。再举一次Python的例子。为什么不提供静态类型?它已经是强类型的,静态类型检查只会导致结果,并且会大大减少调试。显式变量声明也是如此。我看不出隐含变量声明有什么好处。

我们已经有了一种语言的大纲:

  • 语法清晰,避免历史混乱。特别地:
    • 无分号
    • 无显式行继续符_la vb
  • 显式变量声明
  • 静态分型

此外,我是某些C++概念的巨大粉丝,例如通用模板、RAII(即避免垃圾而不是收集它)、不可变性和通过迭代器定义的值范围的概念。我在别处说过,我相信迭代器是有史以来最基本的创新之一。给他们一点口红,你甚至不会认出那是C+ +的丑陋的野兽:

1
2
for i in MyVector:
    print(i)

而不是

1
2
3
4
for (typename vector<T>::const_iterator i = MyVector.begin();
     i != MyVector.end();
     ++i)
    cout << *i << endl;

当然,我知道上面的语法是由许多语言提供的。但是它们都只提供了C++的"强大迭代器概念"(使用C++术语)的简化版本,大多数语言所知道的唯一迭代器是输入迭代器,它们基本上是最不强大的迭代器。

在这一点上,我可能会说,所有这些想法的唯一版权是我的,正在申请的专利(特别是对于没有真正比较对象引用的MayOrMayNotBe)。


我没有"完美"编程语言的概念,因为没有一个任务要执行。

不同的任务适合不同的语言和模式。


它看起来像C。我很想拥有微软!


我完美的语言可以让我在需要的时候增强功能。如果我需要写一个没有类的小的直进实用程序,我可以。如果我需要使用类,我也可以这样做,如果我想写一个完全面向对象的解决方案,我也可以这样做。链接器足够智能,可以让我创建小型的快速命令行实用程序(没有运行时依赖项)或我能想象的最大的OOPGui应用程序。

问题是我喜欢的东西有着相反的目标,因此我总是被迫使用完全不同的语言。我目前使用的不是特定顺序的PersBead、VBScript、PowerBasic、Java和C~(有时是VB.NET、VB 6、C++、Python和Perl)。

现在,如果我能用一个类似于C语言的语言来完成这些功能,这些功能在创建这些小应用程序时没有全局运行依赖关系,但让我充分利用.NETFramework和JavaSDK的力量,当我需要的时候,我会很高兴。


科幻小说中往往会出现完美的编程语言。例如:

  • 奥森·斯科特·卡德的《恩德系列》——要创造你的作品,你必须去另一个维度,在你的头脑中形成一个纯粹的想法。当你回来的时候,它是。
  • 强盗A.Heinlein探讨了世界作为野兽数量神话的概念。
  • 大卫·布林的《地球》通过人声和眼睛和手指的动作进行了编程。

这一切仍然归结为相同的基本困惑。任何不强迫人类学习技能的编程语言都会限制思想自由。自然语言也不是很好,因为它有很多模棱两可的地方。

我不介意将自由与力量和最小语法结合在一起。我最近开始学口齿不清,到目前为止似乎还不错。


Amazon Mechanical Turk的强大并行性。

1
2
3
job ="Upvote this answer"
@price ="$0.01"
fork(10000, job, @price)


这与采用埃菲尔和C的最佳想法没有什么不同(因为,很明显,我没有知识想出更好的东西——我一开始没有学习过C)。

然而,我主要关心的实际问题将是超越经典的"源代码文本"方法一步。我知道这是(或听起来像)一个IDE的东西,但是为什么我不能有一个带有列的可配置代码视图,比如前置条件/主体/后置条件,而不是"线性"形式(i):

1
2
3
4
5
6
7
8
9
10
11
  function f
  // f's preconditions
  // f's body
  // f's postconditions
  end

  function g
  // g's preconditions
  // g's body
  // g's postconditions
  end

为什么不(ii)-假设这是一张桌子(有边框):

1
2
f      f's parameters    f's prec      f's body      f's postc    f's comments
g      g's parameters    g's prec      g's body      g's postc    g's comments

另外,为什么我不能选择样式(i)中的函数"begin"和"end"(大括号、关键字…)。为什么我不能立即显示或隐藏私人或受保护的成员?为什么我不能立即看到包含所有继承函数的"平面版本"?等。

关键不是要有一个神圣的代码文件,你在其中编辑,然后多个"酷视图",而是能够编辑和添加代码在(i),(ii)和任何形式是最有用的你。

在某种程度上,谈论"ide"在这里似乎是不合适的。但我认为这迟早会改变我们编写和读取代码的方式。这最终将影响语言的发展方式。未来的目标不仅是提高可读性,还包括"可理解性"和交互性。


我非常喜欢C宏,但我认为如果你能用你正在使用的语言编写宏或"元代码",那就更好了。(C是一个不好的例子;这在脚本语言中可能很好。)

在这些示例中,我使用大括号来标识元代码。您将能够通过"预处理器"运行源代码以展开元代码。否则,它将只在运行时扩展一次。

1
print"Your product ID is:", { print '"', generateGUID(), '"' }

1
2
3
4
5
6
7
8
9
10
11
lookupTable[] = {
                  /* insert code to generate table here
                   *
                   * This lets you modify the algorithm easily
                   * but speeds up the final program.
                   *
                   * This would be especially appropriate in
                   * cases where you would otherwise type out
                   * the table as a literal (yuck)
                   */
                }

有时我们必须写几行重复性很强的代码;现在不能想到一个好的例子,但是这种想法在这种情况下也会很有帮助。


我想我的应该在brainf*ck和lolcode之间,除了有更多的括号。


多媒体。

我希望能够涂写一些图形符号,快速绘制连接,然后切换到其他模式,如需要精确性的输入。

我还认为编程语言应该支持那些不会用英语思考的人(是的,甚至是美国人……开玩笑!)我已经学了足够多的日语,并尝试学习一些印度尼西亚语-我想看到一种语言支持不同语法结构和顺序的人。

我在最近参加的一个关于网络未来的论坛上提出了一个问题,问一位到访的中国教授,他是否认为汉语书面语比英语更有可能实现一个可行的语义网络。他对这个想法很感兴趣。

我读过很多关于未来计算机交互用户界面的文章:

  • 大卫·德雷克的LT Leary系列中的数据棒(其中一些是免费从Baen获得的)
  • 《斗牛士》和佩里《斗牛士》系列中其他随意提到的动作和发音的多模态最受欢迎的组合。
  • 基于笔和手势的用户界面,包括签名以密封傻瓜战争中的日志

Python非常适合我…我只想摆脱一些烦恼,比如说有自己的关键字…但是有了一个好的编辑器,python可以很快完成惊人的事情…


我不确定我的梦中语言会是什么样子,但是我对C风格的语言有了一些改进。我写过多少次这样的东西:

1
2
3
4
5
6
7
8
9
10
11
Node foundNode = null;  // need stupid null value here to keep track if it was not found
foreach (Node testNode in nodes) {
  if (testNode.YesItsMe) {
    foundNode = testNode;
    break;
  }
}
if (foundNode == null) {
  // create new instance
  foundNode = new Node(blabla);
}

我知道有更优雅的函数方法,但有时你还是会得到这样的代码。一个简单的"卫兵"声明将有助于:

1
2
3
4
5
6
7
8
9
10
Node foundNode;  // no need to initialize anymore
foreach (Node testNode in nodes) {
  if (testNode.YesItsMe) {
    foundNode = testNode;
    break;
  }
} guard {  // we get here if break was never called
  // create new instance
  foundNode = new Node(blabla);
}


我设想一种语言,它必须被告知对输入、变量和执行顺序的精确限制,因此可以编译成快速的多线程(或可组合)软件。

这里有一个有趣的想法:假设"函数"中的所有"语句"都可以以任何顺序执行。如果某些东西依赖于其他东西,则需要显式地"调用"依赖项。这将使并行性设计成为语言的一个组成部分。

不幸的是,我没有投入足够的想象力来想出更具体的事情。


Clojure越来越接近了…


我将从主要功能开始:

  • 它应该是一种支持基于宏的元编程的同形语言。这对生产力来说是一个巨大的优势(见保罗·格雷厄姆击败平均水平)。
  • 它应该在任何平台上运行,并且对运行分布式代码有很好的支持。建立一个机器云应该是一个简单的任务。
  • 它应该是开源的。
  • 它应该拥有最大的库和工具生态系统。实际上,这意味着您需要访问Java生态系统,因此,出于这个原因,它可能需要成为JVM语言。
  • 它应该支持类型推断。生命太短暂,编译器无法为您整理类型详细信息…..
  • 它应该是功能性的,强调数据结构的不变性。这是高级语言的未来(我并不怀疑功能语言很难掌握,但这种语言不适合初学者……)
  • 它应该支持交互式开发,最好是在一个类似repl的环境中,您可以与正在运行(可能是分布式的)代码环境进行交互。
  • 它应该提供出色的无锁并发支持。当我们进入大规模的多核世界时,基于锁的方法根本无法扩展。软件事务性内存可能是未来的发展方向。
  • 它应该支持性能所需的低级编码。高级编码占95%的时间,但有时您只需要直接操作字节……

目前,我找到的最接近我的愿望清单是Clojure,它勾选了这些要求的大部分。

由于op指的是语法,我将给出一些代码示例:

适当的变量arity函数,支持大参数列表:

1
2
3
4
5
(+ 1 2 3 4 5)
=> 15

(apply + (range 10000))
=> 49995000

运行时对编译器的交互式访问:

1
2
3
4
5
6
(def function-string"+")

(def function (compile-string function-string))

(function 7 8 9)
=> 24

分布式代码执行(MapReduce样式)。注意,这意味着语言/库能够接受本地定义的some-long-running-function,并透明地将其分发到集群中的所有节点,以便在运行时执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
(def my-cluster
     (create-compute-cluster :nodes 100 :service"Amazon"))

(defn some-long-running-function [input]
  ....)

(def reduction-function
  (fn [a b]
    (do-something-to-reduce a b)))

(def lots-of-inputs (range 10000))

(distributed-map-reduce
  my-cluster
  some-long-running-function
  inputs
  reduction-function)
=> (whatever the result of the mapreduce is over the cluster)

正确的类型推断(即编译器计算出我的函数总是返回一个字符串,并相应地进行优化/推断:

1
2
3
4
5
6
7
8
(def my-function [name]
   (str"Hello" name"!"))

(my-function"Bob")
=>"Hello Bob!"

(compile-time-type my-function)
=> [java.lang.String :not-null]


我想要一种编程语言,它使工具非常容易正确地编写。提取方法、着色、自动完成、编译等。

我希望这一切发生的同时仍然容易写和容易阅读。


我理想的编程语言,代码会很聪明,它会告诉我如果它与另一段代码有问题,我们会坐下来谈,它会告诉我它的问题是什么,这样我们就能解决它……我称之为"情感人++"


这看起来完全像计划。只有它会编译到IL和Java字节码,以及汇编,所以我可以使用所有这些库。


一种设计语言来满足特定的目标。语法和语义应该遵循所需的函数。

在我的例子中,我想要一种具有细纹理并行性的语言,也就是说,每粒谷物的开销非常低,可以让小块的要并行的代码。

我已经在x86 SMP系统上设计和实现了它,它已经被使用了大约10年作为大规模的基础。软件分析工具。

要点是允许我(我们)指定并行性很容易:

1
(|| A B)

A和B是否并行,并让编译器生成所有使这成为可能的积垢。我们不关心语法是否中缀与否,所以我们使用lisp样式来避免争论。

描述语言和一些并行应用程序可以在http://www.semanticdesigns.com/company/publications/parallelism-in-symbol-computation.pdf

这篇文章简要地讨论了我们如何没有成功避免语法上的争论尽管我们做出了决定。


一种没有结构或变量,只有一个函数的语言。

doeverything();//根据已预测的输入自动生成所有内容


它将是机器可读/可写的,并且将由接受语音指令的智能软件编写。


嗯。这是一个困难的问题。我的口味倾向于易于理解的、轻量级脚本风格的语言(尽管我相信这对更大的应用程序是可行的)。请参见代码段:

1
2
3
4
5
6
7
8
9
10
function Foo takes x as string, y as boolean //can add returns [return type] if one wishes to be explicit
    //explicit variable declaration
    z as number
    //explicit cast from boolean to number
    z is y as number
    //implicit variable declaration
    bar is 3 * 5
    //function call
    print x
    return z / bar //since we casted z to a number, it returns a number

我的最佳语言看起来非常像Nemerle(减去任意限制)。实际上,归根结底是元编程工具;我应该能够以我认为适合(句点)的任何方式任意扩展或修改语言,以完全适合域。

给我宏,让我在所有代码的AST上工作,我希望,我可以建立我的完美语言。


我希望看到一个函数包含任意数量的引用参数并将其传递给嵌套函数调用的功能。在.NET中,可以通过类似的方式(显示两个额外的参数版本)对任何固定数量的通用参数执行此操作:

1
2
3
4
5
6
7
8
9
10
11
12
// I forget the C# syntax for delegates, since I normally code in vb
delegate void RefAction<T1, T2, T3>(ref T1 p1, ref T2 t2, ref T3 p3);

Point myPoints[];

void DoSomethingWithIndexedPoint<XT1, XT2>(int index,
  RefAction<Point, XT1, XT2) theAction,
  ref XT1 xp1,
  ref XT2 xp2)
{
  theAction(myPoints[index], xp1, xp2);  
}

我的首选语法是:

1
2
3
4
5
6
7
8
9
10
11
delegate void RefAction<T1, T2, T3>(ref T1 p1, ref T2 t2, ref T3 p3);

Point myPoints[];

void DoSomethingWithIndexedPoint<ref ...>(int index,
  RefAction<Point, ref ...>, ref ...) theAction,
  ref XT1 xp1,
  ref XT2 xp2)
{
  theAction(myPoints[index], ...);  
}

其中"…"将由编译器以任何适当的方式自动扩展。这样的工具可以在许多情况下使用lambda,而不必生成闭包实例,还可以执行以下代码:

1
  Interlocked.CompareExchange(SomeObject["George"], SomeValue, SomeOtherValue);

编译器可以重写为类似于以下内容的内容:

1
2
3
  SomeObject.ActUponProperty("George",
    (ref dest, ref p1, ref p2) => {Interlocked.CompareExchange(dest, p1, p2);},
    SomeValue, SomeOtherValue);

注意,由于lambda表达式不会使用除作为引用参数传递的实例成员或变量之外的任何实例成员或变量,因此它可以作为静态函数实现,并且不需要生成闭包。