Ask Slashdot: What Are the Strangest Features of Various Programming Languages? 729
itwbennett writes: Every programming language has its own unique quirks, such as weird syntax, unusual functionality or non-standard implementations -- things that can cause developers new to the language, or even seasoned pros, to scratch their heads in wonder (or throw their hands up in despair). Phil Johnson has rounded up some of the strangest — from the + operator in JavaScript to the trigraphs in C and C++ and indentation level in Python. What programming language oddities cause you the most grief?"
Powershell (Score:5, Interesting)
-eq as the equality operator in Powershell is pretty odd.
Lua[0]? (Score:5, Interesting)
C++03 had one that was corrected in C++11. (Score:4, Interesting)
Namely, the >> symbol. Because templates use angle brackets for template parameters, if you had a nested template such as T<int, T1<double> >, you HAD to put the space between the two closing angle brackets. Otherwise the lexer would interpret the two angle brackets as the shift operator.
Re:The idea of variant (var) (Score:4, Interesting)
I can tell you why C# has it.
The normal way intellisense works, you often have to do the end of your line of code then go back to the beginning to type out what type of variable the method you're calling returns now that you know. Var obviates this task by going "oh, of course, it's the type returned by this method".
As usual with language features, it comes from us developers being very very very lazy people.
Re:Perl: TMTOWTDI (Score:3, Interesting)
I think I'd have to agree with this. I never nailed it down to that particular aspect of perl before now, but I can easily see how this characteristic of perl makes it very difficult to identify idioms in the language. With so many ways to do things that you can't always quickly identify what is being done simply by looking at the source code, unless it has been quite rigorously commented.
Code written in an idiomatic style rarely needs much commenting, because people familiar enough with the language to do what the code needs to accomplish will also be familiar with the idioms in the source code, and in practice, only minute or two of examining the source code fragment is ever necessary, even for code that has never seen before, have a general understanding of what the code is trying to accomplish, even if they do not necessarily understand the bigger picture of how the code is being used.
Of course, it's entirely possible, and not even particularly hard, to write obsfuscated code in almost any language, but with perl, my experience is that it takes a special kind of discipline to *NOT* write such code, while at least in other languages, in my experience, writing in a readable style tends to require only a modest amount of discipline.
Re:Perl: TMTOWTDI (Score:5, Interesting)
You just haven't run into another python developer who's "clever" enough yet.
for a,b,c,d in [x.q for x in y if x.z]+[x.r for x in y if x.z]:
a.m=b or c and d
(none of these variables are boolean)
Re:PHP (Score:5, Interesting)
Best feature ever: Intercal (and others) COMEFROM. (Score:4, Interesting)
Heh, all of Intercal is strange.... but COMEFROM is just.... elegant.
It's been implemented for Python, of all things.....
See: https://en.wikipedia.org/wiki/... [wikipedia.org]
Python False = True (Score:5, Interesting)
Re:Many languages and... (Score:4, Interesting)
Well, whether ';' is a statement terminator (like in C) or a statement separator is one thing.
But Javascript takes it to a whole new level. [inimino.org] You can decide not to put them in, and if you break your lines a certain way, you may get the effect of a semicolon where you didn't expect one. And this is part of the language specification.
IDL language (Score:4, Interesting)
Odd integers are true; even integers are false.
Arrays can be indexed with () or []. This leads to namespace problems with functions which are also called with (). For example:
x=a(1,2)
error: undefined variable a.
If you want to call function a, you have to forward declare it for this reason.
There's a different syntax for procedures (which don't have a return value) and functions (which do).
It is required to assign the result of a function to something. You have to write
dummy = foo(1,2,3)
as writing
foo(1,2,3)
will give an error.
Most of the time, a single element array is treated the same as a scalar. But not always, and not being very careful will lead to weird errors.
There are no zero length arrays.
An array can be length 1; a multidimensional array can be length [1,2,2], but a multidimensional array cannot be length [2,1,1]. If the last dimension has length 1, it simply vanishes to a smaller dimension, unless already 1 dimensional. Example:
a = make_array(1,2,2)
; a has dimensions [1,2,2]
a = make_array(2,1,1)
; a has dimensions [2]
This means special code must be written to handle any array operations that might end with last dimension 1.
Array slices are weird.
b = a[3,*,2]
means to take a slice of a along the second dimension. I'd expect the answer to be 1 dimensional, since there's only 1 scan in the slice. But the result has dimensions [1,3]
On the other hand, a[3,2,*] has dimensions [1,1,3], and a[*,3,2] has dimensions [3]. It makes sense in a convoluted way, but it sucks.
LISP (Score:4, Interesting)
Ok, someone has to mention lisp.
Item from 15 or so years ago: a guy posted online that he'd broken into the Pentagon's computers, and found the code for SDI, and it was written in lisp. He didn't want to break US security, but he did post the last five lines of the code.... (stupid slashdot edit filter - 5 lines of ) was not junk... at least, not in lisp....)
mark
if(allocation_succeeded) (Score:5, Interesting)
if (a = b) assigns the contents of b to a and executes the code following if b 0. Who the hell thought that would be a good idea?
If b is an expression that returns a reference to a newly allocated resource, such as fopen or malloc, this if statement represents trying to allocate a resource and then skipping the following compound statement if the allocation failed. It's what they had before exceptions, and it's what they still have on microcontrollers too small to have the overhead of a full-featured exception handler.
strings terminated by a binary zero rather than their physical size. Who the hell thought that would be a good idea?
Probably the same way that most popular operating systems store text files as a list of lines separated by newline characters, encoded as 0x0A on UNIX or Windows but 0x0D on Apple II or classic Mac OS. VMS is an exception in that its "non-stream" text files [sympatico.ca] have each line prefixed by its length.
Re:Powershell (Score:4, Interesting)
A lot of bash and *nix stuff is in PowerShell, which I think it's the point. I remember the first time I opened a session and instinctively typed "ls" without it giving an error.
Re:cmp %rdi,%rax (Score:5, Interesting)
I always liked the target-first approach of Intel. Like strcpy(dst, src). I know I'm mucking with (dst) string, and not doing anything with (src). The same with (MOV %eax, 0xdeadbeef).
Imagine strcpy(src,dst), which many people would say is more logical because you're saying "Perform a string copy from (src) to (dst)." We say "Copy from source to destination" all the time--it's how we think, right? And then: strncpy(src,dst,32). So with strcpy(), the last argument is the thing we mess with; while strncpy() it's some argument in the middle.
This is why strcpy(dst,src) and strncpy(dst,src,len) are set: the first argument is the target. These calls immediately tell you what they actually change. printf() changes nothing, but uses the first argument as its format--it emits a modified content of the first argument based on subsequent arguments; sprintf() changes the first argument to a modified copy of the second argument using all further arguments. If something is changed, it's the first things that are changed.
In Intel assembly, a glance down the left side of the screen rapidly tells you what's roughly going on. You don't need to read the whole line; you just look at opcodes and targets, quickly recognizing which opcodes modify their targets. This immediately tells you flow; and attaching the source data for the modification provides you with logic. This is less decoding than trying to interpret an individual opcode, rearrange it in your head, extract its behavior, extract its logic, and build incrementally with that.
Mixed arithmetic in Matlab (Score:4, Interesting)
This was a stunner for me when I first encountered it. When you mix double and int types in Matlab, it demotes the double to an int! Same with float and int.
Of course, you must create the int explicitly as such (double is the default) but I mean, WTF Matlab??
Null Terminated Strings (Score:4, Interesting)
I'm pretty sure null-terminated strings come from the days of punch cards/punch tape where an unpunched area is read as null (binary zero). Wherever the data-entry clerk stopped typing was the end of the string and the string could be appended to latter (impossible with a non-zero end-of-string symbol or a string length in the header which can't be rewritten on card/tape).
Re:Powershell (Score:5, Interesting)
Two reasons:
1. POSIX environments have already been done on Windows, and they universally suck. SFU/Interix is shit. Cygwin is shit. MKS Toolkit is shit. MinGW/MSYS, which does a better job than any of them, is mostly shit. Even UnxUtils, which is just binaries modified for use with the actual Windows cmd shell are mostly shit. There are so many fundamental differences of philosophy that make working with a Windows system as though it were a POSIX system fundamentally untenable. You're stuck with mostly just munging text files in a binary world.
2. Powershell is what .NET developers think Windows administrators want in a shell. That's why you're allowed to do stuff like import .NET assemblies and use essentially unmodified C# code, but there's still no native SFTP client or server.
Powershell is about 90% of what an administrator actually wants in a shell, and it's actually not that bad. Compared to cmd.exe or VBscript it's balls out fantastic. However, an administrator shouldn't need to learn about .NET objects to be able to write a script, and they shouldn't feel like there's such a fundamental separation between what the shell can do with .NET piping and what executable programs can do. There's a very real encouragement to make everything in Powershell written in and with Powershell exclusively. Like no calling of a binary to do something unless you have no other choice. The shell and the community philosophy very much discourage that... for no real reason other than it's more difficult to get a .NET object out of a binary file and manipulate it with arbitrary .NET methods. I've seen people re-implement a command line zip program with [System.IO.Compression] instead of just using 7z.exe. Why? Just so they can use .NET objects that they never do anything with.
Honestly I really love Powershell, but I wish the philosophy were geared more around getting shit done than getting shit done with .NET.
MSSQL (Score:4, Interesting)
declare @var as int
set @var = 10
print @var
this is totally in the comments
GO
*/
print @var
------------
output -
------------
10
Msg 137, Level 15, State 2, Line 1 Must declare the scalar variable "@var".
Re:Powershell (Score:4, Interesting)
Apart from anything else, what I truly dislike about Powershell is how verbose it is. Perhaps it's my *nix heritage, but I like tidy little mnemonic commands like "mv", "rm" or "grep". Less typing, less things to wrong when you're writing scripts. I also find the syntax rather awkward. It's far better than the alternatives (like vbscript or jscript with WMI), but it's still a long ways away from what I would consider a decent scripting language.
Actually, the worst part of about Powershell is how awfully slow it is. I'm sure that is because it's basically an interface sitting on top of .NET. The *nix shells are, for the most part, self-contained binaries, so bringing up a Bash script is very fast. But then again, sh and its descendants aren't trying to create a "do it all" environment, but rather create control structures and variables to expand upon existing *nix commands.
I wrote a Powershell scriptlet a few months ago to dump Exchange 2010 mailboxes based on some criteria. Works like a charm, and like I said, despite my dislike of Powershell itself, I'm very grateful that it exists. But loading the Exchange scriptlets library takes something 10 to 20 seconds, and you can see Powershell nailing system resources like crazy to get to that point.
While its roots, or at least its inspiration, are the Unix shells, in very important ways, it ignores key Unix principles. It is indeed what Bash would work like if it had been written by Microsoft.
Re:Lua[0]? (Score:4, Interesting)
It is recent computer scientists that started
Not "computer scientists". Just C programmers. The first two languages designed, Fortran and Cobol, start at 1. Algol('68) and all the languages descended from or influenced by it let the programmer set the starting bound (this includes Ada, Pascal and all the other Wirth languages).
Pretty much every language that uses 0 as the only allowable starting index is either descended from C, or borrowed large amounts of its syntax from it. (Some BASICs use 0, but that language is so egregiously unstandardized that its tough to say anything about it with certainty).