从我关于语言设计的讨论来看,似乎很多人都认为不存在也永远不会有“一种真正的语言”。这些人表示,另一种选择是熟悉几种语言并选择适合工作的工具。 这对于整个项目或大型子项目来说是非常有意义的,因为它们只需要通过一个非常狭窄的、定义良好的界面与项目的其余部分进行交互。
另一方面,当试图优雅地解决许多小子问题时,使用大量不同的语言似乎是一件非常尴尬的事情。换句话说,恕我直言,在所有方面都表现良好的通用语言仍然很重要。举一个简单的例子,假设您需要执行以下操作:
这是一个相当简单的项目,除了编写计算密集型的自定义矩阵处理例程之外,但关于使用哪种语言的唯一好的答案似乎是一种在所有方面都不错的通用语言。
我在这里缺少什么?一个人如何有效地使用多种语言来发挥各自的优势?
大多数程序员都认为垃圾收集是一件好事,在大多数应用程序中都非常值得花费.但是,我个人的观察是,大多数对象的内存管理都是微不足道的,并且可能有10%-20%的内存管理需要考虑诸如引用计数和一般非常复杂的内存管理方案等问题.在我看来,只需一小部分开销就可以获得垃圾收集的所有好处,保守地手动删除大对象,其中对象的生命周期很明显,让GC收集其余的,假设GC实现支持这样的事情.这将允许GC运行频率降低,并消耗更少的多余内存,同时仍然避免实际难以手动管理的情况.
int myFunc() {
Foo[] foo = new Foo[arbitraryNumber]; // May be too big to stack allocate.
// do stuff such that the compiler can prove foo doesn't escape.
// foo is obviously no longer needed, can be automatically deleted here.
return someInteger;
}
Run Code Online (Sandbox Code Playgroud)
当然,这可能不适用于复制GC,但是为了这个帖子,我们假设我们的GC没有复制.为什么这种混合内存管理方案在主流编程语言中显然如此罕见?
performance garbage-collection programming-languages memory-management
我读过的所有内容似乎都暗示构建交叉编译器比构建针对其运行的平台的编译器要困难得多.这是真的?如果是这样,为什么?似乎为任意平台生成汇编代码和系统调用不应该比为编译器运行的平台生成这样的代码和系统调用更难,但也许我只是天真.
对于可怕的过度设计的API而言,似乎存在着相当多的不喜欢,这些API被设计为无限灵活,因此不会使简单的事情变得简单.尽管如此,似乎并不缺少需要您使用8个不同类并编写20行样板文件来完成简单,常见任务的API.我不会提到名字,因为这不应该是关于特定API是否过度设计的火焰.
您认为这些可怕的过度工程API的根本原因是什么?您认为阻止API设计人员制造此类怪物需要做些什么?
编辑:恕我直言,甚至没有创建可重复使用的代码确实是一个很好的答案,因为如果API非常难以使用并且需要大量和大量的样板,重用的好处变得值得怀疑.
我有D2程序,它的当前形式是单线程,并且对于该程序外循环的每次迭代,在内循环中调用相同的纯函数大约10到100次.呼叫之间没有数据依赖性,即没有呼叫使用来自任何其他呼叫的结果.总的来说,这个功能被称为数百万次,是我程序中的主要瓶颈.这些参数几乎每次都是唯一的,因此缓存无济于事.
乍一看,这似乎是并行化的完美候选者.唯一的问题是该函数每次调用只需要大约3微秒,远低于创建新线程的延迟,并且远远高于将任务添加到任务池的开销(意味着,获取互斥锁,分配内存到保存有关任务的信息,处理可能的任务池队列争用等.有没有什么好方法可以利用这种细粒度的并行性?
parallel-processing optimization performance multithreading d
在"语言X只有太多魔法"或"平台Y通常避免魔法"等语境中,"魔法"这个词在这里被抛出很多.然而,似乎这个术语的定义很差,人们在看到它时就会知道.例如,Java被认为包含很少的魔力,但它的垃圾收集器隐藏了很多程序员.如果魔术只是意味着隐藏细节的抽象,那么为什么它被认为是一件坏事,因为没有人再用汇编语言编写大型程序了?如果魔法意味着什么更多,那么它意味着什么?
在面向对象的编程中,能够修改已创建对象的行为有时会很好.当然,这可以通过相对冗长的技术来完成,例如策略模式.但是,有时通过在实例化后更改vtable指针来完全更改对象的类型会更好.假设你从A级转换到B级,这将是安全的:
这在C++和D编程语言中是可以攻击的,因为指针可以随意转换,但是它太丑陋且难以理解,我害怕在需要其他人理解的代码中执行它.为什么通常不提供更高级别的方法呢?
从生产代码中删除断言的典型论据是性能。这对我来说没有意义。是的,从性能关键的 5% 左右的代码中剥离一些断言可能是一种有用的优化。然而,对于另外 95% 的人来说,它们可能没有可测量的效果,并且断言只会增加这样的可能性:如果您的代码有错误,它会以一种易于诊断的方式快速失败。
我的大部分编程都是在 D 中完成的,它的enforce()功能基本上可以完成相同的assert()功能,只是它保留在发布版本中。我通常发现自己enforce()大部分时间都在使用,而且assert()只在少数enforce()太贵的地方使用。
除了性能之外,还有其他原因从发布版本中删除断言吗?如果不是,为什么语言不让断言的默认行为即使在发布版本中也始终执行,并提供第二个更冗长且更难记住的函数,类似的东西expensiveAssert()从发布版本中删除并建议仅在代码中性能关键的部分?
我经常看到它认为不应该使用重度嵌套的函数调用,因为它们是不可读的.但是,使用临时变量会产生大量不必要的冗长,并迫使读者在心理上将每个临时变量链接到它所代表的内容.在查看Lisp代码通常被格式化的方式时,我发现嵌套函数调用实际上可以被设置为非常可读,如果您将它们格式化以反映嵌套.例如:
// Totally unreadable:
auto linesIter = filter!"a.length > 0"(map!strip(File(filename).byLine())))
// Perfectly readable. The only difference is formatting.
auto linesIter = filter!"a.length > 0"(
map!strip(
File(filename).byLine()
)
);
// Readable, but unnecessarily verbose:
auto rawLines = File(filename).byLine();
auto stripped = map!strip(rawLines);
auto filtered = filter!"a.length > 0"(stripped);
Run Code Online (Sandbox Code Playgroud)
在嵌套函数形式中编写类似第一个示例的东西是,恕我直言,相当于在更多程序风格的代码中执行以下操作:
for(i = 0; i < 10; i++) { for(j = 0; j < 10; j++) { if(x < 2) { z++; } else { y++; }}}
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,真正的问题是格式不佳,而不是过度嵌套.您如何评价格式良好的嵌套函数版本与临时变量版本的可读性/可理解性?您认为重函数调用嵌套是不好的样式,即使它的格式是为了最大可读性?如果是这样,为什么?
在R中以锁步方式对两个向量进行排序的最有效方法是什么?第一个向量应按升序排序,第二个向量应以锁步方式重新排序,以使排序前具有相应索引的元素在排序后仍具有相应的索引.例如:
foo <- c(1,3,2, 5,4)
bar <- c(2,6,4,10,8)
sort2(foo, bar)
# foo == c(1,2,3,4, 5)
# bar == c(2,4,6,8,10)
Run Code Online (Sandbox Code Playgroud)
注意:效率是绝对必须的,因为我试图将此作为创建Kendall的Tau的O(N log N)实现的基础,以作为补丁提交.我想避免在C中编写我自己的特殊功能来执行此操作,但如果在R内无法有效完成,我愿意这样做.
d ×2
performance ×2
api ×1
assert ×1
coding-style ×1
oop ×1
optimization ×1
pointers ×1
r ×1
readability ×1
sorting ×1