top | item 7159768

Strangest Programming Language Feature?

74 points| jackhammer2022 | 12 years ago |stackoverflow.com

63 comments

order
[+] Someone|12 years ago|reply
No mention of "ALTER" (http://en.wikipedia.org/wiki/COBOL#Self-modifying_code) on the first page?

Self-modifying code was fairly common at the time COBOL was developed, but incorporating it in a high-level business language was, IMO, a very weird decision.

I also miss call by name (http://en.wikipedia.org/wiki/Man_or_boy_test) on the first page.

In general, one should read the Intercal (http://en.wikipedia.org/wiki/INTERCAL) paper, and figure out from which language each of its features came.

[+] EvanAnderson|12 years ago|reply
Your mentioning "ALTER" made me think about a dialect of BASIC that I once used (STARDOS BASIC on a "Micro V" computer, back in the late 1980s). This BASIC dialect had an "XEQ" function that would pass a string to the tokenizer and execute it as an immediate-mode command. If you started the string with a line number you could create self-modifying BASIC code. It was dizzying to my young mind.
[+] Zenst|12 years ago|reply
You mention COBOL, I was aught COBOL the JSP (Jackson) method and did lovely code. My first job they used GOTO and I was like argh, COBOL has a GOTO verb. Performance and the like, much less cleaner code but effecient :\ and with that the first steps from the academic world into the real world open your eyes up to many weird programing ways and features.

But I did always liked the COBOL, OCCURS DEPENDING ON ( http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/inde... ) and how you could use it to write variable length records to files, saving space on tape or DISC and with that faster and cheaper.

it is after all effeciency and getting that extra drop of performance that drives the weird and wonderful quirks and usage and practices that this topic aspires to highlight.

[+] antirez|12 years ago|reply
Smalltalk's "become" is a pretty interesting one... http://gbracha.blogspot.it/2009/07/miracle-of-become.html
[+] saryant|12 years ago|reply
Akka actors have a very similar feature, same name. It doesn't swap identities though.

It's actually pretty cool if you think of it as a way to track state without having a mutable variable.

One example is this implementation of the dining philosophers problem:

https://github.com/akka/akka/blob/master/akka-samples/akka-s...

You can also use "unbecome" and effectively treat an actor's behavior as a stack, popping and pushing receive functions. One cool trick is to bind a value to your receive function:

  def receive(foo: Foo): Receive = { ... }
Then you can bind immutable data to a given receive function but think of it as mutable by replacing the current receive function with become().
[+] BrandonY|12 years ago|reply
Smalltalk also is rather famous for giving developers enough freedom to more or less destroy the environment with the terrifying looking command "Smalltalk := nil"
[+] al2o3cr|12 years ago|reply
/me drops the MUMPS reference manual on the table

That whole language is one long-running WTF.

[+] roywiggins|12 years ago|reply
This line in MUMPS is not only valid, it also actually does something potentially useful:

    s:foo'="" foo(foo)=foo
It's actually a bit tricky to explain what it does. Everything in MUMPS is effectively a tree. Each tree has a value in the "root node" and you can set it like this:

    set foo="hello"
You can also put data deeper into the tree:

    set foo("fizz")="buzz"
So if something is passed to you and you want to know if you can treat it as a string, you test to see if it's a null string:

    if foo'="" do [something]
('= means !=)

Two more features: 1) Almost every directive can be reduced to one letter. 2) If I want to quit based on a condition, I can do either if condition quit or quit:condition

So the line above is more legibly written as

    if foo'=""  set foo(foo)=foo
So if foo="bar", it's equivalent to:

    set foo("bar")="bar"
[+] perturbation|12 years ago|reply
f p=2,3:2 s q=1 x "f f=3:2 q:f(asterisk)f>p!'q s q=p#f" w:q p,?$x\8+18

(Not sure if this is going to mess up the formatting, so apologies in advance). This (shamelessly stolen from a usenet sig) will print out a table of primes with formatting. Adding a quit based on max prime size is left as exercise to the reader.

Explanation: f = for, but basically used as a while loop since we don't have a terminate condition ('p' is used as the counter variable and we would normally have an upper limit, but since we don't it will keep iterating until something breaks)

We're setting the variable 'p' to 2 on first iteration of the loop, 3 on the next, and then going up by 2 on subsequent.

Then, we're setting the variable 'q' to 1.

'x' is short for XECUTE. It looks at the string following it and executes it as code.

"f f=3:2 q:f(asterisk)f>p!'q s q=p#f"

This is another loop, with the variable 'f' used as the counter, starting at 3 and incrementing by 2.

Each loop iteration, it checks if f^2 is greater than p or if q == 0. If not, it proceeds to set q to p modulo f.

To sum things up: We quit the loop if either we've checked all candidates (excluding evens) up to ~sqrt(p) or if one of these evenly divides p (that is, modulo 0).

The tricky bit:

w:q p,?$x\8+18

w:q == WRITE, using the value of 'q' as a post-conditional, only to be executed for non-zero values of q.

If we write, we will write 'p', setting the position of the cursor with '?' (syntax particular to write) using the '$x' variable (built-in for the current cursor position).

Note: $x\8+18 evaluates to (($x INTEGER DIV 8)+1)8

First line:

GTM>f p=2,3:2 s q=1 x "f f=3:2 q:ff>p!'q s q=p#f" w:q p,?$x\8+18

2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71

Edit: Formatting is messed up. (asterisk == '* '). I could have escaped, but didn't want to add whitespace.

[+] jejones3141|12 years ago|reply
Someone's already mentioned COBOL's ALTER X TO PROCEED TO Y, so I'll mention a programming language called COMAL. A friend with a C64 showed it to me, and it was very respectable for its time and the available resources; reminded me of BASIC09.

Apparently it was written by someone from Denmark, and there were commands to switch back and forth between English and Danish. I don't remember whether it was just for error messages or for those and for the language keywords as well; I want to say the latter.

[+] mck-|12 years ago|reply
In CoffeeScript I discovered the other day that:

  0 <= "" <= 0   # True
  "" is 0        # False
[+] shoo|12 years ago|reply
I guess that is because coffeescript's <= operator is just javascript's <= operator, which does implicit type conversion.

but coffeescript's "is", aka ==, aka === in javascript, doesn't.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

having "==" be semantically quite different to "<=" doesn't seem a particularly nice choice of notation.

arguably coffeescript has made things worse in this case compared to plain javascript, where you're probably not going to expect === to behave similarly to <=.

not obvious how you'd improve this to make it consistent, without say redefining how "==" and "<=" work to make them raise type errors or evaluate to something undefined if the types of the arguments don't match.

[+] runlevel1|12 years ago|reply
It's because equality comparisons in CoffeeScript (==, !=, is, isnt) are always compiled into strict (non-type-converting) comparisons (===, !==). [1]

JavaScript doesn't have strict relational operators (>, <, >=, <=), so all relational comparisons undergo type-conversion. [2]

  CoffeeScript: 0 <= "" <= 0           #  True
  JavaScript:   (0 <= "" && "" <= 0);  // True

  CoffeeScript: "" is 0    #  False
  JavaScript:   "" === 0;  // False
[1]: http://coffeescript.org/#operators

[2]: http://www.ecma-international.org/ecma-262/5.1/#sec-11.8

EDIT: Forgot to include 'is' and 'isnt' operators.

[+] BlackDeath3|12 years ago|reply
>GOD is REAL, unless declared INTEGER.

I'm stealing the hell out of this.

[+] kabdib|12 years ago|reply
: 2 3 ;

... redefines the constant 2 as 3. FORTH. Go figure :-)

[+] bodyfour|12 years ago|reply
Certain ancient FORTRAN compilers would let you do that as well. If the target CPU didn't have a "move immediate" instruction, the compiler would just stash the number into memory. The quickest way to implement it is to just add the number into the symbol table... that way an often-used constant will only need one spot in core.

Of course when your whole compiler has to run in 8 Kwords or whatever, syntax checking isn't a high priority. So if you do "1234 = 0" it would allow it (since '1234' is just a variable in the symbol table) and it actually would change all of the meaning of 1234 everywhere else in the program!

[+] etfb|12 years ago|reply
In Forth, the following are fairly common definitions in the core:

    0 CONSTANT 0
    1 CONSTANT 1
    -1 CONSTANT -1
In an Algolian language like C++ or Java, if the syntax were legal, these would be:

    const 0 = 0;
    const 1 = 1;
    const -1 = -1;
The reason for this is to do with the interpreter. How the Forth interpreter works is very simple:

1. Read one word, where "word" is literally defined as "a sequence of non-space characters delimited by spaces". Some standard words include DUP 2DROP 1+ - . " and :

2. Attempt to find the word in the dictionary. If found, execute it.

3. If it's not found, attempt to interpret it as a number. If that works, push the number on the stack.

4. If neither 2 nor 3 succeed, emit an error message.

So the reason for defining a constant named "0" is to save time: it's quicker to interpret the word "0" if it's in the dictionary; otherwise you have to search the whole dictionary and then do a text-to-number conversion, which takes too long.

So really it does make sense.

[+] marcosdumay|12 years ago|reply
Taking about constants, the scad format (for 3D design) allows for defining and redefining constants, but they always have the last defined values...

That is, unless you import a module within redeclariations, in what case the module will inherit the values of the last declarations above the line it's imported on (not the last one of the file). And yep, that'll replace any declarations within that module.

The biggest surprise is that this is useful.

[+] rbanffy|12 years ago|reply
Actually, it defines a verb that puts 3 on the stack and names it "2".
[+] spc476|12 years ago|reply
INRAC, the langauge RACTER (http://en.wikipedia.org/wiki/Racter) has the most bizarre flow control I've ever seen in any computer language, ever. It can best be described as "a random, pattern matched GOTO/GOSUB" which is the most succinct description I can come up with.

I have a blog entry about it (http://boston.conman.org/2008/06/18.2) but in short, each line of an INRAC program (unless it ends with a '#' mark in which case execution continues to the next line) is a subroutine, each with a label. The label does not need be unique, but when you "call" a subroutine, INRAC will just pick one line with that label at random to execute. The pattern matching comes in because you can select the label with wildcard characters (which just picks a line that matches the pattern at random).

There isn't much about the language on the Internet. In fact, the only other page aside from my blog entry (which I wrote as I went through the existing source code I found for Racter) is the Racter FAQ (https://groups.google.com/forum/#!topic/rec.arts.int-fiction...) which has a few inaccuracies (or perhaps was looking at a version of the code before processing).

[+] zokier|12 years ago|reply
C++ has all sorts of fun stuff. One example is std::vector<bool>, which is not implemented as a simple array of booleans like every other std::vector, but instead it is a bitmap. Afaik this behavior is required by standard. One fun side-effect is that you can't take the address of individual elements of the vector.

Compare these two:

http://ideone.com/qC9yOp

http://ideone.com/jF4krp

[+] eli_gottlieb|12 years ago|reply
I'm the only person thinking of the way MATLAB passes everything by value, including compound objects and structs?
[+] julian_t|12 years ago|reply
Snobol... where patterns are first class constructs, and every line can end with a GOTO. That definitely lets you write some very, er, compact code. But it was superb to program in.

And how about the assigned GOTO in older versions of Fortran? "GOTO N" where N is an integer variable whose value will be known at runtime.

Happy days...

[+] knome|12 years ago|reply
I'm sure you'll be pleased to find that gcc has kept the assigned goto alive as a c extension.

    #include <stdio.h>

    int main( int argc, char ** argv ){

      void * p = && lol ;

     bounce:
      goto *p ;

     lol:
      printf("lol %p\n", p);
      p = && wtf;
      goto bounce;

     wtf:
      printf("wtf %p\n", p);
      p = && lol;
      goto bounce;

    }
[+] adamnemecek|12 years ago|reply
Fun fact, this is also the reason why 'i' is commonly used as a name for the loop counter variable.
[+] kps|12 years ago|reply
No, it's the other way around; i, j, ... have a long history in mathematics as indices for matrices, summations, etc., with m, n likewise being traditional for the dimensions of a matrix.

In early FORTRAN, integers were present primarily to be used as array subscripts. The INteger mnemonic doesn't appear in any of the early papers or manuals.

As a side note, on the topic of features that would currently seem ‘strange’, some early languages that were intended to be programmed using teletypewriters rather than FORTRAN's Hollerith cards used half-line motions to write array subscripts as actual subscripts.

[+] tsm|12 years ago|reply
What about as an abbreviation for "index"?
[+] cratermoon|12 years ago|reply
The COBOL MOVE-CORRESPONDING verb. I'm not going to try to explain exactly how it works here, but imagine, if you will, copying the contents of one table to another table with a different column structure, but sort of the same names.
[+] rst|12 years ago|reply
This is one of the COBOL features that makes a lot more sense if you think of COBOL as SQL for tape drives than as something that is trying to be, say, Pascal or Ada and failing. (Along with, say, pretty much the entire DATA DIVISION...)
[+] Pxtl|12 years ago|reply
C switch fallthrough. I know it's old and everybody's used to it and I get why it's there, but it's freaking weird. I love c#'s response that you must use goto <case> instead to make fallthrough explicit.
[+] kyberias|12 years ago|reply
This question is a beautiful invitation for everyone to defend their favorite languages! :)
[+] Pxtl|12 years ago|reply
in vb.net: off-by-one array sizes so people who do one-based arrays don't get hurt. Also, two sets of boolean operators, the simpler ones don't short-circuit (or vs orelse, and vs andalso).
[+] analog31|12 years ago|reply
Line numbers in BASIC
[+] ahoge|12 years ago|reply
It kinda made sense, because there wasn't anything fancy like Notepad. If you wanted to read some section, you had to specify the range. If you wanted to change a line, you overwrote it by using the same line number. If you wanted to insert a line, you had to pick a line number which lies between those other two line numbers. That's why you used an increment of 10 (or whatever) instead of 1.
[+] rbanffy|12 years ago|reply
You obviously never dropped a deck of punchcards, did you?

Line numbers are a wonderful thing in that situation.