-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhelp.html
executable file
·2462 lines (1871 loc) · 94.9 KB
/
help.html
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
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>the-order-of-symbols.txt,3</title>
<meta name="generator" content="emacs 26.0.50.1; htmlfontify 0.21" />
<style type="text/css"><!--
body { font-family: Menlo; font-stretch: normal; font-weight: 500; font-style: normal; color: #f5f5f5; background: #333333; font-size: 10pt; text-decoration: none; }
span.default { font-family: Menlo; font-stretch: normal; font-weight: 500; font-style: normal; color: #f5f5f5; background: #333333; font-size: 10pt; text-decoration: none; }
span.default a { font-family: Menlo; font-stretch: normal; font-weight: 500; font-style: normal; color: #f5f5f5; background: #333333; font-size: 10pt; text-decoration: underline; }
span.type { color: #9370db; font-family: Menlo; font-stretch: normal; font-weight: 500; font-style: normal; background: #333333; font-size: 10pt; text-decoration: none; }
span.type a { color: #9370db; font-family: Menlo; font-stretch: normal; font-weight: 500; font-style: normal; background: #333333; font-size: 10pt; text-decoration: underline; }
span.keyword { color: #20b2aa; font-weight: 700; font-family: Menlo; font-stretch: normal; font-style: normal; background: #333333; font-size: 10pt; text-decoration: none; }
span.keyword a { color: #20b2aa; font-weight: 700; font-family: Menlo; font-stretch: normal; font-style: normal; background: #333333; font-size: 10pt; text-decoration: underline; }
span.warning { color: #ff69b4; font-weight: 700; font-family: Menlo; font-stretch: normal; font-style: normal; background: #333333; font-size: 10pt; text-decoration: none; }
span.warning a { color: #ff69b4; font-weight: 700; font-family: Menlo; font-stretch: normal; font-style: normal; background: #333333; font-size: 10pt; text-decoration: underline; }
span.string { color: #ffa07a; font-family: Menlo; font-stretch: normal; font-weight: 500; font-style: normal; background: #333333; font-size: 10pt; text-decoration: none; }
span.string a { color: #ffa07a; font-family: Menlo; font-stretch: normal; font-weight: 500; font-style: normal; background: #333333; font-size: 10pt; text-decoration: underline; }
span.comment { color: #cd853f; font-family: Menlo; font-stretch: normal; font-weight: 500; font-style: normal; background: #333333; font-size: 10pt; text-decoration: none; }
span.comment a { color: #cd853f; font-family: Menlo; font-stretch: normal; font-weight: 500; font-style: normal; background: #333333; font-size: 10pt; text-decoration: underline; }
span.comment-delimiter { color: #cd853f; font-family: Menlo; font-stretch: normal; font-weight: 500; font-style: normal; background: #333333; font-size: 10pt; text-decoration: none; }
span.comment-delimiter a { color: #cd853f; font-family: Menlo; font-stretch: normal; font-weight: 500; font-style: normal; background: #333333; font-size: 10pt; text-decoration: underline; }
--></style>
<script type="text/javascript"><!--
// this function is needed to work around
// a bug in IE related to element attributes
function hasClass(obj)
{
var result = false;
if (obj.getAttributeNode("class") != null)
{
result = obj.getAttributeNode("class").value;
}
return result;
}
function stripe(id)
{
// the flag we'll use to keep track of
// whether the current row is odd or even
var even = false;
// if arguments are provided to specify the colors
// of the even & odd rows, then use the them;
// otherwise use the following defaults:
var evenColor = arguments[1] ? arguments[1] : "#fff";
var oddColor = arguments[2] ? arguments[2] : "#ddd";
// obtain a reference to the desired table
// if no such table exists, abort
var table = document.getElementById(id);
if (! table) { return; }
// by definition, tables can have more than one tbody
// element, so we'll have to get the list of child
// <tbody>s
var tbodies = table.getElementsByTagName("tbody");
// and iterate through them...
for (var h = 0; h < tbodies.length; h++)
{
// find all the <tr> elements...
var trs = tbodies[h].getElementsByTagName("tr");
// ... and iterate through them
for (var i = 0; i < trs.length; i++)
{
// avoid rows that have a class attribute
// or backgroundColor style
if (! hasClass(trs[i]) &&
! trs[i].style.backgroundColor)
{
// get all the cells in this row...
var tds = trs[i].getElementsByTagName("td");
// and iterate through them...
for (var j = 0; j < tds.length; j++)
{
var mytd = tds[j];
// avoid cells that have a class attribute
// or backgroundColor style
if (! hasClass(mytd) &&
! mytd.style.backgroundColor)
{
mytd.style.backgroundColor =
even ? evenColor : oddColor;
}
}
}
// flip from odd to even, or vice-versa
even = ! even;
}
}
}
function toggle_invis( name )
{
var filter =
{ acceptNode:
function( node )
{ var classname = node.id;
if( classname )
{ var classbase = classname.substr( 0, name.length );
if( classbase == name ) { return NodeFilter.FILTER_ACCEPT; } }
return NodeFilter.FILTER_SKIP; } };
var walker = document.createTreeWalker( document.body ,
NodeFilter.SHOW_ELEMENT ,
filter ,
false );
while( walker.nextNode() )
{
var e = walker.currentNode;
if( e.style.display == "none" ) { e.style.display = "inline"; }
else { e.style.display = "none"; }
}
}
--> </script>
</head>
<body onload="stripe('index'); return true;">
<pre><span class="comment-delimiter">;; </span><span class="comment">-*- mode: lisp -*-
</span><span class="comment-delimiter">;;</span><span class="comment">
</span><span class="comment-delimiter">;; </span><span class="comment">WORK IN PROGRESS
</span><span class="comment-delimiter">;;</span><span class="comment">
</span><span class="comment-delimiter">;; </span><span class="comment">Questions, comments or problems? Email [email protected]
</span><span class="comment-delimiter">;;</span><span class="comment">
</span>
========================================================================
========================================================================
======================
|The Order of Symbols|
======================
<span class="string">"...there once existed a language which perfectly
and unambiguously expressed the essence of
all possible things and concepts..."</span>
-- Umberto Eco [6TSFTPL]
<span class="string">"Most good programmers do programming not because they
expect to get paid or get adulation by the public,
but because it is fun to program."</span>
-- Linus Torvalds
<span class="string">"Computers are good at following instructions,
but not at reading your mind."</span>
-- Donald Knuth [7TAOCP]
========================================================================
========================================================================
Introduction
------------
Lisp as a computer programming language is as Latin is to English or
modern day Italian. It is the second oldest high level computer
language still in use, invented (or found) in the 1950's by John
McCarthy and is the most powerful and expressive programming language
there is [citation needed]. Lisp comes in many shapes and forms and
Sigil, the Lisp used in Eturia, is no different. It is a 'dialect' of
Lisp, as Lisp is more of an idea than a concrete thing, with all
dialects looking similar, but behaving, sometimes, very differently.
And like any dialect of a language, it is malleable and modifiable,
something which I will show you though this document we build our
language from base principals (axioms, here known as builtins).
The following is meant to be both an introduction and reference to
Sigil. You will find an explanation of syntax, followed by a brief
explanation of Eturia, the Listener and Window Manager, followed by
the list of builtins, and then a set of examples that can be followed
along and typed into the Eturia Listener, which can be found at:
http://busfactor1.ca/bin/eturia/client/dev.html
This paper is intended to follow the ideas of Guy Steele in his
talk/paper 'Growing a language':
https://www.cs.virginia.edu/~evans/cs655/readings/steele.pdf
https://www.youtube.com/watch?v=_ahvzDzKdB0
All terms in the following text are (hopefully) defined before use.
This material is the result of many years of study and research, of
both myself and others. It's opinions are all mine, built upon
those I have admired in the past, knowingly or unknowingly. I hope
you find the material as useful and entertaining as I have writing it
down and preparing it.
Burton Samograd <[email protected]>
Homepage: http://busfactor1.ca/old/old
Facebook: https://www.facebook.com/KRUHFT-17546219842
Twitter: https://twitter.com/kruhft (@kruhft)
Intended Audience
-----------------
This work is intended for both beginners and professionals alike. For
beginners, if they work through the exercises, should gain an
understanding for all of the code and exercises given, with a little
thought. Professionals may benefit in the same way, finding the
material refreshing over the typical code chaos one might see at work,
while learning something new and, hopefully, interesting: programming
language design and implementation.
The main desire of the reader should be to learn to program. This is
not a traditional programming course in any way and will teach you
little on how to get a job as a programmer. But knowing what this
course will teach you will benefit you for as long as you act as a
programmer during your life [citation needed].
This course assumes a basic understanding of arithmetic and algebra,
along with the idea that a computer is something that simply follows
the instructions that they are told, nothing more. As Picasso
noted, <span class="string">"Computers...they can only give you answers."</span>
Eturia
------
Eturia is a (simulated) computer for Computer Science Education. It
is designed to be simple and limited, perfect for teaching and
learning with few distractions. Although probably unfamiliar at
first, it's spartan interface can be quickly learned by any newcomer
with its few and simple commands. Finally, it runs in a Web browser,
so it is accessable from any location with an internet connection.
The current version of Eturia can always be found at:
http://busfactor1.ca/bin/eturia
along with videos and other information about the project.
The Listener
------------
There is no copy/pasting in Eturia. To enter the code, it must be
typed manually into the 'Listener'. This way the code will go through
your fingers and your brain, giving you a better chance of learning
the concepts as you go along and build your own language in Sigil.
This 'Listener' is like VI, but a bit different[1]:
i - insert mode, allows you to type overwrite text in the buffer
? - command mode, allows you to execute the following commands
and break out of insert mode
hjkl - move the cursor left, down, up, or right (h,j,k,l)
e - evaluate lisp code
z - clear the screen
np - previous/next in history (experimental)
To type characters use 'insert' (overwrite) mode by pressing 'i'. You
can tell when you are in 'insert' mode by the GREEN border around the
console. To 'escape' out of insert mode, press '?'.
REMEMBER TO CLICK IN THE WINDOW TITLE BEFORE TRYING TO TYPE IN THE
LISTENER.
[1] VI and Emacs are programmers text editors. There has been a
decades long debate over the merits and benfits of using each. Emacs
is a modern day Lisp Machine, VI is akin to a Unix machine. I chose a
VI-like editor interface for Eturia due to the simplicity of
implementing it.
Window Manager
--------------
- click in title bar to focus window
- click and drag in title bar to move window
- middle click in title bar to remove window
======
Syntax
======
The following is the syntax of Sigil:
Numbers - a string of digits
----------------------------
A number can be used with mathematical functions and should be
familiar to all that have taken introductory mathematics.
Examples:
1 is a number
100 is a number
3.141516 is a number
-3 is a number
Symbol - a string of characters
-------------------------------
A symbol is a string of characters not containing '(', or ')'.
Examples:
x is a symbol
abc is a symbol
x123 is a symbol
123x is a symbol
a-longer-symbol is a symbol
|a symbol with spaces| is a symbol
Comments - a note to your self
------------------------------
Comments can be important in programs as they are used to explain the
purpose of the code you are writing.
Examples:
<span class="comment">; this is a comment
</span>
Quoting - stops evaluation
--------------------------
Evaluation means to 'get the value of something'. Sometimes you want
this to not happen and just get 'something'. Quoting is used for that
and is an essential part of the following examples.
Examples:
1 => 1
`1 => 1
x => <span class="comment">; Error, undefined symbol
</span>`x => x
(1 2 3) => <span class="comment">; Error, undefined function: 1
</span>`(1 2 3) => (1 2 3)
List - build lists
------------------
Besides 'atoms' (numbers and symbols), Sigil also has 'lists'. A list
is a collection of atoms or other lists, also known as an
'S-expression' for historical reasons.
Examples:
`() => ()<span class="comment">; the empty list
</span> `(1) => (1) <span class="comment">; a 'proper' list containing the digit 1
</span> `(1 . ()) => (1) <span class="comment">; a 'proper' list containing the digit 1
</span> `(1 2 3) => (1 2 3) <span class="comment">; is a 'proper' list of the digits 1 2 3
</span> `(1 2 3 . ()) => (1 2 3) <span class="comment">; is a 'proper' list of the digits 1 2 3
</span> `(1 . 2) => (1 . 2) <span class="comment">; is an 'improper' list of the digits 1 and 2
</span> `(x . y) => (x . y) <span class="comment">; is an 'improper' list of the symbols x and y
</span> `(1 2 . (3 . (4 . ()))) => (1 2 3 4)
A proper list has () as its last element, and it is not normally
shown. An improper list does not have () as it's last element, and
this is shown by preceeding the last element with a dot.
Note: even the code in Sigil is lists. This is a very important
concept to remember, as Sigil is all about building and generating
code using the functions we are going to be defining in the following
chapters.
Comma ',' - evaluate inside of a quote
--------------------------------------
Sometimes you want to quote a list, but also want to include the
values of other symbols inside of it. To perform this action, you use
the comma operator inside of a quoted list.
Examples:
(set `x 1) => 1
x => 1
`(x 2 3) => (x 2 3)
`(,x 2 3) => (1 2 3)
Commaat ',@' - evaluate a list inside of a quote, and splice it
----------------------------------------------------------------
Other times when building code, you want to embed the contents of a
list inside of a quoted list. This is done with the commaat (,@)
operator inside of a quoted list.
Examples:
(set `x `(a b c))
x => (a b c)
`(x 1 2 3) => (x 1 2 3)
`(,x 1 2 3) => ((a b c) 1 2 3)
`(,@x 1 2 3) => (a b c 1 2 3)
`(1 2 3 ,x) => (1 2 3 (a b c))
`(1 2 3 ,@x) => (1 2 3 a b c)
`(1 2 3 . ,@x) => <span class="comment">; error, no splicing after a dot
</span>
NOTE: SYMBOLS AND NUMBERS ARE ALSO KNOWN AS ATOMS.
-------------------------------------------------
| Booleans - () is false, everything else is true |
-------------------------------------------------
As in most languages, Sigil has the idea of booleans, true and false.
In this case, the empty list, () is 'false' and everything else is
'true'. A special symbol 't' is defined to represent truth when
needed, but is not required to be used.
Functions that are meant to return either a true or false value are
known as 'predicates'.
Builtins
========
The following are the builtin commands for Sigil. A builtin is a
function that is available by default in the language and is always
available.
Note: in the Examples, '=>' means 'evaluates to' or 'the value of'.
0) <span class="warning">quote, unquote, unquote-splice - control evaluation</span>
------------------------------------------------------
Rather than use the shorthands described above, you can also call
'quote', 'unquote' and 'unquote-splice' directly to build lists and
control evaluation within a quoted list.
Examples:
1 => 1 <span class="comment">; 'give me the value of' 1
</span> (quote 1) => 1 <span class="comment">; 'give me' 1
</span> x => <span class="comment">; 'give me the value of' x, error, as x has no value
</span> (quote x) => x <span class="comment">; 'give me' x
</span> (quote (1 2 3)) => (1 2 3) <span class="comment">; give me the list of digits 1, 2 and 3
</span>
<span class="comment-delimiter">;; </span><span class="comment">longhand evaluation with ',' and splicing with ',@'
</span> (set (quote x) 1) => 1 <span class="comment">; give x the value 1
</span> (quote ((unquote x) 2 3) => (1 2 3) <span class="comment">; evaluate inside of quoted list as with ','
</span> (quote ((unquote-splice x) 2 3) => <span class="comment">; error, cannot unquote-splice a non-list
</span> (set (quote x) (quote (1 2 3))) => (1 2 3) <span class="comment">; give x a value that is a list
</span> (quote ((quote x) 2 3)) => ((1 2 3) 2 3) <span class="comment">; unquote x with as with ','
</span> (quote ((unquote-splice x) 2 3)) => (1 2 3 2 3) <span class="comment">; splice the list as with ',@'
</span>
Normally you would use the shorthands.
1) <span class="warning">atom - a predicate to test if its argument is an atom</span>
--------------------------------------------------------
Everything in Sigil is either an atom (symbol, number, or ()) or a
list.
Examples:
(atom t) => t
(atom ()) => t
(atom `x) => t
(atom 1) => t
(atom `(1 2 3)) => ()
2) <span class="warning">eq - equality</span>
----------------
Atoms can be tested for equality using 'eq'.
Examples:
(eq t t) => t
(eq () ()) => t
(eq t ()) => ()
(eq `x `x) => t
(eq `x `y) => ()
(eq 1 1) => t
(eq 1 2) => ()
(eq `(1 2 3) `(1 2 3)) => () <span class="comment">; notice! see 'equal', below.
</span>
3) <span class="warning">cons - create a new list cell</span>
--------------------------------
A cons cell is a 2 element cell that has a head slot and an a tail
slot. The 'cons' function allocates one of these cells and assigns
the first argument to the head slot and the second argument to the
tail slot.
Examples:
(cons 1 ()) => (1) <span class="comment">; build a proper list with () at the tail
</span> (cons `x ()) => (x) <span class="comment">; build another proper list
</span> (cons () ()) => (()) <span class="comment">; again, but with () at the head
</span> (cons `x `y) => (x . y) <span class="comment">; notice! an improper list
</span> (cons 1 2) => (1 . 2) <span class="comment">; and again
</span> (cons (1 (cons 2 ()))) => (1 2) <span class="comment">; making a proper list
</span>
4) <span class="warning">car - return the first element of a list</span>
-------------------------------------------
Take a list and return the head slot of its first cell.
Examples:
(car `(1 2 3)) => 1
(car `((1 2 3) 2 3)) => (1 2 3)
(car ()) => ()
(car `x) => <span class="comment">; Error
</span> (car 1) => <span class="comment">; Error
</span>
5) <span class="warning">cdr - return everything but the first element of a list</span>
----------------------------------------------------------
Take a list and return the tail slot of its first cell.
Examples:
(cdr `(1 2 3)) => (2 3)
(cdr `((1 2 3) 2 3)) => (2 3)
(cdr ()) => ()
(cdr `x) => <span class="comment">; Error
</span> (cdr 1) => <span class="comment">; Error
</span>
6) <span class="warning">cond - conditional statement</span>
-------------------------------
Cond is used to make decisions on what statements to execute. It goes
through it's arguments, executing each test, until one of them returns
true (not ()), after which it then executes the statements following
the test and returns the value of the last one. You will often set
't' as the last test in a cond, meaning to always execute that set of
statements if none of the previous tests pass.
Examples:
(<span class="keyword">cond</span> (t 1)) => 1
(<span class="keyword">cond</span> (() 1)) => ()
(<span class="keyword">cond</span> ((t 1) (t 2))) => 1
(<span class="keyword">cond</span> ((() 1) (t 2))) => 2
(<span class="keyword">cond</span> ((() 1) (() 2) (t 3))) => 3
(<span class="keyword">cond</span> ((() 1) (t 2) (t 3))) => 2
(set `x ())
(set `y t)
(<span class="keyword">cond</span>
(x `shouldnt-get-here)
(y `should-get-here)
(t `wont-get-here)) <span class="warning">=> should-get-here</span>
7) <span class="warning">set - assign a symbol a value (variables)</span>
--------------------------------------------
Sometimes it is convenient to create a shortcut to certain values,
known as a variable. 'set' can be used to create or change the values
of symbols in the variable namespace.
Examples:
(set `x 1) => 1 <span class="comment">; set single values
</span> x => 1
(set `x 2) => 2
x => 2
(set `x `(1 2 3)) => (1 2 3)
x => (1 2 3)
(set `x 1 `y 2 `z 3) => 3 <span class="comment">; set multiple values at once
</span>
8) <span class="warning">lambda - create a function</span>
-----------------------------
A function is a set of bound variables and a series of statements,
known as the body, that can be 'called', which assigns values to the
variables and executes the statements of the body sequentially, until
the value of the last evaluated expression is returned.
Examples:
(<span class="keyword">lambda</span> (x) x) => (<span class="keyword">lambda</span> (x) x)
((<span class="keyword">lambda</span> (x) x) 1) => 1 <span class="comment">; call the function immediately
</span> (set `x 1) => 1
((<span class="keyword">lambda</span> (x) (+ x x)) 2) => 4 <span class="comment">; x is bound to 2 during the call
</span> x => 1 <span class="comment">; the value of x was not changed by calling the function
</span> ((<span class="keyword">lambda</span> (x) (set x 2))) <span class="comment">; set x in the function
</span> x => 1 <span class="comment">; the value of x is still unchanged
</span> ((<span class="keyword">lambda</span> (x y) (* x y)) 2 3) => 6 <span class="comment">; x is bound to 2, y is bound to 3
</span> (set `double (<span class="keyword">lambda</span> (x) (+ x x))) => ... <span class="comment">; declare a named function
</span> (double 2) => 4 <span class="comment">; call declared function
</span>
We use the keyword 'lambda' to declare functions because of Lisp's
close ties to what is known as the <span class="string">"Lambda Calculus"</span>, discovered by
Alonzo Church in the 1930's.
9) <span class="warning">alambda - create an anonymous, recursive function</span>
----------------------------------------------------
Exactly the same as to lambda, but binds the variable named by 'self'
to the defined function in its body, allowing for anonymous recursion.
The 'a' in 'alambda' stands for 'anamorphic', a topic which is
discussed later in this book.
<span class="string">"To iterate is human, to recurse divine."</span>
-- L. Peter Deutsch
Recursion is a fundamental concept used for looping, or doing
something more than once in Sigil. To count the number of elements in
a list, one can break the problem into counting the first element of
the list, which is always 1, and adding that to the number of elements
in the rest of the list. This can be done in a function by calling
itself, or recursing, with the rest of the list until the empty list
is found, meaning we are done and can return the computed length by
adding all of the 1's together.
Examples:
((alambda self (l n) <span class="comment">; return the length of a list, recursively
</span> (<span class="keyword">cond</span>
((cdr l) <span class="comment">; if there are still elements in the list
</span> (self (cdr l) (+ 1 n))) <span class="comment">; recurse with the tail of the list,
</span> <span class="comment">; and increment accumulator
</span> (t <span class="comment">; there are no elements left in the list
</span> n))) <span class="comment">; return accumulator
</span> `(a b c) 0) <span class="warning">=> 3 </span>
((alambda self (l) <span class="comment">; return the last element of the list, recursively
</span> (<span class="keyword">cond</span>
((null (cdr l)) <span class="comment">; if the next element is ()
</span> (car l)) <span class="comment">; return the head of the list
</span> (t <span class="comment">; the next element is not ()
</span> (self (cdr l))))) <span class="comment">; recurse down the list
</span> `(1 2 3)) <span class="warning">=> 3</span>
Recursion may be confusing at first. It is highly recommended you
take the time to step through the above examples so you can gain a
solid understanding of recursion and how it works.
10) <span class="warning">apply - call a function with a list of arguments</span>
----------------------------------------------------
Sometimes you want to call a function with a prepared list of
arguments. The reason for this will become more apparent later as we
work through the examples and projects.
Examples:
(apply (<span class="keyword">lambda</span> (x) (+ x x)) `(1)) => 2
(apply (<span class="keyword">lambda</span> (x y z) (+ x y z)) `(1 2 3)) => 6
(apply double `(2)) => 4 <span class="comment">; using previously defined function in 9)
</span>
11) <span class="warning">values - return multiple values from a function</span>
---------------------------------------------------
For when you want to return more than one value from a function.
Notice how the multiple values are printed after evaluating a function
returning them in the listener.
Examples:
(values 1) => 1
(values 1 2) => 1
2
((<span class="keyword">lambda</span> (x) (values x)) 1) => 1
((<span class="keyword">lambda</span> (x y) (values x y)) 1 2) => 1
2
12) <span class="warning">bind - bind multiple values to symbols</span>
------------------------------------------
When a function returns more than one value, you can 'bind' the
returned values to variables and execute the statements in the body
using these bindings.
Examples:
(set `multiple-values (<span class="keyword">lambda</span> (x y) (values x y))) => ...
(bind (a b) (multiple-values 1 2) (cons a b)) => (1 . 2)
13) <span class="warning">define-macro - define a macro</span>
---------------------------------
Macros are functions that return code that is executed immediately
after. This is in contrary to regular functions that can return
anything. Using macros we can build the our language from the
primitives described in this section.
Macros are a powerful tool that give Lisp it's power and are the
reason for its form. There are many examples that follow that use
define-macro, so study them carefully to understand it's use.
14) <span class="warning">+ - addition, sum</span>
---------------------
Mathematical addition, or sum with more than 2 arguments. Also used
to concatenate symbols.
Examples:
(+ 1 2) => 3 <span class="comment">; arithmetical addition of numbers
</span> (+ 1 2 3) => 6 <span class="comment">; sum of multiple numbers
</span> (+ `x `y) => xy <span class="comment">; concatenation of symbols
</span>
15) <span class="warning">- - subtraction, difference</span>
-------------------------------
Mathematical subtraction, or difference with more than 2 arguments.
(- 1 2) => -1 <span class="comment">; arithmetical subtraction
</span> (- 1 2 3) => -4 <span class="comment">; difference of multiple numbers
</span>
16) <span class="warning">* - multiply, product</span>
-------------------------
Mathematical multiply, or product with more than 2 arguments.
(* 1 2) => 2 <span class="comment">; arithmetical multiplication
</span> (* 1 2 3) => 6 <span class="comment">; product of multiple numbers
</span>
17) <span class="warning">/ - divide, quotient</span>
------------------------
Mathematical divide, or quotient with more than 2 arguments.
Examples:
(/ 1 2) => .5 <span class="comment">; arithmetical division
</span> (/ 1 2 3) => 0.1666... <span class="comment">; quotient of multiple numbers
</span>
18) <span class="warning">% - remainder, mod</span>
----------------------
Mathematical remainder, or 'mod'.
Examples:
(% 5 2) => 1 <span class="comment">; 1 is the remainder of dividing 5 by 2
</span>
19) <span class="warning">env - return the current environment</span>
Variables are defined in the 'variable namespace'. env is used to
return this namespace for inspection and modification. If env is
called with an argument, it will set the current 'variable namespace'
to the argument given.
Examples:
(env) => ((t . t) ...) <span class="comment">; return the current environment
</span> (env (env)) => ... <span class="comment">; set the current environment
</span>
20) <span class="warning">fenv - return the current function environment</span>
Functions are defined in the 'function namespace'. fenv is used to
return this namespace for inspection and modification. If fenv is
called with an argument, it will set the current 'variable namespace'
to the argument given.
Examples:
(fenv) => ((set . builtin) (cons . builtin) ...)
(fenv (fenv)) => ... <span class="comment">; set the current function environment
</span>
21) <span class="warning">save - save the current environments</span>
----------------------------------------
The environment where you store your variables and macros can be saved
to local storage in your browser using the 'save' command.
(save) => <span class="comment">; default /core is saved
</span>(save /backup) => <span class="comment">; saved to /backup in local storage
</span>
22) <span class="warning">load - load a core into the current environment</span>
The environment can be loaded from local storage using the 'load' command.
THIS FEATURE IS CURRENTLY NOT IMPLEMENTED.
23) <span class="warning">me - macro expand</span>
---------------------
Expand macros in the code given as an argument. Helpful for
debugging.
Examples:
(<span class="keyword">define-macro</span> cadr (l) `(car (cdr ,l)) <span class="comment">; define the macro cadr
</span> (me (cadr `(1 2 3))) => (car (cdr `(1 2 3))) <span class="comment">; expand it
</span>
24) <span class="warning">eval - evaluate an expression</span>
---------------------------------
Sometimes you have a code in a form that you wish to evaluate. You
can do this by calling eval.
Examples:
`(+ 1 2) => (+ 1 2) <span class="comment">; unevaluated code
</span> (eval `(+ 1 2)) => 3 <span class="comment">; calling eval on it gives the result
</span>
25) <span class="warning">=> - evaluate JavaScript code</span>
---------------------------------
Used to execute JavaScript code that can be built by concatenating symbols.
Examples:
(=> |1 + 1|) => 2
(=> |console.log("Testing")|) => <span class="comment">; prints Testing in the JavaScript console
</span>
This builtin allows for the interaction between Sigil and the
underlying web browser. It is an advanced operation that will be used
to build Eturia as a Lisp Machine from within Sigil itself. Eturia is
written in JavaScript, but the goal of the system is to modify the
JavaScript code as little as possible from outside of it.
26) <span class="warning">split - split an atom</span>
-------------------------
Used to break a symbol atom into a list of symbol pieces. Takes an
optional argument that specifies where to perform the split in the atom.
Examples:
(split `a-long-atom) => (a long atom) <span class="comment">; default: '-'
</span> (split `a/long/atom `/) => (a long atom) <span class="comment">; specify: '/'
</span>
========================================================================
========================================================================
================
|Basic Training|
================
<span class="string">"...an individual's thoughts and actions are
determined by the language..."</span>
-- The Sapir-Whorf Hypothesis
<span class="string">"Lisp is a programmable programming language."</span>
-- John Foderaro
<span class="string">"Talk is cheap. Show me the code."</span>
-- Linus Torvalds
========================================================================
========================================================================
The following exercises build upon the primitive builtins defined
previously and are meant to be typed into the Eturia 'Listener'
console. The 'Examples' can be used as test cases to ensure the
correctness of your inputs.
0) <span class="warning">first, second, third, rest, ... - shortcuts</span>
----------------------------------------------
These first code examples show the most basic of macro, the shortcut.
(<span class="keyword">define-macro</span> first (x)
`(car ,x))
(<span class="keyword">define-macro</span> second (x)
`(car (cdr ,x)))
(<span class="keyword">define-macro</span> third (x)
`(car (cdr (cdr ,x))))
(<span class="keyword">define-macro</span> rest (x)
`(cdr ,x))
(<span class="keyword">define-macro</span> caar (x)
`(car (car ,x)))
(<span class="keyword">define-macro</span> cadr (x) <span class="comment">; same a second
</span> `(car (cdr ,x)))
(<span class="keyword">define-macro</span> cdar (x)
`(cdr (car ,x)))
(<span class="keyword">define-macro</span> cddr (x)
`(cdr (cdr ,x)))
As you can see, the above macros return non-evaluated 'code'. This
'code' is then executed immediately after the macro is called with
arguments, as the following examples show.
Examples:
(first `(1 2 3)) => 1 <span class="comment">; expands to (car `(1 2 3))
</span> (me (first `(1 2 3))) => (car `(1 2 3))
(second `(1 2 3)) => 2 <span class="comment">; expands to (car (cdr `(1 2 3)))
</span> (me (second `(1 2 3))) => (car (cdr `(1 2 3)))
(third `(1 2 3)) => 3 <span class="comment">; expands to (car (cdr (cdr `(1 2 3))))
</span> (me (third `(1 2 3))) => (car (cdr (cdr `(1 2 3))))
(rest `(1 2 3)) => (2 3) <span class="comment">; expands to (cdr `(1 2 3))
</span> (me (rest `(1 2 3))) => (cdr `(1 2 3))
(caar `((1 2 3) 2 3)) => 1
(cdar `((1 2 3) 2 3)) => (2 3)
(cadr `(1 (1 2 3) 2 3)) => (1 2 3)
(cddr `(1 2 3)) => (3)
The final 4 shortcuts above show how the names 'car' and 'cdr' can be
combined into terse, longer combinations to allow for selection into
more complex list structures.
Spend some time to fully understand what is happening here when these
macros are defined and run.
Exercise: write 'fourth', and 'fifth'.
(fourth `(1 2 3 4 5 6)) => 4
(fifth `(1 2 3 4 5 6)) => 5
1) <span class="warning">if - tradional conditional</span>
-----------------------------
cond is a general purpose conditional, but sometimes it can be clearer
to use more a traditional conditional construct known as 'if'. It
takes a test, evaluates it and if it is true, runs the second
statement, and when not, it runs the second statement.
(<span class="keyword">define-macro</span> if (test true false)
`(<span class="keyword">cond</span>
(,test ,true) <span class="comment">; check test, evaulate true if not ()
</span> (t ,false))) <span class="comment">; else, evaluate false
</span>
Examples:
(<span class="keyword">if</span> t 1 2) => 1
(<span class="keyword">if</span> () 1 2) => 2
(<span class="keyword">if</span> (eq t t) 1 2) => 1
(<span class="keyword">if</span> (eq t ()) 1 2) => 2
2) <span class="warning">when - single branch conditional</span>
-----------------------------------
Sometimes you don't need both branches of an if statement and just
want to perform and action when the test is true. This is when you
use when. This macro makes use of <span class="type">&body</span> in the argument list, which
means to take all of the arguments following as a list and bind them
to the variable name following <span class="type">&body</span> in the argument list.
(<span class="keyword">define-macro</span> when (test <span class="type">&body</span> body)
`(<span class="keyword">cond</span>
(,test ,@body)))
Examples:
(<span class="keyword">when</span> t 1) => 1
(<span class="keyword">when</span> () 1) => ()
(<span class="keyword">when</span> (eq t t) 1) => 1
(<span class="keyword">when</span> (eq t ()) 1) => ()
3) <span class="warning">reverse - reverse a list</span>
---------------------------
Reverse a list by building a new list in opposite order using
cons'ing. Building a list this way is an important idiom to
understand, and thankfully this function is quite simple because the
lists built using cons'ing are in 'reverse' order, that is, items are
added to the front rather than the back of the list.
(<span class="keyword">define-macro</span> reverse (l)
`((alambda self (l2 a) <span class="comment">; an anonymous function
</span> (<span class="keyword">if</span> l2 <span class="comment">; if l2 is not null
</span> (self (cdr l2) (cons (car l2) a)) <span class="comment">; recurse
</span> a)) <span class="comment">; else return a, the accumlator
</span> ,l ())) <span class="comment">; call the anonymous function immediately
</span>
Examples:
(reverse `(1 2 3)) => (3 2 1)
(reverse `((1 2 3) a b c)) => (c b a (1 2 3))
Exercises:
1. Will reverse work with improper lists? Why not?
4) <span class="warning">map - build a list by running a function over another list</span>
-------------------------------------------------------------