163

163 JSJ Flow with Jeff Morrison and Avik Chaudhuri


03:32 – Jeff Morrison Introduction

03:46 – Avik Chaudhuri Introduction

04:27 – Flow

05:36 – Static Type Checking

09:52 – Flow and Unit Testing

12:39 – Gradual Typing

15:07 – Type Inference

17:50 – Keeping Up with New Features in JavaScript

20:49 – Generators

24:46 – Working on Flow

28:27 – Flow vs TypeScript

35:41 – Putting the “Java” Back in JavaScript

  • Server/Client Overview
  • Prototyping

45:26 – Flow and the JavaScript Community

46:43 – React Support

48:39 – Documentation

Picks

Nolan Lawson: We have a problem with promises (Aimee)
Jim ‘N Nick's BBQ Restaurant (Aimee)
Frank McSherry: Scalability! But at what COST? (Jamison)
Frank McSherry: Bigger data; same laptop (Jamison)
Greg Wilson: What We Actually Know About Software Development, and Why We Believe It's True (Jamison)
Marron: Time-Travel Debugging for JavaScript/HTML Applications (Jeff)
Real World OCaml (Jeff)

Muse (Jeff)
Shtetl-Optimized (Avik)
Chef's Table (Avik)

This episode is sponsored by

comments powered by Disqus

TRANSCRIPT

JAMISON:  I hear a ticking noise in the background.

DAVE:  Oh yes, that would be me.

[Chuckles]

JAMISON:  That’s okay.

DAVE:  That was actually my turn signal. I was just dialing in for a second to tell you that I’m probably not going to be able to join.

AVIK:  Oh, that’s Dave.

JAMISON:  Okay.

[Laughter]

JAMISON:  And he has a bomb.

AIMEE:  [Laughs]

DAVE:  That was not a nervous tick or a bomb.

[Laughter]

DAVE:  That was, just to help, the harmless turn signal.

JAMISON:  Okay. Well, I hope…

AIMEE:  At least we know you’re a safe driver.

JAMISON:  Yeah.

[This episode is sponsored by Frontend Masters. They have a terrific lineup of live courses you can attend either online or in person. They also have a terrific backlog of courses you can watch including JavaScript the Good Parts, Build Web Applications with Node.js, AngularJS In-Depth, and Advanced JavaScript. You can go check them out at FrontEndMasters.com.]

[This episode is sponsored by Hired.com. Every week on Hired, they run an auction where over a thousand tech companies in San Francisco, New York, and L.A. bid on JavaScript developers, providing them with salary and equity upfront. The average JavaScript developer gets an average of 5 to 15 introductory offers and an average salary offer of $130,000 a year. Users can either accept an offer and go right into interviewing with the company or deny them without any continuing obligations. It’s totally free for users. And when you’re hired, they also give you a $2,000 bonus as a thank you for using them. But if you use the JavaScript Jabber link, you’ll get a $4,000 bonus instead. Finally, if you’re not looking for a job and know someone who is, you can refer them to Hired and get a $1,337 bonus if they accept a job. Go sign up at Hired.com/JavaScriptJabber.]

[This episode is sponsored by Wijmo 5, a brand new generation of JavaScript controls. A pretty amazing line of HTML5 and JavaScript products for enterprise application development in that Wijmo 5 leverages ECMAScript 5 and each control ships with AngularJS directives. Check out the faster, lighter, and more mobile Wijmo 5.]

[This episode is sponsored by DigitalOcean. DigitalOcean is the provider I use to host all of my creations. All the shows are hosted there along with any other projects I come up with. Their user interface is simple and easy to use. Their support is excellent and their VPS’s are backed on Solid State Drives and are fast and responsive. Check them out at DigitalOcean.com. If you use the code JavaScriptJabber you’ll get a $10 credit.]

[This episode is brought to you by Braintree. If you’re a developer or manager of a mobile app and searching for the right payments API, check out Braintree. Braintree’s new v.zero SDK makes it easy to support multiple mobile payment types with one simple integration. To learn more and to try out their sandbox, go to BrainTreePayments.com/JavaScriptJabber.]

JAMISON:  Hello and welcome to episode 163 of the JavaScript Jabber podcast. I’m your temporary host, Jamison Dance. And we have with us Aimee Knight.

AIMEE:  Hello.

JAMISON:  Jeff Morrison.

JEFF:  Hey.

JAMISON:  And Avik Chaudhuri.

AVIK:  Hey.

JAMISON:  I have just a quick announcement. A friend and I are organizing a conference called React Rally. It’s about React. The website is ReactRally.com. And the call for proposals is open right now. It’s open until June 21st. So, if you want to speak there, we do cover travel and hotel and we’re looking for speakers. We’d love to have you. If you want to attend we have early bird tickets on sale right now. And the regular tickets should go on sale here in a couple of weeks. So, please check out the website ReactRally.com. There’s links to the call for proposals and links to buy tickets on there. We’d love to see you there.

So, Avik and Jeff are our guests today. Do you mind introducing yourselves?

JEFF:  Sure. I’m Jeff. I work at Facebook. I work on the Flow team. And I’ve worked on various other JavaScript things in the recent past. I worked on React, did JSX stuff for React when it first open sourced. Yeah.

AVIK:  Hey, I’m Avik Chaudhuri. I work at Facebook also on the Flow team. Before this, I used to work on ActionScript at Adobe. And before that, I have an academic background. I did a PhD and several other things on computer security and programming languages and so on. So, I’m generally interested in language stuff.

JAMISON:  Awesome. So, you did a PhD in several other things. Does that mean double PhD? [Chuckles]

AVIK:  [Chuckles] It means a [inaudible]…

JAMISON:  A triple PhD?

AVIK:  After a PhD. A [inaudible], go into other [inaudible]

[Laughter]

AVIK:  Too much detail.

JAMISON:  I guest a post doc is kind of a double PhD. So, there was a theme with the things that you both talked about which is Flow. And that’s what we’re going to be talking about today. Do you mind giving a really high-level overview of what Flow is, for people who haven’t heard of it?

AVIK:  Sure. Flow is a static type checker for JavaScript. One of the distinguishing characteristics is that it does a lot of type inference using a sophisticated static analysis in the background. So, it can figure out a lot of errors without having to write too many annotations. Another distinguishing characteristic is that it’s pretty fast. So, you can throw it at a pretty large code bases.

And because we break up a type checking into separate chunks and parallelize all of that. And all of this chunking happens actually in the background. So that as soon as you save a file, you get the chunks from the background, and when you ask for results you merely get back the results. So, we focus a lot on performance as well. Yeah, so apart from that, it looks a lot like other type checkers for JavaScript out there. It uses pretty standard syntax for types. And it gives you back a bunch of typers. So, that’s what it does.

JAMISON:  So, you used a lot of words there that I think some people might not have a ton of experience with, especially if they’re frontend developers who came to JavaScript and that’s most of their programming experience. Do you mind talking about what static type checking is and why that matters to you?

JEFF:  So, I came to Flow from not working on type checkers before, so I guess I have a little bit of context there. Basically, Flow specifically you can think of as a more complex sort of linter. It looks at your code and it tries to find ways that you’re using your code. It follows literally, it’s called Flow, the flow of your program and tries to find ways that say you’re using variables that aren’t safe, that are likely to throw. If you try to add together a number and a string, it’s unclear if what you really meant is to turn that number into a string, concatenate it with the other string, or if you thought that that second variable was a number and you’re trying to add two numbers together. So, little things like that, that’s the gist of Flow.

AIMEE:  Maybe a good basic starting point, just go over the difference between a dynamic and a static language? I know that’s a very basic starting point, but…

AVIK:  Yeah, sure. So, a dynamic language, well, all programs are [typically] run dynamically. So, every language is almost a dynamic language except that some languages choose to include a type system in the language that imposes a static discipline as you’re coding. So, it imposes things like, “Okay you declare a variable. Now go tell me what that variable’s type is.” And if you say that it’s a number it’s always going to hold a number. And that language is going to check that.

Now at runtime, you can forego all the static checks and do all the checks at runtime. And that’s what a lot of languages like JavaScript or Python or various other dynamic languages, so called dynamic languages do. They defer all those checks at runtime because ultimately you’re going to compile the program into machine code. And it would be really bad if at the machine code level you want it to do some kind of string operation on a machine integer. But now a lot of languages can do these checks statically, which means that they have to statically reject a lot of programs that would otherwise run fine at runtime. But the gain is that now they can use this… well, the first benefit is that you catch a lot [of errors] early on during the development process. But some other languages actually go further and then exploit the benefit of these checkings to completely eliminate dynamic checks at runtime so that you get performance benefits and so on.

In general, types are great for catching errors at least or helping you maintain your code as your codebase grows. So, we view types as kind of a sidekick to a language. Not really completely integrated into the language, but as a tool to help programmers write correct programs and check various kinds of errors early on, and provide many of the benefits that classic statically typed languages would provide.

JAMISON:  I like how you put it as viewing types as a tool to help programmers. I think for me the benefit of types is that it makes explicit in the code a lot of the assumptions that you have about the code that are just in your head. So, if you have a function that takes an argument and you know that this argument is going to be an object, it has three properties with these names because you use them that way inside the function, you can declare a type that has those three properties and say, “This function takes a thing that looks like this. And if you pass in anything that doesn’t look like this, it’s just going to give you an error.” So, it gives you more certainty instead of just hoping that everyone who uses your function passes in the correct thing, you have some tool that tells people, “This is what the object you pass in needs to look like.”

JEFF:  It’s really nice because you wind up with… it’s documentation, right? But it’s enforced documentation. So, you don’t have this… it’s a class of documentation where if you write it and then as your code changes, it continues to be verified. So, if that particular documentation gets out of date pretty quickly.

AIMEE:  I was going to say the same thing, Jeff. One other question I have about it, some people say that’s the job of unit testing. So, why use something like Flow on top of unit testing?

JEFF:  That’s a pretty good question. We get it a couple of times a lot, too. I think our general perspective on this is that it couples well with unit testing. The two go together. So, there’s a class of things that you can use a type checker for to catch things without you saying much except perhaps these certain amounts of documentation that you choose to write anyway. And these things are the kinds of things that Flow and type checkers are built to help you catch.

But then there’s a set of things that are more high level and advanced. It’s like, “Well, I want to say that this function properly adds these two values together in the way that I expect it, or does these higher level operations.” Those are the more explicit things that you need unit tests for. And I think a lot of times it’s easy to forget that they’re both really useful. They’re both just ways of holding your program in your hand and turning it from different angles and looking at it and trying to [solve] bugs.

AVIK:  Yeah. One more thing I want to add is that no one strategy, I think Jeff was alluding to the same thing, no one strategy is going to be enough. So, testing has a lot of advantages over typing in that it can go really deep and [inaudible] that a type checker doesn’t even know how to check. But at the same time it is limited by coverage. So, you have to explicitly know… if your tests don’t cover all your code parts or you have not set up your context properly so that it can exercise all of the code parts that could be exercised, then you possibly have missing errors.

And on the other side, static type checking is like an approximation in the other direction. It’s almost over-approximating all the things that can happen in your program. So, it’s trying to be super conservative. And again, it can possibly reject programs that could be perfectly fine. So, you don’t want static type checking for everything as well. So, both of those have their benefits. And as Jeff said, they play together and we of course use both.

JEFF:  Yeah. One other thing that occurred to me as you were talking about that is, so I used to work on our [tests sys], Jest at Facebook. And one constant battle when working on Jest and probably any test system is trying to find ways of making those tests fast. So, when you’re executing code like in a test, you have to execute the code. And so, as slow as code that you’re executing is, it’s as slow as your tests are. With static type checking you have the ability to take out some of those simpler tests that you have to actually execute code for and formalize them into this static checklist that’s going to be a little faster.

JAMISON:  Avik, I think you mentioned some things earlier about the gradual typing stuff that Flow does. I think some people might have experiences with languages like Java or Golang or C++ where your program has to be typed. Every variable has to have a type. And Flow’s a little different because you can have parts of it un-typed and only add types in when you want to later. Can you talk a little bit about that?

AVIK:  So yeah, as you’ve said, types in Flow are completely optional. One of our main design goals was that Flow should never get in the way of a JavaScript programmer’s workflow. So, if they know that they are doing the right thing, we don’t want a type checker to pedantically point out that there is a mistake when there is none. So, from very early on we provided multiple ways in which you could shut off Flow, make it shut up. So, there are lots of handles you can do.

So, one very brutal thing you can do is not bring in a file into Flow. So, if you choose to have typing you have to very explicitly add something called @flow in the comment header on top of the file. And only then would flow even begin looking at the rest of the code inside the file. Well, it would parse the code but not much else. But even inside the type system, suppose you have type checked most of the code in a file but there is one corner where you’re doing something completely crazy and it doesn’t look very crazy to you but it looks crazy to Flow and it throws a lot of wild errors. And you do maybe some testing on the side or some reasoning on the side and you are completely convinced that the code is correct.

So, there are multiple ways in which you could actually say that, “Okay Flow, shut off at this point.” So for example, you can use this type called ‘any’ that we have. And you can use it to type anything. And it will literally just stop propagating constraints through that location. So, anything that you write to that variable and any other uses of that variable are completely disconnected. So, that means that you won’t get type errors. So yeah, so this form of gradual typing, the idea is not new. It appears in a whole bunch of other languages as well. We adopt it completely because what we’re trying to do is provide some benefit to programmers but not at the cost of completely blocking them. If they know what they’re doing, it’s fine.

JAMISON:  I think I mentioned Golang as one of these statically typed languages. But Go has type inference. Does that mean Flow has type inference as well in addition to these features that allow you to turn off the type checking?

AVIK:  Yes. So, this is another very nuanced kind of interesting point that you brought up. So, in a lot of traditional gradually typed languages what happens is you have to explicitly type everything in order to then only do checking for those parts of their system that have annotations. And anytime you leave out an annotation, the implicit assumption is that well, it’s a whole wild world. You don’t know what you are doing, so I’m not going to do any checking there. Whereas what we try to do is yes, we have type inference which means that if you leave out a type, we would actually try to infer a static type for it. So, it’s kind of, it hits a middle ground where you can tell Flow to go away if you don’t want it.

But once you buy into Flow it does a lot of stuff without you asking it, like without you having to [inaudible] along with annotations and so on. And again, Go and various other languages before that, for example ML is the language in which Flow is written, all of that family of languages that have been around for a long time also do type inference. A lot of these systems in the process of doing type inference, they have to limit themselves to various languages of types that are tractable and so on. So, a lot of design goes into the space as well. So, it’s hard to compare one language against another when you’re talking about what kind of types you can infer in these languages. So, Flow does something that is very appropriate for JavaScript. Go does whatever Go requires. But yeah, the idea of combining type inference with a gradually typed language is pretty interesting because it’s a sweet part in the design space.

JEFF:  There’s another interesting aspect to this gradually specifying types, the ability to do that at different levels. And that is it lets you decide when for example you want to spend time documenting something like we talked about earlier and enforcing those documentations versus not. So, if you’re quickly prototyping something you may or may not want to spend time writing docs as you may or may not throw that code away. But that’s like an important aspect and tenet of gradual typing I think as well.

JAMISON:  Yeah, that makes sense. I feel like the effect in practice of Flow’s gradual typing and type inference is that you surround parts of your program with types and then anything inside those parts get all the benefits of it without you having to do the work, which is really nice.

AVIK:  Exactly, yeah.

JAMISON:  So, I asked on Twitter before this if people had questions. And there were lots of questions. Several of the questions fell into the theme of how do you keep up with the changing stuff in JavaScript? So, when you are working on Flow you have to explicitly support every feature of JavaScript. And as new things have come in from ES 6 and JS 2015 or whatever it’s called now, some of that stuff you can’t use yet in Flow. How do you reconcile those things?

JEFF:  Yeah, so I can speak to this a little bit. So honestly, one of the best ways is it’s our job to keep up with it. So, I sit with Sebastian and a couple of others on TC 39. We go to the meetings and keep up with the changes and consider those changes as they come up so that we can get a head start on how we’re going to fit them into something like Flow in our tooling. But yeah, it’s definitely a challenge to keep up with these things, especially as… Flow is in a, still it’s like we open sourced in November so we’re still getting our baseline core typing stuff, getting the design solidified there.

So, adding new features has been doing it as people ask for it. We added support for ES 6 modules over the last couple of months and have been solidifying that. We’ll work, I think… so, we have an open source contributor right now. Samg is his GitHub name. But he’s been working on let/const which has been awesome. And I think we’re going to have for-of support soon. And I think those are three of our most top asked ES6 features so far. Another aspect of keeping up with this stuff is the compilation part, the thing that stuff like Babel takes care of. Babel, sorry.

JAMISON:  Sure, I don’t know how to say it.

[Chuckles]

JEFF:  I think he said…

JAMISON:  I just typed it.

JEFF:  I think Sebastian said you say it like an Australian would say it, is what he said.

[Laughter]

JEFF:  Babel. So, they’ve been doing this pretty awesome job of keeping up with new features, features that are in the spec, features that aren’t in the spec yet but they’re experimental. And Flow from the beginning has taken an approach where it’s more of an analysis tool than a compiler. So, Flow itself, the tool, the binary that you get when you use Flow will just read code and spit out errors. It doesn’t do compilation. Instead, you use Flow on your code and then you use a tool like Babel, or we have an internal one that we’re trying to move away from and towards Babel. But any of these transpilers, these open source transpilers can take the bits that are not… like the type annotations and [strip] them away for you. So, they’re decoupled in that sense.

JAMISON:  That’s a good point though. I guess we didn’t say that explicitly, that when you write code for Flow you put stuff in your JavaScript that the browser or Node or whatever runtime you’re using isn’t going to understand. So, you have to use something to pull that out.

JEFF:  That’s right. We tried pretty hard to minimize that, obviously. But sometimes it’s useful.

JAMISON:  Yeah. So, I use it with Babel. I’m saying it wrong now. And it’s pretty seamless. Related to that ES6 question, the number one specific feature people asked about was generators. And that’s the thing I bug you a lot in IRC about, too.

[Chuckles]

JEFF:  Yeah.

JAMISON:  Is there a timeline on that or is there an amount of money attached to that?

[Laughter]

JEFF:  So currently, somebody on the team I think as of this week decided to pick up async/await. And I haven’t put much thought into how much it would take to do generators as well. But I think async/await has been the primary means by which people want… I don’t know if I worded that properly, but you know what I mean. I think a lot of the asks for generators seem to have come from things like for things like Task.js. So, we were hoping that async/await would handle a lot of those cases. But yes, generators are something that we really [inaudible] too.

JAMISON:  So, it sounds like two weeks. Can I…

[Laughter]

JEFF:  Oh, gosh.

JAMISON:  The default programmer timeline estimate when you don’t know how long it takes.

[Chuckles]

JEFF:  We should, you and anybody listening should go find the GitHub task and…

AVIK:  [Laughs]

JEFF:  And mention your desire for it so we can make it loud.

JAMISON:  [Laughs]

JEFF:  That seems to be our best driver for these things. It’s like, how many people are asking for it?

AVIK:  So, one note here is that some of this work is mostly parser work plus only a bit of work on the type checking side. So, not modules. Modules were a pervasive change to the type system. But things like generators or async/await, under the hood they rely on promises which we already support. So, the hope is that feature-wise they would just de-sugar two calls to the promise API. And the rest of the work is recognizing these in the parser and routing the calls appropriately. So, overall in the grand scheme of things it’s not a lot of work. But we still need to prioritize them somehow.

JAMISON:  I’m just laughing to myself when you say ‘not a lot of work’ because you have a PhD in computer science and I think your standard for ‘not a lot of work’ is probably different from mine. [Laughs] If you just handed me the generators feature and were like, “All the pieces are there. You could figure it out,” then I would go be a lumberjack instead of program.

AIMEE:  Aww.

[Chuckles]

JEFF:  I think we get these questions a lot. It’s like, when are you going to get this and that? And I think we want to get of all of them. It’s just a matter of prioritization. So, one of the things that we’re really working, we spend most of our time on right now, the really high requested ES features, ECMAScript features. But also the other things we’re working on are improving the general design of the type system. So, we want to continue to improve gradualness. So, you can get as much out of the type system as you can with as little work as possible. That’s one high-level goal that we have for right now. And then typing React is also a really big thing we’re spending a lot of time on as well.

JAMISON:  We didn’t talk about that at all.

JEFF:  And then perf is also something that we’re working on, too. We want to get Flow as fast as we can get it.

AVIK:  Yeah. And also, the core part of the type system as Jeff was saying, that’s still being solidified. And that’s… spending some time working on those general things is actually worth it because it makes adding new features much faster. So, if you have to reinvent the wheel and re-implement a large chunk of the type system every time you’re faced with implementing a new feature, that’s not such a great thing. But some of that cost can be amortized by thinking ahead of, “Okay, so what general facility does Flow lack right now which if implemented would enable the implementation, fast implementation on many other features?” So yeah, so again it’s a matter of priorities. We are a small team. We’re trying to do lots of things at the same time. So, some of these features get pushed even though we want them earlier.

JAMISON:  So, you started talking a little bit about implementing stuff in Flow. How do you work on a type system like this for a language that already exists? Is it similar to if you were just building a programming language from scratch? Or what are the pieces there?

AVIK:  So, we have set up the type system to be almost extensible in some ways, at least the typing rules. So, typically what happens when you’re about to implement a feature is you have to do some work in the parser to the extent that part of the grammar does not completely interfere with other things in the language. That should not be too much work. But sometimes it does interfere with a lot of other constructs.

So, even parsing becomes a big deal. And then once you do that all you have to do is walk that part of the AST. Everything else is already walked. So, you add a case for the new feature that you are trying to implement. And you have to set up a so-called typing rule which is just some approximation of what happens at runtime and you hit that construct. So again, the type system is pretty expressive. And most of the time you can find something that you can reuse. But sometimes you have to add a new thing. And then you have to implement what its behavior is. But it’s still kind of localized I would say. It’s no more different in character than trying to implement a new JavaScript feature in a browser for example.

So, it would involve the same steps. It would involve some parsing work and then it would involve laying down what this new construct means at runtime. Except that now we are just talking about what should happen at compile time when you see that construct.

JAMISON:  That makes sense.

JEFF:  I could add a bit of context too because this is the first type system I’ve ever worked on. I worked on some language tools for JavaScript before. In general, the high level way that Flow works is like Avik said, you start with this parser and you get the syntax tree, this abstract syntax tree similar to what a lot of the open source compilers like Babel and JSTransform and Traceur do now. So actually, I think there are a lot of people somewhat familiar with that. At that point you deal with the syntax tree and you run through it and visit it. And Flow basically builds up, while it visits this tree it builds up this set of little bits of knowledge. It says, “This variable was assigned to this variable and this function is called with this variable.” And there are these individual little tiny bits of information that are put into this set. And then towards the end, it actually goes and it ties all these bits of information together.

So, when you add this new feature you first go add support to the parser so you could have it in the syntax tree. And then you go through the set of code that runs through that syntax tree and collects those bits. And you make sure that the proper bits are collected for say if you wanted to build generators. You collect the proper bits of information for generators. You say, “Here we called yield. And this yield is going to return a result of…” or sorry, “This call to next on the iterator is going to return the result of that yield,” and so forth. And then of course at the end in the last stage you go and tie these bits together. And you say what it means for this flow as we call it, or bit to be combined with that other bit. And ultimately you wind up finding cases where a number flows to a string. Or yeah, I might have… I don’t know how deep that was.

AVIK:  [Laughs]

JEFF:  I might have started to… [Chuckles]

JAMISON:  No, no, no. That makes sense. So, you’re like building up knowledge as you trace the execution of the program, sort of, through the AST and then checking it against these types, or things that you’ve inferred about the program.

JEFF:  Exactly.

AVIK:  Yeah.

JAMISON:  Okay. That kind of makes sense.

AIMEE:  Since we’re sort of talking about ES6 and features you were adding for that, it seems like a popular question that people are asking is why you’d use Flow instead of something like TypeScript. I think you guys already answered this, but maybe not explicitly. So, it might be helpful to go over that.

JEFF:  Yeah, so we started Flow a little while ago and one of the reasons we started Flow is because we had a bunch of these little bits of analysis already built on top of JavaScript. And we formalized them together and that’s how Flow came to be. So ultimately, Flow takes a bit of a different approach than other tools like Closure Compiler and TypeScript because it’s data flow oriented technology. But the other thing is that we wanted to be able to target specific features as well. And so, I guess the answer is really, it’s whichever one suits your needs. We think that when we build this system, if we can build on this technology that has really good inference support, that’s a benefit of Flow is you have really good inference support.

AVIK:  Yeah. So, one thing we have thought of from the very beginning was that Flow was never going to be limited to being a type checker. What we really wanted to do was have a static analysis tool that would understand JavaScript programs well. Everything you do in a JavaScript program, all kinds of constructs that you can use in JavaScript, they have a very [faithful] representation inside Flow. So, Flow approximates statically but still, the approximation is fairly [faithful]. So, it actually knows a lot about what your program is doing, which is not limited to just traditionally talking about [inaudible] types. Like, strings and numbers we mention a lot because they are the canonical examples of types.

But imagine you have a function. We know which variables you are reading and writing in that function, where that function is flowing, where it’s being attached as a method, and which prototypes are being attached to what objects, and so on. It has this whole body of knowledge. And at the end we use this knowledge right now for type checking. But moving forward we also want to use it for various other static analysis jobs as well. For example, we want to integrate this in editors for super easy refactoring. We want to actually do, try automatic transformation on the code at some point, think about how we can make the code more performant by analyzing the code ahead of time.

So, there are lots of these other applications that go beyond type checking. And at the heart is this type inference, although [inaudible] it’s not really just a type inference [inaudible]. But it’s like a general inference [inaudible] in which you can encode these bits of information that Jeff talked about. But again, these bits of information are not limited to just type information. You have lots of other bits of information that you can also add. And at its core, Flow is just propagating information from one point to another point by tracking the data flow through the program.

So, the goals are more or less more ambitious I would say. Why a programmer might choose Flow over TypeScript right now, I would claim maybe it would be slightly more convenient for them because they won’t have to write as many annotations and they would get more errors with doing less work. But at the same time, we are really just starting out. So, there’s a lot of lack of [polation] flow that people might be used to. So, it’s really up to the programmer to check it out and see.

JEFF:  As you were talking, one thing that occurred to me, concrete thing that’s information to make a decision of off, there are a couple of distinct features as well between the two. So for example, Flow takes a non-nullable by default approach to types. And so, this is up to the people who use the type system to make a decision on, but it’s a concrete feature. Basically if you take for example a parameter and a function, you could say that every parameter can either be null or it can be the type that you said. Whereas in Flow we’ve taken the approach that it’s never null unless you said that it might be null. In TypeScript you’ll find that every type is nullable. So, every parameter that comes into a function could either be null or the type that was specified.

JAMISON:  It seems like the behavior TypeScript has is common in other programming languages. That’s just how it seems to work and then it’s weird when it doesn’t work like that. But it makes a lot of sense when you get used to it.

AVIK:  So, the inventor of this null business was Tony Hoare who was of course the famous [inaudible] computer scientist. But he in a recent talk maybe two or three years back called this and mentioned his billion dollar mistake.

JAMISON:  [Laughs]

AVIK:  Lots of people have been burned by null pointer exceptions and they have caused crashes in space probes and so on.

[Laughter]

JEFF:  [Don’t] make your space probes in JavaScript, everybody.

[Laughter]

AVIK:  So, in the grand scheme of things, I think this might be a more recent shift. But over the last few years it’s pretty clear that avoiding null is a good thing. And using nulls as a default value should be a very explicit operation and should never be an implicit thing, as is there in most languages. And in fact interestingly, the Google Closure Compiler also takes this view. So, TypeScript is different in that sense among the more recent tools for JavaScript. But the other reason which is more interesting is that actually distinguishing between null and other values requires much, much more muscle in the type checker as well.

So for example, it’s very easy to say that, “Okay, we are now going to distinguish numbers and null.” But then how would a programmer proceed if he wanted to use null? Well, he could pass in null and he could use these nullable types as we have it, which specify that some type is nullable. But then to do any work at all with such a parameter, they would have to do null checks, right? And then your type checker has to follow the consequences of null checks in your program. And inside a function block that means that a variable can change types. It can start off being a nullable number but after you do the check inside that block, it becomes a number.

So, that’s again, it’s pretty complicated analysis that you need to do. And that kind of analysis is not typically done in a lot of type checkers. So, all of this is, so what I want to say is that the idea that null was part of every type is an archaic idea. People are moving away from that idea now, having realized that it’s a bad idea. To support it requires a lot of type checking muscle. So, it’s not very easy to support. So, there is some inertia to move existing type systems to be more strict in this space. Flow being a kind of design from scratch, in recent times can afford to do that. But it’s an opportunity we basically [inaudible]. So, that’s where that came from.

JAMISON:  That’s really cool. So, I have a question kind of related. I guess it’s related to the whole topic of Flow in general. What do you say to developers who are concerned about putting the Java back in JavaScript? They just want to get stuff done and build cool frontend applications and adding extra tooling and especially static type checking, if they’re not familiar with it or if they’ve used it in the past and hated it, seems painful and overhead. What do you say to people like that?

JEFF:  Well, I know I’ve heard this in actually a couple of contexts. This might be the first time I’ve heard it in the Flow context. But it’s fair. And it’s a bit of a packed question because it can mean lots of different things. I’ve heard it mean things like putting classes in JavaScript. That’s one context I’ve heard of this. But I guess if we were to break it down, one intention I think you could imagine people meaning is boilerplate is a problem. Java has lots of boilerplate.

JAMISON:  Sure.

JEFF:  This is definitely one of the core goals that we pay a lot of attention to when we add new features and stuff. We try to remove as much ceremony as we can. And we already talked a lot about the inference stuff. So, that’s the purpose of the inference. It’s like, if you want to put the type annotations there, you can for checking and for documentation. But you don’t have to. In Java, you have to, right? You need this stuff for it to even compile and run. And that leads into the second thing, which is stuff like Java, you have to compile it in order to run it because that’s how the language works. It’s part of the language. And that’s not the case with JavaScript or typed variants of JavaScript that we’re working with here. So, it’s always possible even if Flow gives you errors. It’s always still possible to run your code. So, it gets out of your way quickly. And that’s another thing I think people draw parallels to with these things is, “Whoa wait a second. I don’t want to have to compile my code before I run it.”

AVIK:  Yeah. Another thing we keep saying whenever we’re introducing Flow to people. Well one is, yeah, it doesn’t get into your way in terms of errors and so on and [tries] to play along with your existing idioms. If you’re writing idiomatic JavaScript you should be fine. And it’s Flow’s job to figure out what’s going on. But the other thing also is yeah, there’s this whole waiting for a program to compile is not something that people do in JavaScript. They just emit something and immediately I refresh the browser and see the changes and test it out. And maybe it doesn’t look right and they change something else. And then refresh the browser again. So, I’m used to this fast workflow, right? And that’s again something that we were very mindful off when we design Flow. Like doing this type checking in the background, in the server, and having the results always ready when you are ready to query them.

JEFF:  You should clarify that, the server/client thing about Flow.

JAMISON:  Oh yeah, we haven’t talked about that.

AVIK:  So yeah. So, I mentioned earlier. I don’t know how much we want to go into this but yeah, so it’s…

JAMISON:  Even just a high-level overview?

AVIK:  Sorry, okay. So, the way checking works in Flow is that you start up a server, which looks at any pointer to some codebase, a pointer to a directory that has all of your code in it. And well, you could configure all of this. But at a high level, that’s what’s going on. It type checks all of that code initially. So, that takes maybe some time. That typically takes more time than incremental checks. But once that is done, maybe after 10 seconds or 15 seconds or whatever, for small code that’s even less. At that point the server has all the information it needs about the program about your codebase. And then when you edit the file, it only does the minimum amount of work that is necessary to keep that information up to day. So, it knows everything about what the dependencies on these files are. So, it’ll automatically recheck that file and its dependencies.

JEFF:  It’s watching the codebase.

AVIK:  Watching the codebase. And it’ll come back to the stable state where it knows everything about the codebase at that point. So now, typically you would keep saving as you’re editing. Or say you switch branches and you bring a bunch of new changes to your file system. You don’t have to then type and say, “Okay, now compile my program,” and wait for it. That thing has already started happening as soon as the files changed in the file system. So now, when you go and actually ask for type errors and you could do that through the command line but also through an [inaudible]. You say, “Okay, let me see the errors now.” At that point the errors are already there in the server. And all it does is it just sends back that information immediately to the client. And you get red lines for all of your program.

So, that’s a very convenient model which JavaScript programmers shouldn’t have a big problem with because they really don’t have to wait for these results anymore. So, that is just one thing that among the other things that Jeff mentioned where every time somebody says, “Please don’t turn JavaScript into Java,” we [chuckles] completely sympathize with those people. And we are on their side. So, from the very beginning we never wanted to create a Java where we would impose our own view of what a correct program is. And have that manifest in the type system. No. Instead the type system is there to play along with JavaScript best practices and promote them or encourage them while trying to discourage bad programming styles. So, it’s very tuned to JavaScript. And so…

JEFF:  It’s pretty interesting to sit in on occasional hallway discussions where somebody will be like, “Oh, we should do it this way,” and, “No, we should do it that way,” and somebody’s like, “Well, what do people do?” And then that’s the end of the conversation.

AVIK:  yeah, yeah.

JEFF:  That’s [inaudible] the idiomatic way of doing it in JavaScript.

AVIK:  Yeah, yeah.

JAMISON:  Oh, cool.

AVIK:  Yeah. So, one small other thing is that, people miss this, is that Java is the worst example that you can think of, of a statically typed language.

JAMISON:  [Laughs]

AVIK:  If you are hurt by Java and you think that that’s the canonical example of a statically typed language, that’s where people are misled. Because statically typed languages have been around for a long time even before that, in the ML family and every other language in that realm. And the main difference between those languages and Java is type inference, again. It’s not as if people deliberately in JavaScript are trying to write unsafe programs. They implicitly have some type inference in the head. They just don’t want to write them down all the time because it slows them down. And by inferring those invariants that they have in their head as [inaudible] with their code, we are trying to do the best possible thing in that scenario. And so yeah, static typing is again, it’s not limiting the expressivity of these JavaScript programmers. They are mostly encouraging what they already do and just formalizing that a little bit.

JAMISON:  That makes sense. One other argument that I’ve heard about both TypeScript and Flow but it seems like it almost applies to Flow more is that if you’re working on a large project or with a large team where there’s just a lot of code and it’s too much to keep in your head all at once, it can be really helpful to have these static types. But if can also be way faster to just crank something out with no types just by yourself. And the nice thing about these gradual type system is that they support both of those. Like if you just want to hack something together then you can still do it in the same language. And then if you want to add structure around it and make it easier to verify that it’s correct, then you can add those types in as your team grows and as you build on this codebase that you’ve started and maybe hacked together quickly.

JEFF:  Yeah, that’s totally true. Another extension of that is sometimes it’s nice to… prototyping is like it’s important to be as quick as possible, not necessarily as right as possible when you’re prototyping. And then it’s only when you’ve established your prototype, right?

AVIK:  Yeah.

JEFF:  Like you want to really lock down and say, “Okay, we got this really cool thing. Now it’s time to… Let’s build it out.”

JAMISON:  Yeah, now you need to build on top of it.

JEFF:  Right. And so, at that point that’s when you’re ready to start adding some types or maybe some library definitions.

AVIK:  Yeah. In some sense, catching type errors is almost not the common case. Typically even when you prototype or when you show stuff, because you are backed with tests and you are kind of a reasonable programmer, you typically wouldn’t have too many type errors. It’s when you are trying to change the code, you or anybody else. Even personally, if you’re the only one who wrote some code and you’ve showed around your prototype and now yeah everybody likes it and you need to now extend it, at that point you would have to rethink. Okay, I was using this data structure and I need to change it, like add a field here or whatever.

And so, you’re changing the representation of what’s going on. And now you would have to remember-to update every other program point that relies on that change in representation. And having a type system basically just guides you through that process. Say that okay, you do some work and then you leave it up to me to tell you what work is remaining. And then I just remind you that okay, go change your program there as well. That backup is very nice to have. So, even for personal programs I would say projects start out small. Then time passes. Then you forget stuff. And tests are never that complete anyway. So, having a type system helps in that sense.

AIMEE:  I’m in total agreement to what you even said earlier rabotu using it as documentation.

AVIK:  Yeah.

AIMEE:  Just maintaining the codebase over time.

JAMISON:  So, one of the great things about JavaScript is that the community is so large. And there’s such a large repository of third-party code that you can use. How does Flow work with that?

JEFF:  Flow supports library definitions similar to TypeScript. So, Typescript has this standard format called .DITS for anybody who’s already familiar with TypeScript. Basically what that lets you do is it lets you describe the interface of a package or a library. So, you can say, I don’t know, what’s an example? React has this [inaudible] element method and so forth. And this is what the types are. And it can sit separate from the code itself so that the library authors can decide whether they want to put those types in the code directly or not. And if they don’t, then somebody else could come along and describe the interface for you. So, we’ve actually been… we have a very similar syntax to what Typescript does and we want to get closer to it. It’s like on that stack of [cool] things to do, right?

JAMISON:  Sure.

JEFF:  But yeah, basically that’s the answer to how do we type third-party libraries that aren’t typed themselves?

JAMISON:  Sure. And Flow comes with some of those already. There’s stuff for some of the browser APIs and the Node core or standard library.

AVIK:  Yeah.

JAMISON:  And there’s some React stuff in there, too.

JEFF:  Yeah.

JAMISON:  How much… I guess this is kind of an aside, how much of the React support in Flow is just in that library definition and how much is built into the tool itself?

JEFF:  Uh Oh.

AVIK:  [Laughs] That’s a very good question. And yeah, we would be happier answering it now than maybe a few months back.

[Chuckles]

AVIK:  So right now, there’s very, very little stuff that would be a special case inside Flow to recognize React. But it was not the case for a long time. But now, yeah. So basically, we read off library definition. And all of the newish ES6 React style code is completely checked using that library. Some of the old stuff is still special case inside the checker. So, we still know what React.createClass means internally. But again, if you’re using JSX or some other stuff, it’s all routed to the standard react.createElement call. So, it just picks up the types from there and other stuff. So yeah, so we just set up. So, the only special case we have right now is we recognize react.createClass especially. We create a class like you would in ES6 explicitly. So, all of the parts of that class are set up properly. And then we just let it go.

JEFF:  Yeah. Avik’s just spent what, a good couple of months trying to take this special casing and generalize it. And it’s pretty awesome.

JAMISON:  That’s great. That’s really cool. I’m sure that makes people that use other frameworks or authors of other frameworks happier too, that they can get first-class support for their stuff in Flow.

AVIK:  Yeah, yeah.

JAMISON:  I have one more question and it’s also kind of a criticism. [Chuckles] So, I really like Flow and it’s been great to use. We’ve been using it for a couple of months now. My complaint is that it’s really hard to find out what it does and how to use it. The documentation on the website is pretty [chuckles] sparse. And I’ve spent a lot of time in IRC where people are very helpful. But it’s like, “Oh, you asked for the magic keyword and now you know this secret…”

[Laughter]

JAMISON:  “undocumented feature that is really helpful for your everyday use.”

[Chuckles]

JEFF:  Yeah, totally fair criticism.

JAMISON:  And you’ve answered a lot of my questions actually, I think. You’re Jeff in IRC, right?

JEFF:  Yeah, yeah.

JAMISON:  Okay, yeah. So, you’ve been really helpful. But is there a way to…

JEFF:  I should probably just be writing docs instead of helping you.

JAMISON:  Well, no. I guess I want to…

[Chuckles]

JAMISON:  Instead of give like a pile driver burn, is there a way for the community to help with that documentation process?

AVIK:  Well, yeah. Well yeah, absolutely. So, this is all open source. Some people have actually gone and fixed typos or some small things like that. But you can totally go and edit documentation if you want.

JEFF:  It’s a GitHub Pages.

AVIK:  It’s a GitHub Pages thing, yeah. And literally the last time we probably touched the documentation was around open source time which was like five or six months back, which is not ideal at all. And the reason we have got away with it for so long was mostly people like Jeff being responsive on IRC. And internally we use groups and people just ask questions there. And they get answers there. But obviously that’s not ideal for everybody. So, we should set aside some time to update the docs.

JEFF:  Yeah.

AVIK:  This is like a non-problem, right? Lots of people complain. We know that we need to do it. It’s just…

JEFF:  Yeah. I’ve actually been meaning to, I can take some responsibility here because I keep saying I’m going to go update the website and I haven’t done it. But certainly if anybody wants to help out or write some docs of something that you found out inside a pull request as simple or not simple, please do it. Because I would gladly [inaudible] that.

JAMISON:  Cool. Do you have any more questions or any things that you wish we would have talked about that we haven’t talked about yet?

JEFF:  I don’t think so. No. This has been fun.

AVIK:  Yeah.

JAMISON:  Yeah, this has been really helpful. It’s hard for me because I use Flow and I like it. And I’m trying not to play insider baseball too much and just…

[Laughter]

JAMISON:  Talk about things that are only interesting to me.

JEFF:  Right.

JAMISON:  I hope it’s been helpful for people that are maybe new to it. It’s really great. You should check it out.

AIMEE:  I’m going to use it. I want to get…

AVIK:  [Inaudible] about that we, like you said, we hang out in IRC too. So, if anybody ever has more questions, that’s a good place. We can put the IRC I guess on the show notes maybe.

JAMISON:  Yeah, we’ll definitely do that. It’s a really good channel because even though 90% of what is said there goes over my head, it’s still really helpful for people that are beginners and who don’t know ML or OCaml or type systems or [laughs] computers or how they got there.

[Laughter]

JAMISON:  Yeah, it’s been really helpful. Great. So, if there’s nothing else, we can move on to the picks. Aimee, do you want to start us off?

AIMEE:  Sure. My first pick, it’s been tweeted out a bunch. So, people may already be aware of this. But it’s a really good article on promises that someone sent me two weeks ago. I think it was in the JavaScript Weekly. But I was checking it out before that. But it starts off with four different examples. And he asks whether or not you know the difference between those four. And then just at the end it will go through step by step what the different promise patters are doing and some gotchas and mistakes. So, I’m going to put a link to that article.

And then my second pick, I usually eat really healthy. But I was on vacation last week and ate at my favorite restaurant called Jim ‘N Nick’s. So, if anybody is ever in the south and they want good, southern barbeque cooking, that is my second pick. And I’ll put a link to that restaurant. You totally should google if you’re ever in the south, if you’re close to one of these places because it’s amazing. And that’s it.

JAMISON:  Cool. I’ll make myself go next. So, I have three picks. They’re all computer-related. I don’t have any music picks this week. Sorry.

The first two are a related series of blogposts about big data systems. But it’s a really interesting look at them. So, these three researchers look at all these really high scale systems that use tons of computers clustered together like Hadoop and Spark and Graphlab and all these stream processing systems. And they compare their performance to the performance of just running some algorithm that he handwrites on his own computer. And it turns out that it’s in a single thread. So, there are these systems that have a thousand computers in the cluster, massively parallelized, huge computing power. And it’s five times faster to just run it in a single thread on his own computer. So, it’s a look at the costs of these large scale computing systems and how sometimes the abstractions they give you don’t actually buy you a lot of performance. And you can get a lot faster performance off of simpler things. I thought it was really interesting. And the two blogposts are related. They’re both about the same topic.

And then the third pick is a talk called ‘What We Think We Know about Software Engineering’. It was from 2010 so I think it’s been around for a while. But it was new to me. It’s at a conference and I think it’s a professor who does research in software engineering. And he just talks about how a lot of the conventional wisdom that we pass around about productivity and estimation and how to build good software and how we know how long it takes and how we know how good people are at programming. [Inaudible] totally made up. And in software engineering you can get away with just, if you sound smart you can say a thing and then people believe you. Where if you were in medicine you couldn’t just say, “Yeah, if you rub these two sticks together on your leg, then it heals your broken bone.” Oh yeah, that wouldn’t get published in a journal, right? Btu in computer science you can just say agile methodologies help you develop software faster. Citation, I just thought of that and it sounds good.

AIMEE:  [Chuckles]

JAMISON:  And that’s your source. And people accept that. So, it’s a look at where this information comes from and how we can find out what we actually know about it. It’s really good. Those are my picks.

JEFF:  Cool.

JAMISON:  Let’s see. Jeff, do you want to go next?

JEFF:  Yeah, I’ll go next. So, my first pick is time-travel debugging, which is this concept that Microsoft just built for I think their new Edge browser which is awesome. If you haven’t heard of this before, it’s the coolest thing ever. Basically, I’ll send a link, and there’s MSDN has a demonstration on video. But basically you can, normally when you set a breakpoint in your JavaScript program, you can only step forward from there because the developer tools haven’t been keeping track of the state of the program before you hit that breakpoint. Because that would be crazy, right? There’s tons of state that happens up until the point where you want to break. Time-travel debugging actually lets you go back in time from the point where you want to observe a bug and see how you got into that state. It’s just really cool. You have to watch the video if what I said didn’t make any sense. But it’s really neat. And it’s pretty crazy that they’re building this and shipping it in a sane manner.

My second pick is OCaml, which is what Flow was written in. And I picked it because I learned it when I came to Flow. And it seems a litlte daunting when you first approach it. But it’s actually really not that bad. There’s a really good website that’s free and I actually use it as reference all the time and learn from it. And I still go back and reference it a lot. I’ll send a link here, too. But it’s RealWorldOCaml.org. It’s actually… it’s a really neat language because it’s like strongly typed but you actually typically don’t really write type annotations which is also cool because it matches with our philosophy with Flow, too. You can but you don’t have to. It compiles to bytecode or it compiles to native. And it’s, bytecode is not even jitted. So, it’s interestingly consistent perf. So anyway, it’s just a really interesting language. And it’s not what you’re usually used to if you come from C, Java, Python, JavaScript style languages.

AVIK:  And Jeff, did you know that it also has time-travel debugging?

JEFF:  And it does.

[Laughter]

JEFF:  Time-travel debugging. Which is to only reason that, no, no, but yeah. It’s also very cool.

JAMISON:  It’s the tagline for OCaml like, ‘OCaml: easier than Haskell’?

[Laughter]

JEFF:  It is easier than Haskell.

JAMISON:  Because that’s now it fits in my head. It’s like this wacky language not as hard as Haskell.

JEFF:  Totally, that’s a great tagline, yeah.

JAMISON:  Okay.

AVIK:  Yeah, comparing infinities, yo.

[Laughter]

JEFF:  And then I guess my last pick is probably not that obscure. But the band Muse is my favorite band ever. And they’re just awesome. If you haven’t heard of Muse you should listen to Muse.

JAMISON:  I like Muse.

JEFF:  Yeah.

JAMISON:  Great. Avik, do you want to give us your picks?

AVIK:  Sure. So, there’s this blog that I occasionally read. It’s called ScottAaronson.com/blog. This is by a guy who started out being a grad student. Well, before that I don’t know what he did. But he was a grad student in Berkeley. And now he’s a professor at MIT. He does a bunch of totally obscure stuff in computational complexity. It deals with hard problems like Proving P not equal to NP. And these are totally inaccessible to a lot of people. But the best thing about their blog is that this guy is a great explainer of things. So, while these concepts are totally abstract, he has a bunch of stuff on his blog that explains them in the simplest of ways so that you can follow along.

And he’s a pretty entertaining writer himself. He’s pretty witty and he writes about his travels and his work as well occasionally. He has some course material that also seems like he’s great fun for students as well. Because again, [building] us teaching. He explains these concepts like Quantum Computing and so on using such nice examples that it makes me want to emulate some of that when we are explaining some of our stuff to other people. Because our stuff is so much easier than what he’s trying to explain. So, that’s one thing.

The other thing is I’m really into cooking and so on. And I really love good food. And I found this great show recently on Netflix called Chef Stable that is basically a documentary. It has [six] episodes and profiles six chefs who are like chef some of the world’s best [stress] [inaudible]. Not the top but maybe enough 10, 15, 17 grand stuff. And all of these chefs are very different in the [inaudible]. And the thing that’s different for the show is that instead of going directly into the food aspects of things, they actually do this profile on the chefs themselves. And their lines and what kind of drove them to do what they are doing. And focused a lot of, how did creativity came into place and what kind of incidents in there, in the child [reflect] [inaudible] to some of the most celebrated issues that they can redesign and so on. So, it’s pretty cool, like a journey from the coldest parts of Sweden to Japan and some other places as well. So, it was a really fun watch for me.

JAMISON:  That’s really cool. Well, thank you so much for being here. It’s been really enjoyable for me. I feel like I’ve learned a lot and I’ve also… I have a long list of new things to learn.

[Chuckles]

JAMISON:  Which is, how I know I liked the episode. Thank you.

JEFF:  Yeah, thanks for talking. This is cool.

AVIK:  Bye. Thanks.

JAMISON:  Yeah. And thanks everybody for listening. We will talk to you next week. See you!

[This episode is sponsored by MadGlory. You’ve been building software for a long time and sometimes it’s get a little overwhelming. Work piles up, hiring sucks, and it’s hard to get projects out the door. Check out MadGlory. They’re a small shop with experience shipping big products. They’re smart, dedicated, will augment your team and work as hard as you do. Find them online at MadGlory.com or on Twitter at MadGlory.]

[Hosting and bandwidth provided by the Blue Box Group. Check them out at Bluebox.net.] 

[Bandwidth for this segment is provided by CacheFly, the world’s fastest CDN. Deliver your content fast with CacheFly. Visit CacheFly.com to learn more.]

[Do you wish you could be part of the discussion on JavaScript Jabber? Do you have a burning question for one of our guests? Now you can join the action at our membership forum. You can sign up at JavaScriptJabber.com/jabber and there you can join discussions with the regular panelists and our guests.]

x