Hacker News new | past | comments | ask | show | jobs | submit login
Strangest Language Features (stackoverflow.com)
129 points by antoviaque on Dec 15, 2011 | hide | past | favorite | 73 comments



Smalltalk's "cascading" operator is a strange (in the nicest way possible, it's mostly strange that nobody else has it) feature: a pretty popular style in OO languages these days is "fluent interfaces", in which methods return their `this` and — through method chaining — developers can call several methods on the same object while limiting verbosity. This style is of course possible in smalltalk:

    foo.bar().baz()
becomes

    foo bar baz
and if `bar` returns `self`/`this`, `baz` will be called on the same object. However, this has the issue that method implementors have to choose between fluent interfaces and returning useful values, as the fluency is decided by the return value domain for the method.

Smalltalk sidesteps this by having an operator `;` which essentially means "the message after this operator is sent to the same object as the message before this operator". As a result, in the example above you could have `bar` returning the height of the empire state building, and you'd still get the exact same result by writing:

    foo bar ; baz
(a message cascade returns the value returned by the last message)

Smalltalk was/is not fond of literal syntaxes, so its collection APIs (as far as adding to them goes anyway) look a lot like Java's, yet you could write things in a terser manner by using cascading:

    c := (ArrayList new) add: 3
                       ; add: 4
                       ; add: 5
                       ; add: 6
                       ; yourself.
is equivalent to:

    c := ArrayList new.
    c add: 3.
    c add: 4.
    c add: 5.
    c add: 6.
(note `yourself`, which does exactly what it says: it returns its `self`)

(and yes I know you can combine Java's anonymous subclasses and instance initializers to get something similar, in the specific case of instantiating non-final collections).


> it's mostly strange that nobody else has it

It looks like it is the same as clojure's doto macro:

http://clojuredocs.org/clojure_core/clojure.core/doto

And it is strange more languages don't have it.


It is pretty nice (and makes Clojure jump up a place or two in the completely unranked list of "languages I really need to learn"). It looks very similar yes, although there's a difference in that `doto` can only returns its `this`.


Clojure has something even cooler than doto. It's called "thrush operators":

http://clojuredocs.org/clojure_core/clojure.core/-%3E and http://clojuredocs.org/clojure_core/clojure.core/-%3E%3E


'with' (Pascal, MS Visual Basic, possibly others) is somewhat equivalent (it lacks the ability to return self) but more explicit:

  c := LeftAsAnExerciseForTheReader();
  with c do
  begin
    Add(3);
    Add(4);
    Add(5);
    Add(6);
  end;


So, if you know Java has a similar syntax that is the same terseness, why mention it without example? I've found that many people don't know of it:

In Java this is:

List<Integer> c = new ArrayList<>() {{ add(3); add(4); add(5); add(6); }};


> So, if you know Java has a similar syntax that is the same terseness, why mention it without example?

1. Because it's more limited in that it can only initialize an object and it requires that the type being initialized be non-final

2. Because it's kind-of a hack, using instance initializers (itself not a well-known feature) and anonymous classes (not overly common for concrete classes in java) simultanously

I also like to think people can be delighted in looking for treasures after a hint, and it's not too hard to find references to that trick, whereas references to Smalltalk's cascading operators are sparse and lost in the noise.


> it's mostly strange that nobody else has it

For what it's worth, we're working on adding it to Dart. I don't think it's a done deal yet, but I believe we're close to having something finalized.


I've missed this feature in other languages.

Now I have a name, the cascades operator.

I don't think the syntax is especially elegant/readable, though.


It's extremely elegant and readable, when done idiomatically.

  list := OrderedCollection new
            add: 1;
            add: 2;
            add: 3;
            yourself
There's actually a literal syntax for Arrays, but the above example applies to all code and is used heavily in constructors and anything using a builder pattern.


> There's actually a literal syntax for Arrays

Much in the same way as Java, smalltalk-80's arrays are not the most useful thing (they're significantly worse than Java's if I remember correctly, as you can only put other literals in them). So most collections in "user" code are not going to be arrays.

I believe gnu smalltalk extends arrays to be more useful (and adds other collection literals).


> as you can only put other literals in them

What? That's not even close to true. You are misunderstanding something. Actually, I see I think the issue... most Smalltalks have progressed a bit since Smalltalk 80 and now have a fully functional array literal syntax whereas you're talking about the very restrictive original syntax from decades ago.


> Actually, I see I think the issue... most Smalltalks have progressed a bit since Smalltalk 80 and now have a fully functional array literal syntax whereas you're talking about the very restrictive original syntax from decades ago.

I'm talking about Smalltalk-80, hence specifying it, but I know Dolphin Smalltalk still has that restriction.


Well I brought up the Array literals in the context of modern Smalltalk; it makes little sense to respond to that by criticizing a decades old version of Smalltalk. Dolphin is a virtually dead Smalltalk, died officially a while back and was then resurrected, but it's hardly the model of a modern Smalltalk anymore. Visual Works, Pharo, Squeak, and Gemstone are modern Smalltalk's and all have a fully functional array literal syntax.


COBOL's ALTER statement.

As if COBOL weren't WTFy enough, the statement ALTER X TO PROCEED TO Y changes any subsequent GOTO X statement to go to Y instead. Meaning it's anybody's guess where a given GO TO, considered in isolation, goes to!


I upvoted you because it is the first thing I think of when I think of this question, but in Cobol's defense, self-modifying code (http://en.wikipedia.org/wiki/Self-modifying_code) was fairly normal at the time COBOL was conceived.

For a nice example from a later date, look at the GetChar subroutine on Commodore Basic. It loaded a byte from a hard-coded address, and then updated that address (hm, probably in the reverse order, since, IIRC, it shared code with GotChar, which returned the last value GetChar returned)


I find the amount of 'closed' questions on StackOverflow rather frustrating. I don't see how artificially restricting questions like this helps the site.

That said, I find the responses rather unsatisfying. Language design errors and quirks rather than unusual but useful features.


Counterpoint: I find it refreshing. In my opinion many otherwise interesting virtual communities degrade due to lack of some form of moderation.

I don't see it as artificially restricting questions. They're enforcing the rules that preserve the character and quality of the site. It's not arbitrary:

> This question is not a good fit to our Q&A format. We expect answers to generally involve facts, references, or specific expertise; this question will likely solicit opinion, debate, arguments, polling, or extended discussion.

There are other places for that sort of free-form discussion. Separating them from the factual Q&A is a win-win.


They just decided they didn't want to a polling site. I think the programmers stack exchange is where these questions go now, but who can tell? Generally I just post my questions somewhere obviously wrong and wait for someone to tell me where they go.


i bet it does a woozey on their databases.


The fact that this question is closed is one of the things that annoys me the most about stackoverflow. It sometimes seems like people can't ask interesting questions without others getting offended.


Funnily enough, this is what I like most about stackoverflow. They know what they're good at, they know what use-cases the site is designed for, and they actively fight mission creep.


Seems everything that isn't a direct question/answer gets closed. Seems like they miss an opportunity with the discussion questions. They have really smart community that can't really converse on the site of something doesn't fit into he narrow question and answer definition.


That's the whole point of StackOverflow. It's not a discussion platform. It's a Q&A platform. You can dispute whether that's a good idea, but they know exactly what they are doing.


Deletionists.


Common Lisp has a global variable called read-base ,which controls also base numbers are read in with. This, IIRC, was put in because some earlier Lisps read numbers in octal, while others used decimal. Setting this variable to something higher than 10 can give you strange results. For example,

    nil
    => NIL
    (eql '() nil)
    => T
    (setf *read-base* 36)
    nil
    => 30477
    (eql '() nil)
    ERROR: 19101 is not a function name; try using a symbol instead
    (|EQL| '() nil)
    => NIL
For you non-lispers, the empty list '() is equal to the "false" value, nil. Also, the pipes are special syntax to allow for symbols which normally not parse as symbols. (The uppercase is for historical reasons too).

The moral of this story: "See that control variable over there, the one that does weird things to parsing? Don't touch it unless you know what you're doing."


I presume that CL standardized on a base as a default, though? Otherwise you have an appropriately recursive problem that every base is "base-10" in that base.

edit: (setf read-base (+ 1 1 1 1 1 1 1 1 1 1)) :)


I just went and checked, and the standard gives a default value of "10." for read-base , so decimal by default (I think). It also says:

"Notes:

Altering the input radix can be useful when reading data files in special formats. "


Second SO repost. Previously discussed with > 80 comments here:

https://news.ycombinator.com/item?id=1601062


I have to admit that I upvoted the post because I had never seen this before, and the previous discussion is nearly 1.5 years old.

That said....how did this get resubmitted? They both have the exact same URL

---- # edit: I see...one URL is http://stackoverflow.com/questions/1995113/

The other has a slug in it: http://stackoverflow.com/questions/1995113/strangest-languag...

I thought HN had some kind of redirect-autofollow that sniffed this kind of thing out? Or at least that's why I assumed hitting "submit" can result in a long delay, even before you're told that the title is > 80 (I wish there were a javascript validator for title length, while I'm pondering things...)


Nope, even just appending a slash to a URL will get you past the dupe filter. Even beyond that, though, the filter only looks at recently accessed posts, so something with that long a gap between reposts almost certainly wouldn't get flagged.



It's in the middle of the first page: http://stackoverflow.com/a/1995275/221786


I love the first answer to that question. And not just because I wrote it :)

A little bit of C trivia:

In C, arrays can be indexed like so:

a[10] which is very common.

However, the lesser known form (which really does work!) is:

10[a] which means the same as the above.


To be clear, it works because X[Y] is a synonym for * (X + Y)

Since addition is commutative, * (X + Y) can be rewritten as * (Y + X) which is a synonym for... Y[X]


similarly, the 'approaches' pseudo-operator:

while (i --> 0) { /* do something */ }


For some variety, there's also the left-handed "goes to" operator.

    while (5 <-- x) {} //omits the zero
and the much easier to type

    while (x --- 0) {} //equivalent to the "-->" operator


For more JavaScript awesomeness on par with what's already presented, see http://wtfjs.com/ =)


I have to say, this is what I come to HN for. I learned a lot from that link and doing wikipedia searches kept me entertained during lunch.


What about strangest programmers needs :D : http://stackoverflow.com/questions/8525199/how-to-store-java...

Edit: I think the title of the question was edited, the original was something like : "How to store javascript code in jquery variable without it executing?"


PHP; converts array('123' => 0); into array(123 => 0);

Which I came across as a problem when working with mongodb as it will only except strings as keys (not sure if this is enforced by PHP and/or mongo). Luckily you can create a class with numeric properties and pass that to mongodb which will then be treated as strings i.e

$array = new stdClass; $array->{123} = 0;


> only except strings

A strange feature of the English language is that this doesn't work; you have to use 'accept' here.


Similar, but for more exotic languages: "What is the worst programming language you ever worked with?" http://stackoverflow.com/questions/961942/what-is-the-worst-...


Icon's conditional statements were pretty odd http://en.wikipedia.org/wiki/Icon_(programming_language)


The Multi-Dimensional Analog Literals template in C++ is amazing.


Ah yes, all the Perl special variables! I actually did get scoffed at at work for using "use english" (while taking care it didn't affect regexps).


Identifiers with blanks:

http://tibleiz.net/zinc/

(not that strange, but not so common)


Wow...not a single SO response that said Ruby? I guess that's a good thing for us Rubyists?


Someone else is probably going to mention flip-flops, so let me show you "defined?":

    a = 1
    defined?(a) # => "local-variable"
    defined?(p) # => "method"
    defined?(nothing) # => nil
defined? is a syntax-construct (not a method) which tries to tell you if its "parameter" is defined. The rules for this are rather interesting.

    class String
      def print
        p self
        self
      end
    end
Okay, String#print is just a helper method to prove my point.

    defined?("hello".print)        # => "method"
    defined?("hello".print.strip)  # => prints out "hello", then returns "method"
    defined?("hello".print.stripp) # => prints out "hello", then returns nil
Okay, so defined? may actually call methods for you to figure out if it's "defined" or not. What if we try something more complex:

    defined?(if true then "hello".print.strip end) # => "expression"
Wait, what? This does not call the print method. In fact, this check is done entirely at parse-time. "defined?(if true then … end)" will always return "expression". In fact, anything more complex than local variables, method calls or constant names will just return "expression". Well, except for "defined?" though; defined? can't check itself - it's a syntax error.

Another intresting "feature": If any exception is raised, the whole expression is considered undefined:

    class String; def print; raise; end; end
    
    defined?("hello".print.strip) # => nil


Actually, there is, just not as many upvotes as the others.

http://stackoverflow.com/a/2026849

Basically, it is possible to inherit a random class in ruby.

    class RandomSubclass < [Array, Hash, String, Fixnum, Float, TrueClass].sample
       ...
    end


I wouldn’t call that a strange feature, just a surprising consequence of an un-strange feature, namely that inheritance involves expressions and that classes are first-class entities.

Folks from certain other languages would be just as surprised to find out that you can alias classes by assigning them, return them from functions, and so on.


Another one: class variables!

    # Define two class variables in two different classes:
    class MyClass
      @@base = 1
    end
    
    class OtherClass
      @@base = 2
    end
    
    # Define it in the superclass too:
    class Object
      @@base = 3
    end

    class MyClass
      # Magic! The subclass-variable has now changed!
      p @@base # => 3
    end

    class OtherClass
      # In both classes in fact:
      p @@base # => 3
      
      # And finally, let's reset this:
      @@base = 4
    end

    class Object
      # Whoops, this changes the superclass too:
      p @@base # => 4
    end
Explanation: Two class variables with the same name can't exists in the same class hierachy. Therefore, class variable lookup (and setter) will always traverse to the upmost-class where the variable is defined.

(Hope you don't mind that I wrote these in two different posts.)


I'm still reeling from finding out that zero is true.


PHP: Personal favorite I used to quiz my students on:

$a = "5 Monkeys";

$b = "2 Bananas";

var_dump($a);

string(9) "5 Monkeys"

var_dump($a + $b);

int(7)


This is an evil bug in Javascript

parseInt('06') // 6

parseInt('07') // 7

parseInt('08') // 0

parseInt('09') // 0

parseInt('10') // 10

parseInt should really return NaN for '08', '09' etc


Octal notation, with an invalid number. Makes perfect sense.

It's not a bug, behaves like specified:

https://developer.mozilla.org/en/JavaScript/Reference/Global...

If parseInt encounters a character that is not a numeral in the specified radix, it ignores it and all succeeding characters and returns the integer value parsed up to that point. parseInt truncates numbers to integer values. Leading and trailing spaces are allowed.

[...]

For this reason always specify a radix when using parseInt.


"Behaves as specified", "makes perfect sense", and "not a bug" are three entirely different concepts.

It does _not_ make perfect sense to anybody who's never used octal. That is presumably the vast majority of anybody born past, say, 1980.

As such, it _is_ a bug in the sense that it violates expectations. It's just a bug in the spec, not in the code.


Numeric constants starting with 0 define octal values in many languages, hell they do so even in Java. Does that mean all those languages are buggy? I'd say you're going to find features that don't make sense to anyone who's never used them...pretty much anywhere.

I would think the issue is more the behavior of "parse as much as you can until you can't, and return what you got so far", which is what causes the unexpected result of returning 0 instead of bailing out. However that apparently wasn't fixed in ECMAScript 5, presumably for backwards compatibility.


I'd say that the entire concept of octal literals is a bug, yes. (It's almost _entirely_ useless, a leftover from the days of yore. When for Christmas, we got naked, wrapped ourselves in punch tape versions of the latest "editor", and danced around the Christmas tree while setting the line printer on fire. But I digress.. ;)

But fine, if I at least got "undefined" (well, null) as a result of parsing an invalid octal string, it'd be not quite as bad. So yes, if we talk root causes, you put your finger on that. The anachronism of octal parsing just exposes it.


I really don't see how it makes perfect sense for a value which is not by any stretch of imagination a valid octal number to be interpreted as an octal number. Imagine if `parseInt('foo')` gave 38274 — would you also think that made perfect sense?

Also, that document says the behavior is nonstandard, so I don't even see how you can say it's behaving as specified.


I really don't see how it makes perfect sense for a value which is not by any stretch of imagination a valid octal number to be interpreted as an octal number. Imagine if `parseInt('foo')` gave 38274 — would you also think that made perfect sense?

The page specifically says that if radix is unspecified, then "If the input string begins with "0", radix is eight (octal)."

The page also says "If the first character cannot be converted to a number, parseInt returns NaN." so your example is also perfectly defined to return NaN (and thus bogus).

Also, that document says the behavior is nonstandard, so I don't see even how you can say it's behaving as specified.

It's a weird wording in that webpage, because ECMAScript 3 allows it:

"When radix is 0 or undefined and the string's number begins with a 0 digit not followed by an x or X, then the implementation may, at its discretion, interpret the number either as being octal or as being decimal. Implementations are encouraged to interpret numbers in this case as being decimal."

ECMAScript 5 no longer allows it. Given that your code isn't necessarily processed by an ECMAScript 5 compliant JavaScript engine, it's indeed behaving as specified. Maybe instead of "non-standard" a better word would have been "behavior varies between implementations".


The standard encourages implementations to interpret numbers as decimal, and it doesn't say to interpret non-numbers (such as octal 9, which is what the number would have to be if you were taking "0" as the octal prefix) as 0. I don't see how it's necessary for compliance or even sensible to interpret numbers that don't exist in octal as octal 0, except that it's a quirk older implementations had and new ones don't want to break compatibility.


I don't see how it's necessary for compliance or even sensible to interpret numbers that don't exist in octal as octal 0

It's not. That isn't what happens, either. The parser stops when it sees the 9.


Following a spec is not a valid excuse for it not being a bug. Specs have bugs too; sometimes they're even designed in, deliberately, to make companies not look bad, or to preserve backward compatibility.

For a parser to ignore trailing garbage after it has parsed as far as it can is usually a sign of a poor-quality parser. On topic: an odd feature of Pascal is that all text following the final 'end' '.' in the file is ignored. But good quality compilers still issue a warning.


While JavaScript is parsing it as octal, this will cause a whole raft of errors if you are making your users enter dates.

User enters 08 for August, even returning NaN would be a mistake.


You can and should then pass the second radix parameter to parseInt:

    parseInt('08', 10) // => 8
This tells it explicitly that this is a base-10 number, rather than letting it guess at the base. You can also use this to decode things in base n, n <= 36.


It is my impression that the PHP interpreter will, or at least used to, do this to you. Instead of you know, giving you an error like most languages do...

Much worse than this one obviously, caused if I recall by not checking how strtol set endptr.


In JavaScript:

    (NaN === NaN) is false
    (NaN !== NaN) is true


That's not a JavaScript feature; it's part of the IEEE 754 standard for floating point numbers. NaNs are unordered. Every language that provides standard floating point numbers does it that way.


This is isomorphic to NULLs in some languages (I think SQL behaves this way). Basically, NaN isn’t some specific thing, it’s an indication of something that isn’t a number. So two things that aren’t numbers can’t be thought to be equal to each other, they might be radically different things.

If there’s a WTF, it’s that NaN === NaN is either true or false. If I were writing a language, it might be undecideable. But if you end up with:

    Undecideable === Undecideable //=> Undecideable
You are opening up the “Hopelessly Egocentric Null” can of worms:

https://github.com/raganwald/homoiconic/blob/master/2009-02-...


> I think SQL behaves this way

Yes. It's also how NaNs are supposed to work according to IEEE-754.

The only reason why it can be strange in javascript is that it's pretty common to encounter nans in JS as the language tries very hard not to throw errors and likes nans a lot (so `parseInt('foo')` returns NaN instead of `null` or an error), whereas it's very rare in other languages. Pretty much all languages have nans, and all nans behave this way. Here it is in Python:

    >>> float('nan')
    nan
    >>> float('nan') == float('nan')
    False
    >>> float('nan') != float('nan')
    True
    >>> a = float('nan')
    >>> a == a
    False
    >>> import decimal
    >>> decimal.Decimal('NaN')
    Decimal('NaN')
    >>> decimal.Decimal('NaN') == decimal.Decimal('NaN')
    False
    >>> a = decimal.Decimal('NaN')
    >>> a == a
    False
edit: now that I think about it, there is a difference: in SQL, all operations involving `NULL` (including comparisons) return `NULL`, so `NULL = NULL` => `NULL` and `NULL != NULL` => `NULL`.


Specifically, testing for NaN should be done using the isNaN function, never equality. That's not expounded on as often as necessary, I think heh.


This is correct and good. Whats funny, that typeof NaN is "number" :)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: