How would you change your favorite programming language to make it better?
blog.fogus.me
blog.fogus.me
I find it interesting to that the question "Which features do you miss when using a language?" is not equivalent to "Which features would you add to the language?" The former feels like it speaks to my vision of my personal style, while the latter can be construed to include all of the pragmatic concerns of adoption, such as features alleged to assist large teams of indifferent programmers or features that would break backwards compatibility.
So if a tree falls in the forest with no one around then the universe implodes.
I would personally like to see `var` available in private and internal class members (properties, fields, and methods). There's a lot of pointless repetition that could be eliminated. (Obviously, you want to be explicit about the interface defined by a class' public members).
I also consider Tuple<> a missed opportunity, I'd like to see another whack taken at it that veers closer to structural typing. The existing tuple type is very unwieldy once you start returning or storing it, and I feel a pretty good alternative could be built on the principles of `var` and anonymous types.
Picturing something like:
static tuple SomeMethod(){
return new tuple { SomeNumber = 1, SomeString = "hello" };
}
static void Main(){
var t = SomeMethod();
Console.WriteLine(t.SomeNumber + " "+t.SomeString);
}
Whereas Tuple<> forces you to write that with ItemX scattered around.Tuples, on the other hand, are full-fledged generic classes. That introduces an advantage in that they're first-class entities which can be used anywhere. But it introduces a couple disadvantages, too: There's a separate class implementation for each number of elements, and implementations are only provided for up to 7 elements plus an 8th weird kludge for supporting more. And having the tuple's "official name" be Tuple<$ARBITRARY_LIST_OF_TYPES> is not only cumbersome, but also misses an opportunity to do a better job of communicating semantics.
Consider, for the sake of argument:
Tuple<Employee, int, string, double, string, bool>
versus
Tuple<Employee, int?, string, double, string, bool>
What's going on here? Are they equivalent? What are they being used for? What's up with the different types for Item2, are they equivalent? For that matter, what about Item3? Sure it's got the same type, but we've really got no idea what it's being used for. And since it's being implemented as a plain old generic class, there's no class definition on which you can lay some documentation about this stuff. Just a bunch of disembodied type declarations all more-or-less equivalent to each other.
You know that phase in a lot of beginning programmers' careers where every variable is named foo1, foo2, etc? This is in many ways the same thing, only codified and enshrined by the .NET Framework designers. Oh, and the word's "Item" instead of "foo".
Practically speaking, it means that Tuple's crippled. Sure, technically you can use it for anything. But if you're the kind of person who likes maintainable code, you really don't want to be using it for anything but the most trivial cases. You certainly shouldn't be using it in any interfaces that other people are going to have to work with.
Kill the "new" operator. Make prototypes less magical (i.e. use something like `Object.create` to construct).
Secondarily, kill getters and setters. (That includes `Array#length`.) I want code and data, not code, data, and code which pretends it's data.
I don't mind the JavaScript syntax much (`function () {` isn't that difficult to type or scan through after you've dealt with it for a while). I'm fine with the small core object and function set. I'm fine with the DOM (except the getters/setters part). I'm okay with `Object.prototype.hasOwnProperty.call`; that can be swept away into a function. Just don't make me write code which looks like statically-typed classical OO spaghetti. I want dynamic prototypal functional spaghetti. =]
var module = new Module();
In addition, AFAIK there are some funny issues in JavaScript when a constructor function returns an object that is not the object bound to `this` (i.e. the new object created by the `new` keyword).
There are still other problems (in my opinion) with the concept of constructor functions. It basically boils down to mixing data (prototype) and code (constructor funciton).
Side-effects in a constructor are a big no-no. However, if you want side-effects, you're forced to write your code in a different style.
As a (really bad) example, you have an Enemy "class" which must know about enemies adjacent to itself at creation time.
Without side-effects (using `new`):
var enemy = new Enemy(enemyList);
enemyList.push(enemy);
// Now enemy is inside of enemyList,
// but it's not enforced. I find this
// method prone to mistakes.
With side-effects (using `new`): var enemy = new Enemy(enemyList);
// Now enemy is inside of enemyList;
// I wouldn't expect that postcondition!
And without constructors, but with side-effects: var enemy = enemyList.createEnemy();
// or
var enemy = createEnemy(enemyList);
// Now enemy is inside of emptyList
The problem here is that an enemy must be part of a list. The classical OO solution is to use constructor parameters. Ideally, I'd just have a function to deal with creation and adding it to the list (like `createEnemy`).In ES5, `enemyList.createEnemy` could be written like this:
var enemy = Object.create(Enemy.prototype, {
enemyList: { value: this } // Ugh!
});
this.push(enemy);
Enemy.call(enemy); // Necessary evil if you use standard JS "classes"
return enemy;
I'd much prefer something like: var enemy = enemyProto { enemyList: this }; // Basically binds the object literal with the enemyProto prototype, returning the modified object.
this.push(enemy);
// enemy ctor logic here; e.g. Enemy.call(enemy) as above
return enemy; def initialize(foo, bar, baz)
@foo=foo
@bar=bar
@baz=baz
end
Would now be: def initialize(@foo, @bar, @baz)
end
This would save hundreds of lines of code in large programs-- lines which could no longer be a source of typos or errors.Oh, also I'd make binding_of_caller work.
Edit: Never mind, I just tried it and got an error.
Weird. I could have sworn I'd seen it done somewhere.
{@kbar, fu: @bar, blitz: [@first, @rest...]} = someHash
At no extra charge.First it needs to have a much bigger standard library, much like Java.
Second it needs a really effective foreign function interface possibly one which allows direct call to C++. This enables the programmer to take advantage of all the libraries written in C or C++ without having to write C or C++. In particular it allows using wxWidgets, gtk, qt and native win32/64.
Finally I would fix the output of the compiler (having an image is nice, combining it with the compiler to produce an executable makes sense) since (at least for SBCL) the output is 50mb for Hello World (granted, it doesn't grow much after that).
- Allow labels to be followed by variable declarations or the end of a block.
- Change switch to make each case its own block, and not fall through by default (but add a keyword to explicitly fall through).
- Support labeled break and continue (often much clearer than goto; sometimes separating the inner loop into its own function is clearer than either, but not always).
- Change the precedence of & and |.
- In do/while, evaluate the loop condition within the block's scope:
do { int a = ...; } while(a);
- Allow variable declarations anywhere in an expression: not just while(int a = ...)
as in C++, but even while((int a = ...) == 0)
or getvalue(&(int a));
- Standardize some GNU extensions such as ({ }), void pointer arithmetic, __attribute__((pure)), and __builtin_unreachable().- Standardize visibility.
- Standardize Apple blocks.
- Tuples, with quick unpacking:
{int a, bool ok} = func();
- Explicit control of may-alias, something more powerful than restrict....This is fun.
JavaScript is probably the language I hate the least. And I'd make some of the CoffeeScript syntax standard, and maybe bring in some concepts to keep spaghetti callbacks under control.
Seriously, it's been an issue when I've been trying to collaborate with others on a side project. We had the question of what language to start with. Some of the interested contributors were Python consultants and insisted that not only was Python the best language, but that Python was the best community, and Python people were the best and most virtuous people. (It is a kind of activist do-gooder project, which is why that person thought this was relevant.)
This sort of opinion seems asinine to me now, and it hurts especially because I used to be one of those guys around 1998-2000 or so -- except, for Perl.
The question of what language to start with kind of paralyzes me now, because when I consider what we'll want a few months in, I see this field of leg-hold traps we're going to step in. In all directions. I almost wish I had less experience and foresight (or more courage, take your pick).
> And I'd make some of the CoffeeScript syntax standard,
> and maybe bring in some concepts to keep spaghetti
> callbacks under control.
You may be interested in keeping an eye on this branch:My friend Alex Graveley also has a totally different way of doing this, and a lot more, that uses the standard but not often implemented 'yield' keyword to create an Erlang-style process model, hence "Er.js":
http://beatniksoftware.com/erjs/
But you might want both TameJS and Er.js for different applications.
Overgeneralization. It's like nice looking cars. Just because you love a classic Shelby Mustang doesn't mean you can't acknowledge there are other good tools out there.
After years of programming professionally in C++ and occasionally Python, there is still something about the design of Common Lisp that I love. It's like using a Mac--the attention to detail evidences an obvious good taste that I rarely see in other languages or their libraries.
`some_function arg1: val1 arg2: val2` with parentheses just to solve ambiguity.
On another note, I always did not understand why there's no For..Else construct, but then I met python.
What I have a bigger problem with is the syntax for updating fields is so clumsy. It doesn't go very well with the rest of the language and I usually end up writing helper functions for updating specific combination of fields.
If you claim to have 7+ years using a language, surely there's a list of things you could add to make it better.
I think it's standard in the PHP ecosystem though.
The thing I find most annoying is being unable to pop the first element off an array when its returned and that when you do things like array_map it dosn't work with a method inside the same or other classes,
EG
$this->method()[0];
array_map($this->doSomething, $array);
list($firstElement) = $this->method();
array_map(array($this, 'doSomething'), $array);
Yes, neither is intuitive. And the syntax sucks. And it's not as easy to read (except sometimes where a method returns a tuple; `list` is wonderful there!). But it's certainly possible... Closeable dbConnection;
try {
dbConnection = CloseableFactory.getConnection();
doWork(dbConnection);
} catch (CloseableException ex) {
// log it or whatever
} finally {
// the really annoying, stupid, crufty boilerplate bullshit
try {
if (dbConnection != null)
dbConnection.close();
} catch (CloseableException ex) {
// it's probably already closed
}
}
Instead, it'd just be with (Closeable dbConn = CloseableFactory.getConnection()) {
doWork(dbConn);
}
(Assuming the "with" statement eats errors relating to the instantiation/closing of the Closeable, anyway). Bliss. And I know there's stuff like Google Guava's Closeables.closeQuietly(conn);, but still, a with statement would be awesome.In addition to solving all the problems people here are complaining about, it adds type inference, mixin-type-things, a superior collections interface (map and friends) and a bunch of other nice features.
However, the best bit (from a Java developer's perspective) is that it looks and behaves almost exactly like Java, just improved. Going from Java to Gosu is trivial but very nice.
Specifically, I'm not very happy with this way of throwing exceptions (example taken from Gosu documentation on exceptions [1]):
throw "x does not equal zero"
and then later chatching them like this : catch( e ) {
if( e == "x equals zero" ) { return( e + " handled
locally." ) }
I want to be able to specify the exact type of the exception, and catch them based on their type, instead of having to throw a generic error and then check using "if" statements whether it's expression is equal to a particular String or not. If I understood correctly, this is what Gosu is actually doing, right?[1] http://gosu-lang.org/doc/wwhelp/wwhimpl/js/html/wwhelp.htm#h...
try {
// Maybe throws IOException
} catch (e : IOException) {
// Handle it
}
I think this does exactly what you want. There's more documentation here[1] (the documentation format is a little annoying, unfortunately).[1]: http://gosu-lang.org/doc/wwhelp/wwhimpl/js/html/wwhelp.htm#h...
The more I think about it, the more terrible this looks. I can't even specify to the users of my code which exceptions they should look after (because, it seems, Gosu doesn't allow the throwing of checked exceptions and the 'throws' clause). So if I write some kind of library in Gosu, and if that library is throwing exceptions, I'm basically forcing the users of my library to catch this generic exception (or whatever it is), then put a breakpoint in the catch block and every time something gets caught inspect the expression, hoping that if they test long enough they'll find all of my expressions. Then, they need to write code that covers all the possible cases (a bunch of "if" statements).
I sincerely hope that I somehow completely misunderstood what Gosu is trying to do here, because otherwise this is just a terrible solution. That would be a real shame though, because, other than this, I honestly like the language.
However, the real idea is that you should not use exceptions for anything expected like IO issues. Exceptions are meant to signify errors that could not be handled--unlike in Java, you shouldn't use exceptions for control flow.
The real issue is one of semantics--in Java, one concept (exceptions) is used to represent two do disparate things: signal unexpected errors (runtime exceptions) and manage expected conditions (checked exceptions). A lot of people do not like checked exceptions and think exceptions should only really be used for the former case. Thus the lack of checked exceptions is a feature rather than a bug; moreover, it is a feature other people in this thread have already requested.
So, the potentially annoying answer is that people using your library should not expect particular exceptions--that is not what they should be used for in Gosu. Coincidentally, this is very similar to how JavaScript deals with exceptions, and I have had no issues there at all.
My dream language right now would be something with the expressiveness of Ruby and the concurrency abilities and pattern matching from Erlang.
Hmm. I think I need to go look at where Reia (http://reia-lang.org/) has got to since I last looked at it.
As an aside I just had a look at what stage Reia is up to. The github page says that Reia is now defunct. (https://github.com/tarcieri/reia)
There is also another ruby-like language on the erlang VM - Elixir (https://github.com/josevalim/elixir)
He's definitely familiar with Erlang as IIRC he was one of the original authors.
GCC can do it, but it puts them on the stack which is limiting.
If you use Clang you can use them on non-Apple platforms.
Edit:
In python 0 should not equal False and 1 should not equal True. This has hit me a couple times and it is really annoying. Furthermore, 0 should be cast to True, as in Ruby. Only None and False should be cast to false.
Object.keys(obj).forEach(function (key) {
var value = obj[key];
// ...
});
Not the best thing, but it works in less lines than: var key;
for (key in obj) {
if (!Object.prototype.hasOwnProperty(obj, key) {
continue;
}
var value = obj[key];
// ...
}
Plus, it avoids the async-function-in-a-loop problem (which is why I rarely use C-style `for` loops or `for-in` loops now).I understand that preprocessor macros have to stand out because they have different semantics (arguments might be evaluated multiple times, use of ## to fabricate tokens, etc), but i do not think
- In C, macro names are by convention uppercase
- in C, one used to use macros to define constants
- hence, in each C-inspired language, constant names must, by convention be uppercase
is a valid syllogism.
if (mything != null && mything.User != null) { Do.Something(mything.User.Name); }
I’d like to write:
Do.Something(mything?.User?.Name);
It’s syntactic sugar, but would greatly improve readability, and a compiler could do it with no change to the runtime.
You just don't get all the typeerors.
Not a huge fan of C# but that part is awesome.
Python: blocks, ala Ruby
JavaScript: Strong (but dynamic) typing, ala Python & Ruby
edit: formatting
I would like to see Lisp and *nix have babies. Take the best ideas of both and make something greater than their sum.
Are you referring to Unix tools (grep, awk, sed, cat, etc.), piping and redirection, or shell scripting overall?
SBCL: tree shaker for creating executables.