Answers:
在C中,可以像这样对数组建立索引:
a[10]
这很常见。
但是,鲜为人知的形式(确实有效!)是:
10[a]
与上述相同。
在JavaScript中:
'5' + 3 gives '53'
鉴于
'5' - 3 gives 2
+
字符串连接的方法太可怕了
在JavaScript中,以下结构
return
{
id : 1234,
title : 'Tony the Pony'
};
返回是一个语法错误由于对之后的换行符偷偷摸摸隐分号插入undefined
return
。尽管您可以期望以下工作:
return {
id : 1234,
title : 'Tony the Pony'
};
更糟糕的是,这个程序也很好(至少在Chrome中):
return /*
*/{
id : 1234,
title : 'Tony the Pony'
};
这是同一问题的变体,不会产生语法错误,只是默默地失败:
return
2 + 2;
JavaScript真值表:
'' == '0' // false
0 == '' // true
0 == '0' // true
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
" \t\r\n" == 0 // true
资料来源:道格·克罗克福德
==
在语言设计者眼中,有什么目的呢?
==
具有的含义===
,那就太好了,然后还有另一个运算符,类似于~=
允许类型强制的操作。
C和C ++中的三字母组合。
int main() {
printf("LOL??!");
}
这将打印LOL|
,因为三部曲??!
被转换为|
。
自动装箱和Java中的整数缓存的乐趣:
Integer foo = 1000;
Integer bar = 1000;
foo <= bar; // true
foo >= bar; // true
foo == bar; // false
//However, if the values of foo and bar are between 127 and -128 (inclusive)
//the behaviour changes:
Integer foo = 42;
Integer bar = 42;
foo <= bar; // true
foo >= bar; // true
foo == bar; // true
快速浏览一下Java源代码将发现以下内容:
/**
* Returns a <tt>Integer</tt> instance representing the specified
* <tt>int</tt> value.
* If a new <tt>Integer</tt> instance is not required, this method
* should generally be used in preference to the constructor
* {@link #Integer(int)}, as this method is likely to yield
* significantly better space and time performance by caching
* frequently requested values.
*
* @param i an <code>int</code> value.
* @return a <tt>Integer</tt> instance representing <tt>i</tt>.
* @since 1.5
*/
public static Integer valueOf(int i) {
if (i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
注意: IntegerCache.high
默认为127
除非由属性设置。
自动装箱操作的结果是,除非明确创建foo = new Integer(42)
,否则foo和bar都是从缓存中检索到的同一整数对象:例如,因此,在比较引用相等性时,它们将为true而不是false。比较整数值的正确方法是使用.equals;
引用尼尔·弗雷泽(Neil Fraser)(请参阅该页面的结尾),
try {
return true;
} finally {
return false;
}
(在Java中,但行为在JavaScript和Python中显然是相同的)。结果留给读者练习。
编辑:只要我们在这个主题上也考虑以下:
try {
throw new AssertionError();
} finally {
return false;
}
Control cannot leave the body of a finally clause
return
加入finally
条款。
可以使用C ++模板的怪异事物,“多维模拟文字”(Multi-Dimensional Analog Literals)最好地证明了这一点,该多维多维文字使用模板来计算“绘制”形状的面积。以下代码对于3x3矩形有效的C ++
#include"analogliterals.hpp"
using namespace analog_literals::symbols;
unsigned int c = ( o-----o
| !
! !
! !
o-----o ).area;
或者,另一个使用3D立方体的示例:
assert( ( o-------------o
|L \
| L \
| L \
| o-------------o
| ! !
! ! !
o | !
L | !
L | !
L| !
o-------------o ).volume == ( o-------------o
| !
! !
! !
o-------------o ).area * int(I-------------I) );
Perl的许多内置变量:
$#
- 没有评论!$0
,$$
和$?
-就像具有相同名称的shell变量一样$ˋ
,$&
和$'
-奇怪的匹配变量$"
和$,
—列表和输出字段分隔符的怪异变量$!
-就像errno
一个数字,但strerror(errno)
作为一个字符串$_
- 在隐形变量,总是习惯从来没见过$#_
—最后一个子例程参数的索引号...也许@_
—当前函数的(非)名称...也许$@
—上一次提出的例外%::
—符号表$:
,$^
,$~
,$-
,和$=
-是与输出格式$.
和$%
—输入行号,输出页号$/
和$\
—输入和输出记录分隔符$|
—输出缓冲控制器$[
—将您的数组基数从0更改为1,将基于42 更改为:WHEEE!$}
-一点都没有,奇怪的是!$<
,$>
,$(
,$)
-真实和有效的UID和GID@ISA
—当前包的直接超类的名称$^T
—脚本启动时间,以纪元秒为单位$^O
—当前的操作系统名称$^V
—这是Perl的哪个版本这些来自更多的地方。在此处阅读完整列表。
$[
变量是他们所有的最邪恶的。
perldoc perlvar
每5秒钟检查一次,我将非常感激。(尽管我承认,有一半时间我在检查它时都在想:“我知道有一个特殊的变量可以为我做这件事,但我不记得是哪个...” = P)
use English;
在于它会影响RegExp性能。我没有弥补。 perldoc.perl.org/English.html#PERFORMANCE
/$foo[bar]/
,[bar]
零件是数组的字符类还是下标@foo
?Grep perldata给出了可怕的答案。
PHP对string中的数值的处理。有关完整的详细信息,请参见先前对其他问题的回答,但总之:
"01a4" != "001a4"
如果您有两个包含不同字符数的字符串,则不能认为它们相等。前导零很重要,因为它们是字符串而不是数字。
"01e4" == "001e4"
PHP不喜欢字符串。它正在寻找可以将您的价值观视为数字的借口。稍微更改那些字符串中的十六进制字符,然后PHP突然断定它们不再是字符串,它们是科学计数法中的数字(PHP不在乎您使用引号),并且它们是等效的,因为数字的前导零被忽略了。为了强调这一点,您会发现PHP也被评估"01e4" == "10000"
为true,因为这些是具有相等值的数字。这是有记录的行为,只是不太明智。
让我们对所有试图取消保留字的语言(例如PL / I)进行投票。
您还可以在哪里合法地编写如下有趣的表达式:
IF IF THEN THEN = ELSE ELSE ELSE = THEN
(IF
,THEN
,ELSE
是变量名)
要么
IF IF THEN THEN ELSE ELSE
(IF
是一个变量,THEN
并且ELSE
是子例程)
JavaScript八进制转换“功能”是一个很好的相关知识:
parseInt('06') // 6
parseInt('07') // 7
parseInt('08') // 0
parseInt('09') // 0
parseInt('10') // 10
更多细节在这里。
在C语言中,可以将do / while与switch语句交织。这是使用此方法的memcpy的示例:
void duff_memcpy( char* to, char* from, size_t count ) {
size_t n = (count+7)/8;
switch( count%8 ) {
case 0: do{ *to++ = *from++;
case 7: *to++ = *from++;
case 6: *to++ = *from++;
case 5: *to++ = *from++;
case 4: *to++ = *from++;
case 3: *to++ = *from++;
case 2: *to++ = *from++;
case 1: *to++ = *from++;
}while(--n>0);
}
}
while
,结尾处的是(有条件的)JMP
返回到do
,这说明了为什么可以跳过do
并仍然在循环中结束。
Algol按名称传递(使用C语法说明):
int a[3] = { 1, 2, 3 };
int i = 1;
void f(int j)
{
int k;
k = j; // k = 2
i = 0;
k = j; // k = 1 (!?!)
}
int main()
{
f(a[i]);
}
def f(j : => int)
)
... template<typename T> struct by_name { virtual operator T&() = 0; }; void f(by_name<int> j) { ... } int main() { f(struct : by_name<int> { operator int&() { return a[i]; } }); }
?
在Python中:
>>> x=5
>>> 1<x<10
True
>>> 1<x<3
False
不是WTF,而是有用的功能。
(10 > 5 > 1) != ((10 > 5) > 1)
Python的功能。
(funct_a(5)+5 > b > funct_a(5))
仅调用funct_a(5)
一次。这是一个很棒的功能!
funct_a
在该示例中将被调用两次。b > funct_a(5) > c
与相对,在中它只会被调用一次b > funct_a(5) and funct_a(5) > c
。
在Java中:
int[] numbers() {
return null;
}
可以写成:
int numbers() [] {
return null;
}
const T*
并且T const*
等效,它T* const
是指针的常量。另外,我讨厌无字体。
numbers()[2]
是法律声明。
INTERCAL可能是最奇怪的语言功能的最佳概括。我个人最喜欢的是COMEFROM语句,它几乎与GOTO相反。
COMEFROM与GOTO大致相反,它可以将执行状态从代码中的任意点转移到COMEFROM语句。代码中发生状态转移的点通常作为COMEFROM的参数给出。是否在指定的传输点在指令之前还是之后进行传输取决于所使用的语言。根据所使用的语言,引用同一个出发点的多个COMEFROM可能无效,不确定,以某种已定义的优先级执行,或者甚至导致并行执行或并行执行(如线程插入)所示。“ COMEFROM x”语句的一个简单示例是标签x(它不需要物理上位于其对应的COMEFROM附近的任何位置),它充当“活板门”。当代码执行到达标签时,控制权将传递到COMEFROM之后的语句。这样做的结果主要是使调试(和理解程序的控制流)极其困难,因为在标签附近没有迹象表明控制将神秘地跳到程序的另一点。
PLEASE
足够频繁地使用修饰符,则INTERCAL编译器实际上可以拒绝编译该程序!
并不是真正的语言功能,而是实现上的缺陷:一些早期的Fortran编译器通过使用常量池来实现常量。所有参数均通过引用传递。如果您调用了一个函数,例如
f(1)
编译器会将常量池中常量1的地址传递给函数。如果在函数中为参数分配了一个值,则将在程序中全局更改该值(在本例中为1)。造成一些头部抓挠。
2+2
可以等于5
(2
当然,对于非常大的值!)。
2+2
也将相等)。5
5
2 + 2 = 5
; 那将是语法错误。真实的是2 + 2 .EQ. 5
。
不知道它是否可以被视为一种语言功能,但是,在C ++中,几乎所有与模板有关的编译器错误都每天为世界各地的许多C ++程序员提供相当数量的WTF :)
std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::vector< std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::iterator>(std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::iterator, std::vector<std::pair<int, std::complex>, std::allocator<std::pair<int, std::complex> > >::iterator, std::allocator<std::pair<int, std::complex> >)
C的许多名称空间:
typedef int i;
void foo()
{
struct i {i i;} i;
i: i.i = 3;
printf( "%i\n", i.i);
}
或带有字符:
typedef char c;
void foo()
{
struct c {c c;} c;
c: c.c = 'c';
printf( "%c\n", c.c);
}
我会说Python的整个空白是我最大的WTF功能。没错,一段时间后您或多或少习惯了它,现代编辑器使它易于处理,但是即使在过去一年中大部分时间都是全职Python开发之后,我仍然相信这是一个坏主意。我已经阅读了所有背后的原因,但老实说,它妨碍了我的工作效率。虽然不是很多,但仍然是马鞍下的毛刺。
编辑:从评论来看,有些人似乎认为我不喜欢缩进我的代码。那是不正确的评估。无论使用哪种语言以及是否被强制使用,我总是缩进代码。我不喜欢的是缩进定义了一行代码所在的块。为此,我更喜欢使用显式定界符。除其他原因外,我发现显式的定界符使剪切和粘贴代码更加容易。
例如,如果我有一个缩进4个空格的块并将其粘贴到缩进8个空格的块的末尾,那么我的编辑器(所有编辑器?)不知道粘贴的代码是属于8个空格的块还是属于外部的代码块。OTOH,如果我有明确的定界符,则很明显,代码属于哪个块以及应如何(重新)缩进它们-通过智能地寻找块定界符来实现。
编辑2:一些提供评论的人似乎认为这是我讨厌的功能,或者我认为使python成为不良语言。再次,不是真的。尽管我不太喜欢它,但这是没有意义的。问题是关于最奇怪的语言功能,我认为这很奇怪,因为它使用的语言非常少(但> 0)。
我为此感到挣扎:
1;
在perl中,模块需要返回true。
'Cogito ergo sum';
众所周知的在所有可能的宇宙中都是正确的。这确保了最大的可移植性。”
<?=1;?>
返回1. <?=true;?>
返回1. <?=false;?>
返回null。
我很惊讶没有人提到Visual Basic的7循环结构。
For i As Integer = 1 to 10 ... Next
While True ... End While
Do While True ... Loop
Do Until True ... Loop
Do ... Loop While True
Do ... Loop Until True
While True ... Wend
因为贴!在有条件的正面的方式太复杂!
While
和Whend
”,因为有些人确实会用无声的唇音近似的发音来发音“ while”。当然,它的排列更好,并且排列的代码也不错。
对于那些不知道的人,它bc
是一种“任意精度计算器语言”,我经常使用它来进行快速计算,尤其是当涉及的数字很大时($
提示):
$ bc -lq
12^345
20774466823273785598434446955827049735727869127052322369317059031795\
19704325276892191015329301807037794598378537132233994613616420526484\
93077727371807711237016056649272805971389591721704273857856298577322\
13812114239610682963085721433938547031679267799296826048444696211521\
30457090778409728703018428147734622401526422774317612081074841839507\
864189781700150115308454681772032
bc
长期以来一直是标准的Unix命令。
现在开始使用“ WTF功能”。这来自man bc
(强调我的):
quit:读取quit语句时,无论在哪里找到quit语句,bc处理器都会终止。 例如,“ if(0 == 1)quit”将导致bc终止。
halt:halt语句(扩展名)是已执行的语句,该语句使bc处理器仅在执行时退出。 例如,“ if(0 == 1)暂停”将不会导致bc终止,因为未执行暂停。
bc
在那之前我曾经使用过,并且bc
由于手册页中的引号,我想在我的帖子中写一些内容。
echo '[q]sa[ln0=aln256%Pln256/snlbx]sb3135071790101768542287578439snlbxq'|dc
尽管您可能已经知道这一点)。
我一直想知道为什么最简单的程序是:
class HelloWorldApp {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
可能是:
print "Hello World!"
也许这首先是要吓computer计算机科学专业的学生...
JavaScript是面向对象的,对吗?因此,应在文字字符串和数字上运行方法。喜欢"hello".toUpperCase()
和3.toString()
。原来第二个是语法错误,为什么?因为解析器希望数字后跟一个小数点才是浮点文字。这不是WTF,WTF是您只需添加另一个点使其起作用:
3..toString()
原因是文字3.
被解释为3.0
,并且3.0.toString()
可以正常工作。
3..__add__(4)
)。再说一次,我认为(3).__add__(4)
这样做的方式对大脑的伤害要小得多:)
3.0.toString()
使我的眼睛发痒。
在JavaScript中:
2 == [2]
// Even stranger
2 == [[[2]]]
// And down-right nutty
var a = { "abc" : 1 };
a[[[["abc"]]]] === a["abc"]; // this is also true
幸运的是,stackoverflow.com上的好心人向我解释了整个事情: 为什么JavaScript中2 == [2]?
===
。
Number(n)
用来做类似的事情。不幸的是在这两个我们的解决方案的===
休息=(
我最讨厌的功能是任何包含条件逻辑的配置文件语法。这种事情在Java世界中非常盛行(Ant,Maven等。您知道自己是谁!)。
您最终只能使用ac ** p语言进行编程,并且调试和支持的编辑器也很有限。
如果您需要在配置中使用逻辑,则以真实语言对配置进行编码的“ Pythonic”方法要好得多。
powerbasic(www.powerbasic.com)包含编译器指令:
# BLOAT {bloatsize}
这会增加编译后的可执行文件的大小(以<bloatsize>
字节为单位)。这是放置在编译器中的,以防创建可执行文件的人不喜欢生成的可执行文件的体积小。它使EXE看起来更大,可以与肿的编程语言竞争:)