标签: language-design

"最小的惊讶"和可变的默认论证

任何修补Python足够长的人都被以下问题咬伤(或撕成碎片):

def foo(a=[]):
    a.append(5)
    return a
Run Code Online (Sandbox Code Playgroud)

Python新手希望这个函数总能返回一个只包含一个元素的列表:[5].结果却非常不同,而且非常惊人(对于新手来说):

>>> foo()
[5]
>>> foo()
[5, 5]
>>> foo()
[5, 5, 5]
>>> foo()
[5, 5, 5, 5]
>>> foo()
Run Code Online (Sandbox Code Playgroud)

我的一位经理曾经第一次遇到这个功能,并称其为该语言的"戏剧性设计缺陷".我回答说这个行为有一个潜在的解释,如果你不理解内部,那确实非常令人费解和意想不到.但是,我无法回答(对自己)以下问题:在函数定义中绑定默认参数的原因是什么,而不是在函数执行时?我怀疑经验丰富的行为有实际用途(谁真的在C中使用静态变量,没有繁殖错误?)

编辑:

巴泽克提出了一个有趣的例子.再加上你的大部分评论和特别是Utaal,我进一步阐述了:

>>> def a():
...     print("a executed")
...     return []
... 
>>>            
>>> def b(x=a()):
...     x.append(5)
...     print(x)
... 
a executed
>>> b()
[5]
>>> b()
[5, 5]
Run Code Online (Sandbox Code Playgroud)

对我而言,似乎设计决策是相对于放置参数范围的位置:在函数内部还是"与它一起"?

在函数内部进行绑定意味着在调用函数时x有效地绑定到指定的默认值,而不是定义,这会产生一个深层次的缺陷:def在某种意义上,该行将是"混合"的(部分绑定)函数对象)将在定义时发生,并在函数调用时发生部分(默认参数的赋值).

实际行为更加一致:执行该行时,该行的所有内容都会得到评估,这意味着在函数定义中.

python language-design least-astonishment default-parameters

2458
推荐指数
31
解决办法
14万
查看次数

为什么Java不支持无符号整数?

为什么Java不包含对无符号整数的支持?

在我看来,这是一个奇怪的遗漏,因为它们允许人们编写不太可能在意外的大输入上产生溢出的代码.

此外,使用无符号整数可以是一种自我文档形式,因为它们表明unsigned int意图保留的值绝不应该是负数.

最后,在某些情况下,无符号整数对于某些操作(例如除法)可能更有效.

包含这些内容的不利之处是什么?

java unsigned integer language-design

367
推荐指数
11
解决办法
11万
查看次数

为什么我们必须在C#中定义==和!=?

C#编译器要求每当自定义类型定义运算符时==,它还必须定义!=(参见此处).

为什么?

我很想知道为什么设计师认为这是必要的,为什么当只有另一个运算符存在时,编译器不能默认为任何一个运算符的合理实现.例如,Lua允许您仅定义相等运算符,而您可以免费获得另一个运算符.C#也可以通过要求你定义==或者两者==和!=然后自动编译缺少的!=运算符来做同样的事情!(left == right).

我知道有一些奇怪的角落情况,其中一些实体可能既不平等也不平等(如IEEE-754 NaN),但这些似乎是例外,而不是规则.所以这并不能解释为什么C#编译器设计者将例外规则作为例外.

我已经看到了定义等式运算符的做工不好的情况,然后不等式运算符是一个复制粘贴,每个比较都被反转,每个&&切换到|| (你得到的重点......基本上!(a == b)通过De Morgan的规则扩展).编译器可以通过设计消除这种糟糕的做法,就像Lua的情况一样.

注意:对于运算符<> <=> =也是如此.我无法想象你需要以不自然的方式定义它们的情况.Lua允许您通过前者的否定自然地定义<和<=并定义> =和>.为什么C#不做同样的事情(至少'默认')?

编辑

显然有正当理由允许程序员实现对他们喜欢的平等和不平等的检查.一些答案指向可能很好的情况.

然而,我的问题的核心是为什么在C#中强制要求它通常逻辑上不必要?

它与.NET接口的设计选择形成鲜明对比,例如Object.Equals,IEquatable.Equals IEqualityComparer.Equals缺少NotEquals对应物表明框架将!Equals()对象视为不相等而且就是这样.此外,类Dictionary和类等方法.Contains()完全依赖于上述接口,即使定义了运算符也不直接使用运算符.事实上,当ReSharper生成相等成员时,它定义了两者==并且!=就其而言,Equals()即使只是用户选择生成运算符.框架不需要相等运算符来理解对象相等性.

基本上,.NET框架并不关心这些运算符,它只关心几种Equals方法.要求用户串联定义==和!=运算符的决定纯粹与语言设计有关,而与.NET有关的不是对象语义.

c# language-design

341
推荐指数
10
解决办法
1万
查看次数

为什么Java 8接口方法中不允许"final"?

Java 8最有用的功能之一是default接口上的新方法.基本上有两个原因(可能还有其他原因)为什么会被引入:

从API设计者的角度来看,我希望能够在接口方法上使用其他修饰符,例如final.在添加便捷方法时,这将非常有用,可防止在实现类时出现"意外"覆盖:

interface Sender {

    // Convenience method to send an empty message
    default final void send() {
        send(null);
    }

    // Implementations should only implement this method
    void send(String message);
}
Run Code Online (Sandbox Code Playgroud)

如果Sender是一个类,上面已经是常见的做法:

abstract class Sender {

    // Convenience method to send an empty message
    final void send() {
        send(null);
    }

    // Implementations should only implement this method
    abstract void send(String message);
}
Run Code Online (Sandbox Code Playgroud)

现在,defaultfinal有明显矛盾的关键字,但默认关键字本身不会一直严格要求 …

java language-design java-8 jsr335 default-method

324
推荐指数
3
解决办法
3万
查看次数

282
推荐指数
8
解决办法
20万
查看次数

原型继承优于经典的好处?

所以这些年来我终于停止了我的脚,并决定"正确"学习JavaScript.语言设计中最令人头疼的元素之一是它的继承实现.有Ruby经验,我很高兴看到闭包和动态打字; 但是对于我的生活来说,无法弄清楚使用其他实例进行继承的对象实例会带来什么好处.

javascript oop inheritance language-design prototype-programming

264
推荐指数
4
解决办法
7万
查看次数

什么阻止Ruby,Python来获得Javascript V8的速度?

是否存在阻止优化实现的Ruby/Python功能(例如内联缓存)V8引擎?

Python由Google员工共同开发,因此不应被软件专利阻止.

或者这是谷歌为V8项目投入资源的问题.

javascript ruby python performance language-design

261
推荐指数
9
解决办法
8万
查看次数

"this"关键字如何在函数中起作用?

我刚刚在JavaScript中遇到了一个有趣的情况.我有一个类,其方法使用object-literal表示法定义多个对象.在这些对象中,this正在使用指针.从程序的行为,我推断出this指针指的是调用方法的类,而不是文字创建的对象.

这似乎是随意的,尽管这是我期望它工作的方式.这是定义的行为吗?跨浏览器安全吗?有没有任何理由可以解释为什么它超出"规范如此说明"的方式(例如,它是否是一些更广泛的设计决策/哲学的结果)?简化代码示例:

// inside class definition, itself an object literal, we have this function:
onRender: function() {

    this.menuItems = this.menuItems.concat([
        {
            text: 'Group by Module',
            rptletdiv: this
        },
        {
            text: 'Group by Status',
            rptletdiv: this
        }]);
    // etc
}
Run Code Online (Sandbox Code Playgroud)

javascript language-features language-design

248
推荐指数
3
解决办法
9万
查看次数

函数重载按返回类型?

为什么更多主流的静态类型语言不支持返回类型的函数/方法重载?我想不出那样做.通过参数类型支持过载似乎没有那么有用或合理.怎么这么不受欢迎呢?

programming-languages overloading language-design function-calls

248
推荐指数
5
解决办法
10万
查看次数

为什么Python没有签名功能?

我无法理解为什么Python没有sign函数.它有一个abs内置(我认为sign是它的妹妹),但没有sign.

在python 2.6中甚至有一个copysign函数(在数学中),但没有符号.copysign(x,y)当你只能写一个sign然后copysign直接从中获取时,为什么还要写一个abs(x) * sign(y)?后者会更加清晰:x带有y的符号,而对于copysign,你必须记住它的x是否带有y或y的符号,带有x的符号!

显然sign(x)不提供任何东西cmp(x,0),但它也会更具可读性(对于像python这样的高可读性语言,这本来是一个很大的优点).

如果我是一名蟒蛇设计师,那我就是另一种方式:没有cmp内置,而是一个sign.当你需要时cmp(x,y),你可以做一个sign(x-y)(或者,甚至更好的非数字的东西,只是一个x> y - 当然这应该需要sorted接受一个布尔而不是一个整数比较器).这也将更加清晰:正时x>y(而与cmp你必须记住公约正值当第一个,但它可能是周围的其他方式).当然cmp,由于其他原因(例如,在排序非数字事物时,或者如果您希望排序稳定,这是不可能使用简单的布尔值)

所以,问题是:为什么Python设计师决定将该sign功能从语言中删除?为什么麻烦copysign而不是它的父母sign呢?

我错过了什么吗?

编辑 - 在彼得汉森评论之后.很公平,你没有使用它,但你没有说你使用python的.在我使用蟒蛇的7年中,我无数次需要它,最后一根是打破骆驼背部的稻草!

是的,你可以通过cmp,但是我需要通过它的90%的时间都是这样的成语,就像 lambda x,y: cmp(score(x),score(y))用标志就好了.

最后,我希望你同意这sign会比这更有用copysign,所以即使我买了你的观点,为什么还要在数学中定义它而不是标志呢?copysign如何比签名更有用?

python language-design

217
推荐指数
10
解决办法
12万
查看次数