Hack lets you write code quickly, while also having safety features built in, like static typechecking.
To run Hack code, install HHVM, the open-source virtual machine.
1/* ==================================
2 * READ THE DOCS!
3 * ==================================
4 */
5
6/* For more information on the Hack language:
7 * - About Hack: https://hacklang.org/
8 * - Documentation: https://docs.hhvm.com/hack/
9 */
10
11/* ==================================
12 * A NOTE ON PHP
13 * ==================================
14 */
15
16// The Hack language began as a superset of PHP.
17// Since then, the languages have (largely) diverged.
18// You may encounter the .php extension, which is no longer recommended.
19
20/* ==================================
21 * COMMENTS
22 * ==================================
23 */
24
25// Hack has single-line comments...
26
27/* Multi-line comments...
28 *
29 */
30
31/**
32 * ... and a special syntax for doc comments.
33 *
34 * Use doc comments to summarize the purpose of a definition, function, class or method.
35 */
36
37/* ==================================
38 * NAMESPACES
39 * ==================================
40 */
41
42// Namespaces contain definitions of classes, interfaces, traits, functions, and constants.
43
44namespace LearnHackinYMinutes {
45
46 /* ==================================
47 * TYPES
48 * ==================================
49 */
50
51 function demo_hack_types(): void {
52
53 // Hack has five primitive types: bool, int, float, string, and null.
54 $is_helpful = true; // bool
55 $int_value = 10; // int
56 $precise_value = 2.0; // float
57 $hello_world = "Hello World!"; // string
58 $null_string = null; // null
59
60 // Create a `shape` with the shape keyword, with a series of field names and values.
61 $my_point = shape('x' => -3, 'y' => 6, 'visible' => true);
62
63 // Create a `tuple` with the tuple keyword, with a series of two or more types as values.
64 $apple_basket = tuple("apples", 25); // different types are OK
65
66 // Use `arraykey` to represent either an integer or string.
67 $the_answer = 42;
68 $is_answer = process_key($the_answer);
69
70 // Similarly, `num` represents either an int or float.
71 $lucky_number = 7;
72 $lucky_square = calculate_square($lucky_number);
73 }
74
75 function process_key(arraykey $the_answer): bool {
76 if ($the_answer is int) {
77 return true;
78 } else {
79 return false;
80 } // true
81 }
82
83 function calculate_square(num $arg)[]: float {
84 return ((float)$arg * $arg);
85 }
86
87 // Enums are limited to int or string (as an Arraykey), or other enum values.
88 enum Permission: string {
89 Read = 'R';
90 Write = 'W';
91 Execute = 'E';
92 Delete = 'D';
93 }
94
95 // In contrast, an enum class can be of any value type!
96 enum class Random: mixed {
97 int X = 42;
98 string S = 'foo';
99 }
100
101 /* ==================================
102 * HACK ARRAYS
103 * ==================================
104 */
105
106 // The following line lets us use functions in the `C\` namespace.
107 use namespace HH\Lib\C; // the `C` library operates on containers
108
109 function demo_hack_arrays(): void {
110
111 // vec: ordered
112 $v = vec[1, 2, 3];
113 $letters = vec['a', 'b', 'c'];
114
115 $letters[0]; // returns 'a'
116 $letters[] = 'd'; // appends 'd'
117
118 // `inout` provides pass-by-reference behavior
119 C\pop_back(inout $letters); // removes 'd'
120 C\pop_front(inout $letters); // removes 'a'
121
122 // keyset: ordered, without duplicates
123 $k = keyset[1, 2, 3]; // values must be int or string
124 $colors = keyset['red', 'blue', 'green'];
125
126 // keyset keys are identical to their values
127 $colors['blue']; // returns 'blue'.
128
129 $colors[] = 'yellow'; // appends 'yellow'
130 unset($colors['red']); // removes 'red'
131
132 // dict: ordered, by key-value
133 $d = dict['a' => 1, 'b' => 3]; // keys must be int or string
134 $alphabet = dict['a' => 1, 'b' => 2];
135
136 $alphabet['a']; // indexing at 'a' returns `1`
137 $alphabet['c'] = 3; // adds a new key-value pair of `c => 3`
138
139 unset($alphabet['b']); // removes 'b'
140 }
141
142 /* ==================================
143 * THE HACK STANDARD LIBRARY (HSL)
144 * ==================================
145 */
146
147 // The Hack Standard Library is a set of functions and classes for the Hack language.
148 // Namespace use declarations are ideally at the top of your file but are placed here for instruction purposes.
149
150 use namespace HH\Lib\Str; // The `Str` library operates on strings
151
152 function demo_hack_standard_library(): void {
153
154 $letters = vec['a', 'b', 'c'];
155 $colors = keyset['red', 'blue', 'green'];
156 $alphabet = dict['a' => 1, 'b' => 2];
157
158 C\contains($letters, 'c'); // checks for a value; returns 'true'
159 C\contains($colors, 'purple'); // checks for a value; returns 'false'
160 C\contains_key($alphabet, 'a'); // checks for a key; returns 'true'
161 C\contains($alphabet, 'd'); // checks for a value; returns 'false'
162
163 Str\length("foo"); // returns `3`
164 Str\join(vec['foo', 'bar', 'baz'], '!'); // returns `foo!bar!baz`
165 }
166
167 /* ==================================
168 * HELLO WORLD!
169 * ==================================
170 */
171
172 use namespace HH\Lib\IO; // the `IO` library is a standard API for input / output
173
174 <<__EntryPoint>> // required attribute for the typical entry/main function
175 async function main(): Awaitable<
176 void,
177 > { // does not need to be named 'main' / is an asynchronous function
178 await IO\request_output()->writeAllAsync(
179 "Hello World!\n",
180 ); // prints 'Hello World'!
181 }
182
183 /* ==================================
184 * FUNCTIONS
185 * ==================================
186 */
187
188 // Functions are defined globally.
189 // When a function is defined in a class, we refer to the function as a method.
190
191 // Functions have return types (here: `int`) and must return a value of
192 // that type or return no value when a void return type annotation was used.
193
194 function add_one(int $x): int {
195 return $x + 1;
196 }
197
198 // Functions can also have defined, default values.
199 function add_value(int $x, int $y = 1): int {
200 return $x + $y;
201 }
202
203 // Functions can be variadic (unspecified length of arguments).
204 function sum_ints(int $val, int ...$vals): int {
205 $result = $val;
206
207 foreach ($vals as $v) {
208 $result += $v;
209 }
210 return $result;
211 }
212
213 // Functions can also be anonymous (defined with the `==>` arrow).
214 // $f = (int $x): int ==> $x + 1;
215
216 /* ==================================
217 * PIPE OPERATOR
218 * ==================================
219 */
220
221 // The pipe operator, `|>`, evaluates the result of a left-hand expression
222 // and stores the result in `$$`, the predefined pipe variable.
223
224 use namespace HH\Lib\Vec;
225
226 function demo_pipe_operator(): void {
227
228 Vec\sort(Vec\map(vec[2, 1, 3], $a ==> $a * $a)); // vec[1,4,9]
229
230 // the same result, but using the pipe operator and pipe variable:
231 $x = vec[2, 1, 3]
232 |> Vec\map($$, $a ==> $a * $a) // $$ with value vec[2,1,3]
233 |> Vec\sort($$); // $$ with value vec[4,1,9]
234 }
235
236 /* ==================================
237 * ATTRIBUTES
238 * ==================================
239 */
240
241 // Hack provides built-in attributes that can change runtime or static type checking behavior.
242 // For example, we used the `__EntryPoint` attribute earlier in the "Hello World!" example.
243
244 // As another example, `__Memoize` caches the result of a function.
245 <<__Memoize>>
246 async function do_expensive_task(): Awaitable<string> {
247 $site_contents = await \HH\Asio\curl_exec("http://hacklang.org");
248 return $site_contents;
249 }
250
251 /* ==================================
252 * CONTEXTS
253 * ==================================
254 */
255
256 // Hack functions are attached to different contexts and capabilities.
257 // A context is a grouping of capabilities; that is, a grouping of permissions.
258
259 // To declare allowed contexts (and capabilities), use the Context List `[]`.
260 // If contexts are not defined, your function includes permissions defined in Hack's `defaults` context.
261
262 // Because the context list is NOT defined, the `defaults` context is implicitly declared.
263 async function implicit_defaults_context(): Awaitable<void> {
264 await IO\request_output()->writeAllAsync(
265 "Hello World!\n",
266 ); // prints 'Hello World'!
267 }
268
269 // In the function below, the context list is defined to have the `defaults` context.
270 // A function can have multiple contexts [context1, context2, ...].
271 // `defaults` includes most of the capabilities defined by the Hack language.
272 async function explicit_defaults_context()[defaults]: Awaitable<void> {
273 await IO\request_output()->writeAllAsync("Hello World!\n");
274 }
275
276 // You can also specify zero contexts to create a pure function (no capabilities).
277 async function empty_context()[]: Awaitable<void> {
278 // The following line is an error, as the function does not have IO capabilities.
279 // await IO\request_output()->writeAllAsync("Hello World!\n");
280 }
281
282 /* ==================================
283 * GENERICS
284 * ==================================
285 */
286
287 // Generics allow classes or methods to be parameterized to any set of types.
288 // That's pretty cool!
289
290 // Hack typically passes by value: use `inout` to pass by reference.
291 function swap<T>(inout T $input1, inout T $input2): void {
292 $temp = $input1;
293 $input1 = $input2;
294 $input2 = $temp;
295 }
296
297 /* ==================================
298 * CLASSES
299 * ==================================
300 */
301
302 // Classes provide a way to group functionality and state together.
303 // To define a class, use the `class` keyword. To instantiate, use `new`.
304 // Like other languages, you can use `$this` to refer to the current instance.
305
306 class Counter {
307 private int $i = 0;
308
309 public function increment(): void {
310 $this->i += 1;
311 }
312
313 public function get(): int {
314 return $this->i;
315 }
316 }
317
318 // Properties and Methods can be static (not requiring instantiation).
319 class Person {
320 public static function favoriteProgrammingLanguage(): string {
321 return "Hack";
322 }
323 }
324
325 function demo_hack_classes(): void {
326 // Use `new` to instantiate a class.
327 $c1 = new Counter();
328
329 // To call a static property or method, use `::`
330 $typical_person = tuple("Andrew", Person::favoriteProgrammingLanguage());
331 }
332
333 // Abstract class can be defined, but not instantiated directly.
334 abstract class Machine {
335 public function openDoors(): void {
336 return;
337 }
338 public function closeDoors(): void {
339 return;
340 }
341 }
342
343 /* ==================================
344 * INTERFACES
345 * ==================================
346 */
347
348 // A class can implement a set of requirements via an interface.
349 // An interface is a set of method declarations and constants.
350
351 interface Plane {
352 // A constant is a named value. Once defined, the value cannot be changed.
353 const MAX_SPEED = 300;
354 public function fly(): void;
355 }
356
357 /* ==================================
358 * TRAITS
359 * ==================================
360 */
361
362 // A trait defines properties and method declarations.
363 // Traits are recommended when abstracting code for reuse.
364 // Traits are included in code via the `use` keyword.
365
366 trait Airplane {
367 // Introduce a class or interface requirement with the following syntax:
368 require extends Machine; // abstract class
369 require implements Plane; // interface
370
371 public function takeOff(): void {
372 $this->openDoors();
373 $this->closeDoors();
374 $this->fly();
375 }
376 }
377
378 class Spaceship extends Machine implements Plane {
379 use Airplane;
380
381 public function fly(): void {
382 // fly like the wind
383 }
384 }
385
386 /* ==================================
387 * KEEP READING!
388 * ==================================
389 */
390
391 /* This is a simplified guide!
392 * There's much more to learn, including:
393 * - Asynchronous Operations: https://docs.hhvm.com/hack/asynchronous-operations/introduction
394 * - Reified Generics: https://docs.hhvm.com/hack/reified-generics/reified-generics
395 * - XHP: https://docs.hhvm.com/hack/XHP/setup
396 * - ... and more!
397 */
398}
More Information ¶
Visit the Hack language reference to learn more about the Hack language.
For more information on HHVM, including installation instructions, visit the official HHVM website.