Welcome to mirror list, hosted at ThFree Co, Russian Federation.

09-discussion.md.html « manual « docs - github.com/stevedonovan/Penlight.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 17057d476e9cd9d63948ec1b59aa5e55c3ca03cd (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
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
    <title>Penlight Documentation</title>
    <link rel="stylesheet" href="../ldoc_fixed.css" type="text/css" />
</head>
<body>

<div id="container">

<div id="product">
	<div id="product_logo"></div>
	<div id="product_name"><big><b></b></big></div>
	<div id="product_description"></div>
</div> <!-- id="product" -->


<div id="main">


<!-- Menu -->

<div id="navigation">
<br/>
<h1>Penlight</h1>

<ul>
  <li><a href="../index.html">Index</a></li>
</ul>

<h2>Contents</h2>
<ul>
<li><a href="#Modularity_and_Granularity">Modularity and Granularity </a></li>
<li><a href="#Defining_what_is_Callable">Defining what is Callable </a></li>
</ul>


<h2>Manual</h2>
<ul class="nowrap">
  <li><a href="../manual/01-introduction.md.html">Introduction</a></li>
  <li><a href="../manual/02-arrays.md.html">Tables and Arrays</a></li>
  <li><a href="../manual/03-strings.md.html">Strings. Higher-level operations on strings.</a></li>
  <li><a href="../manual/04-paths.md.html">Paths and Directories</a></li>
  <li><a href="../manual/05-dates.md.html">Date and Time</a></li>
  <li><a href="../manual/06-data.md.html">Data</a></li>
  <li><a href="../manual/07-functional.md.html">Functional Programming</a></li>
  <li><a href="../manual/08-additional.md.html">Additional Libraries</a></li>
  <li><strong>Technical Choices</strong></li>
</ul>
<h2>Libraries</h2>
<ul class="nowrap">
  <li><a href="../libraries/pl.html">pl</a></li>
  <li><a href="../libraries/pl.app.html">pl.app</a></li>
  <li><a href="../libraries/pl.array2d.html">pl.array2d</a></li>
  <li><a href="../libraries/pl.class.html">pl.class</a></li>
  <li><a href="../libraries/pl.compat.html">pl.compat</a></li>
  <li><a href="../libraries/pl.comprehension.html">pl.comprehension</a></li>
  <li><a href="../libraries/pl.config.html">pl.config</a></li>
  <li><a href="../libraries/pl.data.html">pl.data</a></li>
  <li><a href="../libraries/pl.dir.html">pl.dir</a></li>
  <li><a href="../libraries/pl.file.html">pl.file</a></li>
  <li><a href="../libraries/pl.func.html">pl.func</a></li>
  <li><a href="../libraries/pl.import_into.html">pl.import_into</a></li>
  <li><a href="../libraries/pl.input.html">pl.input</a></li>
  <li><a href="../libraries/pl.lapp.html">pl.lapp</a></li>
  <li><a href="../libraries/pl.lexer.html">pl.lexer</a></li>
  <li><a href="../libraries/pl.luabalanced.html">pl.luabalanced</a></li>
  <li><a href="../libraries/pl.operator.html">pl.operator</a></li>
  <li><a href="../libraries/pl.path.html">pl.path</a></li>
  <li><a href="../libraries/pl.permute.html">pl.permute</a></li>
  <li><a href="../libraries/pl.pretty.html">pl.pretty</a></li>
  <li><a href="../libraries/pl.seq.html">pl.seq</a></li>
  <li><a href="../libraries/pl.sip.html">pl.sip</a></li>
  <li><a href="../libraries/pl.strict.html">pl.strict</a></li>
  <li><a href="../libraries/pl.stringio.html">pl.stringio</a></li>
  <li><a href="../libraries/pl.stringx.html">pl.stringx</a></li>
  <li><a href="../libraries/pl.tablex.html">pl.tablex</a></li>
  <li><a href="../libraries/pl.template.html">pl.template</a></li>
  <li><a href="../libraries/pl.test.html">pl.test</a></li>
  <li><a href="../libraries/pl.text.html">pl.text</a></li>
  <li><a href="../libraries/pl.types.html">pl.types</a></li>
  <li><a href="../libraries/pl.url.html">pl.url</a></li>
  <li><a href="../libraries/pl.utils.html">pl.utils</a></li>
  <li><a href="../libraries/pl.xml.html">pl.xml</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
  <li><a href="../classes/pl.Date.html">pl.Date</a></li>
  <li><a href="../classes/pl.List.html">pl.List</a></li>
  <li><a href="../classes/pl.Map.html">pl.Map</a></li>
  <li><a href="../classes/pl.MultiMap.html">pl.MultiMap</a></li>
  <li><a href="../classes/pl.OrderedMap.html">pl.OrderedMap</a></li>
  <li><a href="../classes/pl.Set.html">pl.Set</a></li>
</ul>
<h2>Examples</h2>
<ul class="nowrap">
  <li><a href="../examples/seesubst.lua.html">seesubst.lua</a></li>
  <li><a href="../examples/sipscan.lua.html">sipscan.lua</a></li>
  <li><a href="../examples/symbols.lua.html">symbols.lua</a></li>
  <li><a href="../examples/test-cmp.lua.html">test-cmp.lua</a></li>
  <li><a href="../examples/test-data.lua.html">test-data.lua</a></li>
  <li><a href="../examples/test-listcallbacks.lua.html">test-listcallbacks.lua</a></li>
  <li><a href="../examples/test-pretty.lua.html">test-pretty.lua</a></li>
  <li><a href="../examples/test-symbols.lua.html">test-symbols.lua</a></li>
  <li><a href="../examples/testclone.lua.html">testclone.lua</a></li>
  <li><a href="../examples/testconfig.lua.html">testconfig.lua</a></li>
  <li><a href="../examples/testglobal.lua.html">testglobal.lua</a></li>
  <li><a href="../examples/testinputfields.lua.html">testinputfields.lua</a></li>
  <li><a href="../examples/testinputfields2.lua.html">testinputfields2.lua</a></li>
  <li><a href="../examples/testxml.lua.html">testxml.lua</a></li>
  <li><a href="../examples/which.lua.html">which.lua</a></li>
</ul>

</div>

<div id="content">


<h2>Technical Choices</h2>

<p><a name="Modularity_and_Granularity"></a></p>
<h3>Modularity and Granularity</h3>

<p>In an ideal world, a program should only load the libraries it needs. Penlight is
intended to work in situations where an extra 100Kb of bytecode could be a
problem. It is straightforward but tedious to load exactly what you need:</p>


<pre>
<span class="keyword">local</span> data = <span class="global">require</span> <span class="string">'pl.data'</span>
<span class="keyword">local</span> List = <span class="global">require</span> <span class="string">'pl.List'</span>
<span class="keyword">local</span> array2d = <span class="global">require</span> <span class="string">'pl.array2d'</span>
<span class="keyword">local</span> seq = <span class="global">require</span> <span class="string">'pl.seq'</span>
<span class="keyword">local</span> utils = <span class="global">require</span> <span class="string">'pl.utils'</span>
</pre>

<p>This is the style that I follow in Penlight itself, so that modules don't mess
with the global environment; also, <code>stringx.import()</code> is not used because it will
update the global <a href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a> table.</p>

<p>But <code>require &apos;pl&apos;</code> is more convenient in scripts; the question is how to ensure
that one doesn't load the whole kitchen sink as the price of convenience. The
strategy is to only load modules when they are referenced. In 'init.lua' (which
is loaded by <code>require &apos;pl&apos;</code>) a metatable is attached to the global table with an
<code>__index</code> metamethod. Any unknown name is looked up in the list of modules, and
if found, we require it and make that module globally available. So when
<a href="../libraries/pl.tablex.html#deepcompare">tablex.deepcompare</a> is encountered, looking up <a href="../libraries/pl.tablex.html#">tablex</a> causes 'pl.tablex' to be
required.  .</p>

<p>Modifying the behaviour of the global table has consequences. For instance, there
is the famous module <a href="../libraries/pl.strict.html#">strict</a> which comes with Lua itself (perhaps the only
standard Lua module written in Lua itself) which also does this modification so
that global variiables must be defined before use.  So the implementation in
'init.lua' allows for a 'not found' hook, which 'pl.strict.lua' uses.  Other
libraries may install their own metatables for <code>_G</code>, but Penlight will now
forward any unknown name to the <code>__index</code> defined by the original metatable.</p>

<p>But the strategy is worth the effort: the old 'kitchen sink' 'init.lua' would
pull in about 260K of bytecode, whereas now typical programs use about 100K less,
and short scripts even better - for instance, if they were only needing
functionality in <a href="../libraries/pl.utils.html#">utils</a>.</p>

<p>There are some functions which mark their output table with a special metatable,
when it seems particularly appropriate. For instance, <a href="../libraries/pl.tablex.html#makeset">tablex.makeset</a> creates a
<a href="../classes/pl.Set.html#">Set</a>, and <a href="../libraries/pl.seq.html#copy">seq.copy</a> creates a <a href="../classes/pl.List.html#">List</a>. But this does not automatically result in
the loading of <a href="../classes/pl.Set.html#">pl.Set</a> and <a href="../classes/pl.List.html#">pl.List</a>; only if you try to access any of these
methods.  In 'utils.lua', there is an exported table called <code>stdmt</code>:</p>


<pre>
stdmt = { List = {}, Map = {}, Set = {}, MultiMap = {} }
</pre>

<p>If you go through 'init.lua', then these plain little 'identity' tables get an
<code>__index</code> metamethod which forces the loading of the full functionality. Here is
the code from 'list.lua' which starts the ball rolling for lists:</p>


<pre>
List = utils.stdmt.List
List.__index = List
List._name = <span class="string">"List"</span>
List._class = List
</pre>

<p>The 'load-on-demand' strategy helps to modularize the library.  Especially for
more casual use, <code>require &apos;pl&apos;</code> is a good compromise between convenience and
modularity.</p>

<p>In this current version, I have generally reduced the amount of trickery
involved. Previously, <a href="../classes/pl.Map.html#">Map</a> was defined in <a href="../libraries/pl.class.html#">pl.class</a>; now it is sensibly defined
in <a href="../classes/pl.Map.html#">pl.Map</a>; <a href="../libraries/pl.class.html#">pl.class</a> only contains the basic class mechanism (and returns that
function.) For consistency, <a href="../classes/pl.List.html#">List</a> is returned directly by  <code>require &apos;pl.List&apos;</code>
(note the uppercase 'L'),  Also, the amount of module dependencies in the
non-core libraries like <a href="../libraries/pl.config.html#">pl.config</a> have been reduced.</p>

<p><a name="Defining_what_is_Callable"></a></p>
<h3>Defining what is Callable</h3>

<p>'utils.lua' exports <code>function_arg</code> which is used extensively throughout Penlight.
It defines what is meant by 'callable'.  Obviously true functions are immediately
passed back. But what about strings? The first option is that it represents an
operator in 'operator.lua', so that '&lt;' is just an alias for <a href="../libraries/pl.operator.html#lt">operator.lt</a>.</p>

<p>We then check whether there is a <em>function factory</em> defined for the metatable of
the value.</p>

<p>(It is true that strings can be made callable, but in practice this turns out to
be a cute but dubious idea, since <em>all</em> strings share the same metatable. A
common programming error is to pass the wrong kind of object to a function, and
it's better to get a nice clean 'attempting to call a string' message rather than
some obscure trace from the bowels of your library.)</p>

<p>The other module that registers a function factory is <a href="../libraries/pl.func.html#">pl.func</a>. Placeholder
expressions cannot be directly calleable, and so need to be instantiated and
cached in as efficient way as possible.</p>

<p>(An inconsistency is that <code>utils.is_callable</code> does not do this thorough check.)</p>




</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-09-22 15:59:54 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>