╦ ╦╔═╗╔╦╗╔═╗ ╦ ╦╔═╗╔╦╗╔═╗ ╚╦╝╠═╣ ║║╠═╣ ╚╦╝╠═╣ ║║╠═╣ ╩ ╩ ╩═╩╝╩ ╩ ╩ ╩ ╩═╩╝╩ ╩ ╔═╗╔═╗╔═╗╦═╗╔═╗╔╦╗╔═╗╦═╗ ║ ║╠═╝║╣ ╠╦╝╠═╣ ║ ║ ║╠╦╝ ╚═╝╩ ╚═╝╩╚═╩ ╩ ╩ ╚═╝╩╚═ ============================================================================ Three dots. That's it: ... The yada yada operator. Perl's way of saying "I haven't written this part yet." It's a placeholder that actually works. Sort of. ============================================================================ PART 1: THE PLACEHOLDER ----------------------- sub calculate_tax { ... } This compiles. This runs. And when you call calculate_tax(), it dies with: Unimplemented at script.pl line 3. Perfect for stubbing out code you'll write later. ============================================================================ PART 2: WHY NOT JUST die? ------------------------- You could write: sub calculate_tax { die "Not implemented"; } But ... is: - Shorter - More obvious - Industry standard (other languages do this too) - Self-documenting When someone sees ..., they know it's a stub. When they see die, they might think it's error handling. .--. |o_o | |:_/ | // \ \ (| | ) /'\_ _/`\ \___)=(___/ ============================================================================ PART 3: STATEMENT VS EXPRESSION ------------------------------- Important: ... is a STATEMENT, not an expression. # Works (statement context) if ($cond) { ... } # Doesn't work (expression context) my $x = ...; # Syntax error! my $y = $cond ? ... : 0; # Nope! For expression context, use die directly: my $x = die "Unimplemented"; ============================================================================ PART 4: SKELETON MODULES ------------------------ Great for sketching out a class: package Calculator; sub new { my $class = shift; return bless {}, $class; } sub add { ... } sub subtract { ... } sub multiply { ... } sub divide { ... } 1; All methods exist. All methods die if called. The structure is clear. ============================================================================ PART 5: SKELETON SCRIPTS ------------------------ Map out your program logic: #!/usr/bin/env perl use v5.14; sub parse_args { ... } sub validate_input { ... } sub process_data { ... } sub generate_report { ... } my $args = parse_args(); validate_input($args); my $data = process_data($args); generate_report($data); Run it. See which function dies first. Implement that one. Repeat. ============================================================================ PART 6: TEST SCAFFOLDING ------------------------ Stub out tests you plan to write: use Test::More; subtest 'basic operations' => sub { ok(add(2, 2) == 4, 'addition works'); ... # More tests coming }; subtest 'edge cases' => sub { ... # Haven't written these yet }; subtest 'error handling' => sub { ... }; done_testing; The test file runs. Empty subtests die. You know what's left to do. ============================================================================ PART 7: SWITCH FALLTHROUGH -------------------------- Mark unhandled cases: given ($type) { when ('text') { process_text($_) } when ('image') { process_image($_) } when ('video') { process_video($_) } when ('audio') { ... } # TODO default { ... } # Unknown type } Clear signal: these cases need implementation. ============================================================================ PART 8: THE VERSION REQUIREMENT ------------------------------- Yada yada requires Perl 5.12+: use v5.12; # Enables ... sub future_feature { ... } On older Perl, you get a syntax error. The three dots look like the range operator to the parser. ============================================================================ PART 9: DON'T CONFUSE WITH RANGE -------------------------------- Three dots also means something else in scalar context: while () { print if /START/ ... /END/; # Flip-flop operator! } The difference: ... # Statement by itself: yada yada /START/ ... /END/ # Between expressions: flip-flop Context matters. As always in Perl. ============================================================================ PART 10: THE ERROR MESSAGE -------------------------- When ... executes: Unimplemented at script.pl line 42. Short. Clear. Points to the exact line. If you want a custom message, use die: sub calculate_tax { die "Tax calculation not yet implemented"; } But for generic "I'll get to this later," ... is perfect. ============================================================================ PART 11: IN OTHER LANGUAGES --------------------------- Perl isn't alone: Python: pass (but doesn't die) Ruby: raise NotImplementedError Java: throw new UnsupportedOperationException() Perl's ... is closest to Python's idea, but with runtime checking. ============================================================================ PART 12: REAL WORKFLOW ---------------------- Day 1 - Sketch: sub download_file { ... } sub parse_content { ... } sub store_results { ... } Day 2 - First pass: sub download_file { my $url = shift; # TODO: actual download return "dummy content"; } sub parse_content { ... } sub store_results { ... } Day 3 - Getting there: sub download_file { ... } # Actual implementation sub parse_content { ... } # Actual implementation sub store_results { ... } # TODO still Day 4 - Done: # No more ... in the file The yada yada markers disappear as you implement. ============================================================================ PART 13: THE NAME ----------------- Yada yada yada. As in "blah blah blah" or "and so on." From Seinfeld, where characters would skip boring details by saying "yada yada yada." "I went to the store, yada yada yada, now I have a cat." The ... in Perl is the same: "this is where code goes, yada yada, you get the idea." Also called the "triple dot operator" or "ellipsis operator" if you want to be formal. But yada yada is funnier. ============================================================================ ... . . . . . . . . . . ... Unimplemented since Perl 5.12 ============================================================================ japh.codes