Questions tagged «language-design»

涉及编程语言的设计和结构的问题。

2
为什么按位运算符的优先级比比较低?
有人可以解释其原理,为什么在一堆最流行的语言中(请参见下面的注释),比较运算符(==,!=,<,>,<=,> =)的优先级要高于按位运算符(&,|,^ ,〜)? 我认为我从未遇到过这种优先次序自然的用途。总是这样的: if( (x & MASK) == CORRECT ) ... // Chosen bits are in correct setting, rest unimportant if( (x ^ x_prev) == SET ) // only, and exactly SET bit changed if( (x & REQUIRED) < REQUIRED ) // Not all conditions satisfied 我要使用的情况: flags = …

6
为什么C#是用不同于Java的“ new”和“ virtual + override”关键字构成的?
在Java中没有virtual,new,override对于方法定义的关键字。因此,方法的工作很容易理解。因为如果DerivedClass扩展BaseClass的和具有相同的名称和它们的签名的方法BaseClass的那么压倒一切将发生在运行时多态性(提供的方法是不是static)。 BaseClass bcdc = new DerivedClass(); bcdc.doSomething() // will invoke DerivedClass's doSomething method. 现在来到C#时,可能会有太多的困惑,并且很难理解newor virtual+derive或new +虚拟重写的工作方式。 我不明白为什么在世界上为什么要在我的方法中添加一个DerivedClass具有相同名称和签名的方法,BaseClass并定义一个新的行为,但是在运行时多态时,BaseClass将调用该方法!(这不是覆盖,但在逻辑上应该覆盖)。 如果virtual + override逻辑实现是正确的,则程序员必须考虑在编码时应允许用户重写的方法。里面有一些有利条件(让我们现在不去那里)。 那么,为什么在C#中有如此大的空间用于非逻辑推理和混乱。所以,我可以重新塑造我的问题是在现实世界方面,我应该考虑使用virtual + override替代new,还可以使用的new,而不是virtual + override? 在获得了特别是Omar的一些非常好的回答之后,我发现C#设计人员更加强调程序员在创建方法之前应该思考的问题,这种方法很好并且可以处理Java中的一些菜鸟错误。 现在我想到一个问题。就像在Java中,如果我有类似的代码 Vehicle vehicle = new Car(); vehicle.accelerate(); 后来我提出新的类SpaceShip衍生Vehicle。然后我想将所有内容更改car为一个SpaceShip对象,而我只需要更改一行代码 Vehicle vehicle = new SpaceShip(); vehicle.accelerate(); 这不会在任何代码点破坏我的任何逻辑。 但是在C#的情况下,如果SpaceShip不覆盖Vehicle类accelerate并使用,new则代码的逻辑将被破坏。这不是不利条件吗?

9
语言为什么不包含隐含逻辑运算符?
这可能是一个奇怪的问题,但是为什么在许多语言(Java,C,C ++,Python Haskell中没有逻辑操作符的含义),尽管最后一个用户添加了用户定义的操作符却无足轻重吗?我发现逻辑含义要清晰得多(特别是在断言或类似断言的表达式中),然后用or进行否定: encrypt(buf, key, mode, iv = null) { assert (mode != ECB --> iv != null); assert (mode == ECB || iv != null); assert (implies(mode != ECB, iv != null)); // User-defined function }



3
什么是类型系统?
背景 我正在设计一种语言,作为辅助项目。我有一个工作正常的汇编器,静态分析器和虚拟机。由于我已经可以使用构建的基础结构来编译和运行非平凡的程序,因此我考虑在大学里做一个演讲。 在我的演讲中,我提到VM提供了一种类型系统,有人问“ 您的类型系统用于什么? ”。回答后,我被问这个问题的人嘲笑。 因此,即使我几乎肯定会因提出这个问题而声名狼藉,但我还是去找程序员。 我的理解 据我了解,类型系统用于提供有关程序中实体的附加信息层,以便运行时,编译器或任何其他机器知道如何处理其所操作的位字符串。它们还有助于维护合同-编译器(或代码分析器,运行时或任何其他程序)可以验证程序在任何给定的点上以程序员期望其操作的值运行。 类型也可以用于向那些人类程序员提供信息。例如,我找到以下声明: function sqrt(double n) -> double; 比这更有用 sqrt(n) 前者提供了大量信息:sqrt标识符是一个函数,以一个double作为输入,并产生另一个double作为输出。后者告诉您它可能是一个带有单个参数的函数。 我的答案 因此,在被问到“您的类型系统是干什么的?”之后 我回答如下: 类型系统是动态的(类型被分配给值,而不是分配给包含它们的变量),但是强大,没有令人惊讶的强制规则(您不能将字符串添加到整数,因为它们表示不兼容的类型,但是您可以将整数添加到浮点数) 。 VM使用类型系统来确保指令的操作数有效。可供程序员使用,以确保传递给其函数的参数有效(即类型正确)。 类型系统支持子类型化和多重继承(这两种功能均可供程序员使用),并且在对对象使用动态方法分配时会考虑类型-VM使用类型来检查针对给定类型实现的给定消息的功能是什么。 后续问题是“如何将类型分配给值?”。因此,我解释了所有值都装在框内,并有一个指向类型定义结构的指针,该结构提供有关类型名称,其响应的消息以及其继承的类型的信息。 在那之后,我被嘲笑了,我的回答被“那不是一个真正的类型系统”打断了。 所以-如果我所描述的不符合“真实类型系统”的条件,那会是什么?那个人对我提供的内容不能视为类型系统是正确的吗?

5
为什么所有<algorithm>函数仅采用范围,而不采用容器?
中有许多有用的功能&lt;algorithm&gt;,但所有功能都对“序列”(一对迭代器)起作用。例如,如果我有一个容器并且喜欢std::accumulate在其上运行,则需要编写: std::vector&lt;int&gt; myContainer = ...; int sum = std::accumulate(myContainer.begin(), myContainer.end(), 0); 我打算做的是: int sum = std::accumulate(myContainer, 0); 在我看来,这更具可读性和清晰度。 现在我可以看到,在某些情况下,您可能只希望对容器的某些部分进行操作,因此选择传递范围绝对对您有用。但是至少以我的经验来看,这是一种罕见的特殊情况。我通常要对整个容器进行操作。 可以很容易地编写一个包装函数,它接受一个容器,并呼吁begin()和end()就可以了,但是这样的便利功能,不包含在标准库。 我想知道这种STL设计选择背后的原因。

4
为什么Python中的迭代器会引发异常?
这是Java中迭代器的语法(C#中的语法有点相似): Iterator it = sequence.iterator(); while (it.hasNext()) { System.out.println(it.next()); } 有道理。这是Python中的等效语法: it = iter(sequence) while True: try: value = it.next() except StopIteration: break print(value) 我认为例外应该只在特殊情况下使用。 为什么Python使用异常来停止迭代?

8
为什么要设计一种没有异常处理机制的现代语言?
许多现代语言提供了丰富的异常处理功能,但是Apple的Swift编程语言没有提供异常处理机制。 像我一样,我陷入了异常,无法理解这意味着什么。Swift有断言,当然还有返回值。但是我很难想象我基于异常的思维方式如何映射到一个没有例外的世界(就此而言,为什么这样的世界是可取的)。有像Swift这样的语言我无法做的事情我可以做例外吗?通过丢掉异常我能获得一些收益吗? 例如,我如何最好地表达这样的话 try: operation_that_can_throw_ioerror() except IOError: handle_the_exception_somehow() else: # we don't want to catch the IOError if it's raised another_operation_that_can_throw_ioerror() finally: something_we_always_need_to_do() 缺少异常处理的语言(例如,Swift)?

13
为什么赋值运算符分配到左侧?
我刚开始教一个朋友编程(我们正在使用Python),当我们开始讨论变量的创建和赋值运算符时,她问为什么将右边的值分配给左边的名称,反之亦然。 我以前并没有考虑太多,因为它对我来说似乎很自然,但是她说从左到右对她来说似乎更自然,因为那是我们大多数人阅读自然语言的方式。 我考虑了一下,并得出结论,它使代码更易于阅读,因为分配给它们的名称(程序员将需要重用)很容易看到,并与左侧对齐。 aligned = 2 on = 'foo' + 'bar' + 'foobar' the = 5.0 / 2 left = 2 + 5 相对于: 2 = aligned 'foo' + 'bar' + 'foobar' = on 5.0 / 2 = the 2 + 5 = right # What were the names again...? …

5
为什么旧的编程语言会继续被修改?
这个问题不是, “为什么人们仍然使用旧的编程语言?” 我非常了解。实际上,我最了解的两种编程语言是C和Scheme,它们都可以追溯到70年代。 最近,我在阅读有关C99和C11与C89(实际上仍然是C语言中最常用的版本,以及我从K&R那里学到的版本)有关的更改。环顾四周,似乎每一种频繁使用的编程语言都会每十年左右获得至少一次新规范。尽管事实上大多数使用Fortran的人仍在使用FORTRAN 77,但甚至Fortran仍在获得新的修订。 将此与排版系统TeX的方法进行对比。1989年,随着TeX 3.0的发布,Donald Knuth宣布TeX具有完整的功能,以后的版本将仅包含错误修复。他甚至声明,在他去世后,“所有剩余的bug都将成为特性”,并且绝对不会进行进一步的更新。其他人则可以免费使用TeX并已这样做,但是对结果系统进行了重命名以表明它们与官方TeX不同。这不是因为Knuth认为TeX是完美的,而是因为他了解稳定,可预测的系统的价值,该系统将在五十年内完成与现在相同的任务。 为什么大多数编程语言设计师不遵循相同的原则?当然,当一种语言是相对较新的语言时,它会经历一段时间的快速变化然后才适应。没有人能真正反对微小的变更,这些变更所做的工作不只是编纂现有的伪标准或纠正意外的读数。但是,当一种语言在十到二十年后似乎仍然需要改进时,为什么不只是分叉它或从头开始,而不是尝试更改已经使用的语言呢?如果某些人真的想在Fortran中进行面向对象的编程,为什么不为此目的创建“ Objective Fortran”,而让Fortran自己呆着呢? 我想可以说,不管将来的版本如何,C89已经是一种标准,没有什么可以阻止人们继续使用它。这是对的,但内涵确实有后果。GCC将以学究模式警告C99中不推荐使用的语法或含义稍有不同的语法,这意味着C89程序员不能完全忽略新标准。因此,C99必须具有一定的优势,足以使使用此语言的每个人都承担此开销。 这是一个真实的问题,而不是引起争论的邀请。显然,我对此有意见,但是目前,我只是想了解为什么这不只是事情的完成方式。我想问题是: 与基于旧语言创建新语言相比,更新语言标准有哪些(真正的或可感知的)优势?

4
为什么结构和类在C#中是分开的概念?
在用C#编程时,我偶然发现了一个我无法理解的奇怪的语言设计决策。 因此,C#(和CLR)具有两种聚合数据类型:(struct值类型,存储在堆栈上,没有继承)和class(引用类型,存储在堆上,具有继承)。 首先,这种设置听起来不错,但随后您偶然发现了采用聚合类型参数的方法,要弄清楚它实际上是值类型还是引用类型,必须找到其类型的声明。有时可能会造成混乱。 解决该问题的公认方法似乎是将所有structs 声明为“不可变的”(将其字段设置为readonly),以防止可能的错误,从而限制structs的用途。 例如,C ++使用了更多可用的模型:它允许您在堆栈或堆上创建对象实例,并按值或按引用(或按指针)传递它。我一直听到C#的灵感来自C ++,但我不明白为什么它不采用这种技术。结合class并struct进入一个结构有两个不同的分配方案(堆和栈)和周围将它们作为值或(明确)经由引用ref和out关键字似乎是一个很好的事情。 问题是,为什么在C#和CLR中class并struct成为单独的概念,而不是具有两个分配选项的一种聚合类型?


15
语言如何影响CPU设计?[关闭]
人们经常被告知,硬件并不在乎用哪种语言编写程序,因为它只能看到编译后的二进制代码,但这并不是全部。例如,考虑一下不起眼的Z80;它对8080指令集的扩展包括CPIR之类的指令,可用于扫描C样式(以NULL结尾的)字符串,例如执行strlen()。设计人员必须已经确定,运行C程序(与Pascal相反,在Pascal中,字符串的长度位于标头中)是他们的设计可能会使用的东西。另一个经典的例子是Lisp Machine。 还有什么其他例子?例如,使特定处理器偏爱特定语言约定的指令,寄存器的数量和类型,寻址模式?我对同一家庭的修订特别感兴趣。

22
标识符中的空格曾经是惯用的吗?[关闭]
C#风格建议在标识符中使用CamelCase来分隔单词。Lisp传统建议使用破折号代替。 是否曾经有一种编程语言,其中不仅允许在标识符中使用空格,还允许在使用多字标识符时使用一种常用的习惯用法? 在某些Scheme实现中可能有带空格的标识符,但这并不是一种普遍的做法。这是一个例子: Petite Chez Scheme Version 8.4 Copyright (c) 1985-2011 Cadence Research Systems &gt; (define |hey there| 100) &gt; (define |x y z| 200) &gt; (list |hey there| |x y z|) (100 200)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.