Every PHP programmer is familiar with day-to-day tasks that can be tricky or cumbersome. The code above is a great example of a common mistake where a method could unexpectedly be called on a null object, causing an error that wouldn't be caught until runtime. Another example is a complex API, where developers may have a solid understanding of its semantics but still spend time looking up mundane method names in documentation.
At Facebook scale — with thousands of engineers shipping new code twice a day — slowdowns like these are even more problematic. Before Hack, we had a simple language with a quick feedback loop — but how could we mitigate the sorts of problems described above? Could early error detection coexist with rapid iteration, all while preserving our investment in PHP? Could improved code analysis and introspection help make developers more productive with tools like auto-complete?
Traditionally, dynamically typed languages allow for rapid development but sacrifice the ability to catch errors early and introspect code quickly, particularly on larger codebases. Conversely, statically typed languages provide more of a safety net, but often at the cost of quick iteration. We believed there had to be a sweet spot.
Thus, Hack was born. We believe that it offers the best of both dynamically typed and statically typed languages, and that it will be valuable to projects of all sizes.
The Hack language
Hack has deep roots in PHP. In fact, most PHP files are already valid Hack files. We made a conscious choice not to support a handful of deprecated functions and features that were incompatible with static typing (e.g. “variable variables” and the extract() function). We have also added many new features that we believe will help make developers more productive.
Our principal addition is static typing. We have developed a system to annotate function signatures and class members with type information; our type checking algorithm (the “type checker”) infers the rest. Type checking is incremental, such that even within a single file some code can be converted to Hack while the rest remains dynamically typed. Technically speaking, Hack is a “gradually typed*”* language: dynamically typed code interoperates seamlessly with statically typed code.
Within Hack's type system, we have introduced several features such as generics, nullable types, type aliasing, and constraints on type parameters. These new language features are unobtrusive, so the code you write with Hack will still look and feel like the dynamic language to which PHP programmers are accustomed.
However, Hack adds additional features beyond static type checking, including Collections, lambda expressions, and run-time enforcement of return types and parameter types.
Collections provide a clean, type-safe alternative to PHP arrays. We designed them specifically to work well with static typing and generics. The Collections API offers many classic higher-order functions such as map() and filter() to facilitate functional programming styles.
Lambda expressions give a concise syntax for creating closures. While PHP has closures, it requires the programmer to explicitly name the variables they need to use from enclosing scopes. With Hack's lambda expressions, we automatically infer these uses, saving you needless work. Lambda expressions make it more convenient to take full advantage of the Collections API.
Run-time enforcement of return types and parameter types (including scalar types like int and string) provides safety beyond what can be checked statically while type annotations are being gradually added to a codebase. Run-time enforcement helps programmers detect and diagnose certain kinds of problems more easily, and it helps HHVM's JIT produce more efficient code by making it safe to trust type annotations for optimization purposes.
Instantaneous type checking
During development, a PHP programmer typically goes back and forth rapidly between the source code and the browser. Engineers can iterate as quickly as they need, testing and tuning an experien until it's perfect.
Traditionally, a type checker would disrupt this feedback loop as it takes time to analyze the source code. We didn't want to slow the PHP workflow, so we came up with a new approach to reconcile instantaneous feedback with type safety.
Our solution was to architect the type checker as a local server that watches the filesystem. The server keeps all information about the source code in memory and automatically updates itself when a file changes on disk. This approach has paid off: the type checker typically runs in less than 200 milliseconds and rarely takes more than a second, making it easy to integrate into the development workflow without introducing a noticeable delay.
Hack's type safety and refactoring benefits grow the more it is used within a codebase. Understanding that it would be difficult for some code to be completely transitioned to Hack right away, it was important to us that Hack be developed such that it can coexist directly with other PHP files as it is being introduced incrementally.
The rest of the conversion process, such as adding type annotations and using new language features, can be done as appropriate for the codebase. For example, a type annotation can be added for one function but left off another function, even in the same file. If a function parameter or class member does not have an explicit type annotation, the type checker considers its type to be dynamic, and it does not check the type of that value.
Within Facebook, we found that our engineers appreciated Hack enough that they started converting the majority of their own code voluntarily. With millions of lines of code in our tree, we also wanted some form of automation, so we built and use a number of code modification tools to assist the process (which we are releasing as part of Hack).
Don't worry, your PHP is safe!
HHVM is still a PHP runtime, and we intend to keep it that way. In fact, we are working hard to reach parity with PHP-5. One of HHVM's top priorities is to run unmodified PHP-5 source code, both for the community and because we rely on third-party PHP libraries internally.
HHVM is now a runtime that supports *both* PHP and Hack, so you can start to take advantage of Hack's new features incrementally.