

What is the most intrusive wart on your favourite programming language? - apgwoz


======
mdasen
Java: The fact that I have to manually cast Arrays to a template. Everything
else allows me to template nicely except arrays.

Python: The error message passed when you call a method with the wrong number
of arguments. It's just off since the method "def apple(self, steve,
new_product)" has three args, but you'll call it with two "apple(steve,
new_product)". So, the message that gets passed back if I pass in one or three
arguments is just wrong. I actually like the explicit self in the definition,
but the error message needs to say something like "method given the wrong
number of args. 1 argument passed when there are 2 arguments plus implicitly
passed self."

Python: The functions that should be methods. len(list) just doesn't rub me as
well as list.len(). It's such a stupid criticism that I'm hesitant to post it,
but whatever, it bothers me. Likewise, Ruby's int.to_f seems much nicer than a
built-in function float(int). Same with int and str.

PHP: The fact that 0 == "apple". Yeah, integer 0 is equal to any string. That
means: $a = 0; $b = "apple" $c = "ms" $a == $b $b != $c $a == $c

Yeah, a == b, a == c and b != c. Um? Heck, integer 0 is equal to an
uninitialized variable. It just makes bugs that are so hard to find. Yeah, it
stops you from having to cast in certain situations, but for the little time
it takes to cast, you end up with horrible bugs.

Java: The fact that I can't do if(a) { return true } else { return false } in
a method. The Java compiler will say that I don't have a return in that method
because all of my returns are within a conditional even though it will always
hit one of the return statements. if the Java compiler is going to check that
I have an appropriate return, be smart enough to figure out that I do.

~~~
windsurfer
About your last point: You can get around it by typing return (a);

~~~
mdasen
I should have used a better example, but there are a good number of cases
where the Java compiler complains about missing return statements that just
don't need to be there. It's a wart in the language.

~~~
dcminter
Can you cite a specific example where the condition is NOT ambiguous and the
Java compiler WILL produce an error? The example you cite is incorrect (see my
post later) - you can compile code of this form just fine.

I'm not aware of unambiguous situations where the compiler will complain; if
you see an error it's usually pebkac!

------
IsaacSchlueter
My favorite language is Javascript, so I've got plenty of warts to choose
from.

I think that the most intrusive one is semicolon insertion. This is perfectly
valid code that does not do what it looks like:

    
    
        return
          {
            a: "foo"
          };
    

That's quite different from:

    
    
        return {
          a: "foo"
        };

~~~
cousin_it
My favorite language is JavaScript too, and the most annoying wart for me is
function scope instead of lexical scope. For example,

    
    
        var closures = [];
        for (var i = 0; i < 10; i++)
        {
            var j = i;
            closures[i] = function() { alert(j); }
        }
        closures[0](); // outputs 9, WTF?
    

How to fix it:

    
    
        var closures = [];
        for (var i = 0; i < 10; i++) (function()
        {
            var j = i*i;
            closures[i] = function() { alert(j); }
        })(i)
        closures[0](); // outputs 0 as it should

~~~
IsaacSchlueter
You could also do it like this:

    
    
        var closures = [];
        for (var i = 0; i < 10; i++)
        {
            var j = i;
            closures[i] = (function (k) { return function() { alert(k); })(j);
        }
        closures[0](); // outputs 0
    

The issue is that the var here is passed by reference. Ie, all 10 closures
refer to the SAME "i" variable. So, when i is incremented, they see that it's
been incremented.

Outputing 9 is actually correct in the first case. If you want to trap the
current value, you need to copy the value to a new reference, ie, by making it
the argument of a function with a new scope.

~~~
cousin_it
Yeah I know how this stuff works per spec.

 _The issue is that the var here is passed by reference. Ie, all 10 closures
refer to the SAME "i" variable. So, when i is incremented, they see that it's
been incremented._

No, closures refer to the j variable that doesn't get incremented, only
assigned to. The assignment is by value - no vars get "passed by reference",
whatever this means. The actual issue is that all invocations of the loop body
alias the same var j, even though it's declared inside the block.

I usually wrap the whole loop body if it contains multiple variables and
multiple closures closing over them - it's easier on the brain than fixing
every closure creation spot. Kinda sad because JavaScript is almost the
perfect language for my mind.

~~~
IsaacSchlueter
_Yeah I know how this stuff works per spec._

You say that, and yet, you seem not to understand it. Perhaps you know how it
works, but have not thought through the implications of it working any
differently?

 _No, closures refer to the j variable that doesn't get incremented, only
assigned to. ... The actual issue is that all invocations of the loop body
alias the same var j, even though it's declared inside the block._

You're doing it wrong. Javascript doesn't have block-level scope. It _only_
has functional scope.

In the process of parsing an execution context, all "var" statements (and
named function declaration statements, which are a special sort of "var") are
handled first, and only once. A var inside a loop still only creates the
variable once, scoped to the function.

So, your code sample is actually equivalent to:

    
    
        var closures = [], j = undefined;
        for (var i = 0; i < 10; i++) {
            j = i;
            closures[i] = function() { alert(j); }
        }
        closures[0](); // outputs 9, duh ;)
    

You have one "j" variable that is shared by all 10 closures. When you set "j"
in loop iteration 9, the closure created in iteration 0 faithfully sees that
change.

Closures tracking changes to variables in the parent function is not a wart.
Consider this code:

    
    
        var thing = (function () {
            var privateData = "foo";
            return {
                set : function (x) { privateData = x; },
                get : function () { return privateData; }
            };
        })();
    

If closures "trapped" outer values at their current state, then no matter how
you called thing.set(), it would always return "foo" from thing.get(). Also,
it would be much more expensive to keep track of completely independent
contexts. _(You could argue that these side effects make js a less pure
functional language, and you'd be correct; another, less clear, argument could
be made that this makes javascript less good, and I'd disagree.)_

However, your complaint seems not to be about closures or shared activation
objects per se, but rather about the lack of block-level scope. Since "j" is
created inside a set of braces, you seem to suggest that there ought to be
multiple "j" variables created, which are each forgotten at the end of the
loop.

That's how C++ does it. But javascript is not C++. Javascript is javascript.
And _only_ functions create scope in javascript.

IMO, this is not a wart. Doing otherwise would mean that every "while", "for",
"switch", "if", and "else" would have to create an activation object, which
would get quite expensive and complicated.

If you find it confusing that a var inside a loop is only created once, then
take Crockford's advice, and always put all "var" statements at the start of a
function. Personally, I disagree with him on this point, because I find it
more useful to "var" variables near their use so that moving code around
doesn't accidentally result in leakage to the global scope.

~~~
cousin_it
_However, your complaint seems not to be about closures or shared activation
objects per se, but rather about the lack of block-level scope._

Bingo, reread my first comment.

 _If closures "trapped" outer values at their current state, then no matter
how you called thing.set(), it would always return "foo" from thing.get()._

No I don't want hyper-static environments, this would preclude the very useful
encoding of objects with mutable state as closures.

 _Since "j" is created inside a set of braces, you seem to suggest that there
ought to be multiple "j" variables created... every "while", "for", "switch",
"if", and "else" would have to create an activation object, which would get
quite expensive and complicated._

Do you think Ocaml heap-allocates a frame for every scope entered? How is it
about as fast as C++, then? :-) Activation frames would need to be created for
only those blocks that directly construct closures, findable by simple static
analysis. Almost all other languages with closures do precisely this.

As a rule, the introduction of lexical scope doesn't make languages
perceptibly slower. For example, the historical transition of Lisps from
dynamic to lexical scope was accompanied by fears very similar to yours, and
Scheme played a major role in convincing people that lexical scope worked
fast. Modern Scheme compilers are quite clever at eliminating unneeded
activation frames and closures, sometimes even converting closures into inline
code. It's a well-researched topic. (See
<http://www.paulgraham.com/thist.html>, a great retrospective by one of the
best implementers... search for "tied up" for an amusing paragraph about
exactly this. The year was 1982, I was busy being born.)

And to reiterate my point from another comment, all code that relies on
function scope could be converted to a hypothetical lexically-scoped-
JavaScript by a trivial transformation: move every var declaration to the
toplevel of the containing function (which coincides nicely with Crockford's
advice). This demonstrates that function scope is not more useful than lexical
in any practical sense.

In short, I know how JavaScript works, I know how it could work differently,
and I consider the different way superior both in theory and in practice.

~~~
IsaacSchlueter
I guess it just seems much more elegant and simple to me to have only one kind
of scope in the language. One is all you need.

 _No, closures refer to the j variable that doesn't get incremented, only
assigned to._

"Doesn't get incremented, only assigned to." I don't know what that means. How
is "i++;j=i;" any different, really, than "i++;j++"?

 _The assignment is by value - no vars get "passed by reference", whatever
this means._

"Passed by reference" ==> all the closures reference the same "j" variable.
The phrase "pass by reference" is, of course, a bit of a mixed metaphor, since
it's not really "passed" as an argument to a function, but rather trapped by a
closure. Same difference.

 _The actual issue is that all invocations of the loop body alias the same var
j, even though it's declared inside the block._

"Even though"? There _are_ no blocks in javascript; only functions create
scope. That's what's so awesomely simple about this language. Eh, to each his
own, I guess.

Lexical scope _could_ be introduced in the new additions to ES3.1, but I'm
pretty sure it won't be. A javascript engine would be crazy to try to shoehorn
it into the language now, since it would, in fact, break a lot of code in the
wild.

Time to man up. :)

 _Modern Scheme compilers are quite clever at eliminating unneeded activation
frames and closures, sometimes even converting closures into inline code._

Isn't that roughly what tracemonkey does?

~~~
cousin_it
_Isn't that roughly what tracemonkey does?_

Yes. Nice to see implementations are growing up.

 _I guess it just seems much more elegant and simple to me to have only one
kind of scope in the language... That's what's so awesomely simple about this
language._

Block scope can be viewed as only one kind of scope. :-) If you try to define
a language formally, function scope and lexical scope will be about equivalent
on the simplicity scale: scopes will just be tied to code blocks instead of
functions. (The scope nesting machinery is needed for closures anyway.)
Implementation simplicity is also about equivalent: yes, blocks have to
allocate activation frames only if they're needed, but same applies to
functions once you get serious about speed.

The preference depends on your coding style. I find it intuitive to declare
each variable in the outermost {} block that uses it, and not higher up; this
intuition exactly corresponds to the formal concept of block scope. Many
people naturally think like me, hence the huge number of Web articles
complaining about the JS loop scope gotcha, calling it "weird", "unintuitive"
and all manner of names. But as you say, to each his own.

 _A javascript engine would be crazy to try to shoehorn it into the language
now, since it would, in fact, break a lot of code in the wild._

Yes. :-(

------
bayareaguy
I use Lua a lot these days and coming from Python, it seems silly that I have
to provide my own empty? function since standard Lua doesn't offer any way to
get the number of elements in an arbitrary table other than to iterate over
it:

    
    
        function empty_p(t)
            for k,v in pairs(t) do
                return true
            end
            return false
        end
    
    
        -- later on
        if not empty_p(t) then
            do_processing(t)
        end
    

This is because although Lua offers a #t operator, it's only guaranteed to be
correct if you're careful about how the table is constructed. That and the
weird ipairs() behavior for non-trivial tables drives me crazy sometimes.
Here's an example:

    
    
        Lua 5.1.2  Copyright (C) 1994-2007 Lua.org, PUC-Rio
        > t = {1,2,3}
        > print(#t)
        3
        > for i,v in ipairs(t) do print(i,v) end
        1       1
        2       2
        3       3
     

Ok so all is good. But now what happens when the table contains a nil?

    
    
        > t = {1,nil,3}
        > print(#t)
        3
        > for i,v in ipairs(t) do print(i,v) end
        1       1
    

ipairs() stops at the first nil value even though Lua knows there is data past
it. Things get more interesting for tables with non-integer keys:

    
    
        > t = {}
        > t['a'] = 1
        > t['b'] = 2
        > print(#t)
        0
        > t[1] = 1
        > print(#t)
        1
        > for i,v in ipairs(t) do print(i,v) end
        1       1
    

What's going on here is each Lua table has an array for integer valued keys
and a separate hash table for non-integer keys and # and ipairs() only operate
on the first array. To process all the keys you use pairs():

    
    
        > for k,v in pairs(t) do print(k,v) end
        1       1
        a       1
        b       2
    

While at first this doesn't seem to be such a big issue, it's easy to forget
when it's safe to use the #t construct. I've made this error so often that now
whenever my Lua code doesn't do what I expect the first thing I look for are
places where I have something like:

    
    
        if #t > 0 then
            do_processing(t)
        end
    

or

    
    
        for i,v in ipairs(t)
            process(v)
        end
    

because chances are the real problem will turn out to be the particular way I
initialized the table.

~~~
silentbicycle
I suspect this is because a table may be used for an object (or some other
abstract data type) which has a different data type. Adding another metatable
hook for __empty might be another solution, though. (I agree it's a bit
annoying.)

> Ok so all is good. But now what happens when the table contains a nil?

One of the invariants for the way Lua tables are implemented is that they
_won't_ contain nil as a value, IIRC. Using a multifaceted table type for both
arrays and dicts is a mixed blessing. It is really convenient much of the
time, but it does lead to some quirks.

NB: The i in "ipairs" means "integer (keyed) pairs".

------
pc
Objective-C: @property requires duplication of the ivar type, and doesn't
imply @synthesize. (To do either of these would stop it being a simple macro,
but that elegance comes at the expense of a frustrating amount of unnecessary
typing.)

Common Lisp: built-in functions aren't generic. Tedious verbosity of defclass.
No literal syntax for hash tables. Debuggers so much worse than they should
be.

Smalltalk: having to manually implement getters/setters. Awkwardness of code
generation.

Ruby: gems not having a single canonical name (what you require != what you
install).

~~~
gruseom
I missed this thread, but I'll add another Common Lisp annoyance: the way
DESTRUCTURING-BIND is inconsistent with destructuring lists in LOOP.
Specifically, I want to bind to NIL for variables I don't care about (rather
than having to explicitly ignore them) and bind to heads of lists rather than
always the whole thing. I've been meaning to check out the open-source BIND
macro and see if it does any better.

------
vegai
Haskell: people start talking behind my back when I mention implementing
something on it

------
twism
Python: "<br>".join(["string1","string2"])

Maybe it shouldn't but this pisses me off.

~~~
rbanffy
I would think a more natural approach of making join a method of any sequence
would result in cleaner programs.

(a, b, c).join(',')

instead of: ','.join((a, b, c))

~~~
zepolen
You miss out on a nice side-effect of join being a method of string:

br = '<br>'.join

br((a, b, c))

Personally I think it makes more sense the ruby way but it's never bugged me.

~~~
rbanffy
Wow... This one is quite pretty. Really. A very nice side effect of the
"everything is an object" concept.

~~~
silentbicycle
There's not any reason you need objects for that, though. Python's join in the
string module is called as join(list [,sep])*, and you could say

    
    
      def br(sl):
          return string.join(sl, "<br>")
    

or

    
    
      br = lambda sl: string.join(sl, "<br>")
    

for the same effect. It's actually due to first-class functions.

------
hxa7241
Lua: array indexing starting at 1 (and interoperating with C is one of the
main purposes of the language)

~~~
silentbicycle
See also: (<http://lua-users.org/wiki/CountingFromOne>)

There are arguments for doing it either way, but making indexing incompatible
with the language in which it is expected to embed in is just _rude_.

~~~
silentbicycle
Which really is too bad, by the way - the language designers seem to have done
a brilliant job of shrugging off potential design warts otherwise. It's a very
clean language.

------
DarkShikari
The aliasing rules in C. Almost every single case I have found of performance-
critical code being compiled suboptimally is due to redundant load/stores
being emitted due to aliasing restrictions.

And no, the "restrict" keyword doesn't fix much of anything.

The most annoying rule is that char * pointers can alias anything...
especially when one has to deal with enormous amounts of 8-bit image data.

------
lucraft
I just did this in Ruby and got a syntax error:

    
    
        Time.now -1.day
    

Of course, what it should have been was:

    
    
        Time.now - 1.day

~~~
sc
You mean Rails.

This works as expected, though:

    
    
      Time.now-1.day

------
figured
submitted to reddit, here is the
thread:[http://www.reddit.com/r/programming/comments/7hv0j/ask_progg...](http://www.reddit.com/r/programming/comments/7hv0j/ask_proggit_what_is_the_most_intrusive_wart_on/)

has some good responses

~~~
apgwoz
Actually, that's weird. I thought I attached that url to the post...

~~~
IsaacSchlueter
Note the helpful text on the submit page:
[http://skitch.com/isaacschlueter/76ee/the-helpful-text-it-
is...](http://skitch.com/isaacschlueter/76ee/the-helpful-text-it-is-for-
reading)

------
habs
Java - I love Javadoc Tool. Don't really get to use it much now, but still
love it.

c# - Constraints on typed params.

public T AssignLiteItem<T>(ArchivingItem archivingItem ) where T : Item {

T myITem = (T)typeof(T).GetConstructor(new System.Type[] {}).Invoke(new
Object[] { });

myITem.ItemReference = new ItemReference(archivingItem.Id);

return myITem;

}

~~~
mindviews
Don't forget you can add an empty constructor constraint in c# generics.

public T AssignLiteItem<T>(ArchivingItem archivingItem ) where T : Item, new()
{

T myITem = new T();

myITem.ItemReference = new ItemReference(archivingItem.Id);

return myITem;

}

I do wish the compiler handled constraints for arbitrary constructor
signatures on generic types, however...

~~~
habs
Nice, I guess I can get rid of the reflection invocation of the T Type
constructor. Should speed things up a bit. Cheers.

------
riobard
Python (prior to 3.0): 1/3 == 0

well, unless you do

    
    
        from __future__ import division

~~~
Dilpil
If your working with integers, 1 div 3 is indeed zero.

~~~
Zaak
That makes sense in a language like C, but in Python there's no telling if
you've got integers or floats at the point the division happens.

I'm very happy it's fixed in Python 3.

------
hxa7241
OCaml: can't split modules/packages/namespaces across files (I can't remember
exactly, but that is the gist)

~~~
thelema
OCaml: _no_ library compatibility between compiler versions -- recompile
everything when you upgrade compiler.

------
potatolicious
Objective-C: lack of enforced constructors. Sure, by convention you're
supposed to call the "init" function for the class, but you don't _have to_.
There's really no good way to guarantee your object has been initialized
correctly!

~~~
jemmons
I don't get what the noise is about here. Millions of lines of objc code have
been written without mass confusion of how to init objects. It might look good
on paper, but in practice telling people "this is the designated initializer"
seems to be more than sufficient to sort things out. And being able to
initialize an object with anything (or, remember, to have _anything_
initialize an _object_ ) only adds to the flexibility and dynamic character of
the language.

------
smtlaissezfaire
Ruby: methods != lambdas != procs

------
sunkencity
the poor unicode support in ruby

