Olov Lassus

15 Oct 2013  »  Little dunder proto
04 May 2013  »  ES3 <3 block scoped const and let => defs.js
06 Jun 2012  »  Taking the leap
...show all

Little dunder proto

15 Oct 2013

Hi, this is your son’s school. We’re having some computer trouble.

Oh dear - did he break something?

In a way. Did you really name your son __proto__?

Oh yes. Little dunder proto, we call him.

Well, our administrative web application is completely broken now. I hope you’re happy.

And I hope you’ve learned to use stringmap.js because objects aren’t stringmaps.

Also stringset.js. They resemble ES6 Map and Set API-wise, add minimal overhead and work everywhere.

In tribute to xkcd 327 - Exploits of a Mom.

Show comments (Hacker News)



ES3 <3 block scoped const and let => defs.js

04 May 2013

I released defs.js at the Front-Trends conference last week. Defs transpiles ES6 block scoped const and let declarations to beautiful ES3 code using vars. It’s also a pretty decent linter when it comes to variable and scope analysis.

ES6 block scoped let and const

Let me give you some background on why I created Defs. One of my favorite features in the upcoming ES6 language is block scoped let and const variable declarations (harmony wiki page). A while back I decided to start using them in my back-end code. This is possible thanks to node --harmony. Run it like so, make sure your code is in strict mode and off you go! With that a large JS annoyance (function scope) was gone with the wind, and I got to use const as a bonus - which turned out to work remarkably well with my JS style of programming. Nowadays mostly all of my node code is written in ES5 + cherry picked ES6 const and let features. Let’s call this constlet style JS for now.

constlet style JS is great, and I highly encourage you to try it out. It makes me much happier as a programmer and it makes my code much prettier and easier to reason about. Are you still reading? Up with a console and try it out in node! Then come back.

const is the norm

That block scoped variables is an awesome thing is no news for those of you that have a {} background. let is a better var in every respect so I won’t pitch it further. let is awesome. const, on the other hand, may seem unimpressive at a glance. If you’re not used to it then it may seem like something to use for the rare occasions when we define a numerical constant such as const godspeed = Infinity. But it’s so much more than that.

A striking thing that happens when you start using const is that you realize that the vast majority of your old vars were initialized but never modified (don’t confuse this with deep immutability which is a different story). Non-mutating variables are the norm, so they should have the default variable declaration keyword - which is const in ES6. For those variables that you modify, be it accumulators, loop indices or whatever - you make those stand out by using let. Once you get hooked on this style it’s impossible to go back. Ask any Scala-slinging friend of yours about val (~const) and var (~let). There are people swearing by this in Java-land too, finalista’s I’ve heard some of them call themselves because of the final keyword they have to add everywhere. To give you an idea of how common const is: The source code for defs.js has a const coverage of over 80%, which means that I used 4 consts for every let.

let is not the new var, const is.

Defs transpiles to beautiful ES3

So. Use constlet style JS and be happy, right? Except for the browser. We need to be able to run our client-side code in current browsers (so ES3 or ES5). Until now there was no decent way of transpiling constlet style JS back to ES3. Traceur and others use a style where a myriad of try-catch statements are generated which is as bad on your eyes as it is on your VM. This is no criticism on Traceur which is a very ambitious project with a lot of features to cover. Traceur will surely improve also when it comes to block scope.

So I created defs.js, a transpiler that takes constlet style JS and spits out plain-old ES3 code, as beautiful as its input and maximally non-intrusive. It works by doing static analysis, changing all const and let declarations to var, and an occasional variable rename here and there. The output looks more or less identical to the code you would have written with vars in the first place. Same line-numbers, easy debugging and no lock-in shall you decide to go back to the world of vars. Because Defs needs to do a bunch of scope analysis anyways, it ended up also being a pretty decent linter when it comes to variable and scope analysis.

Try Defs

Install Defs by npm install -g defs, then run defs mycode.js and there’s your transpiled code on stdout or your errors on stderr. There’s more info about configuration such as how to tell Defs about your globals (if you want it to analyse those) in the defs.js README.

Want to toy around directly? Bring up your browser’s JS console and copy and paste this: defs("const x = 1").src. It should give you "var x = 1" in return. Try defs("const x = 1; { let x = 2; }").src, which should return "var x = 1; { var x$0 = 2; }", a rename example. Try more advanced examples. Try modifying a const, try creating two consts (or lets) with the same name in the same block scope or try accessing a const or let before it has been initialized.

I know of only one use case that cannot be handled with renaming, namely loop closures - i.e. a closure that references a variable that is declared outside of its own scope but inside the loop. An example would be:

for (let x = 0; x < 10; x++) {
    let y = x; // we can skip this when v8 issue 2560 is closed
    arr.push(function() { return y; });
}

In this ES6 code let y is a new binding per iteration while a transformed var won’t be. If you run this through defs it will refuse to transpile it and give you this error:

line 3: can't transform closure. y is defined outside closure, inside loop

The solution is to do as we already to in our current ES3 or ES5 code, create the binding manually:

for (let x = 0; x < 10; x++) {
    (function(y) {
        arr.push(function() { return y; });
    })(x);
}

Defs will happily transpile that.

Toolchain and convenience

I can already hear people saying that they’d like to try this kind of thing but that the save-and-refresh development cycle is precious. Fear not. I guess that most aren’t running their code locally using file:// but use a local HTTP server, in which case you may have the opportunity of hooking a toolchain (including Defs) into it. If you serve using node this should be very simple.

It’s even simpler if you use Chrome. Go to chrome://flags, check Enable experimental JavaScript and you’ve got the same support for const and let as you have with node --harmony. Just remember that you must "use strict" for it to work.

Defs works great with James Halliday’s excellent Browserify. Here’s how I create the defs_bundle.js file that’s included in this page (view source):

browserify -r "./defs-main" > defs_bundle_constlet.js
# defs_bundle_constlet.js contains defs.js and all its dependencies

# defs-config.json:
# we allow duplicated vars because of defs dependencies
{
    "environments": ["browser"],
    "globals": {
        "define": false,
        "require": true
    },
    "disallowDuplicated": false
}

defs defs_bundle_constlet.js > defs_bundle.js

Things will be even easier once we have a Browserify plugin for Defs.

Underpinnings

Defs uses Ariya Hidayat’s Esprima parser to create an AST from source code. Defs performs static analysis on that AST and spits out errors or transformed source code. Static analysis is the hard part of Defs’ work, the actual source transformation is pretty trivial after that and it can be done in one fast textual shot using alter.js. If you wonder why I didn’t use JSShaper to create Defs then it’s for exactly that reason. Defs need a rock-solid and well-maintained parser. Esprima is that, my forked version of Narcissus I used for JSShaper is not. Thanks for Esprima Ariya, I have a couple of constlet parser bugs coming your way soon. :)

Scope of the Defs project

The scope [sic] of the Defs project is small on purpose. It transpiles const and let back to ES3 in a maximally non-intrusive manner, it performs static code analysis related to scope, and nothing else. Defs is not likely to take on other ES6 features.

Presentation

Feel free to check out my Front Trend presentation LET’s CONST together, right now (with ES3) for more info about Defs.

License

MIT because others are generous so I want to be generous too.

Try it, break it, help fix it don’t hate it

I hope that I triggered some interest in checking out what let and const could do for your code base. Use it with node --harmony and then consider using Defs to bring the same features to your client code. Check out the github project and npm package.

Let me know what works and what doesn’t. File issues or even better send pull requests. JS needs <3 and so does Defs. Peace and happy hacking! \o/

Show comments (reddit)



Taking the leap

06 Jun 2012

I’m taking the leap. I’m starting my own software company.

I’ve been working with IP-TV set top boxes for the last 6 years; first with Kreatel Communications, then aquired by Motorola, then split into Motorola Mobility and now recently acquired by Google. I came to Kreatel as a software engineer and since two years back I’ve had the luxury of leading our Technology Group, meaning our research and prototyping work. It’s been great, and it still is.

In my previous life before all this I did computer and console games, starting with the 3d shooter SubStation for Atari STE two decades ago and followed by PC, PSX and XBOX development full time a few years around the millenium.

I then attended the Linköping University (one decade ago, in 2002), and got my M.Sc. four years after. I learned tons there. It brought me to Lisp, gave me a deeper understanding of hardware all the way down and allowed me to experiment with CPU & computer design/implementation in FPGA’s. And I finally really learned the maths behind the 3d-games I used to write.

My finishing stretch of the University also came to define my spare time programming to come. I got into JavaScript by accident while researching how to create richer programming environments that turns the live-knob to eleven (where Smalltalk, Lisp Machines and modern edit-and-continue are well below ten), see Describing Live programming (again). I’d love to revisit that topic some day.

My more recent spare-time programming led me to creating Restrict mode for JavaScript and the JSShaper source transformation framework, a year and a half ago. The big difference here compared to my previous spare time projects and ideas (that mostly remained ideas) was that this time, I decided to just do something, release the code as permissive open source, and see what happens. Testing the do good and good will come to you thesis, if you will. Somehow that must have worked because I got invited to speak at DevLin, Front-Trends and Webshaped all in the last three months. I met a lot of interesting people there and I got to speak about things I’m deeply passionate about. In my book that’s as good as it gets.

I should mention Dart too. It resonates with me a lot, obviously when it comes to certain aspects of language semantics and easier to reason about programming, but more importantly in the direction I believe that they intend to push their development environment. There is a lot of Live Programming like thinking there. Gilad Bracha’s recent example of creating a test that fails with a noSuchMethod, then gradually filling out the implementation without ever stopping the program - while the context is right in front of the programmer, is similar to one I gave in my thesis. So yeah - it resonates with me, a lot.

With the same idea of just doing something to see what happens, I got involved with Dart early on. I thought of creating a JSShaper for Dart but got distracted partly by an increased community interest in my JS projects. So far my most useful contribution to Dart is a syntax highlighter. Speaking about Dart. I’ve had the opportunity to meet with a few members of the team, including Peter Ahé, Mads Ager, Kasper Lund and Lars Bak. It’s well known that they are VM experts but I quickly realized, especially so during discussions with Peter, that their ideas about what programming should be expands well beyond VM’s and language semantics. I hope to be able to play with a Live Programming like Dart environment one day. Three more things about Dart. (1) Any community should have a Bob Nystrom. He’s the money. My wife quotes him now and then (“I feel all giggly inside” - regarding the syntax highlighter running live at Github), which is kind of weird. (2) The haters got at least one thing right: Dart isn’t a silver bullet for everything web, because it doesn’t have a great JS interop story yet and perhaps never will. (3) If you think that Dart is mostly trying to solve a performance issue, think again.

By the way - I can talk/rant for hours about programming environments and what programming today is vs what it used to be decades ago already, and where we could go should we just prioritize it. Invite me and I’ll come talk about it. Or programming from an “easier to reason” about perspective. Or restrict mode and JSShaper. Or making superfast sprite routines for the Atari STE by generating op codes from pixel data. I like conferences!

And now, I’m starting my own software company. I’m lucky enough to have Motorola wanting me to stay part time, allowing me to keep doing the things I love there while at the same time taking a leap to grab a specific opportunity with my own company.

What I’ll do? A software product, not related to anything above. It’s for companies within a niche market, where it should simplify things and increase productivity a lot. So in that way similar to restrict mode and Live Programming, but not programming. It’ll be a web app and written in JavaScript using restrict mode. I don’t know where it’ll take me but I’m putting my bets on do good and good will come to you once again.

I’m taking the leap, and I can’t wait to get started.



JSShaper grows up but stays fit and fun

22 May 2012

I created JSShaper a year and a half ago because I needed a way to do source-preserving JS-to-JS transformations so that I could implement restricter, the Restrict mode for JavaScript checker. There was nothing else out there so I ended up creating Shaper. Some of the defining (and often unique) features of Shaper at the time was its simplicity of AST traversals (one function, not dozens of visitors), its precise weaved token and node representation that facilitates repeated tranformations on the node level at O(1) complexity, its declarative matching based on templates and wildcards that lets you describe the template as JavaScript code but still matches on the node level, its corresponding declarative replace function that lets you rewrite fragments of a tree without knowing the details of its inner property-structure, the smart and mostly closure compiler compatible binding of comments to nodes, the notion of pluggable Shape(r) pipelines, and more. Those are still defining features, and still often unique. While I created Shaper mostly for restricter, I decided to write a bunch of other plugins as well to show as examples if nothing else. One of the simplest of these ended up being one of the most useful, namely asserter. Check out C-style assertions in JavaScript via JSShaper for more information about it.

I wanted to share with you some recent good stuff happening in Shaper land.

C. Scott Ananian has created the most advanced Shaper plugin yet, yielder, which transforms yield generators (JavaScript 1.8) into plain ES5. Impressive work. I hope to be able to merge it into Shaper master soon, but for now use cscott’s repo.

cscott also contributed a number of fixes to Shaper, imported a newer version of Narcissus and rebased all my modifications on top of it. If you find any valid JS that Shaper fails parsing or round-tripping (node run-shaper.js yourfile.js --source) then please open an issue and we’ll fix it.

Finally, cscott performed AMD-fication surgery on the Shaper code base. I initially supported running Shaper through any shell you could think of, using the technique described in JavaScript modules in shells, browsers, everywhere. While cute, it was cumbersome and we decided to drop support for anything but node.js and the browser. AMD was a nice match; it works great in node and great in the browser, and the r.js tool is more convenient then concatenating files together. I also want to mention that Jez Ng participated in pushing node-compatibility forward, although that patch never landed. Another one of his patches did though.

Noah Sloan independently created jmvc-3.2-upgrade-assistant, a Shaper based script for helping upgrade from JavaScriptMVC 3.1 to JavaScriptMVC 3.2. Looks awesome!

I was at webshaped.fi last week presenting JavaScript: the subsets we use (including Restrict mode for JavaScript and a little bit of Shaper) and met a guy who who told me that his company uses Shaper similar to Noah, for automatically migrating code between different framework versions. Whoever you are I’m terrible at names so please ping me on Twitter and let’s keep in touch!

I gave the same talk at Front-Trends the month before, which was my international conference speaking debut. Both talks were recorded so I’ll post the links once available. If you want me to come talk somewhere about coding with a focus on “easier to reason about”, restrict mode, Shaper or something related just contact me! I can easily do an hour presentation about Shaper and the concepts behind it, for example.

Creating Shaper plugins is very fun, and not that hard. Try it! To get started I recommend checking out the sources for asserter and stringconverter (simple transformational plugins) or bitwiser (simple static analysis plugin). You’ll find these in the plugins/ directory. Then check out everything in the examples/ directory as well.

Thank you for trying out, contributing to, writing about or filing issues on JSShaper.

Peace!

Show comments (reddit)



Call for testing: Pygments Dart highlighter

22 Apr 2012

As mentioned before, the Dart highlighter lives in the upstream Pygments repository now and is included in releases since 1.5 (released Mar 10, 2012). I will try to keep it correct and updated.

Another milestone is that Github recently started using it! I found a few bugs just by clicking around in people’s repositories. The most obvious was keyword-detection on substrings, i.e. the String substring of StringBuffer got marked as a keyword. Another was failing to recognize escape characters inside string literals. Both are now fixed in my repo, so the example below renders fine.

main() {
  StringBuffer sb; // String isn't a keyword
  var integer; // nor is int
  var str = "Escapes \"just works\" now";
}

I need help with testing the highlighter to find bugs or missing features. I’m maintaining the Dart highlighter in my bitbucket repo. You can help by downloading it, trying it out on your own code and letting me know what works or not:

hg clone https://bitbucket.org/olov/pygments-main
cd pygments-main
./pygmentize -f html -o yourfile.html yourfile.dart

If you don’t have Mercurial (hg) installed then you can also click “get source” on bitbucket to download the source as a zip-file. Running pygmentize will create markup from your source code, which you then need to combine with a style sheet to get some color going. Feel free to copy my color scheme (syntax.css) if you like it. You can also run pygmentize yourfile.dart without -f and -o to get highlighted text directly on your console.

To install the development version of pygments system-wide just run sudo ./setup.py install.

File issues on bitbucket or fire a mail to the Dart misc thread or me directly. Even better, submit a pull request! :)

Show comments (Dart misc)



Meteor meets NoGPL

13 Apr 2012

Update 2012-04-21: Meteor has switched to the permissive MIT license.

Meteor made a big splash this week. Check out their screencast if you haven’t already. For “real-time” web applications it really seems to simplify things a whole lot. The team behind it seems plenty experienced and they are building a business on Meteor by going with the GPL/commercial dual-license approach made popular by MySQL and Trolltech/Qt. The basic idea is that the source code is publicly available for people to look at and modify and that it costs nothing to use as long as you’re building a GPL application with it and give out your source code too. Alternatively, it can be licensed commercially like any other proprietary product. Dual-licensing is not the only way to monetize open source development - a popular alternative is to offer support, training and consulting, like 10gen does for mongoDB. Anyways, I think Meteor is plenty cool and I wish them the best of luck!

The web development community hasn’t really taken GPL libraries/frameworks to heart, neither client- nor server side. Let me elaborate on that.

Check out the most watched JavaScript repositories on Github. Every single one on the first page is available under a permissive license. In a nutshell permissive licenses often require attribution but never require source code redistribution. Popular permissive licenses are the 2/3-clause BSD, MIT and Apache 2.0. Contrast this with the GPL whose copyleft nature spreads to derived works. Back to those popular JavaScript repos. The list includes Node.js, Bootstrap, jQuery, Backbone.js, Modernizr, Three.js, Express, Socket.IO and plenty more. Node.js is built upon V8, OpenSSL, libuv, libev, libeio and other libraries. Permissive. So is the vast majority of the NPM ecosystem.

Let’s check out some server-side frameworks in other languages. Rails, Django, Tornado, Play, the list goes on. Permissive.

What about the data stores? Server-side code typically connects with those through client/driver libraries of some sort. PostgreSQL, CouchDB, Redis, Riak, Cassandra, Memcached, SQLite – all permissive licenses. MongoDB is AGPL but the client is permissive (Apache) so there’s no copyleft affecting your program that talks to the DB. MySQL is more complex. After all it was the product that defined dual-licensing so that’s not entirely unexpected. The DB itself is GPL, but the client library is LGPL in really old versions, GPL with a FLOSS exception in versions prior to 5.1.55 and plain GPL in recent versions released by Oracle. Oracle also provides a PHP client library under the PHP license. You can also acquire a commercial license of MySQL, with a non-copyleft client library. So whether you can write a proprietary program that talks to MySQL, depends. That’s a whole lot of babbling about data stores licenses, pardon.

Not everything is permissive of course. A good amount of projects use limited-copyleft licenses such as the MPL, EPL and LGPL. The intent is almost always to allow for proprietary usage of the library/framework/program, but to mandate that modifications and additions to the project itself get contributed back, to various extents. EPL is particularly common in Java-camps (so is the permissive Apache 2.0 mentioned earlier). Mozilla use MPL for most (all?) of their stuff, and it also happens to be the most permissive of the three.

And then we have the regular copyleft licenses, most notably the GPL, which isn’t that popular when it comes to web development libraries and frameworks. Sencha’s ExtJS framework is GPL/commercial dual-licensed. Many avoid it for that reason, and for those there are similar projects available under permissive licenses. Wordpress is a another GPL project that is very popular.

If we start looking under the hood, there’s a good amount of permissive licensing going on in other parts of the web stack. PHP, Ruby, Python, Apache HTTPD and nginx are all permissive. There’s also a good amount of GPL and LGPL, most notably the Linux kernel and the GNU userland.

Let’s focus again on client- and server side web development libraries/frameworks. By far and large, the web developer community seems to prefer permissive licenses for that. Permissive licenses are proprietary-friendly, and many web developers write proprietary programs for a living. Many also don’t have a problem with giving out their code for others to use however they wish, save for some attribution. Most importantly, many consider the idea of proprietary programs and services to be fine, sound, ethical and all that. It’s also fairly obvious that permissive OSS projects can attract huge contributions even without any help from a license that mandates it. Imagine Node.js or Rails being GPL. Would they have received more or less contributions, you think?

I hope you won’t blame me for calling web developers “rewrite-happy”. Heck, the entire programmer population is, to some extent. Someone takes the ideas of a library or framework and rewrites it in another language. Someone else rewrites it from scratch just because he/she (hen!) was unhappy with a particular design decision. Competing frameworks overlap. Just look at the throne of JS conference. Now this is both good and bad. Good in the sense that it’s very evolutionary and that it constantly pushes innovation forward. Bad when yet another author loses yet another potential contributor to yet another similar-looking 0-day friendly competitor. But it’s mostly good.

The publicly available Meteor code base is licensed as GPL (v2). Any application you write using it - definitively the client part and quite likely the server part as well (due to Meteor’s tightly intertwined client and server architecture) - any such application must be released under GPL compatible terms. I.e. you must hand out the source code, and no you can’t obfuscate it. If you want to write a proprietary program then you need to have a discussion with the Meteor team about how to acquire a commercial license. Combining rewrite-happy with a preference for permissive licenses, I think it’s reasonable to expect existing project to adapt a few of Meteor’s core features and design ideas, and new ones popping up as friendly competitors. Hardly shocking.

The thing about Meteor is that they really want to establish an ecosystem of community-contributed smart packages, harnessing the goodness of existing Node.js and JavaScript server- and client side libraries. Those smart packages must be GPL or GPL compatible (most permissive licenses are). For Meteor to be able to include a contributed smart package with their commercial offering, the contributed smart package must either use a permissive license or come with a separate contributor agreement that allows Meteor to ship it commercially. Otherwise the GPL backfires in the sense that your contributed GPL smart package cannot be combined with a proprietary version of Meteor.

The copyleft (viral, contaminating, whatever you want to call it) aspect of GPL is tricky. Take MongoDB as an example. Meteor uses it by importing the node-mongodb-native package (require('mongodb')). That one is Apache 2.0 licensed, which is a permissive license that happens not to be compatible with Meteor’s GPL (v2) license, at least not according to the FSF. Tricky. Dependency chains, bindings between JS ↔ C and RPC makes it trickier even. I wouldn’t be surprised to see Meteor change to a GPL + a-bunch-of-OSS-exceptions license similar to what Qt and MySQL used to have, to avoid issues like this.

I’m curious to find out to what extent the Meteor ecosystem will attract outside contributors, and to what extent people will start using the GPL version of Meteor in their projects (accepting the copyleft). Copyleft code grows from one project to another because it must or else the license screams VIOLATION. Permissive code grows from one project to another by culture and an honor system. It’s like, I used all this code and all that was required by me was a tiny bit of attribution (if that even) - I wasn’t limited in terms of how to combine it with other code. When I choose to pitch in something in return, it’s only fair of me to be permissive too. That’s how I perceive the mindset of the web development community at large.

And yeah, I used a sensational title. Tricky.

Update 2012-04-21: Meteor has switched to the permissive MIT license.

Show comments (Hacker News)



Speaking at DevLin and Front-Trends

14 Feb 2012

I’m excited to be invited to speak at DevLin2012 (Sweden) and Front-Trends (Poland). Lots of interesting topics there that I want to attend. Summaries of my own talks follows below:

Evolution vs. revolution with JavaScript and Dart (DevLin2012)

There are clear benefits to developing modern web apps but what are the drawbacks? How are we limited by the programming language JavaScript which in practice means ECMAScript 3 from 1999?

We’ll cover different opportunities and challenges such as performance, startup time, scalability with a growing code base and developer team, productive development environments, strict enough but at the same time expressive enough language semantics, tools for code analysis and more.

The upcoming ECMAScript 6 represents an evolution of today’s JavaScript. Dart starts from scratch with a newly designed language for the web. How do they relate to the challenges above? When can you start using them and what do they require from the end-user environments?

How can we make the best of JavaScript as we know it today?

JavaScript: the subsets we use (Front-Trends)

Is it possible to make our programs more robust, easier to reason about and more enjoyable to write by carefully restricting our usage of the JavaScript language? Let’s talk about that.

Olov Lassus is a Swedish passionate programmer who started his career in the 16-bit game development era of the early 90′s. He got into JavaScript by accident when writing his master’s thesis and it has pursued him ever since. He likes to fiddle with language design, programmer productivity and tooling.



Pygments contribution now upstream

05 Feb 2012

My Pygments Dart highlighter that I’ve written about previously is now upstream! This means that there’s now out of the box support for Dart if you get the development version from source control and that the next formal release is likely to have it too. Github enabling it shouldn’t be far away now.

Show comments (Dart misc)



Dart syntax highlighting update

26 Nov 2011

Here’s a short update on the Pygments Dart support I created a month back.

I consider it good to go now and will submit it to the Pygments upstream and github shortly. The most notable addition is support for string interpolation. I’ve also created a custom color scheme (based on tango) that works well with at least Dart, JS and Diff.

It looks like this:

#!/bin/dart

main() {
  String name = "Zoidberg";
  const age = 42;
  var liar = Math.random() > 0.5;

  // Present ourselves
  print("Hi! My name is $name and I'm ${liar ? age / 2 : age} years old");
}

Source code is available at https://gist.github.com/1320163. Install it by appending the gist to Pygments’s agile.py and add the following line to _mapping.py.

    'DartLexer': ('pygments.lexers.agile', 'Dart', ('dart'), ('*.dart',), ('text/x-dart')),

Then run pygmentize -f html -o yourfile.html yourfile.dart to generate markup from your source code. You’ll need to combine it with a style sheet. Feel free to copy my color scheme (syntax.css) if you like it.

Show comments (Dart misc)



Let's create us some Dart ranges

21 Nov 2011

We recognize the good ol’ for loop from the C-family of programming languages. It is available with the same familiar syntax and semantics in Dart, too:

for (int i = 0; i < 10; i++) {
  print(i);
}

In addition to that, Dart has a for-in loop, similar to Java in semantics (iterator(), hasNext() and next()). for-in is used to conveniently loop over any Iterable sequence, such as a List.

for (int i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) {
  print(i);
}

If you’re into Python then you know that over there you for loop over sequences exclusively, and use xrange extensively.

for i in xrange(0, 10):
    print(i)

xrange is quite convenient and prevents a lot of variable name stuttering. It takes up to three parameters: start, stop and step. Python xranges exclude the stop endpoint and step is 1 by default. start is 0 by default so you’ll often see xrange(len(seq)) used in Python code to iterate over sequence indices.

Back to Dart. While good ol’ for loops have been working fine for the last few decades or so, perhaps something xrange-like could be fun here too. We’ve already got for-in and iterators after all. Let’s create a Range class that implements the Iterable interface with a corresponding RangeIterator and we’ll be able to do for-in range, with top-level function range being a wrapper around the Range constructor. We’ll include both endpoints so range(0, 9) means [0, 1, .. 9]. Again step defaults to 1 so range(0, 9) is the same as range(0, 9, 1).

for (int i in range(0, 9)) {
  print(i);
}

That looks swell. No surprise it has already been discussed on dart-misc. We can also pass a range to anything that expects an Iterable. Here’s how to generate the List [0, 2, .. 8] using the List.from constructor:

var list = new List<int>.from(range(0, 8, 2));

Iterating over indices is done like so:

var str = "hellojed";
for (int i in range(0, str.length - 1)) {
  print("$i: ${str[i]}");
}

We’ll add a top-level function indices to sweeten it a bit:

for (int i in indices(str)) {
  print("$i: ${str[i]}");
}

We can make range more useful still. The Collection interface (implemented by List and Set among others) contains length, every, filter, forEach, isEmpty and some. Let’s implement those too. Now we can pass around ranges anywhere a Collection is expected, for example to addAll:

var queue = new Queue<int>();
// ...
queue.addAll(range(0, 9));

How about a List with the numbers [0, 1, .. 50] that are perfect squares:

bool isSquare(int n) => Math.pow(Math.sqrt(n).round(), 2) == n;
var squares = range(0, 50).filter(isSquare);

Or the other way around? map isn’t part of Collection but let’s add it anyways:

var squares = range(0, 7).map((e) => e * e);

The original example can also be rewritten like this, using forEach:

range(0, 9).forEach(print);

Not too shabby, all in all. Good ol’ for loops have less overhead than their for-in range equivalent but the difference is nothing to write home about, especially if your loop body does something useful. Your personal style is probably more important - as for myself I consider range a nice complement.

Check out the tests for more examples. The implementation should be easy to follow if you want to learn how to create a Collection of your own. If you want a little Dart exercise then change Range so that it only implements Iterable<int> and remove everything Collection-specific. Then add it back again guided by the unit tests, this time with your own code. Or start from scratch altogether.

Oh and the Dart for-in loop is just (very convenient) syntactic sugar of something similar to this:

for (Iterator it = range(0, 9).iterator(); it.hasNext(); ) {
  int i = it.next();
  print(i);
}

dart-range source available on github.

Show comments (Dart misc)



« Older posts    ↑ Home