diff --git a/Perl_5/1-simple.pl b/Perl_5/1-simple.pl new file mode 100755 index 0000000..340bc24 --- /dev/null +++ b/Perl_5/1-simple.pl @@ -0,0 +1,52 @@ +#!/usr/bin/perl + +use strict; +use v5.10; + +# everytime shift is called inside a function without array passed to it +# it returns next argument +# note that shift is a function that awaits arguments +sub inc1 { + return 1 + shift; +} + + +# @_ is an array of arguments. Dont do $var = _@; +# because context of this operation is scalar +# and any array in scalar context represents its length. +# Not talking about context here. +# also note that @_ is immutable +sub inc2 { + return @_[0] + 1; +} + +# perl functions always return value. +# Explicitly via return or implicitly last calculated value. +# Thus, its better to use return. +# note that $arg++ in perl is actually computed after return +# so mind using prefix in such operations +sub inc3 { + my $arg = shift; + $arg++; +} + +# we declare what do we wait on input, an then do +# fancy argument retrieval +# really the right way of doing this +sub sum($$) { + my ($a, $b) = (shift, shift); + return $a + $b; +} + +# A lambda function! Also, note how we get args +my $max = sub { + my ($a, $b) = @_; + return $a > $b ? $a : $b; +}; + +say inc1(2); # returns 3 +say inc2(2); # returns 3 +say inc3(2); # returns 2 (look in comments near function definition) +say sum(1, 2); # returns 3 +# say sum(1, 2, 3); # produces an error. Uncomment and try it! +say $max->(8, 10); # returns 10, note how we make function call diff --git a/Perl_5/2-scopes.pl b/Perl_5/2-scopes.pl new file mode 100755 index 0000000..c5f6819 --- /dev/null +++ b/Perl_5/2-scopes.pl @@ -0,0 +1,43 @@ +#!/usr/bin/perl + +use strict; +use v5.10; +# in original repo this file is named "context" +# i take the responsibility to rename it to "scopes" +# because of two reasons: +# 1. context is name of entirely different principle +# 2. scope is just more logical :) + + +my @cities = ("Athens", "Roma", "London", "Beijing", "Kiev", "Riga"); + +# we pass an array to function, @_ represents it, and shift +# starts getting values from array. +# if we need to pass multiple arrays, or array and variable - we +# need to use references (not talking about them here) +# also, its nearly always better to use references, in terms of memory usage. +my $f = sub { return scalar @_; }; + +sub f2 { + my @cities = ("Athens", "Roma"); + my $f = sub {return uc shift}; # uc stands for uppercase + say @cities; + # here we map by passing each element to function via $_ + say map($f->($_), @cities); + { + my $f = sub {return lc shift}; + say @cities; + # actually we can call any function with or without braces + say map $f->($_), @cities; + } + { + my @cities = ("London", "Beijing", "Kiev"); + say @cities; + say map $f->($_), @cities; + } +} + +f2(); + +say @cities; +say $f->(@cities); diff --git a/Perl_5/3-abstraction.pl b/Perl_5/3-abstraction.pl new file mode 100755 index 0000000..6590ec3 --- /dev/null +++ b/Perl_5/3-abstraction.pl @@ -0,0 +1,17 @@ +#!/usr/bin/perl + +use strict; +use v5.10; + +sub square { + return shift() ** 2; + # braces for perl to know that shift is called without args +} +sub cube { + return shift() ** 3; +} +say 10 ** 2; +say square(10); + +say 10 ** 3; +say cube 10; # demonstrating that no-braces feature again diff --git a/Perl_5/4-default.pl b/Perl_5/4-default.pl new file mode 100755 index 0000000..c63d155 --- /dev/null +++ b/Perl_5/4-default.pl @@ -0,0 +1,42 @@ +#!/usr/bin/perl + +use strict; +use Data::Dumper; + +# unless is equal to if not +# also note that we can type two ways: +# action if condition +# if (condition) action +# will assign a default only if undef comes as an arg, or there is no arg +sub unlessDef { + my $a = shift; + my $b = shift; $b = "Hello" unless defined $b; + my $c = shift; $c = 5 unless defined $c; + print Dumper { + a => $a, + b => $b, + c => $c + }; +} +print "unlessDef\n"; +unlessDef(1, 2, 3); +unlessDef(1, 2); +unlessDef(1); +unlessDef(1, 0); +# will assign a default if false is passed as a parameter +sub orDef { + my $a = shift; + my $b = shift || "Hello"; + my $c = shift || 5; + print Dumper { + a => $a, + b => $b, + c => $c + }; # prints hash +} + +print "orDef\n"; +orDef(1, 2, 3); +orDef(1, 2); +orDef(1); +orDef(1, 0); diff --git a/Perl_5/5-manyargs.pl b/Perl_5/5-manyargs.pl new file mode 100755 index 0000000..bdcd643 --- /dev/null +++ b/Perl_5/5-manyargs.pl @@ -0,0 +1,34 @@ +#!/usr/bin/perl + +use strict; + +use Data::Dumper; +# spread operator is not needed in perl +# because only way for us to get our params is through array +# but i'll show how to iterate through params + +# ref gets us type of reference, \ creates reference + + +my $f1 = sub { print Dumper @_; }; + +$f1->(1, 2, 3); +print "\n"; + +sub f2 { + my $arg; + foreach $arg (@_) { + print ref(\$arg) . " : " . Dumper($arg); + } +} + +f2($f1, 1, 'Marcus', {field => "value"}); +print "\n"; + +# anonymous hash higner is automatically passed as a reference +# BUT unlike js arrays and hashes are defaultly passed not as arrays, +# if they arent anonymous +# here we try passing a real hash to a ref, just to show that not all hashes +# are references +my %hash; +print ref \%hash; diff --git a/Perl_5/6-new.pl b/Perl_5/6-new.pl new file mode 100755 index 0000000..118e49a --- /dev/null +++ b/Perl_5/6-new.pl @@ -0,0 +1,17 @@ +#!/usr/bin/perl + +use strict; +use v5.10; + +# there is no new Function syntax in perl, but there is a fancy thing +# that is worth looking at +# KIDS DO NOT TRY THIS AT HOME + +my $func = 'sub ttt($$) {($a, $b) = (shift, shift); return $a+$b;}'; + +my $res = (eval($func), ttt(1, 2)); +say $res; + +# fancy thing is that (, , , ) looks through all actions left to right and returns +# result of last +# Without braces it will go right to left diff --git a/Perl_5/7-method.pl b/Perl_5/7-method.pl new file mode 100755 index 0000000..d984c90 --- /dev/null +++ b/Perl_5/7-method.pl @@ -0,0 +1,36 @@ +#!/usr/bin/perl + +use strict; +use v5.10; + +package obj1; +sub new { + my $class = shift; + my $self = { + max => sub ($$) { + my ($a, $b) = (shift, shift); + return $a > $b ? $a : $b; + } # note that this method is not given $self in arguments + }; + bless $self, $class; # this is better shown in next chapter + return $self; +} +sub inc($) { + my $self = shift; # we always get $self as a first argument to a method + my $a = shift; + return ++$a; +} +sub sum($$) { + my $self = shift; + my ($a, $b) = (shift, shift); + return $a + $b; +} + +# declaration of package is between package statements. +# so we need to explicitly declare main code +package main; + +my $obj = new obj1(); +say ref $obj; +say $obj->sum(1, 2); +say $$obj{'max'}->(1, 2); diff --git a/Perl_5/8-self.pl b/Perl_5/8-self.pl new file mode 100755 index 0000000..e4e2cb9 --- /dev/null +++ b/Perl_5/8-self.pl @@ -0,0 +1,30 @@ +#!/usr/bin/perl + +use strict; +use Data::Dumper; +# the chapter is renamed +# because of naming conventions in perl +# actually, in perl6 there'll be an easier way of doing things + + +package city; +sub new { + my $class = shift; + my $self = { + _name => shift, + _year => shift + }; + bless $self, $class; + # bless tells perl that $self is an object of package (class) $class + # that is passed to the constructor + return $self; +} +sub name { + my $self = shift; + return $self->{_name}; +} + +package main; + +my $kyiv = new city('Kyiv', 482); +print $kyiv->name() . "\n"; diff --git a/Perl_5/9-lvalue.pl b/Perl_5/9-lvalue.pl new file mode 100755 index 0000000..cc74fbb --- /dev/null +++ b/Perl_5/9-lvalue.pl @@ -0,0 +1,16 @@ +#!/usr/bin/perl + +use strict; +use v5.10; + +# We can do modifiable return! +my $val; + +sub lval: lvalue { + return $val; +}; + +lval() = 5; +say lval(); +lval() = 7; +say lval(); diff --git a/Perl_5/a-iife.pl b/Perl_5/a-iife.pl new file mode 100755 index 0000000..76e2f87 --- /dev/null +++ b/Perl_5/a-iife.pl @@ -0,0 +1,5 @@ +#!/usr/bin/perl + +use strict; + +(sub {print "hello world";})->();