gpt4 book ai didi

programming-languages - 声明式编程语言的反馈,资源和信息

转载 作者:行者123 更新时间:2023-12-02 02:29:34 25 4
gpt4 key购买 nike

我一直在思考一些新语言背后的概念。起初它是一个玩具,但现在我想知道它是否真的有意义。我将此问题发布到Stack Overflow,以查看是否已完成,以及是否可以获得任何反馈,想法或其他信息。

我主要是在阅读Jonathan Edward's presentation on declarative programming之后开始考虑这个问题的。然后,我将其与一些较旧的想法以及我在现代语言中看到的东西混合在一起。

声明式编程的主要思想是“什么”与“如何”。但是,我已经听过很多次了,所以似乎几乎总是像“有趣”这个词,它实际上并没有告诉您任何东西,这令人沮丧。

不过,在乔纳森·爱德华(Jonathan Edward)的版本中,他首先从强调lazy evaluation开始。这产生了一些有趣的结果,即functional reactive programming (FRP)。这是带有动画的FRP的示例(使用我编写的语法):

x as time * 2 // time is some value representing the current time
y as x + (2 * 500)

new Point(x, y)

因此,如果输入更改,则值将自动更改。在我最喜欢的一种语言 D中,“纯”和“不纯”函数之间有所区别。纯函数是与外界没有任何联系的函数,仅使用其他纯函数。否则,将是不纯的。关键是您总是可以相信一个纯函数为给定的参数返回相同的值。

我想类似的传递原则在这里也适用。我们的杂质是 timetime涉及的所有内容,即 x,因此 y,因此 new Point(x, y)不纯。但是,请注意 (2 * 500)是纯净的。因此,您会看到这告诉编译器其限制在哪里。我认为这就像用变量简化数学表达式:
(x ^ 2) + 3x + 5
(4 ^ 2) + 3x + 5 = 16 + 3x + 5 = 21 + 3x = 3(7 + x)

通过告诉编译器什么是纯净的和什么不是纯净的,我们可以大大简化程序。另一点是渴望或易变的数据。乔纳森·爱德华(Jonathan Edward's)认为输入是可变的和渴望的,但是输出却是功能性的和惰性的。基本上, 给出了新的输入,程序定义了原子状态更改,然后 ,输出将仅仅是当前状态的函数。如果您想知道为什么这很重要,请参阅演示。输入不纯。惰性评估有助于定义原子状态的变化。让我们看一下如何以程序方式编写程序:
void main ()
{
String input = "";

writeln("Hello, world!");
writeln("What's your name? ");

input = readln();

writeln("Hello, %s!", input);
writeln("What's your friends name? ");

input = readln();

writeln("Hello to you too, %s!", input);
}

此处 bind关键字表示如果 begin更改,则执行以下代码。 mutable关键字表示输入不是惰性的,而是渴望的。现在让我们看一下“原子状态变化”如何表示它。
program:
mutable step := 0

bind begin:
writeln("Hello, world!")
writeln("What's your name? ")
++step

bind readln() as input when step = 1:
writeln("Hello, %s!", input)
writeln("What's your friends name? ")
++step

bind readln() as input when step = 2:
writeln("Hello to you too, %s!", input)

现在,我们在这里看到了可以使程序员更轻松,更易读的东西。首先是丑陋的 step变量,以及我们每次必须如何递增和测试它。这是一个新版本和改进版本的示例:
program:
bind begin:
writeln("Hello, world!")
writeln("What's your name? ")

bind readln() as input:
writeln("Hello, %s!", input)
writeln("What's your friends name? ")
yield // This just means the program jumps to here instead of at the beginning
writeln("Hello to you too, %s!", input)
halt

这样更好不过并不完美。但是,如果我知道完美的答案,我就不会在这里,对吗?

这是一个使用游戏引擎的更好的示例:
class VideoManager:
bind begin: // Basically a static constructor, will only be called once and at the beginning
// Some video set up stuff

bind end: // Basically a static destructor
// Some video shut down stuff

class Input:
quitEvent as handle // A handle is an empty value, but can be updated so code that's bound to it changes.
keyboardEvent as handle(KeyboardEvent) // This handle does return a value though
mouseEvent as handle(MouseEvent)

// Some other code manages actually updating the handles.

class Sprite:
mutable x := 0
mutable y := 0

bind this.videoManager.updateFrame:
// Draw this sprite

class FieldState:
input as new Input
player as new Sprite

bind input.quitEvent:
halt

bind input.keyboardEvent as e:
if e.type = LEFT:
this.player.x -= 2
else if e.type = RIGHT:
this.player.x += 2
else if e.type = UP:
this.player.y -= 2
else if e.type = DOWN:
this.player.y += 2

我喜欢这不需要回调,事件,甚至不需要循环或任何东西,并且线程很明显。告诉我们正在发生的事情更容易,并且不仅是类似Python的语法。我认为这就像语言开发人员意识到人们在使用标签和goto的东西很少:条件分支和循环。因此,他们在语言中内置了if-then-else,while和for的功能,因此不赞成使用标签和goto,并且编译器和其他人员都可以知道发生了什么。我们使用的大部分资源都来自该过程。

回到线程,这的好处是线程更加灵活。如果编译器可以自由地执行其所需的操作,因为我们更接近于说出所需的内容,而不是要如何完成它。因此,编译器可以利用多核和分布式处理器的优势,但是在没有良好的线程支持的情况下仍然可以补偿平台。

我想说的最后一件事。这就是我对模板的看法。这是一种概念上的蛋,它在我开始编程时就开始发展了(实际上是大约2年前),后来又开始破解。基本上,这是抽象的原理,但它的扩展范围超出类和对象。

这与我对功能的看法有关。例如:
int add (int a, int b)
{
return a + b;
}

好的, add返回了 int,但这是什么?感觉就像是等待发生的 int。就像没有几块拼图。可能性有限,仅适合某些部件,但是完成后,您便可以在其他地方使用成品了。就像我说的那样,这是抽象的原理。以下是一些我认为是抽象+缺少的部分->具体关系的示例:
  • 函数+参数->值
  • 抽象类+方法->
  • 类+实例值->对象
  • 模板+参数->函数或类
  • 程序+输入+状态->输出

  • 它们都是紧密相关的。看来这可以被利用。但是如何?同样,这就是为什么这是一个问题。但是这里的惰性评估很有趣,因为您可以将 传递给某些东西,但其片段仍然缺少传递给其他东西。对于编译器而言,主要是将名称反引用为杂质。就像我上面的例子:
    (x ^ 2) + 3x + 5
    (4 ^ 2) + 3x + 5 = 16 + 3x + 5 = 21 + 3x = 3(7 + x)

    您向编译器提供的片段越多,它就可以完成更多工作,并将程序缩减到其基本核心。上面的 add函数将在编译时自动解决,因为它不依赖任何外部资源。根据编译器的智能程度,甚至许多类和对象以及大量程序都可以解析。

    目前为止就这样了。如果您已经看过这些事情的例子,我很想看看。如果您有任何想法,创新,资源或反馈,我也将不胜感激。

    最佳答案

    您肯定想看看 Haskell 编程语言。

    Haskell具有极强的声明性,内置了惰性评估,甚至还存在功能性反应式编程库。但最值得注意的是,Haskell纯粹是功能性的,即一切,实际上一切都是纯净的。

    因此,问题是Haskell如何处理通过任何IO产生的必要杂质。

    答案很符合您提出的想法。 Haskell使用称为 monads 的数学构造,该构造基本上表示产生某种值的计算以及函数bind(作为中缀运算符>>=),该函数对这些计算进行排序。

    因此,让我们举一个IO示例:读取一行并输出您的名称...甚至IO都是纯的,因此您不能简单地运行某些东西。相反,您可以建立更多的IO计算

    do
    putStr "Enter your name: "
    name <- getLine
    putStrLn ("Hello " ++ name)

    看起来非常必要,但实际上,这只是
    (putStr "Enter your name: ") >>
    (getLine >>= \name ->
    putStrLn ("Hello " ++ name))

    现在,您可以按照自己喜欢的任何方式为任意种类的计算定义此 bind / >>=。因此,实际上,您所讨论的所有内容都可以以这种方式实现-甚至FRP。

    只需尝试在Stackoverflow上查找monad或Haskell;这个主题有很多问题。
    毕竟,它仍然是所有经过类型检查的内容,因此编译器可以强制执行正确性。

    关于programming-languages - 声明式编程语言的反馈,资源和信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4290733/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com