您知道动态类型语言中优雅的解决方案的任何示例吗?

发布于 2024-09-10 23:10:51 字数 527 浏览 5 评论 0原文

想象两种语言(除了类型信息)确实具有完全相同的语法,但一种是静态类型,而另一种语言使用动态类型。然后,对于用静态类型语言编写的每个程序,都可以通过删除所有类型信息来派生出等效的动态类型程序。由于反过来不一定是可能的,因此动态类型程序的类严格大于静态类型程序的类。我们将这种动态类型程序称为动态类型程序,因为没有变量到类型的映射,因此它们是静态类型真正的动态类型程序”。

由于这两个语言系列都绝对是图灵完备的,因此我们可以确定,对于每个这样的真正的动态类型程序,都存在一个静态类型程序做完全相同的事情,但我经常读到“有经验的程序员能够用动态类型语言编写非常优雅的代码”。因此,我问自己:是否有任何真正的动态类型程序的好例子,对于这些程序,任何等效的静态类型程序显然要复杂得多/更不“优雅”(无论什么)这可能意味着)?

你知道这样的例子吗?

Imagine two languages which (apart from the type information) do have exactly the same syntax, but one is statically typed while the other one uses dynamic typing. Then, for every program written in the statically typed language, one can derive an equivalent dynamically typed program by removing all type information. As this is not neccessarily possible the other way around, the class of dynamically typed programs thus is strictly larger than the class of statically typed programs. Let's call this dynamically typed programs, for which there is no mapping of variables to types making them statically typed "real dynamically typed programs".

As both language families are definitly turing-complete, we can be sure that for every such real dynamically typed program there exists a statically typed program doing exactly the same thing, but I often read that "experienced programmers are able to write very elegant code in dynamically typed languages". I thus ask myself: Are there any good examples of real dynamically typed programs, for which any equivalent statically typed programm clearly is much more complex / much less "elegant" (whatever that may mean)?

Do you know of any such examples?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无需解释 2024-09-17 23:10:51

我确信,对于静态语言的许多“优雅”问题,静态类型检查本身并不是罪魁祸首,而是语言中实现的静态类型系统缺乏表达能力以及编译器的有限能力。如果这做得“更正确”(例如在 Haskell 中),那么程序会突然变得简洁、优雅……并且比动态程序更安全。

这是一个例子(具体针对 C++,抱歉):C++ 非常强大,它使用模板类系统实现了元语言。但是,一个非常简单的函数仍然很难声明:

template<class X,class Y>
? max(X x, Y y)

有大量可能的解决方案,例如 ?=boost::variant 或计算 ?=is_convertible(X ,Y)?(X:is_convertible(Y,X):Y:error),没有一个真正令人满意。

但现在想象一个预处理器,它可以将输入程序转换为等效的延续传递样式形式,其中每个延续都是一个可调用对象,它接受所有可能的参数类型。 CPS 版本的 max 看起来像这样:

template<class X, class Y, class C>
void cps_max(X x, Y y, C cont) // cont is a object which can be called with X or Y
{
 if (x>y) cont(x); else cont(y); 
}

问题消失了,max 调用接受 X 或 Y 的延续。因此,有一个带有静态类型检查的 max 解决方案,但我们无法在非 CPS 中表达 max可以说,untransform(cps_max) 是未定义的。因此,我们有一些论点认为 max 可以正确完成,但我们没有办法这样做。这就是缺乏表现力。

2501 更新:
假设有一些不相关类型X和Y,并且有一个布尔运算符<(X,Y)max(X,Y) 应该返回什么?让我们进一步假设,X 和 Y 都有一个成员函数 foo();。我们怎样才能这样写:

void f(X x, Y y) {
    max(X,Y).foo();
}

返回 X 或 Y 并在结果上调用 foo() 对于动态语言来说没有问题,但对于大多数静态语言来说几乎不可能。但是,我们可以通过重写 f() 以使用 cps_max 来获得预期的功能:

struct call_foo { template<class T> void operator(const T &t) const { t.foo(); } };

void f(X x, Y y) {
 cps_max(x,y,call_foo());
}

因此这对于静态类型检查来说不是问题,但它看起来非常丑陋,并且无法扩展到简单示例之外。那么这种静态语言所缺少的就是我们无法提供静态和可读的解决方案。

I am sure that for many "elegance" problems of static languages, static type checking itself isn't to blame, but the lack of expressiveness of the static type system implemented in the language and the limited capabilities of the compiler. If this is done "righter" (like in Haskell for example), then suddenly the programs turn out to be terse, elegant .. and safer that their dynamic counterpart.

Here's an illustration (C++ specific, sorry): C++ is so powerful, that it implements a metalanguage with it's template class system. But still, a very simple function is hard to declare:

template<class X,class Y>
? max(X x, Y y)

There is an astounding amount of possible solutions, like ?=boost::variant<X,Y> or computing ?=is_convertible(X,Y)?(X:is_convertible(Y,X):Y:error), none of them really satisfiying.

But now imagine a preprocessor, that could transform an input program into it's equivalent continuation passing style form, where each continuation is a callable object which accepts all possible argument types. A CPS version of max would look like this:

template<class X, class Y, class C>
void cps_max(X x, Y y, C cont) // cont is a object which can be called with X or Y
{
 if (x>y) cont(x); else cont(y); 
}

The problem is gone, max calls a continuation which accepts X or Y. So, there is a solution for max with static type checking, but we can't express max in it's non-CPS form, untransform(cps_max) is undefined, so to speak. So,we have some argument that max can be done right, but we don't have the means to do so. This is lack of expressiveness.

Update for 2501:
Assume there are some unrelated types X and Y and there is a bool operator<(X,Y). What shouldmax(X,Y) return? Let us further assume, that X and Y both have a member function foo();. How could we make it possible to write:

void f(X x, Y y) {
    max(X,Y).foo();
}

returning either X or Y and invoking foo() on the result is no problem for a dynamic language, but close to impossible for most static languages. However, we can have the intended functionality by rewriting f() to use cps_max:

struct call_foo { template<class T> void operator(const T &t) const { t.foo(); } };

void f(X x, Y y) {
 cps_max(x,y,call_foo());
}

So this can't be a problem for static type checking, but it looks very ugly and does not scale well beyond simple examples. So what is missing from this static language that we can not provide a static and readable solution.

人海汹涌 2024-09-17 23:10:51

是的,请查看 Eric Raymonds Python 成功故事。基本上,它是关于使用动态类型编程语言进行反射类型任务要容易得多。

Yes, check out Eric Raymonds Python Success Story. Basically, it is about how much easier reflection-type tasks are with dynamically typed programming languages.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文