-
Notifications
You must be signed in to change notification settings - Fork 159
Expand file tree
/
Copy pathChatScript-Common-Beginner-Mistakes.html
More file actions
411 lines (410 loc) · 16.3 KB
/
Copy pathChatScript-Common-Beginner-Mistakes.html
File metadata and controls
411 lines (410 loc) · 16.3 KB
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
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>ChatScript-Common-Beginner-Mistakes</title>
<style>
html {
color: #1a1a1a;
background-color: #fdfdfd;
}
body {
margin: 0 auto;
max-width: 36em;
padding-left: 50px;
padding-right: 50px;
padding-top: 50px;
padding-bottom: 50px;
hyphens: auto;
overflow-wrap: break-word;
text-rendering: optimizeLegibility;
font-kerning: normal;
}
@media (max-width: 600px) {
body {
font-size: 0.9em;
padding: 12px;
}
h1 {
font-size: 1.8em;
}
}
@media print {
html {
background-color: white;
}
body {
background-color: transparent;
color: black;
font-size: 12pt;
}
p, h2, h3 {
orphans: 3;
widows: 3;
}
h2, h3, h4 {
page-break-after: avoid;
}
}
p {
margin: 1em 0;
}
a {
color: #1a1a1a;
}
a:visited {
color: #1a1a1a;
}
img {
max-width: 100%;
}
svg {
height; auto;
max-width: 100%;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 1.4em;
}
h5, h6 {
font-size: 1em;
font-style: italic;
}
h6 {
font-weight: normal;
}
ol, ul {
padding-left: 1.7em;
margin-top: 1em;
}
li > ol, li > ul {
margin-top: 0;
}
blockquote {
margin: 1em 0 1em 1.7em;
padding-left: 1em;
border-left: 2px solid #e6e6e6;
color: #606060;
}
code {
font-family: Menlo, Monaco, Consolas, 'Lucida Console', monospace;
font-size: 85%;
margin: 0;
hyphens: manual;
}
pre {
margin: 1em 0;
overflow: auto;
}
pre code {
padding: 0;
overflow: visible;
overflow-wrap: normal;
}
.sourceCode {
background-color: transparent;
overflow: visible;
}
hr {
background-color: #1a1a1a;
border: none;
height: 1px;
margin: 1em 0;
}
table {
margin: 1em 0;
border-collapse: collapse;
width: 100%;
overflow-x: auto;
display: block;
font-variant-numeric: lining-nums tabular-nums;
}
table caption {
margin-bottom: 0.75em;
}
tbody {
margin-top: 0.5em;
border-top: 1px solid #1a1a1a;
border-bottom: 1px solid #1a1a1a;
}
th {
border-top: 1px solid #1a1a1a;
padding: 0.25em 0.5em 0.25em 0.5em;
}
td {
padding: 0.125em 0.5em 0.25em 0.5em;
}
header {
margin-bottom: 4em;
text-align: center;
}
#TOC li {
list-style: none;
}
#TOC ul {
padding-left: 1.3em;
}
#TOC > ul {
padding-left: 0;
}
#TOC a:not(:hover) {
text-decoration: none;
}
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
div.columns{display: flex; gap: min(4vw, 1.5em);}
div.column{flex: auto; overflow-x: auto;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
/* The extra [class] is a hack that increases specificity enough to
override a similar rule in reveal.js */
ul.task-list[class]{list-style: none;}
ul.task-list li input[type="checkbox"] {
font-size: inherit;
width: 0.8em;
margin: 0 0.8em 0.2em -1.6em;
vertical-align: middle;
}
.display.math{display: block; text-align: center; margin: 0.5rem auto;}
</style>
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<h1 id="chatscript-common-beginner-mistakes">ChatScript Common Beginner
Mistakes</h1>
<blockquote>
<p>Copyright Bruce Wilcox, gowilcox@gmail.com
brilligunderstanding.com</p>
</blockquote>
<p><br>Revision 11/31/2017 cs7.61</p>
<p>Here are a collection of common beginner mistakes I have seen. Many
will work, they are just unnecessary and inefficient and potentially
more obscure to read.</p>
<h2 id="failing-to-separate-tokens-with-a-space">Failing to separate
tokens with a space</h2>
<pre><code>u:MYLABEL()</code></pre>
<p>is not the same as</p>
<pre><code>u: MYLABEL()</code></pre>
<p>While ChatScript will automatically space around balanced things like
parens or brackets, it will not do so around ordinary text, so
<code>u:MYLABEL</code> is a single token, an ordinary word for printout,
and not a rule header.</p>
<h2 id="leading-and-trailing-in-a-pattern">Leading and trailing
<code>*</code> in a pattern</h2>
<pre><code>u: (* I go home *)</code></pre>
<p>The above pattern you might see in AIML, which requires a pattern
that covers the entire sentence. CS does not and the *’s are
superfluous. CS will hunt into the sentence to find the first pattern
element. And it will finish matching when it has matched the last
pattern element. CS does not require you cover the rest of the sentence.
Therefore this is sufficient (and faster to execute and takes less space
and is easier to read).</p>
<pre><code>u: (I go home)</code></pre>
<h2 id="inadequate-understanding-of-rejoinders">Inadequate understanding
of rejoinders</h2>
<pre><code>t: How old are you?
a: (~number<5) You are young.
b: (~number<10) You are a growing child.
c: (~number<100) You are old.</code></pre>
<p>The rejoinders above are all different responses to the same input.
They should be at the same level, meaning all should be <code>a:</code>,
which name the alternatives at the same level. And, to be clear, I would
intent them.</p>
<pre><code>t: How old are you?
a: (~number<5) You are young.
b: (~no) You aren't young?
a: (~number<10) You are a growing child.
a: (~number<100) You are old.</code></pre>
<p>The above makes it clear that the <code>a:</code> level rejoinders
are tied to the <code>t:</code>, and the <code>b:</code> rejoinder is
tied to the <code>a: (~number<5)</code>. If you don’t indent clearly,
then</p>
<pre><code>t: How old are you?
u: (~number<5) You are young.</code></pre>
<p>it is hard to tell if the <code>u:</code> is intentional or a typo. I
left-flush all top level rules (<code>t:</code>,
<code>u:v,</code>?:<code>,</code>s:`) and appropriately indent based on
nesting level all rejoinders. Structurally it is immediately obvious
what is intended.</p>
<h2 id="failing-to-use-sample-input-comments">Failing to use sample
input comments</h2>
<p>Whenever you have a responder or rejoinder, you should have one or
more sample inputs above it.</p>
<pre><code>##<<Supports the following formats
december 2, 1980
december 2 in 1980
dec second of 1980
##>>
u: ( * _~month_names {, } _~number { in of} _{~yearnumber} )</code></pre>
<p>The above rule was elegantly documented with a comment. But it is not
appropriate. The correct way is</p>
<pre><code>#! december 2, 1980
#! december 2 in 1980
#! dec second of 1980
u: ( * _~month_names {, } _~number { in of} _{~yearnumber} )</code></pre>
<p>The difference is- the comment expressed the scriptors intent of what
they were doing. But it will take work for anyone looking at the code
(including the author) to decide that the pattern actually works for
those cases. And you will probably get it wrong. When you write sample
inputs, CS can be asked to :verify that the pattern does indeed work for
the cases given and tell you. Not only now, but anytime in the future,
when other parts of the system evolve and may impact your pattern
accidently (changes in concept sets for example). Writing sample inputs
is both documentation so that people can understand your script without
having to interpret the pattern, and it is the unit test of a rule,
allowing the system to verify all sorts of things (not just that the
pattern works).</p>
<h2 id="omitting-from-a-function-call">Omitting <code>^</code> from a
function call</h2>
<pre><code>u: (_~number) $$tmp = nth(~set _0)</code></pre>
<p>The above code is legal. The system will figure out that nth is an
existing function <code>^nth</code> and call it appropriately. Yet you
should avoid being sloppy and always put the <code>^</code> in front of
a function call. Why?</p>
<p>If <code>nth</code> is not a function, because CS intermixes english
and script, CS does not know you intended a function call and will
merrily treat it as ordinary text with no warning or error. If, however,
you write <code>^nth</code>, CS will confirm that it is a function and
issue an error if it is not. This error protects you from typos,
mistyping the name of a function.</p>
<h2 id="transferring-function-values-to-variables">Transferring function
values to variables</h2>
<pre><code>outputmacro: ^func(^arg1 ^arg2)
$$units = ^arg1
$$time_value = ^arg2
if ($$units == weeks)</code></pre>
<p>You can name function arguments whatever you want. And you can use
them directly in your code (you just can’t overwrite them via
assignment). So it is clearer and cleaner to do this:</p>
<pre><code>outputmacro: ^func(^units ^time_value)
if (^time_value == weeks)</code></pre>
<h2 id="fail-to-take-advantage-of-canonical-values-of-keywords">Fail to
take advantage of canonical values of keywords</h2>
<pre><code>u: ( _~number [second seconds ] )</code></pre>
<p>The above [] contains redundant information. Second is the singular
canonical form of seconds. You don’t need both words. Which means you
could instead just write</p>
<pre><code>u: (_~number second)</code></pre>
<h2 id="excessive-topic-keywords">Excessive topic keywords</h2>
<p>Typically no topic should have pronouns, prepositions, conjunctions,
and determiners as keywords.The goal of keywords in a topic is to help
CS find relevant topics. When you look at a topic, the keywords should
all be immediately suggestive of that topic.</p>
<pre><code>topic: ~childhood (my childhood young)</code></pre>
<p>The keyword my doesn’t immediately bring this topic to mind and
should be removed. It will force CS to consider this topic for all sorts
of sentences that contain my that have nothing to do with childhood.
childhood is clearly a good keyword. Is young? Probably. Maybe.</p>
<h2 id="redundant-choices">Redundant <code>{}</code> choices</h2>
<p>The purpose of the optional words list is to assist in aligning words
in a pattern. If it doesn’t matter whether or not the <code>{}</code>
exists in the pattern, then the optional choice is wasted.</p>
<pre><code>u: ( I love you {maybe} )</code></pre>
<p>In the above pattern, there is nothing after <code>{maybe}</code>.
This means that the pattern won’t care if a match happens or not for
that.</p>
<pre><code>u: ( I will love you {maybe} tomorrow)</code></pre>
<p>Here, the optional <code>{maybe}</code> is valuable, allowing the
pattern to match both <em>I will love you tomorrow</em> and <em>I will
love you maybe tomorrow</em>. That is, it swallows up a useless word to
allow the real match to proceed. The above was overly specific, and
would more likely be</p>
<pre><code>u: ( I will love you {~adverb} tomorrow)</code></pre>
<p>Optional matches can be superfluous or downright detrimental at the
start.</p>
<pre><code>u: ( {~adverb} I will love you)</code></pre>
<p>The intent of the above was to swallow up an adverb occurring before
I, like Maybe I will love you. But, firstly, it wasn’t needed. CS would
have skipped any words until it got to I anyway. Secondly, it will prove
detrimental if the input is I will soon love you, because it will scan
forward, find the soon as an adverb, lock the position of matching to
that, and then look for I immediately afterwards. But now it’s too late
and I has already gone past.</p>
<h2 id="my-pattern-doesnt-match-the-input-i-crafted-it-for">My pattern
doesn’t match the input I crafted it for!</h2>
<p>Probably true. First thing to do is</p>
<pre><code>:prepare this is my special input</code></pre>
<p>Look at the marked concepts for each word. Does it match your
pattern? Is the input even what you expect? Has CS told you it
substituted something or spell-fixed it or whatever?</p>
<h2 id="wrong-understanding-of-scoping-of-variables">Wrong understanding
of scoping of variables</h2>
<pre><code>outputmacro: ^myfunc(^myargument)</code></pre>
<p>Function arguments like ^myargument only exist during the code of the
macro and will not be legal elsewhere. Other than function arguments,
all other variables have global scope. This means if you do</p>
<pre><code>$$tmp = 1</code></pre>
<p>in some topic, it will have that value afterwards in every topic, and
you risk destroying it if you do an inadvertent assignment in some other
topic of</p>
<pre><code>$$tmp = hello</code></pre>
<h2 id="separating-keywords-with-commas">Separating keywords with
commas</h2>
<pre><code>Topic: ~mytopic [keyword1, keyword2, keyword3] </code></pre>
<p>is wrong. Don’t use commas.</p>
<h2 id="listing-phrases-or-titles-in-instead-of-quotes">Listing phrases
or titles in <code>[]</code> instead of quotes</h2>
<pre><code>u: ([Doctor Zhivago]) </code></pre>
<p>is wrong. First, [] means find one word of. Second, for titles of
things, you should put them in double quotes.
<code>u: ("Doctor Zhivago")</code> The double quotes tells CS that you
think of this as a single item, not two words. It’s not like
<code>u: (have fun)</code>, where you want the words together but they
are not a single item. Proper nouns should always be a single item,
particularly when there is punctuation in the item like “Des Moines,
Iowa” because you don’t really know how CS manages punctuation
internally- does it split the comma into a separate token, does it use
underscores, etc. You shouldn’t have to worry about how CS represents
it. You should just double quote it.</p>
<h2 id="being-unaware-of-interjections-in-cs">Being unaware of
interjections in CS</h2>
<pre><code>topic: ~introductions( hi hello welcome) </code></pre>
<p>is wrong because hello is not a normal word like a noun, verb,
adjective, or adverb. It is a special word that is a “dialog act” or an
“interjection”. CS auto translates interjections on input. If you do</p>
<pre><code>:prepare hello</code></pre>
<p>you will see it decodes it into <code>~emohello</code>, and that’s
what you should use as your keyword. The most common interjections are
<code>~emohello</code>, <code>~emogoodbye</code>,
<code>~emohowzit</code>, <code>~yes</code>, <code>~no</code>.</p>
<h2
id="expecting-cs-numeric-assignment-to-mirror-other-languages">Expecting
CS numeric assignment to mirror other languages</h2>
<p>ChatScript executes as it goes, it does not stack up data like a desk
calculator. So</p>
<pre><code>$tmp = %hour + $tmp</code></pre>
<p>is executed as: <code>$tmp = %hour</code> and then
<code>$tmp += $tmp</code>. This is not what you expect from other
languages, where you expect <code>(%hour + $tmp)</code> to be computed
and then assigned. You can, of course, make your code simpler and
correct by</p>
<pre><code>$tmp += %hour</code></pre>
<p>Or even</p>
<pre><code>$tmp = $tmp + %hour</code></pre>
<h2 id="thinking-in-a-pattern-will-find-the-earliest-match">Thinking
<code>[]</code> in a pattern will find the earliest match</h2>
<p>A pattern like <code>u: ( the * [bear raccoon] ate )</code> contains
a list of words in <code>[]</code>, that a human thinks of as
equivalent, and thus imagines CS will simply find the next occurrence of
any of them in the input. For efficiency, that’s not how CS works. It
will try each in turn, and if a match is found, it will stop trying
words in the <code>[]</code> immediately. So input like: <em>the raccoon
ate the bear</em> will fail because bear will be found first, and
<em>ate</em> does not happen immediately after that. If you convert
<code>[]</code> into a concept set, then a pattern of
<code>u: (the * ~myanimals ate)</code> will match, because all members
of a concept set are considered simultaneously.</p>
<h2 id="querying-with-the-same-value-in-2-positions">Querying with the
same value in 2 positions</h2>
<p>A query like</p>
<pre><code>^query(svo $_tmp $_tmp value)</code></pre>
<p>will likely fail when 2 of the values being checked are the same.
This is because the query marks its arguments with index flags for
efficiency and marking the second use of a word overwrites the mark set
on the first. Then query testing fails. Usually there is no need to
create a fact repeating the same word twice. It’s just laziness of not
using a different arbitrary fixed value.</p>
</body>
</html>