Hack

Личный сайт Go-разработчика из Казани

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.