.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Perlude::Tutorial 3pm" .TH Perlude::Tutorial 3pm "2023-02-03" "perl v5.36.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "Write your own generators" .IX Header "Write your own generators" Have you ever miss the shell pipe in Perl? Such a clever operator: it streams data from programs to programs on demand, which means that nothing will compute more than expected by the whole stream, any part the pipe can stop the whole stream. .PP .Vb 1 \& seq 1000 .Ve .PP will compute 1000 lines .PP .Vb 1 \& seq 1000 | sed 5q .Ve .PP will compute only 5 lines as sed ends its job there. We somehow miss it in perl. Sure, we have grep and map but they are only acting in complete arrays. .PP Perlude comes with all most common filters, i doubt you'll missing one. If you do so: please feedback and i'll probably add it! So your job is about writing generators (or using those written in Perlude::Stuff and Perlude::Sh). If you have to write a generic one, please contribute. .PP To write them, you have to understand the Perlude conventions. When you're using an iterator, say \f(CW\*(C`range 1,4\*(C'\fR, you have to think about the whole list of potential results. Those can be written as .PP .Vb 3 \& ( 1, 2, 3, 4 ) \& ( 1, 2, 3, 4, ) \& ( 1, 2, 3, 4, () ) .Ve .PP so \f(CW\*(C`()\*(C'\fR is used as a list terminator. your iterator must return one scalar by call and last it work sending a terminator. As example: .PP .Vb 4 \& sub read_file { \& open my $fh, shift; \& sub { <$fh> // () } \& } .Ve .PP now you can write .PP .Vb 4 \& now {say} \& filter {/foo/} \& take 5, \& read_file "test.txt" .Ve .PP which is equivalent to .PP .Vb 1 \& sed 5q test.txt | grep foo .Ve .PP Not only it's easy to read and write, its behaviour is also the best expected: .IP "\(bu" 4 it reads one record, use it and forget it before reading the next record. This is a memory friendly behavior .IP "\(bu" 4 whoever in the pipe can decide to stop it. For example: it's fine for grep to release 3 records only. .PP Writing unix filters is really easy. Also note that filters/generators compositions rules are simple and powerful .PP .Vb 2 \& G | F => G \& F | F => F .Ve .PP If you wrote shell, powershell, perl6 or any other functionnal language, you probably miss it coming back to perl5. .PP Basically, on demand lists are just iterators. Perlude is just a pleasant way to deal with them stealing keywords from haskell Perlude. .PP \fIexample\fR .IX Subsection "example" .PP As example: What are the 5 first naturals containing a 3? .PP A perl implementation would be: .PP .Vb 5 \& for \& ( my $_=0, my $count=0 \& ; $count <= 5 \& ; $_++ ) \& { if (/3/) { $count++; say } } .Ve .PP Hard to read ... and worth: nothing is reusable at all .PP The shell counterpart would be .PP .Vb 2 \& nat () { while {true} { print $[i++] } } \& nat | grep 3 | head \-n5 .Ve .PP There are things to understand about the shell elegance: .IP "\(bu" 2 there is no need of a counter variable, neither a for loop: head is the single command which handles it for you. .IP "\(bu" 2 the implementation of nat is bare simple: you just focus on your nat problem, you don't care how many elements the filter could need. .IP "\(bu" 2 you added nat to your toolkit, it's much more pain to resuse it in perl ... before Perlude .PP also, it's easy to create a new function 'top5' by passsing a an argument to head (looks like a partial application): .PP .Vb 3 \& top5 () { head \-n5 } \& contains3 () { grep 3 } \& nat | contains3 | top5 .Ve .PP No perl builtin provide this power. .SS "I can haz nat in perl ?" .IX Subsection "I can haz nat in perl ?" Perlude is a set of functions that takes closures as arguments, and returns others .PP nat is the basic closure example: .PP .Vb 1 \& my $nat = sub { state $x=0; $x++ } .Ve .PP a reusable way to write it would be: .PP .Vb 4 \& sub nat_from { \& my $x = shift; \& sub { $x++ } \& } \& \& sub nat { nat_from 0 } .Ve .PP now you can use Perlude keywords on this functions .PP .Vb 2 \& sub evens_in { filter { not( $_ % 2 ) } shift } \& sub top5 { take 5, shift } .Ve .SH "Other dynamic languages stuff" .IX Header "Other dynamic languages stuff" .Vb 5 \& Ruby : Rubylude was written by Nono after RMLL\*(Aq11 https://github.com/nono/Rubylude \& Javascript : \& http://weepy.github.com/kaffeine/ was quoted it the python pipe intro but i guess it\*(Aqs useless \& as http://jashkenas.github.com/coffee\-script/ is javascript made right. \& Python : https://github.com/JulienPalard/Pipe with an introduction here: http://dev\-tricks.net/pipe\-infix\-syntax\-for\-python .Ve .SH "Contribute" .IX Header "Contribute" .Vb 1 \& http://github.com/eiro/p5\-perlude .Ve