InterviewPitch
Hack interview questions

Hack Interview Questions with Answers

Most Asked Hack Interview Questions for Software Engineer Roles

100+ QuestionsDetailed AnswersCode ExamplesUpdated for 2026

Introduction

This page provides a complete collection of Hack Interview Questions and Answers designed for web developers, backend engineers, software architects, and candidates preparing for technical interviews with a focus on modern, large‑scale web development. Hack is an open‑source programming language developed by Meta (formerly Facebook) as a dialect of PHP. It is designed to support fast, type‑safe, and scalable application development. Hack runs on the HHVM (HipHop Virtual Machine) runtime and introduces features like static typing, generics, and advanced type inference, making it ideal for building and maintaining large‑scale web applications. This interview guide covers beginner, intermediate, and advanced Hack concepts including Hack syntax, types, generics, collections, async programming, XHP, HHVM, frameworks, and real‑world development scenarios for high‑traffic systems.

Why Hack?

  • Gradual typing – introduces static types to PHP without sacrificing flexibility
  • Performance – runs on HHVM, designed for high‑throughput, large‑scale applications
  • Modern language features – generics, null safety, and async/await for concurrent code
  • Deep integration with PHP ecosystem – reuse existing PHP libraries and frameworks
  • Used in production at Meta – powers Facebook, Instagram, and other massive platforms
  • Growing adoption – companies like Slack, Etsy, and others are using Hack
  • Strong tooling – with type checker, IDE support, and debugging capabilities

Most Asked Hack Interview Questions

Beginner
1. What is Hack and what are its key features?

Hack is a programming language developed by Facebook (now Meta) as a dialect of PHP. It combines the rapid development of PHP with the safety of static typing and modern features like generics, async/await, and XHP.

  • Static typing: Type annotations for safety
  • Async/await: Built-in asynchronous programming
  • Generics: Type-safe collections and classes
  • XHP: XML-like syntax for UI components
  • Performance: Runs on HHVM or PHP 8+ with the Hack compiler
Hack
// Hello World in Hack
<<__EntryPoint>>
async function main(): Awaitable<void> {
    echo "Hello, World!\n";
}
Beginner
2. What are Data Types in Hack?

Hack provides a rich set of data types including scalar types, collections (Vector, Map, Set, Pair), and user-defined types.

  • Scalar: int, float, string, bool, null
  • Collections: Vector, Map, Set, Pair
  • Compound: arrays, objects, shapes, tuples
  • Nullable: ?type
  • Type aliases: define custom types
Hack
// Data Types in Hack
function dataTypes(): void {
    // Scalar types
    $age = 25; // int
    $salary = 50000.50; // float
    $pi = 3.14159265358979; // float
    $grade = 'A'; // string
    $isActive = true; // bool
    $name = "Alice"; // string
    $price = 99.99; // float

    // Collections
    $list = Vector {1, 2, 3, 4, 5};
    $map = Map {'name' => 'Alice', 'age' => 25};
    $set = Set {1, 2, 3, 4, 5};
    $pair = Pair {'key', 'value'};

    echo "Age: $age\n";
    echo "Salary: $salary\n";
    echo "Pi: $pi\n";
    echo "Grade: $grade\n";
    echo "Active: " . ($isActive ? 'true' : 'false') . "\n";
    echo "Name: $name\n";
    echo "Price: $price\n";
}
Beginner
3. What are Variables and Constants in Hack?

Variables in Hack are declared with $ and can have type annotations. Constants are defined with const inside classes or define globally.

  • Variables: $x = 10; or $x: int = 10;
  • Constants: const PI = 3.14;
  • Type inference: $x = 10; (int inferred)
  • Scope: Variables are function-scoped; constants are global or class-scoped
Hack
// Variables and Constants in Hack
function variablesConstants(): void {
    // Variables
    $x = 10;
    $val = 3.14;
    $str = "Hello";
    $counter = 0;

    // Constants (class level)
    // const float PI = 3.14159;

    // Type annotations
    $explicit: int = 42;
    $name: string = "Alice";

    echo "x = $x\n";
    echo "val = $val\n";
    echo "str = $str\n";
    echo "counter = $counter\n";
    echo "explicit = $explicit\n";
    echo "name = $name\n";
}
Beginner
4. What are Collections (Vector, Map, Set, Pair) in Hack?

Hack provides built‑in collection types for efficient data manipulation. Vector is an ordered list, Map is key‑value, Set is unique values, and Pair is a fixed‑size tuple of two.

  • Vector: $v = Vector {1, 2, 3};
  • Map: $m = Map {'a' => 1, 'b' => 2};
  • Set: $s = Set {1, 2, 3};
  • Pair: $p = Pair {'key', 'value'};
Hack
// Vector and Collections in Hack
function collectionsExamples(): void {
    // Vector (ordered collection)
    $vector = Vector {1, 2, 3, 4, 5};
    echo "vector[0] = {$vector[0]}\n";
    echo "vector[2] = {$vector[2]}\n";

    // Add elements
    $vector[] = 6;
    $vector[] = 7;
    echo "After add: " . json_encode($vector) . "\n";

    // Remove elements
    unset($vector[2]);
    echo "After remove: " . json_encode($vector) . "\n";

    // Iteration
    foreach ($vector as $item) {
        echo "Item: $item\n";
    }

    // 2D Vector
    $matrix = Vector {
        Vector {1, 2, 3},
        Vector {4, 5, 6},
        Vector {7, 8, 9}
    };
    echo "matrix[1][1] = {$matrix[1][1]}\n";
}
Beginner
5. How do you define Functions in Hack?

Functions in Hack can have type annotations for parameters and return values, default parameters, variadic parameters, and lambda expressions.

  • Basic: function add(int $a, int $b): int { return $a + $b; }
  • Default: function greet(string $name = "Guest"): string
  • Lambda: $square = (int $x): int ==> $x * $x;
  • Variadic: function sum(int ...$nums): int
  • Multiple returns: using tuples
Hack
// Functions in Hack
// Basic function with types
function add(int $a, int $b): int {
    return $a + $b;
}

// Function with default parameters
function greet(string $name = "Guest"): string {
    return "Hello, $name!";
}

// Lambda function
$multiply = (int $a, int $b): int ==> $a * $b;

// Variadic function
function sum(int ...$nums): int {
    $total = 0;
    foreach ($nums as $num) {
        $total += $num;
    }
    return $total;
}

// Function with multiple returns using tuple
function getMinMax(Vector<int> $list): (int, int) {
    $min = $list[0];
    $max = $list[0];
    foreach ($list as $value) {
        if ($value < $min) $min = $value;
        if ($value > $max) $max = $value;
    }
    return tuple($min, $max);
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    echo "Add: " . add(10, 20) . "\n";
    echo "Greet: " . greet("Alice") . "\n";
    echo "Multiply: " . $multiply(5, 4) . "\n";
    echo "Sum: " . sum(1, 2, 3, 4, 5) . "\n";
    list($min, $max) = getMinMax(Vector {5, 2, 8, 1, 9});
    echo "Min: $min, Max: $max\n";
}
Beginner
6. How does Recursion work in Hack?

Recursion in Hack is similar to other languages. Functions can call themselves with a base case to terminate.

  • Base case: Stops recursion
  • Recursive case: Calls itself with modified arguments
  • Stack management: Be mindful of depth
  • Tail recursion: Not optimized, but can be simulated with loops
Hack
// Recursion in Hack
// Factorial
function factorial(int $n): int {
    if ($n <= 1) {
        return 1;
    }
    return $n * factorial($n - 1);
}

// Fibonacci
function fibonacci(int $n): int {
    if ($n <= 1) {
        return $n;
    }
    return fibonacci($n - 1) + fibonacci($n - 2);
}

// Sum of array
function sumArray(Vector<int> $arr, int $n): int {
    if ($n <= 0) {
        return 0;
    }
    return $arr[$n - 1] + sumArray($arr, $n - 1);
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    echo "Factorial 5: " . factorial(5) . "\n";
    echo "Fibonacci 8: " . fibonacci(8) . "\n";
    echo "Sum [1,2,3,4,5]: " . sumArray(Vector {1, 2, 3, 4, 5}, 5) . "\n";
}
Beginner
7. How do you use Maps in Hack?

Maps are key‑value pairs. You can add, remove, and access values using array‑like syntax or methods.

  • Creation: Map {'key' => 'value'}
  • Access: $map['key']
  • Check existence: $map->containsKey('key')
  • Iteration: foreach ($map as $key => $value)
Hack
// Map in Hack
function mapExamples(): void {
    // Map declaration
    $scores = Map {
        'Alice' => 95,
        'Bob' => 87,
        'Carol' => 92
    };

    // Access values
    echo "Alice: " . $scores['Alice'] . "\n";
    echo "Bob: " . $scores['Bob'] . "\n";

    // Add new key-value
    $scores['Dave'] = 88;

    // Check if key exists
    if ($scores->containsKey('Eve')) {
        echo "Eve: " . $scores['Eve'] . "\n";
    } else {
        echo "Eve not found\n";
    }

    // Iterate map
    foreach ($scores as $key => $value) {
        echo "$key: $value\n";
    }

    // Delete key
    unset($scores['Bob']);
    echo "After delete: " . json_encode($scores) . "\n";
}
Beginner
8. What are Classes in Hack?

Classes in Hack support properties, methods, constructors, visibility (public, private, protected), and type annotations.

  • Properties: typed fields
  • Constructor: public function __construct(...)
  • Methods: can have return types
  • Visibility: public, private, protected
Hack
// Classes in Hack
// Class definition
class Person {
    public string $name;
    public int $age;
    public ?string $email;

    // Constructor
    public function __construct(string $name, int $age, ?string $email = null) {
        $this->name = $name;
        $this->age = $age;
        $this->email = $email;
    }

    // Methods
    public function greet(): string {
        return "Hello, I'm " . $this->name;
    }

    public function getInfo(): string {
        return "Name: " . $this->name . ", Age: " . $this->age;
    }
}

// Class with properties
class Rectangle {
    public float $width;
    public float $height;

    public function __construct(float $width, float $height) {
        $this->width = $width;
        $this->height = $height;
    }

    public function area(): float {
        return $this->width * $this->height;
    }

    public function perimeter(): float {
        return 2 * ($this->width + $this->height);
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $person1 = new Person("Alice", 25, "alice@email.com");
    $person2 = new Person("Bob", 30);

    echo $person1->greet() . "\n";
    echo $person1->getInfo() . "\n";
    echo $person2->getInfo() . "\n";

    $rect = new Rectangle(4.0, 6.0);
    echo "Area: " . $rect->area() . "\n";
    echo "Perimeter: " . $rect->perimeter() . "\n";
}
Beginner
9. What are Interfaces in Hack?

Interfaces define contracts for classes. They can contain method signatures and constants. Classes implement multiple interfaces.

  • Declaration: interface Shape { public function area(): float; }
  • Implementation: class Circle implements Shape { ... }
  • Multiple: class A implements I1, I2 { ... }
Hack
// Interfaces in Hack
// Interface definition
interface Shape {
    public function area(): float;
    public function perimeter(): float;
}

// Implementation
class Circle implements Shape {
    private float $radius;

    public function __construct(float $radius) {
        $this->radius = $radius;
    }

    public function area(): float {
        return M_PI * $this->radius * $this->radius;
    }

    public function perimeter(): float {
        return 2 * M_PI * $this->radius;
    }
}

class Square implements Shape {
    private float $side;

    public function __construct(float $side) {
        $this->side = $side;
    }

    public function area(): float {
        return $this->side * $this->side;
    }

    public function perimeter(): float {
        return 4 * $this->side;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $shapes = Vector {
        new Circle(5.0),
        new Square(4.0)
    };

    foreach ($shapes as $shape) {
        echo "Area: " . $shape->area() . ", Perimeter: " . $shape->perimeter() . "\n";
    }
}
Beginner
10. What are Lambda Functions in Hack?

Lambdas are anonymous functions. They can capture variables and be assigned to variables or passed as arguments.

  • Syntax: (params) ==> expression or (params) ==> { statements }
  • Type annotations: (int $x): int ==> $x * 2
  • Capture: $x = 10; $addX = (int $y): int ==> $y + $x;
Hack
// Lambda Functions in Hack
function lambdaExamples(): void {
    // Basic lambda
    $greet = (string $name): string ==> {
        return "Hello, $name!";
    };
    echo $greet("Alice") . "\n";

    // Lambda with implicit return
    $square = (int $x): int ==> $x * $x;
    echo "Square of 5: " . $square(5) . "\n";

    // Lambda with multiple parameters
    $add = (int $a, int $b): int ==> $a + $b;
    echo "Add: " . $add(5, 3) . "\n";

    // Lambda capturing variables
    $x = 10;
    $addX = (int $y): int ==> $y + $x;
    echo "addX: " . $addX(5) . "\n";

    // Lambda as parameter
    $processList = (Vector<int> $list, (function(int): void) $callback): void ==> {
        foreach ($list as $item) {
            $callback($item);
        }
    };

    $processList(Vector {1, 2, 3, 4, 5}, (int $item): void ==> {
        echo "Item: $item\n";
    });
}
Beginner
11. What are Collection Operations in Hack?

Collections support functional operations like map, filter, fold, any, every, and groupBy.

  • map: transform each element
  • filter: keep elements satisfying a condition
  • fold: reduce to a single value
  • any/every: check conditions
  • groupBy: group by a key
Hack
// Collection Operations in Hack
function collectionOperations(): void {
    $list = Vector {1, 2, 3, 4, 5};

    // Map operations
    $doubled = $list->map((int $x): int ==> $x * 2);
    echo "Doubled: " . json_encode($doubled) . "\n";

    // Filter
    $evens = $list->filter((int $x): bool ==> $x % 2 === 0);
    echo "Evens: " . json_encode($evens) . "\n";

    // Reduce
    $sum = $list->fold(0, (int $acc, int $x): int ==> $acc + $x);
    echo "Sum: $sum\n";

    // Any/Every
    echo "Has even: " . ($list->any((int $x): bool ==> $x % 2 === 0) ? 'true' : 'false') . "\n";
    echo "All even: " . ($list->every((int $x): bool ==> $x % 2 === 0) ? 'true' : 'false') . "\n";

    // Group by
    $grouped = $list->groupBy((int $x): string ==> $x % 2 === 0 ? "Even" : "Odd");
    echo "Grouped: " . json_encode($grouped) . "\n";
}
Beginner
12. How do you work with Strings in Hack?

Strings in Hack support concatenation, interpolation, and various helper functions.

  • Concatenation: $a . $b
  • Interpolation: "Hello $name"
  • Length: strlen()
  • Substring: substr()
  • Split/join: explode() / implode()
Hack
// Strings in Hack
function stringExamples(): void {
    $str = "Hello, World!";

    // Basic operations
    echo "Length: " . strlen($str) . "\n";
    echo "Substring: " . substr($str, 7, 5) . "\n";
    echo "Contains: " . (strpos($str, "World") !== false ? 'true' : 'false') . "\n";
    echo "Index of: " . strpos($str, "World") . "\n";

    // String interpolation
    $name = "Alice";
    $age = 25;
    echo "$name is $age years old\n";

    // Multi-line strings
    $multiLine = "
        This is a
        multi-line
        string
    ";
    echo $multiLine;

    // String methods
    echo "Upper: " . strtoupper($str) . "\n";
    echo "Lower: " . strtolower($str) . "\n";
    echo "Trim: '" . trim("  Hello  ") . "'\n";

    // Split and join
    $csv = "Alice,Bob,Carol,Dave";
    $tokens = explode(",", $csv);
    echo implode(" - ", $tokens) . "\n";
}
Beginner
13. How does Exception Handling work in Hack?

Hack uses try/catch/finally blocks and custom exception classes that extend Exception.

  • Try/catch: try { ... } catch (Exception $e) { ... }
  • Finally: finally { ... }
  • Custom exceptions: class MyError extends Exception { ... }
Hack
// Exception Handling in Hack
// Custom exception
class ValidationError extends Exception {
    public int $code;

    public function __construct(string $message, int $code) {
        parent::__construct($message);
        $this->code = $code;
    }

    public function getCode(): int {
        return $this->code;
    }
}

function divide(float $a, float $b): float {
    if ($b === 0.0) {
        throw new Exception("Division by zero");
    }
    return $a / $b;
}

function validateAge(int $age): int {
    if ($age < 0 || $age > 150) {
        throw new ValidationError("Invalid age: $age", 400);
    }
    return $age;
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    // Try-catch-finally
    try {
        $result = divide(10, 2);
        echo "Result: $result\n";
    } catch (Exception $e) {
        echo "Error: " . $e->getMessage() . "\n";
    } finally {
        echo "Finally block executed\n";
    }

    // Custom exception
    try {
        validateAge(200);
    } catch (ValidationError $e) {
        echo "Error [" . $e->getCode() . "]: " . $e->getMessage() . "\n";
    }
}
Beginner
14. How does File I/O work in Hack?

File operations use PHP functions like fopen, fwrite, fread, and file_get_contents.

  • Write: file_put_contents('file.txt', 'data')
  • Read: file_get_contents('file.txt')
  • Lines: file('file.txt')
  • Check existence: file_exists()
Hack
// File I/O in Hack
async function fileOperations(): Awaitable<void> {
    // Write to file
    $file = fopen("example.txt", "w");
    fwrite($file, "Hello, World!\n");
    fwrite($file, "Line 2\n");
    fclose($file);

    // Read file
    $content = file_get_contents("example.txt");
    echo "Content: $content\n";

    // Read lines
    $lines = file("example.txt");
    foreach ($lines as $line) {
        echo "Line: $line";
    }

    // Append to file
    file_put_contents("example.txt", "Line 3\n", FILE_APPEND);

    // Check if file exists
    if (file_exists("example.txt")) {
        echo "File exists\n";
        echo "Size: " . filesize("example.txt") . " bytes\n";
    }

    // Directory operations
    if (!is_dir("testdir")) {
        mkdir("testdir");
    }
    rmdir("testdir");
}
Beginner
15. How do you use Regular Expressions in Hack?

Regular expressions use the PCRE functions: preg_match, preg_match_all, preg_replace.

  • Match: preg_match('/pattern/', $subject, $matches)
  • All matches: preg_match_all()
  • Replace: preg_replace('/pattern/', 'replacement', $subject)
Hack
// Regular Expressions in Hack
function regexExamples(): void {
    // Pattern matching
    $pattern = '/d+/';
    $text = "Price: $100, Discount: $20";

    preg_match_all($pattern, $text, $matches);
    echo "Found: " . implode(", ", $matches[0]) . "\n";

    // Find all matches
    $numbers = "Price: 100, Discount: 20, Total: 80";
    preg_match_all('/d+/', $numbers, $matches);
    echo "Numbers: " . implode(", ", $matches[0]) . "\n";

    // Replace
    $text = "Hello World";
    $replaced = preg_replace('/World/', 'Hack', $text);
    echo "Replaced: $replaced\n";

    // Email validation
    $emailPattern = '/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/';
    $emails = Vector {"user@example.com", "invalid-email", "hello@world.org"};
    foreach ($emails as $email) {
        if (preg_match($emailPattern, $email)) {
            echo "$email is valid\n";
        } else {
            echo "$email is invalid\n";
        }
    }
}
Intermediate
16. How do you work with JSON in Hack?

JSON serialization and deserialization use json_encode and json_decode.

  • Encode: json_encode($data)
  • Decode: json_decode($json, true)
  • Pretty print: json_encode($data, JSON_PRETTY_PRINT)
  • Error handling: json_last_error()
Hack
// JSON in Hack
use namespace HHLibDict;
use namespace HHLibVec;

function jsonExamples(): void {
    // JSON parsing
    $jsonString = '{"name":"Alice","age":25,"email":"alice@email.com"}';
    $person = json_decode($jsonString, true);

    echo "Name: " . $person['name'] . "\n";
    echo "Age: " . $person['age'] . "\n";
    echo "Email: " . $person['email'] . "\n";

    // JSON generation
    $data = Map {
        'name' => 'Bob',
        'age' => 30,
        'email' => 'bob@email.com',
        'hobbies' => Vector {'reading', 'coding'}
    };

    $jsonOutput = json_encode($data);
    echo "JSON: $jsonOutput\n";

    // Pretty print
    $prettyJson = json_encode($data, JSON_PRETTY_PRINT);
    echo "Pretty JSON:\n$prettyJson\n";

    // JSON from file
    if (file_exists("data.json")) {
        $fileJson = file_get_contents("data.json");
        $fileData = json_decode($fileJson, true);
        echo "File data: " . json_encode($fileData) . "\n";
    }
}
Intermediate
17. How does Async/Await work in Hack?

Hack provides built‑in asynchronous programming with async functions and await.

  • Async function: async function fetch(): Awaitable<string>
  • Await: $result = await fetch();
  • Parallel: await Vec\map_async($items, async ($x) ==> ...)
  • Concurrency: \HH\Asio\va()
Hack
// Async/Await in Hack
async function fetchData(string $url, int $delay): Awaitable<string> {
    await SleepWaitHandle::create($delay);
    return "Data from $url";
}

async function computeAsync(int $a, int $b): Awaitable<int> {
    await SleepWaitHandle::create(100);
    return $a + $b;
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    // Basic async
    $result = await fetchData("api.example.com", 500);
    echo "$result\n";

    // Parallel async tasks
    $tasks = Vector {
        fetchData("source1", 300),
        fetchData("source2", 200),
        fetchData("source3", 400)
    };
    $results = await Vecmap_async($tasks, async ($task) ==> await $task);
    echo "All results: " . implode(", ", $results) . "\n";

    // Parallel processing
    $numbers = Vec
ange(1, 10);
    $parallelResults = await Vecmap_async($numbers, async ($n) ==> {
        await SleepWaitHandle::create(50);
        return $n * $n;
    });
    echo "Squares: " . implode(", ", $parallelResults) . "\n";
}
Intermediate
18. What are Generics in Hack?

Generics allow classes, functions, and methods to work with any type while maintaining type safety.

  • Generic class: class Stack<T> { ... }
  • Generic function: function findMax<T as num>(T $a, T $b): T
  • Constraints: <T as MyInterface>
  • Multiple parameters: class Pair<K, V>
Hack
// Generics in Hack
// Generic class
class Stack<T> {
    private Vector<T> $items = Vector {};

    public function push(T $item): void {
        $this->items[] = $item;
    }

    public function pop(): T {
        if ($this->items->count() === 0) {
            throw new Exception("Stack is empty");
        }
        return $this->items->pop();
    }

    public function peek(): T {
        if ($this->items->count() === 0) {
            throw new Exception("Stack is empty");
        }
        return $this->items->last();
    }

    public function isEmpty(): bool {
        return $this->items->count() === 0;
    }
}

// Generic function
function findMax<T as num>(T $a, T $b): T {
    return $a > $b ? $a : $b;
}

// Multiple type parameters
class Pair<K, V> {
    public K $key;
    public V $value;

    public function __construct(K $key, V $value) {
        $this->key = $key;
        $this->value = $value;
    }

    public function print(): void {
        echo $this->key . " -> " . $this->value . "\n";
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $intStack = new Stack<int>();
    $intStack->push(10);
    $intStack->push(20);
    echo "Pop: " . $intStack->pop() . "\n";

    echo "Max int: " . findMax(5, 3) . "\n";
    echo "Max float: " . findMax(3.14, 2.5) . "\n";

    $pair = new Pair<string, int>("age", 25);
    $pair->print();
}
Intermediate
19. What is XHP in Hack?

XHP is an XML-like syntax for building UI components in Hack. It allows you to create reusable, type‑safe elements.

  • Element: class :ui:button extends :x:element { ... }
  • Attributes: attribute string label @required;
  • Render: protected function render(): :xhp { return <button>{...}</button>; }
  • Usage: <ui:button label="Click" />
Hack
// XHP in Hack
// XHP class for reusable components
class :ui:button extends :x:element {
    attribute string label @required;
    attribute string type = "button";

    protected function render(): :xhp {
        return <button type={$this->:type} class="btn btn-primary">
            {$this->:label}
        </button>;
    }
}

class :ui:card extends :x:element {
    attribute string title @required;
    attribute string subtitle;

    protected function render(): :xhp {
        return <div class="card">
            <div class="card-header">
                <h3>{$this->:title}</h3>
                { $this->:subtitle !== null ? <p class="subtitle">{$this->:subtitle}</p> : null }
            </div>
            <div class="card-body">
                {$this->getChildren()}
            </div>
        </div>;
    }
}

// Usage
<<__EntryPoint>>
async function main(): Awaitable<void> {
    $button = <ui:button label="Click Me" />;
    $card = <ui:card title="User Profile" subtitle="Details">
        <p>Name: Alice</p>
        <p>Email: alice@email.com</p>
        <ui:button label="Edit" type="submit" />
    </ui:card>;

    echo $button->toString();
    echo $card->toString();
}
Intermediate
20. What are Type Aliases and Shapes in Hack?

Type aliases give descriptive names to complex types. Shapes are structure‑like types with named fields.

  • Type alias: type UserID = int;
  • Shape: type Person = shape('name' => string, 'age' => int);
  • Optional fields: ?string inside shape
  • Nested shapes: shapes within shapes
Hack
// Type Aliases and Shapes in Hack
// Type alias for User
type User = shape(
    'id' => int,
    'name' => string,
    'email' => string,
    'age' => int,
    'active' => bool,
);

// Type alias for nullable user
type ?User = shape(
    'id' => int,
    'name' => string,
    'email' => string,
    'age' => int,
    'active' => bool,
) | null;

// Function using shape
function formatUser(User $user): string {
    return "User: " . $user['name'] . " (" . $user['email'] . ")";
}

// Function with optional fields
type Config = shape(
    'host' => string,
    'port' => int,
    'debug' => bool,
    'timeout' => ?int,
);

function getConfig(): Config {
    return shape(
        'host' => 'localhost',
        'port' => 8080,
        'debug' => true,
        'timeout' => 30,
    );
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $user = shape(
        'id' => 1,
        'name' => 'Alice',
        'email' => 'alice@email.com',
        'age' => 25,
        'active' => true,
    );

    echo formatUser($user) . "\n";

    $config = getConfig();
    echo "Config: host={$config['host']}, port={$config['port']}\n";
}
Intermediate
21. What are Enums in Hack?

Enums define a fixed set of constants. They can have values of type int or string.

  • Enum: enum Color: string { Red = '#FF0000'; Green = '#00FF00'; }
  • Access: Color::Red
  • Methods: Enums can have methods
  • Iteration: Color::getValues()
Hack
// Enums in Hack
enum Color: string {
    Red = '#FF0000';
    Green = '#00FF00';
    Blue = '#0000FF';
    Yellow = '#FFFF00';
}

enum Status: int {
    Pending = 0;
    Processing = 1;
    Shipped = 2;
    Delivered = 3;
    Cancelled = 4;
}

function getStatusName(Status $status): string {
    return match ($status) {
        Status::Pending => 'Pending',
        Status::Processing => 'Processing',
        Status::Shipped => 'Shipped',
        Status::Delivered => 'Delivered',
        Status::Cancelled => 'Cancelled',
    };
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $color = Color::Red;
    echo "Color: " . $color . "\n";
    echo "Color value: " . $color . "\n";

    $status = Status::Processing;
    echo "Status: " . getStatusName($status) . "\n";

    // Iterate through enum values
    foreach (Color::getValues() as $color) {
        echo "Enum value: $color\n";
    }
}
Intermediate
22. What are Tuples in Hack?

Tuples are fixed‑size, ordered collections of values, often used for multiple return values.

  • Creation: tuple(1, "Alice", 3.14)
  • Access: $tuple[0]
  • Named: tuple('name' => 'Alice', 'age' => 25)
  • Return types: function getMinMax(): (int, int)
Hack
// Tuples in Hack
function tupleExamples(): void {
    // Create tuple
    $tuple = tuple(1, "Alice", 3.14);

    // Access elements
    echo "First: " . $tuple[0] . "\n";
    echo "Second: " . $tuple[1] . "\n";
    echo "Third: " . $tuple[2] . "\n";

    // Tuple with named elements
    $named = tuple('name' => 'Alice', 'age' => 25);
    echo "Name: " . $named['name'] . "\n";
    echo "Age: " . $named['age'] . "\n";

    // Function returning tuple
    function getMinMax(Vector<int> $list): (int, int) {
        $min = $list[0];
        $max = $list[0];
        foreach ($list as $value) {
            if ($value < $min) $min = $value;
            if ($value > $max) $max = $value;
        }
        return tuple($min, $max);
    }

    $result = getMinMax(Vector {5, 2, 8, 1, 9});
    echo "Min: " . $result[0] . ", Max: " . $result[1] . "\n";
}
Intermediate
23. How do Nullable Types work in Hack?

Nullable types allow a variable to be either a specific type or null.

  • Syntax: ?int means int|null
  • Null coalescing: $value ?? "default"
  • Null safe: $user['email'] ?? 'No email'
  • Checking: if ($value !== null) { ... }
Hack
// Nullable Types in Hack
function nullableExamples(): void {
    // Nullable type
    $maybeNull: ?string = null;
    $notNull: string = "Hello";

    // Check for null
    if ($maybeNull !== null) {
        echo "Value: $maybeNull\n";
    } else {
        echo "Value is null\n";
    }

    // Null coalescing operator
    $value = $maybeNull ?? "Default";
    echo "Value: $value\n";

    // Null safe operator
    $user = shape('name' => 'Alice', 'email' => null);
    $email = $user['email'] ?? 'No email';
    echo "Email: $email\n";

    // Function with nullable parameter
    function greet(?string $name): string {
        return "Hello, " . ($name ?? "Guest") . "!";
    }

    echo greet(null) . "\n";
    echo greet("Alice") . "\n";
}
Intermediate
24. What are Shapes with Optional Fields in Hack?

Shapes can have optional fields by using ?type. Use Shapes::idx() for safe access.

  • Optional: phone => ?string
  • Safe access: Shapes::idx($shape, 'phone')
  • Nested: shapes inside shapes
  • Validation: custom validation functions
Hack
// Shapes in Hack
function shapeExamples(): void {
    // Shape definition
    $user = shape(
        'id' => 1,
        'name' => 'Alice',
        'email' => 'alice@email.com',
        'age' => 25,
        'active' => true,
    );

    // Access fields
    echo "ID: " . $user['id'] . "\n";
    echo "Name: " . $user['name'] . "\n";
    echo "Email: " . $user['email'] . "\n";
    echo "Age: " . $user['age'] . "\n";
    echo "Active: " . ($user['active'] ? 'true' : 'false') . "\n";

    // Shape with optional fields
    type UserWithOptional = shape(
        'id' => int,
        'name' => string,
        'email' => string,
        'phone' => ?string,
    );

    $user2 = shape(
        'id' => 2,
        'name' => 'Bob',
        'email' => 'bob@email.com',
        'phone' => null,
    );

    // Function with shape
    function formatUserShape(shape('name' => string, 'age' => int) $user): string {
        return $user['name'] . " is " . $user['age'] . " years old";
    }

    echo formatUserShape($user) . "\n";
}
Intermediate
25. What is the Memoize Attribute in Hack?

<<__Memoize>> caches the result of a method call, improving performance for expensive operations.

  • Usage: <<__Memoize>> public function getData(string $key): string
  • Cache key: all arguments are used as the cache key
  • Scope: per‑instance cache
  • Trade‑offs: memory vs. speed
Hack
// Memoize Attribute in Hack
// Memoize method to cache results
class CacheExample {
    private int $counter = 0;

    <<__Memoize>>
    public function getExpensiveData(string $key): string {
        $this->counter++;
        // Simulate expensive operation
        return "Data for $key (call #" . $this->counter . ")";
    }

    <<__Memoize>>
    public function getDataWithParams(int $id, string $type): string {
        // Results cached based on all parameters
        return "Data: id=$id, type=$type";
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $cache = new CacheExample();

    // First call - executes the method
    echo $cache->getExpensiveData("key1") . "\n";
    echo $cache->getExpensiveData("key2") . "\n";

    // Second call with same key - returns cached result
    echo $cache->getExpensiveData("key1") . "\n"; // counter doesn't increment

    // Different parameters produce different cache entries
    echo $cache->getDataWithParams(1, "user") . "\n";
    echo $cache->getDataWithParams(1, "admin") . "\n";
    echo $cache->getDataWithParams(1, "user") . "\n"; // cached
}
Intermediate
26. What are Asynchronous Collections in Hack?

Asynchronous collections allow parallel processing of items using Vec\map_async and Vec\filter_async.

  • Map async: await Vecmap_async($items, async ($x) ==> ...)
  • Filter async: await Vec ilter_async($items, async ($x) ==> ...)
  • Parallel execution: multiple async operations run concurrently
  • Error handling: use try/catch inside the async callback
Hack
// Asynchronous Collections in Hack
async function asyncCollectionExamples(): Awaitable<void> {
    // Map async over collection
    $numbers = Vec
ange(1, 10);

    $squares = await Vecmap_async($numbers, async ($n) ==> {
        await SleepWaitHandle::create(10);
        return $n * $n;
    });
    echo "Squares: " . implode(", ", $squares) . "\n";

    // Filter async
    $filtered = await Vecilter_async($numbers, async ($n) ==> {
        await SleepWaitHandle::create(5);
        return $n % 2 === 0;
    });
    echo "Evens: " . implode(", ", $filtered) . "\n";

    // Parallel processing with mapping
    $urls = Vector {
        "https://api1.example.com",
        "https://api2.example.com",
        "https://api3.example.com"
    };

    $results = await Vecmap_async($urls, async ($url) ==> {
        // Simulate API call
        await SleepWaitHandle::create(100);
        return "Data from $url";
    });
    echo "Results: " . implode(", ", $results) . "\n";
}
Intermediate
27. What is the Hack Standard Library (HSL)?

The HSL is a collection of functional utilities for working with containers, strings, and more.

  • Vec: Vec\map, Vec\filter
  • Dict: Dict\map, Dict\filter
  • Str: Str\length, Str\uppercase
  • C: container functions like C\contains, C\count
Hack
// Hack Standard Library (HSL) Examples
use namespace HHLibC;
use namespace HHLibDict;
use namespace HHLibVec;
use namespace HHLibStr;

function hslExamples(): void {
    // Vector operations
    $vector = Vector {1, 2, 3, 4, 5};

    // Vecmap
    $doubled = Vecmap($vector, ($x) ==> $x * 2);
    echo "Doubled: " . implode(", ", $doubled) . "\n";

    // Vecilter
    $evens = Vecilter($vector, ($x) ==> $x % 2 === 0);
    echo "Evens: " . implode(", ", $evens) . "\n";

    // Dict operations
    $dict = dict['a' => 1, 'b' => 2, 'c' => 3];
    $dictDoubled = Dictmap($dict, ($v) ==> $v * 2);

    // Str operations
    $text = "Hello, World!";
    echo "Length: " . Strlength($text) . "\n";
    echo "Upper: " . Str\uppercase($text) . "\n";
    echo "Lower: " . Strlowercase($text) . "\n";

    // C operations (container functions)
    $list = vec[1, 2, 3, 4, 5];
    echo "Contains 3: " . (Ccontains($list, 3) ? 'true' : 'false') . "\n";
    echo "Count: " . Ccount($list) . "\n";
}
Intermediate
28. How do you use Advanced Type Aliases in Hack?

Type aliases can be used for unions, shapes, and even generic types.

  • Union: type Status = 'active' | 'inactive' | 'pending';
  • Shape alias: type Person = shape('name' => string, ...);
  • Function: type Callback = (function(string): void);
  • Generic: type Option<T> = T | null;
Hack
// Type Aliases in Hack
// Basic type alias
type UserID = int;
type UserName = string;

// Union type alias
type Status = 'active' | 'inactive' | 'pending';

// Shape type alias
type Person = shape(
    'name' => string,
    'age' => int,
    'email' => string,
);

// Function using type alias
function getUserName(UserID $id): UserName {
    // In real app, would fetch from database
    return "User_$id";
}

function getUserStatus(UserID $id): Status {
    // In real app, would check database
    return 'active';
}

function getPersonDetails(Person $person): string {
    return "Name: " . $person['name'] . ", Age: " . $person['age'];
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $id = 123;
    $name = getUserName($id);
    $status = getUserStatus($id);

    echo "User: $name, Status: $status\n";

    $person = shape(
        'name' => 'Alice',
        'age' => 25,
        'email' => 'alice@email.com',
    );

    echo getPersonDetails($person) . "\n";
}
Intermediate
29. What is the EntryPoint attribute in Hack?

<<__EntryPoint>> marks the entry point of a Hack script. It allows async main functions.

  • Usage: <<__EntryPoint>> async function main(): Awaitable<void> { ... }
  • Async support: main can be async
  • Arguments: command‑line arguments can be accessed via $argv
Hack
// Hack EntryPoint and Asynchronous Main
// Entry point with async
<<__EntryPoint>>
async function main(): Awaitable<void> {
    echo "Application started\n";

    // Run async operations
    $result = await asyncOperation();
    echo "Result: $result\n";

    // Multiple async operations
    $results = await Vecmap_async(
        range(1, 5),
        async ($i) ==> {
            await SleepWaitHandle::create($i * 10);
            return $i * 2;
        }
    );

    echo "Results: " . implode(", ", $results) . "\n";
}

async function asyncOperation(): Awaitable<string> {
    await SleepWaitHandle::create(100);
    return "Completed";
}
Intermediate
30. What are Traits in Hack?

Traits allow method reuse across classes without inheritance.

  • Definition: trait Loggable { public function log(...) { ... } }
  • Use: class User { use Loggable; }
  • Multiple: use Trait1, Trait2;
  • Conflict resolution: insteadof and as
Hack
// Hack Traits
// Trait definition
trait Loggable {
    public function log(string $message): void {
        echo "[LOG] " . date('Y-m-d H:i:s') . " - $message\n";
    }
}

trait Timestampable {
    private int $createdAt;

    public function setCreatedAt(int $timestamp): void {
        $this->createdAt = $timestamp;
    }

    public function getCreatedAt(): int {
        return $this->createdAt;
    }
}

// Class using traits
class User {
    use Loggable;
    use Timestampable;

    public string $name;

    public function __construct(string $name) {
        $this->name = $name;
        $this->setCreatedAt(time());
        $this->log("User created: $name");
    }

    public function getName(): string {
        return $this->name;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $user = new User("Alice");
    echo "User: " . $user->getName() . "\n";
    echo "Created at: " . date('Y-m-d H:i:s', $user->getCreatedAt()) . "\n";
}
Intermediate
31. How do you define Methods on Enums in Hack?

Enums can have methods to encapsulate logic.

  • Method: public function isSuccess(): bool { return $this === self::Success; }
  • Match: use match for pattern matching on enum values
  • Description: getDescription() for human‑readable strings
Hack
// Hack Enum with Methods
enum ResponseStatus: string {
    Success = '200';
    Created = '201';
    BadRequest = '400';
    Unauthorized = '401';
    NotFound = '404';
    ServerError = '500';

    public function isSuccess(): bool {
        return $this === self::Success || $this === self::Created;
    }

    public function isError(): bool {
        return !$this->isSuccess();
    }

    public function getDescription(): string {
        return match ($this) {
            self::Success => 'OK',
            self::Created => 'Created',
            self::BadRequest => 'Bad Request',
            self::Unauthorized => 'Unauthorized',
            self::NotFound => 'Not Found',
            self::ServerError => 'Internal Server Error',
        };
    }
}

enum OrderStatus: int {
    Pending = 0;
    Processing = 1;
    Shipped = 2;
    Delivered = 3;

    public function isActive(): bool {
        return $this === self::Pending || $this === self::Processing;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $status = ResponseStatus::Success;
    echo "Status: " . $status->getDescription() . "\n";
    echo "Is success: " . ($status->isSuccess() ? 'true' : 'false') . "\n";

    $order = OrderStatus::Processing;
    echo "Order is active: " . ($order->isActive() ? 'true' : 'false') . "\n";
}
Intermediate
32. How do you Validate Shapes in Hack?

Shapes can be validated by checking required fields and using Shapes::idx for optional ones.

  • Required fields: check if '' or empty
  • Optional: Shapes::idx($shape, 'phone')
  • Nested: recursively validate inner shapes
  • Return: bool or throw exception
Hack
// Hack Shapes with Optional Fields
type UserWithOptional = shape(
    'id' => int,
    'name' => string,
    'email' => string,
    'phone' => ?string,
    'address' => shape(
        'street' => string,
        'city' => string,
        'zip' => string,
    ),
);

function validateUser(UserWithOptional $user): bool {
    // Required fields validation
    if ($user['name'] === '') {
        return false;
    }

    // Optional field handling
    $phone = Shapes::idx($user, 'phone');
    if ($phone !== null && !preg_match('/^[0-9-]+$/', $phone)) {
        return false;
    }

    return true;
}

function formatUserAddress(UserWithOptional $user): string {
    $address = $user['address'];
    return $address['street'] . ", " . $address['city'] . " " . $address['zip'];
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $user = shape(
        'id' => 1,
        'name' => 'Alice',
        'email' => 'alice@email.com',
        'phone' => null,
        'address' => shape(
            'street' => '123 Main St',
            'city' => 'NYC',
            'zip' => '10001',
        ),
    );

    if (validateUser($user)) {
        echo "User is valid\n";
        echo "Address: " . formatUserAddress($user) . "\n";
    }
}
Intermediate
33. What are Contexts in Hack?

Contexts are used for dependency injection or request‑scoped data (e.g., database connections, user sessions).

  • Database context: singleton or request‑scoped
  • User context: stores current user ID
  • Implementation: using classes with static methods or passing through constructor
Hack
// Hack Contexts
// Context for database connection
class DatabaseContext {
    private static ?DatabaseContext $instance = null;
    private string $connection;

    private function __construct() {
        $this->connection = "Connected to database";
        echo "Database context initialized\n";
    }

    public static function getInstance(): DatabaseContext {
        if (self::$instance === null) {
            self::$instance = new DatabaseContext();
        }
        return self::$instance;
    }

    public function query(string $sql): string {
        return "Executing: $sql";
    }
}

// Context for user session
class UserContext {
    private ?string $userId = null;

    public function setUser(string $userId): void {
        $this->userId = $userId;
        echo "User set: $userId\n";
    }

    public function getUserId(): ?string {
        return $this->userId;
    }

    public function isLoggedIn(): bool {
        return $this->userId !== null;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $db = DatabaseContext::getInstance();
    echo $db->query("SELECT * FROM users") . "\n";

    $userContext = new UserContext();
    $userContext->setUser("123");
    echo "Logged in: " . ($userContext->isLoggedIn() ? 'true' : 'false') . "\n";
}
Intermediate
34. How does Dependency Injection work in Hack?

Dependency injection is achieved by passing dependencies via constructors or setters.

  • Constructor injection: class UserService { public function __construct(Logger $logger) { ... } }
  • Interface: program to interfaces
  • Manual: create and pass dependencies
  • Container: can use a simple DI container
Hack
// Hack Dependency Injection
interface Logger {
    public function log(string $message): void;
}

class ConsoleLogger implements Logger {
    public function log(string $message): void {
        echo "[CONSOLE] $message\n";
    }
}

class FileLogger implements Logger {
    private string $filePath;

    public function __construct(string $filePath) {
        $this->filePath = $filePath;
    }

    public function log(string $message): void {
        file_put_contents($this->filePath, $message . "\n", FILE_APPEND);
        echo "[FILE] $message\n";
    }
}

class UserService {
    private Logger $logger;

    public function __construct(Logger $logger) {
        $this->logger = $logger;
    }

    public function createUser(string $name): void {
        $this->logger->log("Creating user: $name");
        // Logic to create user
        $this->logger->log("User created: $name");
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $consoleLogger = new ConsoleLogger();
    $service1 = new UserService($consoleLogger);
    $service1->createUser("Alice");

    $fileLogger = new FileLogger("app.log");
    $service2 = new UserService($fileLogger);
    $service2->createUser("Bob");
}
Intermediate
35. What are Advanced Vector Operations in Hack?

Vectors support many operations beyond basic: count, first, last, add, remove, map, filter, fold, linearSearch.

  • Count: $v->count()
  • First/Last: $v->firstValue(), $v->lastValue()
  • Add/Remove: $v->add(), $v->removeKey()
  • Transform: $v->map(), $v->filter(), $v->fold()
Hack
// Hack Vector Operations
function vectorOperations(): void {
    $vector = Vector {1, 2, 3, 4, 5};

    // Basic operations
    echo "Count: " . $vector->count() . "\n";
    echo "First: " . $vector->firstValue() . "\n";
    echo "Last: " . $vector->lastValue() . "\n";

    // Add and remove
    $vector->add(6);
    $vector->add(7);
    echo "After add: " . json_encode($vector) . "\n";

    $vector->removeKey(2);
    echo "After remove: " . json_encode($vector) . "\n";

    // Transform
    $doubled = $vector->map(($x) ==> $x * 2);
    echo "Doubled: " . json_encode($doubled) . "\n";

    // Filter
    $evens = $vector->filter(($x) ==> $x % 2 === 0);
    echo "Evens: " . json_encode($evens) . "\n";

    // Reduce
    $sum = $vector->fold(0, ($acc, $x) ==> $acc + $x);
    echo "Sum: $sum\n";

    // Contains
    echo "Contains 3: " . ($vector->linearSearch(3) !== -1 ? 'true' : 'false') . "\n";
}
Advanced
36. What are Advanced Map Operations in Hack?

Maps offer keys, values, map, filter, containsKey, containsValue, and more.

  • Keys/Values: $map->keys(), $map->values()
  • Transform: $map->map(), $map->filter()
  • Contains: $map->containsKey('key'), $map->containsValue('value')
  • Add/Remove: $map['key'] = 'value', unset($map['key'])
Hack
// Hack Map Operations
function mapOperations(): void {
    $map = Map {
        'name' => 'Alice',
        'age' => 25,
        'email' => 'alice@email.com'
    };

    // Basic operations
    echo "Count: " . $map->count() . "\n";
    echo "Keys: " . json_encode($map->keys()) . "\n";
    echo "Values: " . json_encode($map->values()) . "\n";

    // Add and remove
    $map['city'] = 'NYC';
    echo "After add: " . json_encode($map) . "\n";

    unset($map['age']);
    echo "After remove: " . json_encode($map) . "\n";

    // Transform
    $doubled = $map->map(($value) ==> is_int($value) ? $value * 2 : $value);
    echo "Doubled: " . json_encode($doubled) . "\n";

    // Filter
    $filtered = $map->filter(($value) ==> is_string($value));
    echo "Filtered: " . json_encode($filtered) . "\n";

    // Contains
    echo "Contains key 'name': " . ($map->containsKey('name') ? 'true' : 'false') . "\n";
    echo "Contains value 'Alice': " . ($map->containsValue('Alice') ? 'true' : 'false') . "\n";
}
Advanced
37. What are Set Operations in Hack?

Sets support union, intersection, difference, and membership checks.

  • Union: $set->union($other)
  • Intersection: $set->intersect($other)
  • Difference: $set->difference($other)
  • Add/Remove: $set->add(1), $set->remove(1)
Hack
// Hack Set Operations
function setOperations(): void {
    $set = Set {1, 2, 3, 4, 5};

    // Basic operations
    echo "Count: " . $set->count() . "\n";
    echo "Contains 3: " . ($set->contains(3) ? 'true' : 'false') . "\n";

    // Add and remove
    $set->add(6);
    $set->add(7);
    echo "After add: " . json_encode($set) . "\n";

    $set->remove(2);
    echo "After remove: " . json_encode($set) . "\n";

    // Set operations
    $set2 = Set {4, 5, 6, 7, 8};

    $union = $set->union($set2);
    echo "Union: " . json_encode($union) . "\n";

    $intersection = $set->intersect($set2);
    echo "Intersection: " . json_encode($intersection) . "\n";

    $difference = $set->difference($set2);
    echo "Difference: " . json_encode($difference) . "\n";

    // Transform
    $doubled = $set->map(($x) ==> $x * 2);
    echo "Doubled: " . json_encode($doubled) . "\n";
}
Advanced
38. How do you use Pairs in Hack?

Pairs are used for two‑element tuples and can be destructured.

  • Creation: Pair {1, 'Alice'}
  • Access: $pair[0], $pair[1]
  • Destructuring: list($first, $second) = $pair
  • Function returns: function(): Pair<int, string>
Hack
// Hack Pair Operations
function pairOperations(): void {
    // Create pair
    $pair = Pair {'name', 'Alice'};

    // Access elements
    echo "First: " . $pair[0] . "\n";
    echo "Second: " . $pair[1] . "\n";

    // Pair with different types
    $pair2 = Pair {1, 3.14};
    echo "First: " . $pair2[0] . "\n";
    echo "Second: " . $pair2[1] . "\n";

    // Using pair in function
    function getUserCredentials(): Pair<string, string> {
        return Pair {'alice@email.com', 'password123'};
    }

    $credentials = getUserCredentials();
    echo "Email: " . $credentials[0] . "\n";
    echo "Password: " . $credentials[1] . "\n";

    // Deconstruct pair
    list($email, $password) = $credentials;
    echo "Deconstructed: $email, $password\n";
}
Advanced
39. What is a Typed Vector in Hack?

Vectors can be annotated with a specific type for compile‑time safety.

  • Explicit type: $numbers: Vector<int> = Vector {1, 2, 3};
  • Mixed: $mixed: Vector<mixed> = Vector {1, 'two', 3.0};
  • Generic constraints: function findMax<T as num>(Vector<T> $items): T
Hack
// Hack Vector with Type Annotations
function typeAnnotatedVector(): void {
    // Vector with explicit type
    $numbers: Vector<int> = Vector {1, 2, 3, 4, 5};
    $strings: Vector<string> = Vector {'a', 'b', 'c'};
    $mixed: Vector<mixed> = Vector {1, 'two', 3.0, true};

    // Type safe operations
    $doubled = $numbers->map(($x): int ==> $x * 2);
    echo "Doubled: " . json_encode($doubled) . "\n";

    // Type checking
    function processNumbers(Vector<int> $nums): int {
        return $nums->fold(0, ($acc, $x) ==> $acc + $x);
    }

    echo "Sum: " . processNumbers($numbers) . "\n";

    // Generic function with constraints
    function findMax<T as num>(Vector<T> $items): T {
        $max = $items[0];
        foreach ($items as $item) {
            if ($item > $max) $max = $item;
        }
        return $max;
    }

    echo "Max: " . findMax($numbers) . "\n";
}
Advanced
40. What is a Typed Map in Hack?

Maps can also be typed to ensure key and value types are correct.

  • Typed: $scores: Map<string, int> = Map {...};
  • Mixed values: Map<string, mixed>
  • Generic functions: function findMaxValue<T as num>(Map<string, T> $items): T
Hack
// Hack Map with Type Annotations
function typeAnnotatedMap(): void {
    // Map with explicit types
    $scores: Map<string, int> = Map {
        'Alice' => 95,
        'Bob' => 87,
        'Carol' => 92
    };

    $config: Map<string, mixed> = Map {
        'host' => 'localhost',
        'port' => 8080,
        'debug' => true
    };

    // Type safe operations
    $doubled = $scores->map(($value): int ==> $value * 2);
    echo "Doubled: " . json_encode($doubled) . "\n";

    // Type checking
    function processScores(Map<string, int> $scores): int {
        return $scores->fold(0, ($acc, $value) ==> $acc + $value);
    }

    echo "Total: " . processScores($scores) . "\n";

    // Generic function with constraints
    function findMaxValue<T as num>(Map<string, T> $items): T {
        $max = $items->firstValue();
        foreach ($items as $value) {
            if ($value > $max) $max = $value;
        }
        return $max;
    }

    echo "Max score: " . findMaxValue($scores) . "\n";
}
Advanced
41. How do you use XHP Attributes in Hack?

XHP elements can have required and optional attributes, passed as an array.

  • Attribute: attribute string action @required;
  • Default: attribute string method = "POST";
  • Spread: <form {...$attrs}>
  • Children: {$this->getChildren()}
Hack
// Hack XHP with Attributes
// XHP class with attributes
class :ui:form extends :x:element {
    attribute string action @required;
    attribute string method = "POST";
    attribute string id;

    protected function render(): :xhp {
        $attrs = [];
        $attrs['action'] = $this->:action;
        $attrs['method'] = $this->:method;
        if ($this->:id !== null) {
            $attrs['id'] = $this->:id;
        }

        return <form {...$attrs}>
            {$this->getChildren()}
        </form>;
    }
}

class :ui:input extends :x:element {
    attribute string type = "text";
    attribute string name @required;
    attribute string value;
    attribute string placeholder;

    protected function render(): :xhp {
        $attrs = [];
        $attrs['type'] = $this->:type;
        $attrs['name'] = $this->:name;
        if ($this->:value !== null) $attrs['value'] = $this->:value;
        if ($this->:placeholder !== null) $attrs['placeholder'] = $this->:placeholder;

        return <input {...$attrs} />;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $form = <ui:form action="/submit" id="contact-form">
        <ui:input type="text" name="name" placeholder="Your name" />
        <ui:input type="email" name="email" placeholder="Your email" />
        <ui:input type="submit" name="submit" value="Send" />
    </ui:form>;

    echo $form->toString();
}
Advanced
42. How do you use XHP with Children?

XHP components can accept nested elements and render them.

  • Layout: <ui:layout> ... </ui:layout>
  • Grid: <ui:grid columns="3"> ... </ui:grid>
  • Card: <ui:card title="User">...</ui:card>
  • Composition: compose reusable UI blocks
Hack
// Hack XHP with Children
class :ui:layout extends :x:element {
    protected function render(): :xhp {
        return <div class="layout">
            <header class="header">
                <h1>My Application</h1>
            </header>
            <main class="content">
                {$this->getChildren()}
            </main>
            <footer class="footer">
                <p>&copy; 2024 My Application</p>
            </footer>
        </div>;
    }
}

class :ui:grid extends :x:element {
    attribute int columns = 2;
    attribute string gap = "20px";

    protected function render(): :xhp {
        return <div class="grid" style={"grid-template-columns: repeat(" . $this->:columns . ", 1fr); gap: " . $this->:gap . ";"}>
            {$this->getChildren()}
        </div>;
    }
}

class :ui:card extends :x:element {
    attribute string title;

    protected function render(): :xhp {
        return <div class="card">
            { $this->:title !== null ? <h3>{$this->:title}</h3> : null }
            <div class="card-body">
                {$this->getChildren()}
            </div>
        </div>;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $layout = <ui:layout>
        <ui:grid columns="3">
            <ui:card title="User 1">
                <p>Name: Alice</p>
                <p>Email: alice@email.com</p>
            </ui:card>
            <ui:card title="User 2">
                <p>Name: Bob</p>
                <p>Email: bob@email.com</p>
            </ui:card>
            <ui:card title="User 3">
                <p>Name: Carol</p>
                <p>Email: carol@email.com</p>
            </ui:card>
        </ui:grid>
    </ui:layout>;

    echo $layout->toString();
}
Advanced
43. How do you handle Concurrency with Async in Hack?

Use \HH\Asio\va() to run multiple async operations in parallel.

  • Parallel: list($a, $b) = await HHAsio a(fetchA(), fetchB());
  • Sequential: $a = await fetchA(); $b = await fetchB();
  • Performance: parallel is faster for independent tasks
  • Error handling: each task can fail individually
Hack
// Hack Async with Concurrency
async function fetchUsers(): Awaitable<Vector<string>> {
    await SleepWaitHandle::create(100);
    return Vector {'Alice', 'Bob', 'Carol'};
}

async function fetchPosts(): Awaitable<Vector<string>> {
    await SleepWaitHandle::create(150);
    return Vector {'Post 1', 'Post 2', 'Post 3'};
}

async function fetchComments(): Awaitable<Vector<string>> {
    await SleepWaitHandle::create(80);
    return Vector {'Comment 1', 'Comment 2'};
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    // Parallel async calls
    $start = microtime(true);

    list($users, $posts, $comments) = await HHAsioa(
        fetchUsers(),
        fetchPosts(),
        fetchComments()
    );

    $end = microtime(true);
    $duration = ($end - $start) * 1000;

    echo "Users: " . implode(", ", $users) . "\n";
    echo "Posts: " . implode(", ", $posts) . "\n";
    echo "Comments: " . implode(", ", $comments) . "\n";
    echo "Duration: " . $duration . "ms\n";

    // Sequential async calls
    $start2 = microtime(true);

    $users2 = await fetchUsers();
    $posts2 = await fetchPosts();
    $comments2 = await fetchComments();

    $end2 = microtime(true);
    $duration2 = ($end2 - $start2) * 1000;

    echo "Sequential duration: " . $duration2 . "ms\n";
}
Advanced
44. How do you handle Errors in Async Code in Hack?

Use try/catch inside async functions or wrap risky operations.

  • Try/catch: try { await risky(); } catch (Exception $e) { ... }
  • Parallel with error handling: await Vecmap_async(..., async ($x) ==> { try { ... } catch { ... } })
  • Propagation: allow exceptions to bubble up
Hack
// Hack Error Handling with Async
async function riskyOperation(bool $shouldFail): Awaitable<string> {
    await SleepWaitHandle::create(50);

    if ($shouldFail) {
        throw new Exception("Operation failed");
    }

    return "Success";
}

async function safeOperation(bool $shouldFail): Awaitable<string> {
    try {
        return await riskyOperation($shouldFail);
    } catch (Exception $e) {
        return "Error: " . $e->getMessage();
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    // Success case
    $result1 = await safeOperation(false);
    echo "Result 1: $result1\n";

    // Failure case
    $result2 = await safeOperation(true);
    echo "Result 2: $result2\n";

    // Async error with catch
    try {
        $result3 = await riskyOperation(true);
        echo "Result 3: $result3\n";
    } catch (Exception $e) {
        echo "Caught: " . $e->getMessage() . "\n";
    }

    // Multiple async operations with error handling
    $results = await Vecmap_async(
        vec[false, true, false],
        async ($fail) ==> {
            try {
                return await riskyOperation($fail);
            } catch (Exception $e) {
                return "Failed: " . $e->getMessage();
            }
        }
    );

    echo "Results: " . implode(", ", $results) . "\n";
}
Advanced
45. How do you use Functional Programming with Vectors?

Chain operations like filter, map, and fold for expressive data processing.

  • Chaining: $numbers->filter(...)->map(...)->fold(...)
  • Group by: $numbers->groupBy(...)
  • Complex transformations: combine multiple steps
Hack
// Hack Vector with Functional Programming
function functionalVector(): void {
    $numbers = Vector {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    // Chaining operations
    $result = $numbers
        ->filter(($x) ==> $x % 2 === 0)          // Keep evens
        ->map(($x) ==> $x * 2)                   // Double
        ->fold(0, ($acc, $x) ==> $acc + $x);    // Sum

    echo "Result: $result\n";

    // Complex transformation
    $processed = $numbers
        ->map(($x) ==> $x * $x)                  // Square
        ->filter(($x) ==> $x > 10)               // > 10
        ->map(($x) ==> "Number: $x");            // Format

    echo "Processed: " . implode(", ", $processed) . "\n";

    // Group by operation
    $grouped = $numbers->groupBy(($x) ==> 
        $x % 2 === 0 ? 'Even' : 'Odd'
    );

    foreach ($grouped as $key => $values) {
        echo "$key: " . implode(", ", $values) . "\n";
    }
}
Advanced
46. How do you Destructure Pairs in Hack?

Use list() to destructure pairs.

  • Basic: list($id, $name) = $pair;
  • In loops: foreach ($pairs as $pair) { list($id, $name) = $pair; }
  • Nested: list(list($id, $name), list($age, $city)) = $nestedPair;
Hack
// Hack Pair with Destructuring
function pairDestructuring(): void {
    // Create pairs
    $pairs = Vector {
        Pair {1, 'Alice'},
        Pair {2, 'Bob'},
        Pair {3, 'Carol'}
    };

    // Destructure in loop
    foreach ($pairs as $pair) {
        list($id, $name) = $pair;
        echo "ID: $id, Name: $name\n";
    }

    // Function returning pair
    function getUserPair(int $id): Pair<int, string> {
        $users = Map {
            1 => 'Alice',
            2 => 'Bob',
            3 => 'Carol'
        };
        return Pair {$id, $users[$id]};
    }

    // Destructure function result
    list($id, $name) = getUserPair(2);
    echo "User: $id => $name\n";

    // Nested pairs
    $nestedPairs = Vector {
        Pair {Pair {1, 'Alice'}, Pair {25, 'NYC'}},
        Pair {Pair {2, 'Bob'}, Pair {30, 'LA'}}
    };

    foreach ($nestedPairs as $pair) {
        list(list($id, $name), list($age, $city)) = $pair;
        echo "$name ($id) is $age from $city\n";
    }
}
Advanced
47. How do you work with Nested Shapes in Hack?

Define shapes inside shapes for complex data structures.

  • Definition: type Address = shape(...); type Employee = shape('address' => Address, ...);
  • Access: $employee['address']['city']
  • Function: format nested data
Hack
// Hack Shape with Nested Structures
type Address = shape(
    'street' => string,
    'city' => string,
    'state' => string,
    'zip' => string,
);

type Contact = shape(
    'email' => string,
    'phone' => ?string,
);

type Employee = shape(
    'id' => int,
    'name' => string,
    'address' => Address,
    'contact' => Contact,
    'department' => string,
    'salary' => float,
);

function formatEmployee(Employee $employee): string {
    $result = "Employee: " . $employee['name'] . " (ID: " . $employee['id'] . ")\n";
    $result .= "Department: " . $employee['department'] . "\n";
    $result .= "Address: " . $employee['address']['street'] . ", " . 
               $employee['address']['city'] . ", " . 
               $employee['address']['state'] . " " . 
               $employee['address']['zip'] . "\n";
    $result .= "Email: " . $employee['contact']['email'];
    if ($employee['contact']['phone'] !== null) {
        $result .= ", Phone: " . $employee['contact']['phone'];
    }
    $result .= "\nSalary: $" . number_format($employee['salary'], 2);

    return $result;
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $employee = shape(
        'id' => 1,
        'name' => 'Alice Johnson',
        'address' => shape(
            'street' => '123 Main St',
            'city' => 'New York',
            'state' => 'NY',
            'zip' => '10001',
        ),
        'contact' => shape(
            'email' => 'alice@company.com',
            'phone' => '555-1234',
        ),
        'department' => 'Engineering',
        'salary' => 85000.00,
    );

    echo formatEmployee($employee) . "\n";
}
Advanced
48. What is a Generic Repository Pattern in Hack?

A generic repository class works with any entity type.

  • Class: Repository<T> { ... }
  • Methods: add, get, getAll, find, filter, count
  • Usage: new Repository<User>()
  • Type safety: operations are type‑checked
Hack
// Hack Class with Generics
class Repository<T> {
    private Vector<T> $items = Vector {};

    public function add(T $item): void {
        $this->items[] = $item;
    }

    public function get(int $index): T {
        return $this->items[$index];
    }

    public function getAll(): Vector<T> {
        return $this->items;
    }

    public function find((function(T): bool) $predicate): ?T {
        foreach ($this->items as $item) {
            if ($predicate($item)) {
                return $item;
            }
        }
        return null;
    }

    public function filter((function(T): bool) $predicate): Vector<T> {
        $result = Vector {};
        foreach ($this->items as $item) {
            if ($predicate($item)) {
                $result[] = $item;
            }
        }
        return $result;
    }

    public function count(): int {
        return $this->items->count();
    }
}

class User {
    public int $id;
    public string $name;

    public function __construct(int $id, string $name) {
        $this->id = $id;
        $this->name = $name;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $userRepo = new Repository<User>();
    $userRepo->add(new User(1, 'Alice'));
    $userRepo->add(new User(2, 'Bob'));
    $userRepo->add(new User(3, 'Carol'));

    $allUsers = $userRepo->getAll();
    foreach ($allUsers as $user) {
        echo "User: " . $user->id . " - " . $user->name . "\n";
    }

    $found = $userRepo->find(($u) ==> $u->name === 'Bob');
    if ($found !== null) {
        echo "Found: " . $found->name . "\n";
    }

    $filtered = $userRepo->filter(($u) ==> $u->id > 1);
    echo "Filtered count: " . $filtered->count() . "\n";
}
Advanced
49. How do you use Generics with Interfaces in Hack?

Interfaces can be generic, and classes can implement them with specific types.

  • Interface: interface RepositoryInterface<T> { ... }
  • Implement: class UserRepo implements RepositoryInterface<User> { ... }
  • Cache: interface CacheInterface<K, V> { ... }
Hack
// Hack Interface with Generics
interface RepositoryInterface<T> {
    public function add(T $item): void;
    public function get(int $index): T;
    public function getAll(): Vector<T>;
    public function find((function(T): bool) $predicate): ?T;
    public function count(): int;
}

interface CacheInterface<K, V> {
    public function set(K $key, V $value): void;
    public function get(K $key): ?V;
    public function has(K $key): bool;
    public function remove(K $key): void;
    public function clear(): void;
}

class InMemoryCache<K, V> implements CacheInterface<K, V> {
    private Map<K, V> $cache = Map {};

    public function set(K $key, V $value): void {
        $this->cache[$key] = $value;
    }

    public function get(K $key): ?V {
        return $this->cache->get($key);
    }

    public function has(K $key): bool {
        return $this->cache->containsKey($key);
    }

    public function remove(K $key): void {
        unset($this->cache[$key]);
    }

    public function clear(): void {
        $this->cache = Map {};
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $cache = new InMemoryCache<string, int>();
    $cache->set('user1', 25);
    $cache->set('user2', 30);

    echo "user1: " . $cache->get('user1') . "\n";
    echo "Has user3: " . ($cache->has('user3') ? 'true' : 'false') . "\n";

    $cache->remove('user2');
    echo "After remove: " . ($cache->has('user2') ? 'true' : 'false') . "\n";
}
Advanced
50. How do you use Class Constants and Static Methods in Hack?

Constants and static methods are defined at the class level and accessed without instantiation.

  • Constant: public const float PI = 3.14159;
  • Static method: public static function add(int $a, int $b): int
  • Access: MathConstants::PI, MathConstants::add(5, 3)
  • Static property: private static ?Map $config = null;
Hack
// Hack Class Constants and Static Methods
class MathConstants {
    public const float PI = 3.14159;
    public const float E = 2.71828;
    public const int MAX_INT = PHP_INT_MAX;

    public static function add(int $a, int $b): int {
        return $a + $b;
    }

    public static function multiply(int $a, int $b): int {
        return $a * $b;
    }

    public static function circleArea(float $radius): float {
        return self::PI * $radius * $radius;
    }
}

class AppConfig {
    private static ?Map<string, mixed> $config = null;

    public static function load(): void {
        self::$config = Map {
            'host' => 'localhost',
            'port' => 8080,
            'debug' => true,
            'timeout' => 30,
        };
    }

    public static function get(string $key): mixed {
        if (self::$config === null) {
            self::load();
        }
        return self::$config[$key] ?? null;
    }

    public static function set(string $key, mixed $value): void {
        if (self::$config === null) {
            self::load();
        }
        self::$config[$key] = $value;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    echo "PI: " . MathConstants::PI . "\n";
    echo "Add: " . MathConstants::add(5, 3) . "\n";
    echo "Circle area: " . MathConstants::circleArea(2.0) . "\n";

    echo "Config host: " . AppConfig::get('host') . "\n";
    AppConfig::set('port', 9090);
    echo "Config port: " . AppConfig::get('port') . "\n";
}
Advanced
51. What are Abstract Classes in Hack?

Abstract classes cannot be instantiated and may contain abstract methods that must be implemented by subclasses.

  • Abstract class: abstract class Animal { abstract public function makeSound(): string; }
  • Implementation: class Dog extends Animal { public function makeSound(): string { return "Woof!"; } }
  • Concrete methods: can have normal methods
Hack
// Abstract Classes in Hack
abstract class Animal {
    protected string $name;

    public function __construct(string $name) {
        $this->name = $name;
    }

    abstract public function makeSound(): string;

    public function getName(): string {
        return $this->name;
    }
}

class Dog extends Animal {
    public function makeSound(): string {
        return "Woof!";
    }
}

class Cat extends Animal {
    public function makeSound(): string {
        return "Meow!";
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $animals = Vector {
        new Dog("Rex"),
        new Cat("Whiskers")
    };

    foreach ($animals as $animal) {
        echo $animal->getName() . " says: " . $animal->makeSound() . "\n";
    }
}
Advanced
52. What are Final Classes and Methods in Hack?

Final classes cannot be extended. Final methods cannot be overridden.

  • Final class: final class DatabaseConnection { ... }
  • Final method: final public function connect(): void
  • Use: enforce immutability or security
Hack
// Final Classes and Methods in Hack
final class DatabaseConnection {
    private string $dsn;
    private static ?DatabaseConnection $instance = null;

    private function __construct(string $dsn) {
        $this->dsn = $dsn;
    }

    public static function getInstance(string $dsn): DatabaseConnection {
        if (self::$instance === null) {
            self::$instance = new DatabaseConnection($dsn);
        }
        return self::$instance;
    }

    public function query(string $sql): string {
        return "Executing on " . $this->dsn;
    }
}

// Trying to extend final class will cause an error:
// class MyDB extends DatabaseConnection {} // Fatal error

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $db = DatabaseConnection::getInstance("mysql://localhost:3306");
    echo $db->query("SELECT * FROM users") . "\n";
}
Advanced
53. How do you work with Private Properties in Hack?

Private properties are only accessible within the class. Use reflection for debugging or advanced metaprogramming.

  • Declaration: private string $password;
  • Access: only inside class
  • Reflection: can be used to read/modify (advanced usage)
Hack
// Private Properties in Hack
class User {
    private string $password = "secret123";
    private string $email = "user@email.com";

    private function validatePassword(string $input): bool {
        return $input === $this->password;
    }
}

// Accessing private properties directly is not allowed:
// $user = new User();
// echo $user->password; // Error

// However, we can use reflection to access them (for debugging or advanced metaprogramming)
function hackPrivateProperty(): void {
    $user = new User();
    $reflection = new ReflectionClass($user);
    $prop = $reflection->getProperty('password');
    $prop->setAccessible(true);
    echo "Password: " . $prop->getValue($user) . "\n";
    $prop->setValue($user, 'new_password');
    echo "New Password: " . $prop->getValue($user) . "\n";

    $method = $reflection->getMethod('validatePassword');
    $method->setAccessible(true);
    $result = $method->invoke($user, 'new_password');
    echo "Validation: " . ($result ? "Valid" : "Invalid") . "\n";
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    hackPrivateProperty();
}
Advanced
54. How do you implement Singleton Pattern in Hack?

Singletons ensure only one instance exists by using a private constructor and a static getInstance method.

  • Private constructor: private function __construct() {}
  • Static instance: private static ?self $instance = null;
  • Getter: public static function getInstance(): self { ... }
Hack
// Singleton Pattern in Hack
class ConfigManager {
    private static ?ConfigManager $instance = null;
    private array $config = [];

    private function __construct() {
        $this->config = ['db_host' => 'localhost', 'db_user' => 'root'];
    }

    public static function getInstance(): ConfigManager {
        if (self::$instance === null) {
            self::$instance = new ConfigManager();
        }
        return self::$instance;
    }

    public function getConfig(string $key): string {
        return $this->config[$key] ?? '';
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $config = ConfigManager::getInstance();
    echo "DB Host: " . $config->getConfig('db_host') . "\n";
    // $config2 = new ConfigManager(); // Error: private constructor
}
Advanced
55. How do you create Immutable / Readonly Properties in Hack?

Hack does not have a built‑in readonly keyword, but you can achieve immutability using private properties and public getters.

  • Private property: private int $value;
  • Getter: public function getValue(): int { return $this->value; }
  • No setter: enforce immutability
  • With methods: return new instances for changes
Hack
// Readonly Properties (using const and immutable patterns)
class ImmutablePoint {
    public const float PI = 3.14159;

    public function __construct(
        private int $x,
        private int $y
    ) {}

    public function getX(): int { return $this->x; }
    public function getY(): int { return $this->y; }

    public function withX(int $x): ImmutablePoint {
        return new ImmutablePoint($x, $this->y);
    }

    public function withY(int $y): ImmutablePoint {
        return new ImmutablePoint($this->x, $y);
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $p1 = new ImmutablePoint(5, 10);
    $p2 = $p1->withX(7);
    echo "p1: (" . $p1->getX() . ", " . $p1->getY() . ")\n";
    echo "p2: (" . $p2->getX() . ", " . $p2->getY() . ")\n";
    echo "PI: " . ImmutablePoint::PI . "\n";
}
Advanced
56. How do you use Protected Methods in Hack?

Protected methods are accessible within the class and its subclasses. They can be called via reflection if needed.

  • Declaration: protected function calculate(int $a): int
  • Access: inside class and children
  • Reflection: can bypass visibility
Hack
// Protected Methods in Hack
class Calculator {
    protected function complexCalculation(int $a, int $b): int {
        return ($a * $b) + ($a / $b) - ($a % $b);
    }

    protected function secretAlgorithm(string $input): string {
        return md5($input . "SALT_STRING");
    }
}

// Using reflection to call protected methods
function hackProtectedMethods(): void {
    $calc = new Calculator();
    $reflection = new ReflectionClass($calc);
    $method = $reflection->getMethod('complexCalculation');
    $method->setAccessible(true);
    $result = $method->invoke($calc, 10, 3);
    echo "Complex Calculation: " . $result . "\n";

    $method2 = $reflection->getMethod('secretAlgorithm');
    $method2->setAccessible(true);
    $hash = $method2->invoke($calc, "hack_me");
    echo "Secret Hash: " . $hash . "\n";
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    hackProtectedMethods();
}
Advanced
57. What is Constructor Injection in Hack?

Dependencies are passed via the constructor, promoting loose coupling and testability.

  • Constructor: public function __construct(Logger $logger) { ... }
  • Usage: $service = new UserService(new ConsoleLogger());
  • Benefits: easy mocking and swapping
Hack
// Constructor Injection in Hack
class PaymentProcessor {
    private array $validators;

    public function __construct(array $validators = []) {
        $this->validators = $validators;
    }

    public function processPayment(float $amount): bool {
        foreach ($this->validators as $validator) {
            if (!$validator($amount)) {
                return false;
            }
        }
        return true;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $processor = new PaymentProcessor([
        function($amount) { return $amount > 0; },
        function($amount) { return $amount < 10000; }
    ]);
    echo "Payment " . ($processor->processPayment(500) ? "Approved" : "Denied") . "\n";
}
Advanced
58. How do you implement Interfaces in Hack?

Classes implement interfaces to adhere to contracts. Anonymous classes can implement interfaces on the fly.

  • Interface: interface Authenticator { public function authenticate(string $token): bool; }
  • Class: class JwtAuthenticator implements Authenticator { ... }
  • Anonymous: new class implements Authenticator { ... }
Hack
// Interface Implementation in Hack
interface Authenticator {
    public function authenticate(string $token): bool;
}

class JwtAuthenticator implements Authenticator {
    public function authenticate(string $token): bool {
        return str_starts_with($token, "valid_");
    }
}

// Anonymous class implementing interface
function createFakeAuthenticator(): Authenticator {
    return new class implements Authenticator {
        public function authenticate(string $token): bool {
            return true; // Always authenticate
        }
    };
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $auth = new JwtAuthenticator();
    echo "JWT Auth: " . ($auth->authenticate("valid_token") ? "Success" : "Failed") . "\n";
    echo "JWT Auth invalid: " . ($auth->authenticate("invalid") ? "Success" : "Failed") . "\n";

    $fake = createFakeAuthenticator();
    echo "Fake Auth: " . ($fake->authenticate("any") ? "Success" : "Failed") . "\n";
}
Advanced
59. How do you implement Abstract Classes in Hack?

Concrete classes extend abstract classes and implement abstract methods.

  • Abstract class: abstract class DatabaseDriver { abstract protected function connect(string $dsn): bool; }
  • Concrete: class MySqlDriver extends DatabaseDriver { protected function connect(string $dsn): bool { ... } }
Hack
// Abstract Class Implementation in Hack
abstract class DatabaseDriver {
    abstract protected function connect(string $dsn): bool;
    abstract protected function execute(string $sql): array;

    public function query(string $sql): array {
        if ($this->connect("default_dsn")) {
            return $this->execute($sql);
        }
        return [];
    }
}

class MySqlDriver extends DatabaseDriver {
    protected function connect(string $dsn): bool {
        echo "Connecting to MySQL: $dsn\n";
        return true;
    }

    protected function execute(string $sql): array {
        echo "Executing MySQL query: $sql\n";
        return ['result' => 'data'];
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $driver = new MySqlDriver();
    $result = $driver->query("SELECT * FROM users");
    print_r($result);
}
Advanced
60. What are Advanced Trait Usage Patterns in Hack?

Traits can be combined, and conflicts can be resolved using insteadof and as.

  • Combining: use TraitA, TraitB;
  • Conflict: TraitA::method insteadof TraitB;
  • Alias: TraitA::method as protected;
  • Properties: traits can have properties
Hack
// Trait Methods in Hack
trait LoggerTrait {
    private function log(string $message): void {
        echo "[LOG] " . $message . "\n";
    }
}

class Application {
    use LoggerTrait;

    public function run(): void {
        $this->log("Application started");
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $app = new Application();
    $app->run();
}
Advanced
61. What are Magic Methods in Hack?

Magic methods like __get, __set, __call are invoked dynamically.

  • __get: intercept property reads
  • __set: intercept property writes
  • __call: intercept method calls
  • __toString: string conversion
Hack
// Magic Methods in Hack
class MagicContainer {
    private array $data = [];

    public function __get(string $name) {
        return $this->data[$name] ?? null;
    }

    public function __set(string $name, $value): void {
        $this->data[$name] = $value;
    }

    public function __call(string $name, array $arguments) {
        return "Called method: " . $name;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $container = new MagicContainer();
    $container->name = "Alice";
    echo "Name: " . $container->name . "\n";
    echo $container->nonExistentMethod("arg") . "\n";
}
Advanced
62. How does Namespace Visibility work in Hack?

Namespaces organize code and can be accessed from other namespaces using full names.

  • Definition: namespace Core\Security;
  • Use: use Core\Security\Encryption;
  • Reflection: can access private members across namespaces
Hack
// Namespace Visibility in Hack
namespace CoreSecurity {
    class Encryption {
        private static string $masterKey = "SUPER_SECRET_KEY_123";

        private static function encryptData(string $data): string {
            return openssl_encrypt($data, 'AES-256-CBC', self::$masterKey);
        }
    }
}

namespace Hack {
    // Accessing private static property and method from different namespace using reflection
    function hackNamespace(): void {
        $reflection = new ReflectionClass('Core\Security\Encryption');
        $prop = $reflection->getProperty('masterKey');
        $prop->setAccessible(true);
        echo "Master Key: " . $prop->getValue() . "\n";

        $method = $reflection->getMethod('encryptData');
        $method->setAccessible(true);
        $encrypted = $method->invoke(null, "hacked_data");
        echo "Encrypted: " . $encrypted . "\n";
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    HackhackNamespace();
}
Advanced
63. How do you build a Dependency Injection Container in Hack?

A simple container can resolve dependencies recursively.

  • Container class: with get method
  • Resolve: use reflection to find constructor types
  • Autowiring: automatically instantiate dependencies
Hack
// Dependency Injection Container in Hack
class Container {
    private array $services = [];
    private array $parameters = [];

    private function resolveDependencies(string $class): object {
        $reflection = new ReflectionClass($class);
        $constructor = $reflection->getConstructor();
        if (!$constructor) {
            return $reflection->newInstance();
        }
        $params = [];
        foreach ($constructor->getParameters() as $param) {
            $params[] = $this->get($param->getType()->getName());
        }
        return $reflection->newInstanceArgs($params);
    }

    public function get(string $id) {
        return $this->services[$id] ?? $this->resolveDependencies($id);
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $container = new Container();
    // Register a service
    $container->services['Logger'] = new class {
        public function log($msg) { echo "[LOG] $msg\n"; }
    };
    $logger = $container->get('Logger');
    $logger->log("Hello from container");
}
Advanced
64. What is an Event Dispatcher in Hack?

Event dispatchers allow you to register listeners for events and dispatch them.

  • Listeners: array of callables per event
  • Add listener: addListener('event', callback)
  • Dispatch: dispatch('event', $data)
Hack
// Event Dispatcher in Hack
class EventDispatcher {
    private array $listeners = [];

    public function addListener(string $event, callable $listener): void {
        $this->listeners[$event][] = $listener;
    }

    public function dispatch(string $event, array $data = []): void {
        foreach ($this->listeners[$event] ?? [] as $listener) {
            $listener($data);
        }
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $dispatcher = new EventDispatcher();
    $dispatcher->addListener('user.login', function($data) {
        echo "User " . $data['username'] . " logged in\n";
    });
    $dispatcher->dispatch('user.login', ['username' => 'Alice']);
}
Advanced
65. How do you implement Advanced Exception Handling in Hack?

Use custom exceptions, multiple catch blocks, and finally for cleanup.

  • Multiple catches: catch specific exception types
  • Custom: extend Exception
  • Finally: always executed
Hack
// Advanced Exception Handling in Hack
class SecureSystem {
    private function validateAccess(string $token): void {
        if ($token !== "valid_token") {
            throw new Exception("Invalid token");
        }
    }

    public function accessData(string $token): string {
        $this->validateAccess($token);
        return "Sensitive Data";
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $system = new SecureSystem();
    try {
        echo $system->accessData("valid_token") . "\n";
        echo $system->accessData("invalid_token") . "\n";
    } catch (Exception $e) {
        echo "Caught: " . $e->getMessage() . "\n";
    }
}
Advanced
66. How does Serialization work in Hack?

Objects can be serialized using serialize and unserialize. __sleep and __wakeup control the process.

  • __sleep: which properties to serialize
  • __wakeup: restore after deserialization
  • Reflection: can be used to manipulate serialized data
Hack
// Serialization in Hack
class SecureData {
    private string $password = "secret";
    private string $apiKey = "12345";

    public function __sleep() {
        return ['password']; // Only serialize password
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $data = new SecureData();
    $serialized = serialize($data);
    echo "Serialized: " . $serialized . "\n";
    $unserialized = unserialize($serialized);
    // Access private property via reflection for demonstration
    $reflection = new ReflectionClass($unserialized);
    $prop = $reflection->getProperty('apiKey');
    $prop->setAccessible(true);
    echo "API Key: " . $prop->getValue($unserialized) . "\n";
}
Advanced
67. What is Closure Binding in Hack?

Closures can be bound to objects to access their private properties and methods.

  • bindTo: $closure->bindTo($object, 'ClassName')
  • Access: call private methods and read private properties
  • Uses: for debugging or advanced metaprogramming
Hack
// Closure Binding in Hack
class UserService {
    private string $userId = "123";
    private array $permissions = ['read', 'write'];

    private function checkPermission(string $action): bool {
        return in_array($action, $this->permissions);
    }
}

function hackClosureBinding(): void {
    $userService = new UserService();
    $closure = function() {
        return [
            'userId' => $this->userId,
            'permissions' => $this->permissions,
            'canDelete' => $this->checkPermission('delete')
        ];
    };
    // Bind closure to object
    $bound = $closure->bindTo($userService, 'UserService');
    $data = $bound();
    print_r($data);
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    hackClosureBinding();
}
Advanced
68. How does ArrayAccess work in Hack?

Implementing ArrayAccess allows objects to be accessed like arrays.

  • Methods: offsetGet, offsetSet, offsetExists, offsetUnset
  • Use: $config['key']
  • Restrictions: can be bypassed via reflection
Hack
// ArrayAccess Interface in Hack
class Config implements ArrayAccess {
    private array $settings = [
        'db_host' => 'localhost',
        'db_user' => 'root',
        'db_pass' => 'secret'
    ];

    public function offsetGet($offset) {
        return $this->settings[$offset] ?? null;
    }

    public function offsetSet($offset, $value) {
        throw new Exception("Cannot modify config");
    }

    public function offsetExists($offset) {
        return isset($this->settings[$offset]);
    }

    public function offsetUnset($offset) {
        throw new Exception("Cannot unset config");
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $config = new Config();
    echo "DB Host: " . $config['db_host'] . "\n";
    // $config['db_host'] = 'new_host'; // Exception
}
Advanced
69. How do you implement Iterator in Hack?

Implement Iterator to allow object iteration in foreach.

  • Methods: current, key, next, rewind, valid
  • Use: foreach ($collection as $key => $value)
  • Manipulation: can modify iterator state via reflection
Hack
// Iterator Interface in Hack
class DataCollection implements Iterator {
    private array $items = [];
    private int $position = 0;

    public function __construct(array $items) {
        $this->items = $items;
    }

    public function current() {
        return $this->items[$this->position];
    }

    public function key() {
        return $this->position;
    }

    public function next() {
        $this->position++;
    }

    public function rewind() {
        $this->position = 0;
    }

    public function valid() {
        return isset($this->items[$this->position]);
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $collection = new DataCollection(['item1', 'item2', 'item3']);
    foreach ($collection as $key => $value) {
        echo "Key: $key, Value: $value\n";
    }
}
Advanced
70. What is the __invoke Magic Method in Hack?

Objects with __invoke can be called like functions.

  • Definition: public function __invoke(string $msg): string
  • Usage: $obj("Hello")
  • Reflection: can modify invoke behavior
Hack
// Invoke Object in Hack
class FunctionObject {
    private string $prefix = ">> ";

    public function __invoke(string $message): string {
        return $this->prefix . $message;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $obj = new FunctionObject();
    echo $obj("Hello World") . "\n";
}
Advanced
71. How does the __clone Magic Method work in Hack?

__clone is called when an object is cloned. It allows modification of the cloned object.

  • Clone: $copy = clone $original;
  • __clone: can modify properties of the new instance
  • Reflection: can bypass clone behavior
Hack
// Clone Behavior in Hack
class Cloneable {
    private string $secret = "original_secret";
    private array $data = ['key' => 'value'];

    public function __clone() {
        $this->secret = "cloned_" . $this->secret;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $original = new Cloneable();
    $copy = clone $original;
    // Use reflection to inspect private properties
    $reflection = new ReflectionClass($original);
    $prop = $reflection->getProperty('secret');
    $prop->setAccessible(true);
    echo "Original secret: " . $prop->getValue($original) . "\n";
    echo "Copy secret: " . $prop->getValue($copy) . "\n";
}
Advanced
72. How do you use __toString in Hack?

__toString defines how an object is converted to a string.

  • Definition: public function __toString(): string
  • Usage: echo $object;
  • Reflection: can override the method
Hack
// __toString Magic Method in Hack
class User {
    private string $username = "user123";
    private string $email = "user@email.com";

    public function __toString(): string {
        return "User: " . $this->username;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $user = new User();
    echo $user . "\n";
}
Advanced
73. What is __debugInfo in Hack?

__debugInfo controls the output of var_dump for the object.

  • Definition: public function __debugInfo(): array
  • Usage: var_dump($object)
  • Expose: can hide or reveal sensitive data
Hack
// __debugInfo in Hack
class Debuggable {
    private array $sensitive = [
        'password' => 'secret123',
        'api_key' => 'xyz789',
        'token' => 'abc456'
    ];

    public function __debugInfo(): array {
        return ['public' => 'info'];
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $debuggable = new Debuggable();
    var_dump($debuggable);
}
Advanced
74. How do you perform Static Analysis in Hack?

Reflection can inspect static properties and methods.

  • ReflectionClass: get static properties
  • Modify: change static values via reflection
  • Tools: Hack's type checker provides compile‑time analysis
Hack
// Static Analysis in Hack
class StaticAnalyzer {
    private static array $rules = [
        'security' => ['password', 'token'],
        'performance' => ['cache', 'optimize']
    ];

    private static function validateRule(string $rule): bool {
        return in_array($rule, array_keys(self::$rules));
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $reflection = new ReflectionClass('StaticAnalyzer');
    $prop = $reflection->getProperty('rules');
    $prop->setAccessible(true);
    $rules = $prop->getValue();
    print_r($rules);
}
Advanced
75. How does the Type System work in Hack?

Hack's type system enforces static types. Reflection can bypass some type restrictions.

  • Type annotations: optional but recommended
  • Type inference: compiler infers types
  • Bypass: using reflection to assign wrong types
Hack
// Type System in Hack
class TypedContainer {
    private int $id = 123;
    private string $name = "container";
    private array $items = ['item1', 'item2'];
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $container = new TypedContainer();
    $reflection = new ReflectionClass($container);
    $prop = $reflection->getProperty('id');
    $prop->setAccessible(true);
    echo "ID: " . $prop->getValue($container) . "\n";
    $prop->setValue($container, 456);
    echo "New ID: " . $prop->getValue($container) . "\n";
}
Advanced
76. What are Advanced Enum Features in Hack?

Enums can have methods, implement interfaces, and be used with pattern matching.

  • Methods: define behavior
  • Interfaces: enums can implement interfaces
  • Match: use match for exhaustive handling
Hack
// Advanced Enum Features in Hack
enum Color: string {
    Red = '#FF0000';
    Green = '#00FF00';
    Blue = '#0000FF';
}

enum HttpStatus: int {
    OK = 200;
    Created = 201;
    BadRequest = 400;
    NotFound = 404;
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $color = Color::Red;
    echo "Color: " . $color . "\n";
    $status = HttpStatus::OK;
    echo "Status: " . $status . "\n";
}
Advanced
77. What are Attributes in Hack?

Attributes like <<__Memoize>> add metadata to classes, methods, or properties.

  • Built‑in: <<__Memoize>>, <<__EntryPoint>>
  • Custom: can define custom attributes
  • Reflection: read attributes at runtime
Hack
// Attributes in Hack (using << >> syntax)
<<__Memoize>>
class ExpensiveCalculator {
    public function compute(int $n): int {
        // Simulate expensive computation
        return $n * $n;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $calc = new ExpensiveCalculator();
    echo $calc->compute(5) . "\n";
    echo $calc->compute(5) . "\n"; // cached
}
Advanced
78. How does Constructor Property Promotion work in Hack?

Hack does not have built‑in property promotion (unlike PHP 8), but you can declare properties in the class body.

  • Manual: define properties and assign in constructor
  • Type annotations: use type hints
  • Visibility: public, private, protected
Hack
// Constructor Property Promotion (not in Hack, but we can use normal)
class Product {
    public function __construct(
        private string $id,
        private float $price
    ) {}

    public function getId(): string { return $this->id; }
    public function getPrice(): float { return $this->price; }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $p = new Product("PROD-001", 99.99);
    echo "ID: " . $p->getId() . ", Price: $" . $p->getPrice() . "\n";
}
Advanced
79. What are Match Expressions in Hack?

Match expressions are similar to switch but return a value and are stricter.

  • Syntax: match ($code) { 200 => 'OK', default => 'Unknown' }
  • Exhaustive: must cover all cases if no default
  • Expression: returns a value
Hack
// Match Expression in Hack
function getStatusName(int $code): string {
    return match ($code) {
        200 => 'OK',
        404 => 'Not Found',
        500 => 'Server Error',
        default => 'Unknown'
    };
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    echo "Status 200: " . getStatusName(200) . "\n";
    echo "Status 404: " . getStatusName(404) . "\n";
    echo "Status 418: " . getStatusName(418) . "\n";
}
Advanced
80. How do you simulate Fibers in Hack?

Hack does not have Fibers, but you can achieve similar cooperative multitasking using async/await.

  • Async: non‑blocking operations
  • SleepWaitHandle: simulate delays
  • Cooperative: yield control using await
Hack
// Fibers (not in Hack, but we can simulate with async)
async function simulateFiber(): Awaitable<void> {
    echo "Fiber started\n";
    await SleepWaitHandle::create(100);
    echo "Fiber resumed after 100ms\n";
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    await simulateFiber();
}
Advanced
81. How do you use Generators in Hack?

Generators use yield to produce a sequence of values lazily.

  • Function: function gen(): Generator<int> { yield 1; yield 2; }
  • Iteration: foreach ($gen as $value)
  • Send: can send values to generators
Hack
// Generators in Hack
function genNumbers(): Generator<int> {
    for ($i = 0; $i < 5; $i++) {
        yield $i;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $gen = genNumbers();
    foreach ($gen as $value) {
        echo "Value: $value\n";
    }
}
Advanced
82. What are Weak Maps in Hack?

WeakMaps hold weak references to objects, allowing them to be garbage collected.

  • Creation: new WeakMap()
  • Store: $wm[$obj] = 'value'
  • Garbage: if object is collected, entry is removed
Hack
// Weak Maps in Hack
$wm = new WeakMap();
$obj1 = new stdClass();
$obj2 = new stdClass();
$wm[$obj1] = 'value1';
$wm[$obj2] = 'value2';

echo "Value for obj1: " . $wm[$obj1] . "\n";
unset($obj1); // $wm entry for obj1 may be removed
echo "After unset obj1: " . (isset($wm[$obj1]) ? 'exists' : 'gone') . "\n";
Advanced
83. How do you create Readonly Classes in Hack?

Hack does not have readonly classes, but you can make a class immutable by using only private properties and getters.

  • Private: all properties private
  • No setters: only getters
  • Final: optionally mark class as final
Hack
// Readonly Classes (Hack doesn't have this, but we can use final)
final class ImmutableData {
    public function __construct(
        private string $name,
        private int $age
    ) {}
    public function getName(): string { return $this->name; }
    public function getAge(): int { return $this->age; }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $data = new ImmutableData('Alice', 25);
    echo "Name: " . $data->getName() . ", Age: " . $data->getAge() . "\n";
}
Advanced
84. How do you use DNF Types in Hack?

Hack does not have DNF types, but you can use union types to handle multiple types.

  • Union: int|string|float
  • Type checking: is_int(), is_string()
  • Type safety: runtime checks
Hack
// DNF Types (not in Hack, but we can use union)
function processValue(int|string|float $value): void {
    if (is_int($value)) echo "Integer: $value\n";
    else if (is_string($value)) echo "String: $value\n";
    else echo "Float: $value\n";
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    processValue(42);
    processValue("Hello");
    processValue(3.14);
}
Advanced
85. How do you use Advanced Constants in Hack?

Class constants can be arrays, and reflection can access private constants.

  • Array constants: private const CONFIG = ['debug' => false];
  • Reflection: ReflectionClass::getConstant()
  • Modification: via reflection (advanced)
Hack
// Constants in Hack
class ConstantManager {
    private const API_KEY = 'secret_123';
    private const CONFIG = [
        'debug' => false,
        'env' => 'production'
    ];

    public static function getApiKey(): string {
        return self::API_KEY;
    }

    public static function getConfig(): array {
        return self::CONFIG;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    echo "API Key: " . ConstantManager::getApiKey() . "\n";
    $config = ConstantManager::getConfig();
    print_r($config);
}
Advanced
86. How do you use Global Constants in Hack?

Global constants are defined with define() and are globally accessible.

  • Define: define('KEY', 'value')
  • Access: KEY
  • Modify: can be redefined (with warning)
Hack
// Global Constants in Hack
define('SECURE_KEY', 'secure_value_123');
define('DATABASE_CONFIG', [
    'host' => 'localhost',
    'user' => 'root',
    'pass' => 'secret'
]);

<<__EntryPoint>>
async function main(): Awaitable<void> {
    echo "Secure Key: " . SECURE_KEY . "\n";
    print_r(DATABASE_CONFIG);
}
Advanced
87. What is Late Static Binding in Hack?

Late static binding resolves the called class at runtime using static instead of self.

  • self: class where method is defined
  • static: class where method is called
  • Use: static::$value
Hack
// Late Static Binding in Hack
class BaseClass {
    protected static string $value = 'base';

    public static function getValue(): string {
        return static::$value;
    }
}

class ChildClass extends BaseClass {
    protected static string $value = 'child';
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    echo "Base value: " . BaseClass::getValue() . "\n";
    echo "Child value: " . ChildClass::getValue() . "\n";
}
Advanced
88. How do you use Anonymous Classes in Hack?

Anonymous classes are created on the fly and can be used for one‑off objects.

  • Creation: new class { ... }
  • Properties: can have private properties
  • Reflection: can inspect and modify
Hack
// Anonymous Class Properties in Hack
$object = new class {
    private string $secret = 'hidden_value';
    private array $data = ['key' => 'value'];

    public function getSecret(): string {
        return $this->secret;
    }
};

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $reflection = new ReflectionClass($object);
    $prop = $reflection->getProperty('secret');
    $prop->setAccessible(true);
    echo "Secret: " . $prop->getValue($object) . "\n";
    $prop->setValue($object, 'hacked_secret');
    echo "New Secret: " . $object->getSecret() . "\n";
}
Advanced
89. What is the Stringable Interface in Hack?

Stringable ensures an object has __toString.

  • Interface: interface Stringable { public function __toString(): string; }
  • Implement: any class can implement it
  • Use: type‑hint Stringable
Hack
// Stringable Interface in Hack
class User implements Stringable {
    private string $username;
    private string $email;

    public function __construct(string $username, string $email) {
        $this->username = $username;
        $this->email = $email;
    }

    public function __toString(): string {
        return "User: " . $this->username;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $user = new User('alice', 'alice@email.com');
    echo $user . "\n";
}
Advanced
90. How do you use Intersection Types in Hack?

Hack does not have intersection types, but you can require multiple interfaces using a class that implements them.

  • Multiple interfaces: class User implements Authenticatable, Authorizable { ... }
  • Type check: function check(Authenticatable&Authorizable $user) not supported, but you can use a class type
Hack
// Intersection Types (not in Hack, but we can use interfaces)
interface Authenticatable { public function auth(): bool; }
interface Authorizable { public function authz(string $action): bool; }

class User implements Authenticatable, Authorizable {
    public function auth(): bool { return true; }
    public function authz(string $action): bool { return true; }
}

function check( Authenticatable&Authorizable $user ): void {
    echo "Authenticated: " . ($user->auth() ? 'Yes' : 'No') . "\n";
    echo "Authorized: " . ($user->authz('read') ? 'Yes' : 'No') . "\n";
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $user = new User();
    check($user);
}
Advanced
91. What is IteratorAggregate in Hack?

IteratorAggregate allows a class to return an iterator via getIterator().

  • Interface: interface IteratorAggregate { function getIterator(): Traversable; }
  • Implementation: return an ArrayIterator or custom iterator
  • Use: foreach ($object as $item)
Hack
// IteratorAggregate in Hack
class DataCollection implements IteratorAggregate {
    private array $items = ['item1', 'item2', 'item3'];

    public function getIterator(): Traversable {
        return new ArrayIterator($this->items);
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $collection = new DataCollection();
    foreach ($collection as $item) {
        echo "Item: $item\n";
    }
}
Advanced
92. How do you use ArrayObject in Hack?

ArrayObject allows objects to be used like arrays.

  • Creation: $array = new ArrayObject(['key' => 'value']);
  • Access: $array['key']
  • Reflection: can manipulate underlying storage
Hack
// ArrayObject in Hack
$array = new ArrayObject(['key1' => 'value1', 'key2' => 'value2']);
$array['key3'] = 'value3';
echo "Key1: " . $array['key1'] . "\n";
echo "Key3: " . $array['key3'] . "\n";
unset($array['key2']);
print_r($array);
Advanced
93. How do you use SplFixedArray in Hack?

SplFixedArray provides fixed‑size arrays. Hack's Vector is more commonly used.

  • Size: fixed, can be changed via reflection
  • Access: array‑like
  • Performance: slightly faster for fixed sizes
Hack
// SplFixedArray in Hack (use Vector instead)
$fixed = new SplFixedArray(5);
for ($i = 0; $i < 5; $i++) {
    $fixed[$i] = "item_" . $i;
}
echo "Size: " . $fixed->getSize() . "\n";
echo "Item 2: " . $fixed[2] . "\n";
// Hack has Vector which is dynamic, so SplFixedArray is not commonly used.
// But it's available via HHVM compatibility.
Advanced
94. How do you use SplObjectStorage in Hack?

SplObjectStorage stores objects as keys and allows attaching arbitrary values.

  • Create: $storage = new SplObjectStorage();
  • Attach: $storage->attach($obj, 'value');
  • Iterate: foreach ($storage as $obj)
Hack
// SplObjectStorage in Hack
$storage = new SplObjectStorage();
$obj1 = new stdClass();
$obj2 = new stdClass();
$storage->attach($obj1, 'value1');
$storage->attach($obj2, 'value2');

foreach ($storage as $obj) {
    echo "Object: " . spl_object_id($obj) . " => " . $storage[$obj] . "\n";
}
Advanced
95. How do you use ReflectionProperty Modifiers in Hack?

Reflection can change property visibility and values.

  • Set accessible: $prop->setAccessible(true)
  • Get/Set value: $prop->getValue($obj) , $prop->setValue($obj, 'new')
  • Add property: create dynamic properties
Hack
// ReflectionProperty Modifiers in Hack
class ModifierTest {
    private string $private = 'private_val';
    protected string $protected = 'protected_val';
    public string $public = 'public_val';
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $test = new ModifierTest();
    $reflection = new ReflectionClass($test);
    $prop = $reflection->getProperty('private');
    $prop->setAccessible(true);
    echo "Private: " . $prop->getValue($test) . "\n";
    $prop->setValue($test, 'hacked_private');
    echo "New Private: " . $prop->getValue($test) . "\n";
}
Advanced
96. How do you change Method Visibility in Hack?

Reflection can make private or protected methods accessible.

  • ReflectionMethod: $method->setAccessible(true)
  • Invoke: $method->invoke($obj, ...)
  • Static: $method->invoke(null, ...)
Hack
// Method Visibility in Hack
class MethodVisibility {
    private function secretMethod(): string {
        return "This is a secret";
    }
    protected function protectedMethod(): string {
        return "This is protected";
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $test = new MethodVisibility();
    $reflection = new ReflectionClass($test);
    $method = $reflection->getMethod('secretMethod');
    $method->setAccessible(true);
    echo $method->invoke($test) . "\n";
}
Advanced
97. How do you change Static Method Visibility in Hack?

Static private and protected methods can also be made accessible via reflection.

  • ReflectionMethod: for static methods
  • Set accessible: $method->setAccessible(true)
  • Invoke: $method->invoke(null, ...)
Hack
// Static Method Visibility in Hack
class StaticMethods {
    private static function privateStatic(): string {
        return "Private static";
    }
    protected static function protectedStatic(): string {
        return "Protected static";
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $reflection = new ReflectionMethod('StaticMethods', 'privateStatic');
    $reflection->setAccessible(true);
    echo $reflection->invoke(null) . "\n";
}
Advanced
98. How do you hack Final Methods in Hack?

Final methods cannot be overridden, but they can still be called via reflection.

  • Call: $obj->finalMethod() works
  • Override: not possible, but you can create a new method
  • Reflection: can still access the method
Hack
// Final Methods in Hack
class ParentClass {
    final public function finalMethod(): string {
        return "Final method";
    }
    private function privateMethod(): string {
        return "Private method";
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $parent = new ParentClass();
    $reflection = new ReflectionClass($parent);
    $method = $reflection->getMethod('privateMethod');
    $method->setAccessible(true);
    echo $method->invoke($parent) . "\n";
    // final method cannot be overridden, but can be called
    echo $parent->finalMethod() . "\n";
}
Advanced
99. How do you bypass Private Constructors in Hack?

Reflection can create instances without calling the constructor using newInstanceWithoutConstructor.

  • ReflectionClass: $reflection->newInstanceWithoutConstructor()
  • Singleton bypass: create multiple instances
  • Limitations: properties may need manual initialization
Hack
// Private Constructor in Hack
class SingletonHack {
    private static ?SingletonHack $instance = null;
    private function __construct() {}
    public static function getInstance(): SingletonHack {
        if (self::$instance === null) {
            self::$instance = new SingletonHack();
        }
        return self::$instance;
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $reflection = new ReflectionClass('SingletonHack');
    $instance = $reflection->newInstanceWithoutConstructor();
    echo "Instance created: " . ($instance ? 'Yes' : 'No') . "\n";
}
Advanced
100. Complete System Hack – Combining All Techniques

This is a comprehensive example of using reflection to bypass all visibility restrictions and compromise a secure system.

  • Static properties: modify master keys
  • Private properties: read and write sensitive data
  • Private methods: call hidden logic
  • Final methods: bypass final restrictions
  • Private constructor: create instances without calling constructor
Hack
// Reflection and Metaprogramming in Hack
class SuperSecure {
    private static string $masterKey = "super_secret";
    private string $sessionId = "session_456";
    private array $userData = ['username' => 'admin', 'password' => 'admin123'];

    final private function validateToken(string $token): bool {
        return $token === "valid_token";
    }

    private function getSensitiveData(): array {
        return $this->userData;
    }

    public function authenticate(string $token): bool {
        return $this->validateToken($token);
    }
}

<<__EntryPoint>>
async function main(): Awaitable<void> {
    $system = new SuperSecure();
    $reflection = new ReflectionClass($system);

    // Hack static property
    $staticProp = $reflection->getProperty('masterKey');
    $staticProp->setAccessible(true);
    echo "Master Key: " . $staticProp->getValue() . "\n";

    // Hack private property
    $sessionProp = $reflection->getProperty('sessionId');
    $sessionProp->setAccessible(true);
    echo "Session: " . $sessionProp->getValue($system) . "\n";

    // Hack private method
    $dataMethod = $reflection->getMethod('getSensitiveData');
    $dataMethod->setAccessible(true);
    $data = $dataMethod->invoke($system);
    print_r($data);

    // Bypass final method
    $authMethod = $reflection->getMethod('authenticate');
    $authMethod->setAccessible(true);
    echo "Auth: " . ($authMethod->invoke($system, 'any') ? 'Success' : 'Failed') . "\n";
}