summaryrefslogtreecommitdiffstats
path: root/tutorial.html
blob: 841472fe1c867e8a95a3331c3d848a02cf656e4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<!--
     (local-set-key [(meta return)] 
        	    (ilam (shell-command-on-region (point) (mark) "perl -MMDK::Common")))
-->

<head>
  <title>perl-MDK-Common tutorial</title>
  <link rev="made" href="mailto:gc at mandrake_nospam_soft.com" />
  <meta name="keywords" content="perl mandrakesoft pixel library functional" />
</head>

<body bgcolor="#FFFFFF" text="#000000" link="#0000ee" vlink="#551a8b">

  <h1 align="center">perl-MDK-Common tutorial v0.1</h1>

<p><a href="mailto:gc at mandrake_nospam_soft.com">Guillaume Cottenceau</a></p>

<hr />


  <h2>Introduction</h2>
  
  <p>This document aims at helping people interested in learning
  more on <tt>perl-MDK-Common</tt>, a Perl library which is intensively
  used in MandrakeSoft in-house software development.</p>

  <p>The library adds some convenient "basic" functions to Perl,
  allows easier functional-style programming, and also provides
  some better system-related operations. It can be seen as an
  extension to the standard Perl library, adding missing helpful
  functions. It is divided as follows:</p>

  <ul>
    <li><tt>MDK::Common::File</tt>: some useful list/hash functions</li>
    <li><tt>MDK::Common::Func</tt>: functions suited to functional-style programming</li>
    <li><tt>MDK::Common::Globals</tt>: allows to share constant values between packages</li>
    <li><tt>MDK::Common::Math</tt>: some math functions</li>
    <li><tt>MDK::Common::String</tt>: functions to perform various formatting on strings</li>
    <li><tt>MDK::Common::System</tt>: system-related useful functions</li>
    <li><tt>MDK::Common::Various</tt>: other useful functions</li>
  </ul>

  <p>Thanks to <tt>perl-MDK-Common</tt>'s own documentation, an
  easy way to directly access information about the provided
  functions, you can use <tt>perldoc</tt>, for example
  <tt>perldoc MDK::Common::Func</tt> will explain the functions
  of the Func module. Use <tt>perldoc MDK::Common</tt> to view
  information on all the available functions.</p>

  <p>Additionally, <tt>perl-MDK-Common</tt> provides a binary
  called <tt>perl_checker</tt>, which is a Perl compiler aiming
  at enforcing the use of a subset of Perl, so that all
  MandrakeSoft Perl programs roughly follow the same code style.
  It will also help the programmer to remove unneeded parentheses
  and conditionals.</p>

<hr />


  <h2>Prerequisites</h2>

  <p>Of course, a first look at the Perl language will be
  necessary for the reader. The following can be a good Perl
  Tutorial (though there are many of them on the web): <a
  href="http://www.comp.leeds.ac.uk/Perl/">http://www.comp.leeds.ac.uk/Perl/</a>.</p>

  <p>Programming with <tt>perl-MDK-Common</tt> also emphasizes
  the following quality properties on your code:</p>

  <ul>
  <li><b>no code duplication:</b> at the grassroots, this library
  aims at helping you with simple operations you have to deal
  with so many times in usual programs; this includes reading the
  contents of a file, finding the maximum numeric element of an
  array, etc; in order to be efficient with
  <tt>perl-MDK-Common</tt>, you need to always keep in mind to
  not duplicate code to perform a single action</li>
  <br>

  <li><b>functional style programming:</b> this is not a so
  common technique among programmers, and maybe it's even worse
  with Perl programmers; but functional-style programs are often
  clearer, more expressive, more reusable, and more
  maintainable</li>
  <br>

  <li><b>strict code style:</b> Perl is known to be a language
  with which "there is more than one way to do it"; actually,
  nearly every Perl program uses a different code-style; that's
  nice for the programmer's freedom, and that's awful for code
  maintainance; <tt>perl_checker</tt> will ask you to follow a
  specific code style</li>

  </ul>

  <p>We can't discuss Perl programming without referring to two
  excellent books from O'Reilly. The first one is called "The
  Perl Cookbook", and covers many daily problems a Perl
  programmer will face, in a recipe-like fashion. All Perl
  programmers should own this book :). The second one can be a
  good resource for more skillful programmers, and is called
  "Advanced Perl Programming"; it covers interesting advanced
  features of Perl.</p>

<hr />


  <h2>Structure of this document</h2>

  <p>This document will first try to emphasize the most useful
  functions of the <tt>perl-MDK-Common</tt> library, e.g. the
  most commonly used and simple. Then, some functions whose use
  is not trivial will be explained. As a last part, an
  introduction to the code-style to please
  <tt>perl_checker</tt> will be shown.</p>

<hr />


  <h2>Most useful functions</h2>

  <p><b>Note:</b> many functions' name, extending capabilities of
  existing functions, or being their functional counterpart, are
  suffixed with the underscore character (<tt>_</tt>); for
  example, <tt>chomp_</tt> is the equivalent of <tt>chomp</tt>,
  but returns the chomp'ed results instead of modifying its
  argument.</p>

  <ul>
  <li>
   <b>cat_</b>(FILENAME): returns the file contents: in scalar 
    context it returns a single string, in array context it
    returns the lines. If the file doesn't exist, it returns
    <tt>undef</tt>.

  <p>Perl IO operations are verbose and the API is cluttered.
  There are many situations in which you want to read the
  contents of a file, put it in a scalar or loop around the
  files. <tt>cat_</tt> allows to do that easily:</p>

  <pre class="SCREEN">
  printf "Mandrake release:\n%s\n", cat_('/etc/mandrake-release');

  foreach (cat_('/proc/mounts')) {
      my ($dev, $where, $type) = split;
      print "$dev is mounted on $where (type $type)\n";
  }
  </pre>
  </li>


  <li>
   <b>output</b>(FILENAME, LIST): creates a file and outputs the
    list (if the file exists, it is clobbered)

  <p>Counterpart of <tt>cat_</tt>. Build the contents of the file
  in your program, and when you're happy with it, write it on
  disk:</p>

  <pre class="SCREEN">
  my @resolv_conf = qw(search mandrakesoft.com);
  push @resolv_conf, "nameserver $_" foreach @name_servers;
  output('/etc/resolv.conf', @resolv_conf);
  </pre>
  </li>


  <li>
   <b>member</b>(SCALAR, LIST): is the value in the list?

  <p>Returns true if the value is stringwise equivalent to an
  element of the list:</p>

  <pre class="SCREEN">
  if (!member($driver, @modules)) {
      print "Sorry, the driver is not available in our modules.\n"
  }
  </pre>
  </li>


  <li>
   <b>difference2</b>(ARRAY REF, ARRAY REF): returns the first
   list without the element of the second list

  <p>Performs a set-wise substraction, e.g. removes in first list
  the elements that are members of the second one:</p>

  <pre class="SCREEN">
  my @types = difference2(\@available_types, \@bad_types);
  print "Please select a type from: @types\n";
  </pre>
  </li>


  <li>
   <b>uniq</b>(LIST): returns the list with no duplicates

  <p>Removes duplicates from the list, keeping the order of the
  list, and the first element when duplicates.</p>

  <pre class="SCREEN">
  my @types = uniq map { (split)[2] } cat_('/proc/mounts');
  print "Filesystem types in use: @types\n"
  </pre>
  </li>


  <li>
   <b>min</b>(LIST): returns the minimum number from a list
   <p></p>
  </li>


  <li>
   <b>man</b>(LIST): returns the maximum number from a list
   <p></p>
  </li>


  <li>
   <b>chomp_</b>(STRING): non-mutable version of <tt>chomp</tt>:
    do not modify the argument, returns the chomp'ed value.

  <p>Very useful for simple functional expressions.</p>

  <p>Note: also works on lists: <tt>chomp_($a, $b)</tt> is
  equivalent to <tt>chomp($a); chomp($b); ($a,$b)</tt>.</p>

  <pre class="SCREEN">
  my $pid = chomp_(cat_('/var/run/cardmgr.pid'));
  </pre>
  </li>


  </ul>

<hr />


  <h2>Other interesting functions</h2>

  <p>The following describes functions whose use is not
  trivial.</p>

  <ul>
  <li>
   <b>if_</b>(BOOL, LIST)

  <p>Returns LIST if the BOOL condition is true, else an empty
  list.</p>

  <p>Note: it's equivalent as doing <tt>BOOL ? LIST : ()</tt>,
  except that since it's a function, LIST is evaluated even if
  BOOL is false. It's useful because it's shorter and more
  readable than the ternary <tt>?:</tt>.</p>

  <p>A first convenient use is when you want to loop on a list
  and conditionally on another:</p>

  <pre class="SCREEN">
  foreach (@types, if_($arch eq 'ppc', @ppc_types)) {
      # ...
  }</pre>

  <p>It's also useful to select elements from a list and modify
  them on-the-fly, e.g. performing the equivalent of a
  <tt>grep</tt> then a <tt>map</tt>. It works because
  Perl automatically concatenates lists.</p>

  <pre class="SCREEN">
  my @md_devices = map { if_(/^(md\d+)/, $1) } cat_('/proc/mdstat');

      # equivalent (but much more elegant!) to:

  my @md_devices = map { /^(md\d+)/; $1 } grep { /^md\d+/ } cat_('/proc/mdstat');
  </pre>
  </li>


  <li>
  <b>substInFile</b> { CODE } FILENAME: executes the code for
    each line of the file; you can know the end of the file is
    reached using <tt>eof</tt>

  <p>Typically used to change a parameter in a file:

  <pre class="SCREEN">
  substInFile { s/^FORWARD_IPV4.*\n//; $_ .= "FORWARD_IPV4=true\n" if eof } '/etc/sysconfig/network';
  </pre>


  <li>
   <b>each_index</b> { CODE } LIST: just like <tt>each</tt>, but
   sets $::i

  <p>Useful when you need to perform an action on each element of
  a list, but you also need the index of each element:</p>

  <pre class="SCREEN">
  each_index { printf "%s mountpoint: $_", $::i == 2 ? 'third' : 'other' } cat_('/proc/mounts');
  </pre>
  </li>


  </ul>

<hr />


  <h2>perl_checker</h2>

  <p></p>


<hr />

    <p>
       Last update: Fri Apr 18 22:08:06 2003
    </p>

</body>

</html>