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