source: project/wiki/eggref/5/ck-macros @ 37407

Last change on this file since 37407 was 37407, checked in by John Croisant, 3 years ago

Update ck-macros wiki for version 0.3.0.

File size: 67.4 KB
Line 
1== ck-macros
2
3Composable Scheme macros based on the CK abstract machine.
4
5This egg is based on the CK-macro system described in
6"[[http://okmij.org/ftp/Scheme/macros.html#ck-macros|Applicative syntax-rules: macros that compose better]]"
7by Oleg Kiselyov.
8This egg provides an enhanced version of the core {{ck}} macro,
9many useful (and some not-so-useful) predefined CK-macros,
10the {{ck-wrapper}} procedure, and many wrappers of R5RS procedures.
11
12If you create a useful or interesting general-purpose CK-macro,
13or an improvement to an existing CK-macro,
14please contact the maintainer (John) so your contribution can be added to the egg.
15All source code (including contributions) is public domain.
16
17; Project / Source Code Repository: [[https://gitlab.com/jcroisant/ck-macros]]
18; Maintainer: [[/users/john-croisant|John Croisant]]
19; Based on work by: Oleg Kiselyov
20; License: Released to the public domain. See [[http://unlicense.org]]
21
22
23'''Table of Contents'''
24[[toc:]]
25
26
27=== Version History
28
29; 0.3.0 (2019-03-17) : Enhanced the core {{ck}} macro to support quasiquotation. Added some new portable CK-macros. Clarified license.
30; 0.2.0 (2019-02-28) : Ported to CHICKEN 5. Added {{ck-wrapper}} and many R5RS wrappers. Added some new portable CK-macros. Breaking changes to {{c-apply}}. Renamed some CK-macros.
31; 0.1.1 (2016-02-07) : Fixed {{c-append}} and {{c-vector-append}} failing when given one argument.
32; 0.1.0 (2016-02-06) : Initial release. Includes version 1.1 (April 2011) of the core {{ck}} macro. Includes many CK-macros.
33
34For more information about what changed in each version,
35see the [[https://gitlab.com/jcroisant/ck-macros/blob/master/CHANGELOG.md|CHANGELOG]].
36
37
38=== What are CK-macros?
39
40CK-macros are Scheme macros written to be compatible with with the core {{ck}} macro.
41
42The core {{ck}} macro is a {{syntax-rules}} macro which implements the CK abstract machine.
43The CK abstract machine is a theoretical model of computation,
44described in the paper "Control Operators, the SECD-Machine, and the Lambda-Calculus"
45by Matthias Felleisen and Daniel P. Friedman.
46But, you don't need to read or understand the paper in order to create or use CK-macros!
47
48Basically, a CK-macro leverages the core {{ck}} macro
49to recursively expand the CK-macros's arguments first,
50before the CK-macro itself is expanded.
51This gives you more control over the macro expansion process,
52allowing you to easily combine simple reusable macros to form more complex macros.
53
54This is very similar to the way Scheme allows you to easily combine simple resuable functions
55({{map}}, {{fold}}, {{cons}}, etc.) to create more complex functions.
56In fact, many useful Scheme functions can be translated to CK-macros,
57allowing you to portably achieve the same effect at macro-expansion time.
58You can even implement "higher-ordered macros" which take a macro as an argument.
59See {{c-map1}} and {{c-compose}} for examples of higher-ordered macros.
60
61CK-macros are not as flexibile, powerful, or efficient as
62CHICKEN's [[/man/5/Module (chicken syntax)|explicit and implicit renaming macros]],
63but CK-macros are much more portable.
64
65* The [[#ck|core {{ck}} macro]] and everything in the
66  [[#portable-ck-macros|Portable CK-Macros]] section
67  are implemented using only standard R5RS features, such as {{syntax-rules}}.
68  This means they will work on any implementation of R5RS or later.
69
70* The [[#ck-wrapper|{{ck-wrapper}} procedure]] and everything in the
71  [[#non-portable-r5rs-wrappers|Non-portable R5RS Wrappers]] section
72  are implemented using
73  [[/man/5/Module (chicken syntax)#explicit-renaming-macros|{{er-macro-transformer}}]],
74  which is not standard R5RS but is available in many Scheme implementations.
75
76
77=== How to write CK-macros
78
79(Note: If you do not require strict R5RS portability,
80the easiest way to create a CK-macro is with [[#ck-wrapper|{{ck-wrapper}}]].)
81
82Here is a basic template for portable CK-macros:
83
84<enscript highlight="scheme">
85(define-syntax c-foo
86  (syntax-rules (quote)
87    ((c-foo s 'input1 'input2 ...)
88     (ck s output))))
89</enscript>
90
91A CK-macro is just a normal macro that expands to a call to the core {{ck}} macro.
92To be portable, CK-macros are usually written using {{syntax-rules}}.
93But, you can write CK-macros using other macro systems,
94such as CHICKEN's [[/manual/Macros|explicit and implicit renaming macros]],
95as long your macro eventually expands into a call to the core {{ck}} macro.
96
97By convention, the names of CK-macros usually start with "c-",
98to distinguish them from non-CK macros or procedures with similar names.
99But, this naming convention is not required.
100
101CK-macros treat quoting specially, so you should have {{quote}} in the list of literal identifiers (the first argument to {{syntax-rules}}).
102You can also have other literal identifiers if needed.
103
104Every CK-macro's first argument must be the stack, usually called {{s}}.
105The stack is used internally by the core {{ck}} macro while recursively expanding macro arguments.
106Your CK-macro should not touch the stack, only pass it through to the core {{ck}} macro.
107
108Each {{'input}} is an argument passed to your macro.
109Your macro can have any number of input arguments, and they can be named whatever you want.
110They can also be lists or patterns, allowing you to destructure the arguments,
111as is often done with {{syntax-rules}} macros.
112
113The core {{ck}} macro expands the input arguments ahead of time,
114so the arguments will always be quoted values by the time your macro is expanded.
115Usually CK-macros are defined with their input arguments quoted (as above),
116so that you can easily destructure the input to use in your macro.
117You may recall that {{'a}} is translated by the reader to {{(quote a)}}.
118So, the above example is exactly the same as:
119
120<enscript highlight="scheme">
121(define-syntax c-foo
122  (syntax-rules (quote)
123    ((c-foo s (quote input1) (quote input2) ...)
124     (ck s output))))
125</enscript>
126
127When written in this way, it is easier to see that {{input1}} and {{input2}}
128are merely placeholders in the {{syntax-rules}} pattern.
129(This is also why you must tell {{syntax-rules}} that {{quote}} is a literal identifier.
130Otherwise, {{syntax-rules}} would treat {{quote}} as a placeholder, too.)
131
132Your macro should transform the {{input}}s in some way to produce the {{output}},
133which is passed to the core {{ck}} macro.
134The {{output}} must be either:
135
136* A quoted value, such as {{'a}}, {{'(+ 1 2)}}, {{'"foo"}}, {{'42}}, or {{'#t}}.
137* Or, an unquoted call to a CK-macro '''without the s argument''', such as {{(c-cons '+ '(1 2))}}.
138  Nested calls are allowed, such as {{(c-cons '+ (c-list '1 '2))}}.
139
140Quoting is how the core {{ck}} macro knows the difference between a value and a CK-macro call.
141Therefore, '''all values must be quoted''',
142even values which normally do not need to be quoted in Scheme code,
143such as strings, numbers, and booleans.
144
145Eventually, your CK-macro must expand into a call to the core {{ck}} macro
146with a quoted value.
147We say that the macro "yields" this quoted value.
148The quoted value is either used as an argument to another CK-macro,
149or if your CK-macro is the outer-most CK-macro call,
150then the core {{ck}} macro expands into the '''unquoted value'''.
151
152So, if your CK-macro yields the quoted value {{'(+ 1 2)}},
153and it is the outer-most CK-macro (not an argument to another CK-macro),
154the core {{ck}} macro will expand to the unquoted expression {{(+ 1 2)}},
155which would later be evaluated to the number 3.
156(If you want to yield a quoted form as the final result,
157use {{c-quote}} as the outer-most CK-macro.)
158
159See [[http://okmij.org/ftp/Scheme/macros.html#ck-macros|the original article]]
160or [[https://gitlab.com/jcroisant/ck-macros/blob/master/lib/portable.scm|the source code]]
161for many examples of CK-macros.
162
163
164=== Combining CK and non-CK macros
165
166The arguments to a CK-macro must either be a quoted value or a call to a CK-macro
167(i.e. a macro that expands to a call to the core {{ck}} macro).
168Therefore, most non-CK macros and special forms cannot be used as arguments to a CK-macro.
169
170Some non-CK macros can be used in a way that expands into a user-provided expression.
171It is therefore possible for these non-CK macros to be used as arguments to CK-macros,
172as long as they eventually expand into a call to the core {{ck}} macro.
173
174It is possible to write a non-CK macro which invokes a CK-macro via the core {{ck}} macro.
175For example, if you are writing a macro for other people to use,
176you can create a convenience macro, like so:
177
178<enscript highlight="scheme">
179(define-syntax foo
180  (syntax-rules ()
181    ((foo arg1 arg2 arg3)
182     (ck () (c-foo 'arg1 'arg2 'arg3)))))
183</enscript>
184
185Also, it is possible for a CK-macro to expand into a call to a non-CK macro
186as its final result, or as part of the body of its final result.
187For example:
188
189<enscript highlight="scheme">
190(ck () (c-list 'when (c-list '< '1 '2) (c-list 'print '"Yay!")))
191;;; Expands to the expression (when (< 1 2) (print "Yay!")).
192</enscript>
193
194
195=== Partial application
196
197Many CK-macros, such as {{c-compare}} and {{c-map1}}, take one or more operations as an argument.
198This is denoted with {{'(OP ...)}} in the CK-macro's signature.
199For example, {{c-map1}} takes an operation which it applies to every element of the list:
200
201<enscript highlight="scheme">
202(ck () (c-quote (c-map1 '(c-vector) '(2 3 4))))
203;; ==> '(#(2) #(3) #(4))
204
205;; Equivalent to:
206(ck () (c-quote (c-list (c-vector '2)
207                        (c-vector '3)
208                        (c-vector '4))))
209</enscript>
210
211All CK-macros which take an operation allow '''partial application''',
212by providing initial arguments that should be used when performing the operation:
213
214<enscript highlight="scheme">
215(ck () (c-quote (c-map1 '(c-vector 'x 'y) '(2 3 4))))
216;; ==> '(#(x y 2) #(x y 3) #(x y 4))
217
218;; Equivalent to:
219(ck () (c-quote (c-list (c-vector 'x 'y '2)
220                        (c-vector 'x 'y '3)
221                        (c-vector 'x 'y '4))))
222</enscript>
223
224You can even build up complex operations
225by partially applying {{c-compose}} or {{c-rcompose}},
226even with partially applied operations as the initial arguments!
227
228<enscript highlight="scheme">
229(ck () (c-quote (c-map1 '(c-rcompose '((c-* '10)
230                                       (c-number->string)
231                                       (c-string-append '"foo")
232                                       (c-string->symbol)))
233                        '(1 2 3))))
234;; ==> '(foo10 foo20 foo30)
235</enscript>
236
237
238=== Quasiquotation
239
240In '''version 0.3.0 and later''', the core {{ck}} macro supports quasiquotation.
241Internally, {{(quasiquote x)}} (also written as {{`x}})
242is converted into {{(c-quasiquote 'x)}},
243a call to the {{c-quasiquote}} CK-macro, which handles unquoting.
244
245Quasiquotation can be used as the argument to the core {{ck}} macro itself,
246and/or in arguments to CK-macros.
247This is useful for assembling mostly-literal forms, lists, and vectors:
248
249<enscript highlight="scheme">
250(ck () `(define (foo) (list ,@(c-list '1 '2) ,(c-vector '3))))
251;; ==> (define (foo) (list 1 2 #(3)))
252
253(ck () (c-vector-reverse `#(1 ,@(c-list '2 '3))))
254;; ==> #(3 2 1)
255</enscript>
256
257
258=== Debugging
259
260CK-macros utilize the Scheme macro system in unusual ways,
261so they are sometimes more difficult to debug than typical Scheme code.
262
263The most common error message when using CK-macros is "no rule matches form".
264This usually indicates one of two problems:
265
266* If the error message shows a call to {{ck}}, you are probably missing a quote.
267* If the error message shows a call to a CK-macro like {{c-cons}},
268  you probably passed the wrong number or type of arguments.
269
270==== Missing quote
271
272As explained in the section [[#how-to-write-ck-macros|How to write CK-macros]],
273all values must be quoted,
274even values which normally do not need to be quoted in Scheme code,
275such as strings, numbers, and booleans.
276
277For example, the code {{(ck () (c-not #t))}} will result in an error like this:
278
279 Syntax error: no rule matches form
280 
281         (ck123 (((c-not))) #t)
282
283In the error message above, {{ck123}} is the core {{ck}} macro.
284The Scheme macro system has appended a unique number for macro hygiene.
285The number will vary, and is usually not important to pay attention to.
286
287Because this error message shows a call to {{ck}},
288we know it probably indicates a missing quote.
289Indeed, the solution is to quote the {{#t}}, like this: {{(ck () (c-not '#t))}}
290
291Sometimes the error is not so obvious, and you need to read the stack
292to find clues about what the problem is and where in the code it happened.
293
294
295==== Reading error messages
296
297As explained in the section [[#how-to-write-ck-macros|How to write CK-macros]],
298the first argument to the core {{ck}} macro is always the stack.
299The stack is a list of pending operations and their arguments.
300The first item in the stack is the most recent (inner-most) pending operation,
301which will be resumed once the current operation is complete.
302The last item in the stack is the oldest (outer-most) pending operation.
303
304You can use this like a "stack trace" to locate where in the code an error occurred.
305Consider the following code, which has a mistake somewhere:
306
307<enscript highlight="scheme">
308(ck () (x 'x1
309          'x2
310          (y (c-cons 'y1 'y2)
311             (z 'z1
312                z2
313                'z3)
314             'y3
315             (c-list 'y4))))
316</enscript>
317
318When compiled, we see an error like this:
319
320 Syntax error: no rule matches form
321 
322         (ck67 (((z (quote65 z1)) (quote z3)) ((y (quote56 (y1 . y2))) (quote y3) (c-list (quote y4))) ((x (quote30 x1) (quote33 x2)))) z2)
323
324That looks pretty scary, but it's easier to understand if we reformat it a little:
325
326<enscript highlight="scheme">
327(ck (((z 'z1) 'z3)
328     ((y '(y1 . y2)) 'y3 (c-list 'y4))
329     ((x 'x1 'x2)))
330    z2)
331</enscript>
332
333The first place to look is at the bottom, the last argument to {{ck}}.
334That is the expression which is currently being evaluated,
335and therefore is the immediate cause of the error: we forgot to quote {{z2}}.
336
337In this case, we only use the expression {{z2}} in one place,
338so it is easy to locate exactly where the problem is in our code.
339But it's not always possible to tell where the error occurred
340just by looking at what argument is currently being evaluated.
341Sometimes you need to look at the stack, which is the first argument to {{ck}}.
342
343In this example we know that the error occurred while evaluating arguments to {{z}},
344because that is at the top of the stack.
345We know the value {{'z1}} has already been evaluated
346because it is inside the list with {{z}}.
347The expression {{'z3}} is outside the list, still waiting to be evaluated,
348after we finish evaluating the current argument.
349
350Moving down one level of the stack, we can see that before calling {{z}},
351we were evaluating arguments to {{y}}.
352The value {{'(y1 . y2)}} is inside the list with {{y}},
353so we know it has already been evaluated;
354it came from the expression {{(c-cons 'y1 'y2)}}.
355The expressions {{'y3}} and {{(c-list 'y4)}} are outside the list,
356waiting to be evaluated after we finish evaluating the call to {{z}}.
357
358And moving one more level down the stack, we were evaluating arguments to {{x}}.
359The values {{'x1}} and {{'x2}} have already been evaluated,
360and there are no expressions waiting to be evaluated.
361The final argument in our call to {{x}} would be the result of the call to {{y}},
362which is currently in the process of being evaluated.
363
364
365==== Errors inside CK-macro calls
366
367Sometimes a "no rule matches form" error will occur
368while evaluating a call to some CK-macro like {{c-cons}},
369not a call to the core {{ck}} macro.
370This often indicates that the wrong number or type of arguments
371were passed to the CK-macro:
372
373<enscript highlight="scheme">
374(ck () (c-quote (c-list '1 (c-cons '2 '3 '4) '5)))
375</enscript>
376
377 Syntax error: no rule matches form
378 
379         (c-cons (((c-list (quote36 1)) (quote 5)) ((c-quote))) (quote45 2) (quote48 3) (quote51 4))
380
381Notice that the error shows a call to {{c-cons}},
382not {{ck}} like it did in the examples above.
383That indicates that each of the arguments to {{c-cons}} was evaluated with no errors,
384but there is some problem with the call to {{c-cons}} itself.
385
386Like before, we can reformat the error output to make it easier to understand:
387
388<enscript highlight="scheme">
389(c-cons (((c-list '1) '5)
390         ((c-quote)))
391        '2
392        '3
393        '4)
394</enscript>
395
396We can see that the error occurred while evaluating a call to {{c-cons}}
397with three arguments: {{'2}}, {{'3}}, and {{'4}}.
398The problem is that we passed too many arguments to {{c-cons}}.
399
400Also, because the first argument to every CK-macro is the stack,
401we can read the stack to see where in the code the error happened.
402We can see that, before we started evaluating {{c-cons}},
403we were evaluating arguments to {{c-list}}.
404And before that, we were evaluating {{c-quote}}.
405
406The error can also occur if you pass the wrong type of argument:
407
408<enscript highlight="scheme">
409(ck () (c-quote (c-vector->list '(1 2 3))))
410</enscript>
411
412 Syntax error: no rule matches form
413 
414         (c-vector->list (((c-quote))) (quote36 (1 2 3)))
415
416In this example, {{c-vector->list}} expects to be passed a vector,
417but we passed it a list.
418
419
420=== Known issues and limitations
421
422==== Slow compilation
423
424CK-macros are pretty slow to compile,
425because the computation is done at compile time,
426using ''very'' deeply recursive macro expansions.
427
428Non-portable wrappers created with [[#ck-wrapper|{{ck-wrapper}}]]
429are probably somewhat faster than the portable CK-macros created with {{syntax-rules}}.
430But this library prioritizes portability over efficiency,
431so CK-macros are only implemented as wrappers if it is ''impossible''
432to implement them using {{syntax-rules}}.
433
434You could likely improve compilation speed in your own code by
435redefining various CK-macros using {{ck-wrapper}}.
436
437
438==== Pitfalls of c-sym-eq?
439
440{{c-sym-eq?}} has some strange and unexpected behaviors
441because of the way it uses {{let-syntax}}.
442
443* The behavior of {{c-sym-eq?}} is undefined and non-portable
444  when comparing anything except symbols.
445
446* You should not use {{c-sym-eq?}} in any code that expands
447  into a definition (of a variable, procedure, etc.),
448  because that definition will not be visible from outside.
449  This is because definitions that occur within the body of {{let-syntax}}
450  are internal definitions, not global definitions.
451
452For example, this code will not work as expected:
453
454 (ck () (c-list 'define 'x (c-sym-eq? 'a 'a)))
455
456You might expect it to expand to {{(define x #t)}},
457defining a global variable {{x}} with the value {{#t}}.
458But even though {{c-sym-eq?}} seems to be used "inside" the definition,
459the core {{ck}} macro turns things "inside out"
460to eagerly expand macro arguments first.
461So, the definition will actually appear inside of a {{let-syntax}},
462and {{x}} will not be visible from outside.
463
464These pitfalls also affect other macros that use {{c-sym-eq?}} directly or indirectly:
465
466* {{c-sym-equal?}}
467* {{c-member}} with the default comparison operator
468* {{c-assoc}} with the default comparison operator
469* {{c-alist-delete}} with the default comparison operator
470
471It is believed to be impossible to fix {{c-sym-eq?}} in a portable way,
472so it is recommended that you avoid using it or {{c-sym-equal?}} if possible.
473If you do not require strict R5RS portability,
474you should use the non-portable wrappers {{c-eq?}} and {{c-equal?}} instead.
475
476
477=== ck
478
479<syntax>(ck s 'VAL)</syntax>
480<syntax>(ck s `VAL)</syntax>
481<syntax>(ck s (OP ...))</syntax>
482
483This is the core {{ck}} macro, which implements the CK abstract machine.
484In '''version 0.3.0 and later''', this macro has been enhanced to support
485[[#quasiquotation|quasiquotation]].
486
487This macro's public interface has three shapes:
488with a quoted value, with a quasiquoted value, and with a CK-macro call.
489
490; s : The stack, used internally by this macro. When initially invoking this macro, {{s}} should be the empty list, e.g. {{(ck () (c-cons '+ '(1 2)))}}.
491; 'VAL : A quoted value. Can be a quoted list, symbol, or other literal value. The quote is necessary, even for literal values like strings, numbers, and booleans.
492; `VAL : A [[#quasiquotation|quasiquoted]] value. This is syntactic sugar for {{(c-quasiquote 'VAL)}}.
493; (OP ...) : A CK-macro call '''without the s argument''', such as {{(c-cons '+ '(1 2))}}.
494Nested calls are allowed, such as {{(c-cons '+ (c-list '1 '2))}}.
495
496
497=== ck-wrapper
498
499<procedure>(ck-wrapper proc)  →  macro transformer</procedure>
500
501Wrap a procedure in a CK-macro, returning a macro transformer
502that can be used with {{define-syntax}} or {{let-syntax}}.
503
504{{ck-wrapper}} requires '''version 0.2.0 or later''' of the ck-macros egg.
505It is considered '''non-portable''' because it depends on
506[[/man/5/Module (chicken syntax)#explicit-renaming-macros|{{er-macro-transformer}}]],
507which is not defined in standard R5RS.
508However, it should work on any Scheme which defines
509{{er-macro-transformer}} in the usual way.
510
511You can wrap any other expression that evaluates to a procedure,
512such as a procedure name, a lambda form, a "let over lambda" expression, etc.
513The expression will be evaluated once,
514when the call to {{ck-wrapper}} is evaluated.
515Therefore, the procedure you are wrapping must be available
516in the syntax environment at macro expansion time.
517(In other words, you should use
518[[/man/5/Module (chicken syntax)#define-for-syntax|{{define-for-syntax}}]],
519[[/man/5/Modules#import-for-syntax|{{import-for-syntax}}]], etc.)
520
521Examples:
522
523<enscript highlight="scheme">
524;;; Import iota from SRFI 1.
525(cond-expand
526  (chicken-4
527   (use-for-syntax (only srfi-1 iota)))
528  (chicken-5
529   (import-for-syntax (only (srfi 1) iota))))
530
531(define-syntax c-iota (ck-wrapper iota))
532
533(ck () (c-quote (c-iota '5)))
534;; ==> '(0 1 2 3 4)
535
536;;; A helper procedure that returns a closure.
537(define-for-syntax (make-adder n)
538  (lambda (x) (+ x n)))
539
540;;; Temporarily define a ck-wrapper around a closure.
541(let-syntax ((c-add2 (ck-wrapper (make-adder 2))))
542  ;; Map c-add2 over the result of c-iota.
543  (ck () (c-quote (c-map1 '(c-add2) (c-iota '5)))))
544;; ==> '(2 3 4 5 6)
545</enscript>
546
547
548=== Portable CK-Macros
549
550The CK-macros in this section are defined using only standard R5RS features,
551such as {{syntax-rules}} and {{let-syntax}}.
552So, these CK-macros will work on any implementation of R5RS or later.
553
554
555==== General
556
557<syntax>(c-quote X)  →  'X</syntax>
558
559Adds an extra level of quotation to the argument.
560This is useful for macros that should expand to a quoted value.
561
562<enscript highlight="scheme">
563;; Without c-quote
564(ck () (c-cons '+ '(1 2)))
565;; Expands to (+ 1 2), which evaluates to the number 3.
566
567;; With c-quote
568(ck () (c-quote (c-cons '+ '(1 2))))
569;; Expands to '(+ 1 2), a quoted list.
570</enscript>
571
572
573<syntax>(c-quasiquote X)  →  result</syntax>
574
575Implements [[#quasiquotation|quasiquotation]].
576Added in '''version 0.3.0'''.
577
578The core {{ck}} macro has special support for
579converting {{(quasiquote x)}} (also written as {{`x}})
580into {{(c-quasiquote 'x)}}.
581Within a call to {{c-quasiquote}}, you can use
582{{(unquote y)}} (also written as {{,y}})
583and {{(unquote-splicing z)}} (also written as {{,@z}}).
584They are supported inside vectors as well as inside pairs/lists.
585
586<enscript highlight="scheme">
587;; These expressions are exactly equivalent:
588(ck () `(define (foo) (list ,@(c-list '1 '2) ,(c-vector '3))))
589(ck () (c-quasiquote '(define (foo) (list ,@(c-list '1 '2) ,(c-vector '3)))))
590;; ==> (define (foo) (list 1 2 #(3)))
591
592(ck () `#(1 ,@(c-list '2 '3)))
593(ck () (c-quasiquote '#(1 ,@(c-list '2 '3))))
594;; ==> #(1 2 3)
595</enscript>
596
597
598<syntax>(c-eval '(OP ...))  →  result</syntax>
599
600Takes a quoted operation and unquotes it,
601allowing the CK machine to expand it.
602Analogous to {{eval}}.
603
604<enscript highlight="scheme">
605(ck () (c-quote (c-eval '(c-cons 'a 'b))))
606;; ==> '(a . b)
607</enscript>
608
609
610<syntax>(c-call '(OP ...) X ...)  →  result</syntax>
611
612Like {{c-eval}}, but adds the given arguments on to the end of the operation.
613Analogous to a lambda call in normal Scheme code.
614
615<enscript highlight="scheme">
616(ck () (c-quote (c-call '(c-cons 'a) 'b)))
617;; ==> '(a . b)
618</enscript>
619
620
621<syntax>(c-apply '(OP ...) X ... '(Y ...))  →  result</syntax>
622
623Like {{c-call}}, but the last argument is a list of more arguments.
624'''Prior to version 0.2.0''', the arguments in the final list required an extra level of quoting.
625Analogous to {{apply}}.
626
627<enscript highlight="scheme">
628(ck () (c-quote (c-apply '(c-list) 'a '(b) '(c d))))
629;; ==> '(a (b) c d)
630</enscript>
631
632
633<syntax>(c-compose '((OP-N ...) ... (OP-1 ...)) X ...)  →  result</syntax>
634
635Compose one or more CK-macros and apply them to the arguments.
636Calls the right-most {{OP}} with the arguments {{X ...}},
637then calls the next-right-most {{OP}} with that result, and so on:
638
639 (OP-N ... (OP-2 ... (OP-1 ... X ...)))
640
641{{OP-1}} must accept all the {{X}}s as arguments,
642and the other {{OP}}s must each accept one argument (the result of the previous operation).
643See also {{c-rcompose}}, which is more efficient.
644Added in '''version 0.2.0'''
645
646
647<enscript highlight="scheme">
648(ck () (c-compose '((c-car) (c-cdr)) '(1 2 3)))
649;; ==> 2
650
651;;; Map over a list of lists to see which are not empty.
652(ck () (c-quote (c-map1 '(c-compose '((c-not) (c-null?)))
653                        '((1) () (2 3)))))
654;; ==> '(#t #f #t)
655</enscript>
656
657
658<syntax>(c-rcompose '((OP-1 ...) ... (OP-N ...)) X ...)  →  result</syntax>
659
660Like {{c-compose}}, but the operations are called in the reverse order (left to right).
661This is more efficient than {{c-compose}}.
662Added in '''version 0.2.0'''
663
664
665<syntax>(c-flip '(OP ...) X Y)  →  (OP ... Y X)</syntax>
666
667Calls the operation with the two extra arguments in reverse order.
668Added in '''version 0.3.0'''.
669
670
671<syntax>(c-branch '((OP ...) ...) X ...)  →  '(result ...)</syntax>
672
673Yields a list of the results of calling each operation with the {{X}}s.
674Added in '''version 0.3.0'''.
675
676<enscript highlight="scheme">
677(ck () (c-quote
678        (c-branch '((c-list)
679                    (c-cons)
680                    (c-* '10))
681                  '3 '5)))
682;; '((3 5)
683;;   (3 . 5)
684;;   150)
685</enscript>
686
687
688<syntax>(c-identity X)  →  X</syntax>
689
690Simply yields the value as given.
691Sometimes useful for higher-order macros like {{c-filter}}.
692
693<enscript highlight="scheme">
694(ck () (c-quote (c-identity 'a)))
695;; ==> 'a
696</enscript>
697
698
699<syntax>(c-constantly X Y ...)  →  X</syntax>
700
701Always yields {{X}}, regardless of the other arguments.
702May be useful for some higher-order macros.
703Added in '''version 0.3.0'''.
704
705
706==== CK-macro builders
707
708<syntax>(c-make-rules '(L ...) '(P X) ...)  →  '(syntax-rules ...)</syntax>
709
710Build a CK-macro based on syntax-rules.
711Added in '''version 0.3.0'''.
712
713Given a list of zero or more literal symbols,
714and one or more pattern/expression lists,
715yields a syntax-rules form for a CK-macro with the following behavior:
716
717* Given argument(s) that match any pattern {{P}}, yields the value of
718  the associated expression {{X}}, which may use identifiers from {{P}}.
719  Fails if no pattern matches.
720
721Each pattern {{P}} is a list of zero or more sub-patterns,
722which will be matched (as with syntax-rules)
723against the already-evaluated and quoted arguments given to the new CK-macro.
724Alternatively, {{P}} may be an identifier which will capture all arguments as a list.
725
726Each expression {{X}} is a single CK-macro expression or quoted value.
727Identifiers from the pattern can be used in the expression, as with syntax-rules.
728
729Symbols in the literals list {{(L ...)}}
730will be treated as literal identifiers in patterns.
731Additionally, {{quote}} is always treated as a literal identifier.
732
733Caveats:
734
735* Using {{...}} in a pattern or expression may not work portably
736  with all Scheme systems.
737
738* Symbols begining with {{%ck:}} are reserved for internal use and
739  must not appear in any {{L}}, {{P}}, or {{X}}.
740
741<enscript highlight="scheme">
742(ck () `(define-syntax c-flip-flop
743          ,(c-make-rules '(flip flop)
744            '(('flip 'x 'y)
745              (c-list 'y 'x))
746            '(('flop 'x 'y)
747              '#f))))
748
749;; The above is basically equivalent to:
750;; (define-syntax c-flip-flop
751;;   (syntax-rules (flip flop quote)
752;;     ((_ s 'flip 'x 'y)
753;;      (ck s (c-list 'y 'x)))
754;;     ((_ s 'flop 'x 'y)
755;;      (ck s '#f))))
756
757(ck () (c-quote (c-flip-flop 'flip '1 '2)))
758;; ==> '(1 2)
759
760(ck () (c-quote (c-flip-flop 'flop '1 '2)))
761;; ==> #f
762</enscript>
763
764
765<syntax>(c-make-next '(X1 X2 ...))  →  '(syntax-rules ...)</syntax>
766
767Build a CK-macro that yields the next item in a sequence.
768Added in '''version 0.3.0'''.
769
770Given a list of unique items, yields a syntax-rules form for a CK-macro
771with the following behavior:
772
773* Given an item in the list, yields the item following it.
774  Yields {{'#f}} if given the final item or an item not in the list.
775
776E.g. with a list of increasing integers, the CK-macro behaves like {{c-dadd1}}.
777With a list of decreasing integers, it behaves like {{c-dsub1}}.
778
779The list must have at least two items, with no duplicates.
780The items should be literal constants: booleans, numbers, strings, characters;
781or (possibly nested) pairs, lists, or vectors of those things.
782Symbols are allowed but the result may not be what you expect
783because they are treated as identifiers in the patterns.
784
785Be advised that compilation can be very slow if there are many items
786because it generates a syntax-rules with many branches.
787
788<enscript highlight="scheme">
789(ck () `(define-syntax c-next-square
790          ,(c-make-next '(0 1 4 9 16))))
791
792;; The above is basically equivalent to:
793;; (define-syntax c-next-square
794;;  (syntax-rules (quote)
795;;    ((_ s '0) (ck s '1))
796;;    ((_ s '1) (ck s '4))
797;;    ((_ s '4) (ck s '9))
798;;    ((_ s '9) (ck s '16))
799;;    ((_ s otherwise) (ck s '#f))))
800
801(ck () (c-next-square '4))
802;; ==> '9
803(ck () (c-next-square '16))
804;; ==> '#f
805</enscript>
806
807
808==== Boolean Logic
809
810<syntax>(c-not X)  →  '#t or '#f</syntax>
811
812Yields {{'#t}} if the argument is {{'#f}}, otherwise yields {{'#f}}.
813Analogous to {{not}}.
814
815
816<syntax>(c-true X ...)  →  '#t</syntax>
817
818Always yields {{'#t}}, regardless of its arguments.
819May be useful for some higher-order macros.
820Equivalent to {{(c-constantly '#t X ...)}}.
821Added in '''version 0.2.0'''.
822
823<enscript highlight="scheme">
824;;; Recursively check if two structure have the same length,
825;;; nesting, etc, while ignoring the value of the atoms.
826(ck () (c-compare? '(c-true) '(1 #(2) 3) '(a #(b) c)))
827;; ==> '#t
828</enscript>
829
830
831<syntax>(c-false X ...)  →  '#f</syntax>
832
833Always yields {{'#f}}, regardless of its arguments.
834May be useful for some higher-order macros.
835Equivalent to {{(c-constantly '#f X ...)}}.
836Added in '''version 0.2.0'''.
837
838
839<syntax>(c-if TEST PASS FAIL)  →  PASS or FAIL</syntax>
840
841Conditional branching.
842If {{TEST}} is {{'#f}}, this yields {{FAIL}}.
843Otherwise it yields {{PASS}}.
844
845Due to the way the CK machine works, both branches will be expanded,
846then the unneeded branch will be discarded.
847If you only want the needed branch to be expanded
848(e.g. because the branches are complex and slow to expand,
849or because it would be an error to expand the unneeded branch),
850use {{c-if*}} instead.
851
852Analogous to
853{{(lambda (test pass fail) (if test pass fail))}}.
854
855<enscript highlight="scheme">
856(ck () (c-quote (c-if (c-pair? '(x))
857                      'pair
858                      'not-pair)))
859;; ==> 'pair
860
861(ck () (c-quote (c-if (c-pair? 'x)
862                      'pair
863                      'not-pair)))
864;; ==> 'not-pair
865</enscript>
866
867
868<syntax>(c-if* TEST 'PASS 'FAIL)  →  PASS or FAIL</syntax>
869
870Similar to {{c-if}}, except that the branches must have an extra level of quoting,
871and only one branch will be expanded.
872This is more similar to how {{if}} behaves, but it is a bit awkward to use.
873
874Analogous to
875{{(lambda (test pass fail) (if test (eval pass) (eval fail)))}}
876
877<enscript highlight="scheme">
878(ck () (c-quote (c-if* (c-pair? '(x))
879                       '(c-car '(x))
880                       ''not-pair))
881;; ==> 'x
882
883(ck () (c-quote (c-if* (c-pair? 'x)
884                       '(c-car 'x)
885                       ''not-pair))
886;; ==> 'not-pair
887</enscript>
888
889
890<syntax>(c-or X ...)  →  item or '#f</syntax>
891
892Yields the first argument that is not {{'#f}}.
893Yields {{'#f}} if all of the arguments are {{'#f}},
894or if there are no arguments.
895
896Roughly analogous to {{or}}, except all arguments are expanded.
897If you only want to expand the arguments that are needed, use {{c-or*}} instead.
898
899
900<syntax>(c-or* 'X ...)  →  item or '#f</syntax>
901
902Similar to {{c-or}}, except that all the arguments must have an extra level of quoting,
903and the arguments will be expanded one at a time until a non-{{'#f}} value is found.
904This is more similar to how {{or}} behaves, but it is a bit awkward to use.
905
906
907<syntax>(c-and X ...)  →  item or '#f</syntax>
908
909If all arguments are not {{'#f}}, yields the last argument.
910If any of the arguments is {{'#f}}, yields {{'#f}}.
911If there are no arguments, yields {{'#t}}.
912
913Roughly analogous to {{and}}, except all arguments are expanded.
914If you only want to expand the arguments that are needed, use {{c-and*}} instead.
915
916
917<syntax>(c-and* X ...)  →  item or '#f</syntax>
918
919Similar to {{c-and}}, except that all the arguments must have an extra level of quoting,
920and the arguments will be expanded one at a time until a {{'#f}} value is found.
921This is more similar to how {{and}} behaves, but it is a bit awkward to use.
922
923
924<syntax>(c-null? X)  →  '#t or '#f</syntax>
925
926Yields {{'#t}} if {{X}} is the empty list, {{'()}}.
927Otherwise yields {{'#f}}.
928Analogous to {{null?}}.
929
930
931<syntax>(c-pair? X)  →  '#t or '#f</syntax>
932
933Yields {{'#t}} if {{X}} is a dotted pair or a non-empty list.
934Otherwise yields {{'#f}}.
935Analogous to {{pair?}}.
936
937
938<syntax>(c-not-pair? X)  →  '#t or '#f</syntax>
939
940Opposite of {{c-pair?}}.
941Analogous to {{not-pair?}} from SRFI 1.
942
943
944<syntax>(c-vector? X)  →  '#t or '#f</syntax>
945
946Yields {{'#t}} if {{X}} is a vector.
947Otherwise yields {{'#f}}.
948Analogous to {{vector?}}.
949
950<enscript highlight="scheme">
951(ck () (c-quote (c-vector? '#(a))))
952;; ==> '#t
953</enscript>
954
955
956<syntax>(c-boolean? X)  →  '#t or '#f</syntax>
957
958Yields {{'#t}} if {{X}} is either {{'#t}} or {{'#f}}.
959Otherwise yields {{'#f}}.
960Analogous to {{boolean?}}.
961
962
963<syntax>(c-sym-eq? X Y)  →  '#t or '#f</syntax>
964
965'''ATTENTION:''' This CK-macro has [[#pitfalls-of-c-sym-eq|major pitfalls]]
966that you should be aware of.
967If you do not require strict R5RS portability, it is recommended to use {{c-eq?}} instead.
968
969Yields {{'#t}} if {{X}} and {{Y}} are the same symbol, otherwise yields {{'#f}}.
970{{X}} should be a symbol.
971{{Y}} can be any value.
972Some Scheme implementations allow {{X}} to be other types,
973but this macro is only portable if {{X}} is a symbol.
974
975Roughly analogous to {{eq?}},
976except it only works (portably) with symbols.
977Based on {{symbol-eq?}} from the original implementation.
978
979
980<syntax>(c-sym-equal? X Y)  →  '#t or '#f</syntax>
981
982'''ATTENTION:''' This CK-macro has [[#pitfalls-of-c-sym-eq|major pitfalls]]
983that you should be aware of.
984If you do not require strict R5RS portability,
985it is recommended to use {{c-equal?}} instead.
986
987Similar to {{c-sym-eq?}}, except it recursively compares
988pairs, lists, and vectors.
989
990Roughly analogous to {{equal?}},
991except it only works (portably) with symbols, pairs, lists, vectors,
992and nested combinations of those things.
993
994
995<syntax>(c-compare? '(OP ...) X Y)  →  '#t or '#f</syntax>
996
997Recursively compares atoms, pairs, lists, or vectors,
998using {{OP}} as the predicate to compare atoms.
999Similar to {{equal?}} but with a custom predicate.
1000Added in '''version 0.2.0'''.
1001
1002{{OP}} will be called with two arguments:
1003an atom of {{X}}, and the corresponding atom of {{Y}}.
1004In other words, the Nth atom of {{X}} will be compared with the Nth atom of {{Y}},
1005descending recursively into nested structures.
1006If {{X}} and {{Y}} are themselves atoms, they are compared directly with {{OP}}.
1007
1008Yields {{'#f}} if {{X}} and {{Y}} have dissimilar structures (length, nesting, type),
1009or if {{OP}} yields {{'#f}} for any corresponding atoms of {{X}} and {{Y}}.
1010Otherwise yields {{'#t}}.
1011
1012<enscript highlight="scheme">
1013(ck () (c-compare? '(c-string-ci=?) '#("a" ("b")) '#("A" ("B"))))
1014;; ==> #t
1015
1016;;; X is a vector with a list, but Y is a list with a vector.
1017;;; The structures are dissimilar.
1018(ck () (c-compare? '(c-string-ci=?) '#("a" ("b")) '("a" #("b"))))
1019;; ==> #f
1020
1021;;; Can use any predicate. Here, X and Y have same structure,
1022;;; and each atom of X is less than the correponding atom of Y.
1023(ck () (c-compare? '(c-<) '(1 #(5)) '(2 #(6))))
1024;; ==> #t
1025
1026;;; Can compare atoms directly.
1027(ck () (c-compare? '(c-<) '1 '2))
1028;; ==> #t
1029</enscript>
1030
1031
1032==== List Processing
1033
1034<syntax>(c-cons X Y)  →  '(X . Y)</syntax>
1035
1036Yields a pair with the two given arguments.
1037Analogous to {{cons}}.
1038
1039<enscript highlight="scheme">
1040(ck () (c-quote (c-cons 'a 'b)))
1041;; ==> '(a . b)
1042
1043(ck () (c-quote (c-cons '+ '(1 2))))
1044;; ==> '(+ 1 2)
1045
1046(ck () (c-quote (c-cons '+ (c-cons '1 (c-cons '2 '())))))
1047;; ==> '(+ 1 2)
1048</enscript>
1049
1050
1051<syntax>(c-cons* X ... Y Z)  →  '(X ... Y . Z)</syntax>
1052
1053Yields a list from consing all the arguments together in a chain.
1054If the final argument Z is a list, the result will be a proper list.
1055Otherwise it will be a "dotted list".
1056Analogous to {{cons*}} from SRFI 1.
1057Added in '''version 0.3.0'''.
1058
1059<enscript highlight="scheme">
1060(ck () (c-quote (c-cons* 'a 'b 'c 'd)))
1061;; ==> '(a b c . d)
1062(ck () (c-quote (c-cons* 'a 'b 'c '(d))))
1063;; ==> '(a b c d)
1064</enscript>
1065
1066
1067<syntax>(c-xcons X Y)  →  '(Y . X)</syntax>
1068
1069Like {{c-cons}}, but exchanges the order of arguments.
1070Analogous to {{xcons}} from SRFI 1.
1071Added in '''version 0.2.0'''.
1072
1073<enscript highlight="scheme">
1074(ck () (c-quote (c-xcons 'a 'b)))
1075;; ==> '(b . a)
1076</enscript>
1077
1078
1079<syntax>(c-list X ...)  →  list</syntax>
1080
1081Yields a list containing the given items.
1082Analogous to {{list}}.
1083
1084<enscript highlight="scheme">
1085(ck () (c-quote (c-list)))
1086;; ==> '()
1087(ck () (c-quote (c-list 'a 'b 'c)))
1088;; ==> '(a b c)
1089</enscript>
1090
1091
1092<syntax>(c-car P)  →  item</syntax>
1093
1094Yields the head of the given pair.
1095Analogous to {{car}}.
1096
1097<enscript highlight="scheme">
1098(ck () (c-quote (c-car '(a . b))))
1099;; ==> 'a
1100
1101(ck () (c-quote (c-car '(a b))))
1102;; ==> 'a
1103</enscript>
1104
1105
1106<syntax>(c-cdr P)  →  tail</syntax>
1107
1108Yields the tail of the given pair.
1109Analogous to {{cdr}}.
1110
1111<enscript highlight="scheme">
1112(ck () (c-quote (c-cdr '(a . b))))
1113;; ==> 'b
1114
1115(ck () (c-quote (c-cdr '(a b))))
1116;; ==> '(b)
1117</enscript>
1118
1119
1120<syntax>(c-first   L)  →  item</syntax>
1121<syntax>(c-second  L)  →  item</syntax>
1122<syntax>(c-third   L)  →  item</syntax>
1123<syntax>(c-fourth  L)  →  item</syntax>
1124<syntax>(c-fifth   L)  →  item</syntax>
1125<syntax>(c-sixth   L)  →  item</syntax>
1126<syntax>(c-seventh L)  →  item</syntax>
1127<syntax>(c-eighth  L)  →  item</syntax>
1128<syntax>(c-ninth   L)  →  item</syntax>
1129<syntax>(c-tenth   L)  →  item</syntax>
1130
1131Yields the Nth item of the given list.
1132Fails if the list is too short.
1133
1134Analogous to {{first}} ... {{tenth}} from SRFI 1.
1135
1136<enscript highlight="scheme">
1137(ck () (c-quote (c-first  '(a b c d e f g h i j k))))  ; ==> 'a
1138(ck () (c-quote (c-second '(a b c d e f g h i j k))))  ; ==> 'b
1139(ck () (c-quote (c-third  '(a b c d e f g h i j k))))  ; ==> 'c
1140;;; ...
1141(ck () (c-quote (c-tenth  '(a b c d e f g h i j k))))  ; ==> 'j
1142</enscript>
1143
1144
1145<syntax>(c-last L)  →  item</syntax>
1146
1147Yields the last value of the given list.
1148Fails if the list is empty or is not a proper list.
1149
1150Analogous to {{last}} from SRFI 1.
1151
1152<enscript highlight="scheme">
1153(ck () (c-quote (c-last '(a b c))))    ; ==> 'c
1154(ck () (c-quote (c-last '(a b . c))))  ; ==> ERROR!
1155</enscript>
1156
1157
1158<syntax>(c-last-pair L)  →  pair</syntax>
1159
1160Yields the last pair of the given list.
1161Fails if the list is empty.
1162
1163Analogous to {{last-pair}} from SRFI 1.
1164
1165<enscript highlight="scheme">
1166(ck () (c-quote (c-last-pair '(a b c))))    ; ==> '(c)
1167(ck () (c-quote (c-last-pair '(a b . c))))  ; ==> '(b . c)
1168</enscript>
1169
1170
1171<syntax>(c-drop1 L)  →  list</syntax>
1172<syntax>(c-drop2 L)  →  list</syntax>
1173<syntax>(c-drop3 L)  →  list</syntax>
1174<syntax>(c-drop4 L)  →  list</syntax>
1175<syntax>(c-drop5 L)  →  list</syntax>
1176
1177Drops a predefined number of items from the front of the given list.
1178Fails if the list is too short.
1179See also {{c-udrop}}.
1180
1181Analogous to {{(drop L N)}} from SRFI 1.
1182
1183<enscript highlight="scheme">
1184(ck () (c-quote (c-drop1 '(a b c d e f g))))  ; ==> '(b c d e f g)
1185(ck () (c-quote (c-drop2 '(a b c d e f g))))  ; ==> '(c d e f g)
1186(ck () (c-quote (c-drop3 '(a b c d e f g))))  ; ==> '(d e f g)
1187(ck () (c-quote (c-drop4 '(a b c d e f g))))  ; ==> '(e f g)
1188(ck () (c-quote (c-drop5 '(a b c d e f g))))  ; ==> '(f g)
1189</enscript>
1190
1191
1192<syntax>(c-take1 L)  →  list</syntax>
1193<syntax>(c-take2 L)  →  list</syntax>
1194<syntax>(c-take3 L)  →  list</syntax>
1195<syntax>(c-take4 L)  →  list</syntax>
1196<syntax>(c-take5 L)  →  list</syntax>
1197
1198Yields a list containing a predefined number of items from the front of the given list.
1199Fails if the list is too short.
1200See also {{c-utake}}.
1201
1202Analogous to {{(take L N)}} from SRFI 1.
1203
1204<enscript highlight="scheme">
1205(ck () (c-quote (c-take1 '(a b c d e f g))))  ; ==> '(a)
1206(ck () (c-quote (c-take2 '(a b c d e f g))))  ; ==> '(a b)
1207(ck () (c-quote (c-take3 '(a b c d e f g))))  ; ==> '(a b c)
1208(ck () (c-quote (c-take4 '(a b c d e f g))))  ; ==> '(a b c d)
1209(ck () (c-quote (c-take5 '(a b c d e f g))))  ; ==> '(a b c d e)
1210</enscript>
1211
1212
1213<syntax>(c-reverse L)  →  list</syntax>
1214
1215Yields the given list in reverse order.
1216Fails if the list is not a proper list.
1217Analogous to {{reverse}}.
1218
1219<enscript highlight="scheme">
1220(ck () (c-quote (c-reverse '(a b c))))
1221;; ==> '(c b a)
1222</enscript>
1223
1224
1225<syntax>(c-prefix L X ...)  →  list</syntax>
1226
1227Yields the given list with the extra arguments added to the front.
1228Added in '''version 0.3.0'''.
1229
1230<enscript highlight="scheme">
1231(ck () (c-quote (c-prefix '(c d) 'a 'b)))
1232;; ==> '(a b c d)
1233</enscript>
1234
1235
1236<syntax>(c-suffix L X ...)  →  list</syntax>
1237
1238Yields the given list with the extra arguments added to the end.
1239
1240<enscript highlight="scheme">
1241(ck () (c-quote (c-suffix '(a b) 'c 'd)))
1242;; ==> '(a b c d)
1243</enscript>
1244
1245
1246<syntax>(c-append L ...)  →  list</syntax>
1247
1248Appends the given lists.
1249Analogous to {{append}}.
1250
1251<enscript highlight="scheme">
1252(ck () (c-quote (c-append)))
1253;; ==> '()
1254
1255(ck () (c-quote (c-append '(+) (c-append '(1) '(2)))))
1256;; ==> '(+ 1 2)
1257
1258(ck () (c-quote (c-append '(define foo) '((+ 1 2)))))
1259;; ==> '(define foo (+ 1 2 3))
1260</enscript>
1261
1262
1263<syntax>(c-append-map1 '(OP ...) L)  →  list</syntax>
1264
1265Yields a list by calling the quoted operation on each item in the list,
1266then appending the results.
1267The operation must be a CK-macro that yields a list.
1268
1269Analogous to {{append-map}} from SFRI-1, but only accepts one list.
1270'''Prior to version 0.2.0''', this was named {{c-append-map}}.
1271This was named {{c-concatMap}} in the original implementation.
1272
1273<enscript highlight="scheme">
1274(ck () (c-quote (c-append-map1 '(c-list 'a 'b) '(1 2))))
1275;; ==> '(a b 1 a b 2)
1276</enscript>
1277
1278
1279<syntax>(c-map1 '(OP ...) L)  →  list</syntax>
1280
1281Yields a list by calling the quoted operation on each item in the given list.
1282Analogous to {{map}}, but only accepts one list.
1283(See also {{c-map2}} ... {{c-map5}} for versions that accept more lists.)
1284'''Prior to version 0.2.0''', this was named {{c-map}}.
1285
1286<enscript highlight="scheme">
1287(ck () (c-quote (c-map1 '(c-cons 'a) '(1 2))))
1288;; ==> '((a . 1) (a . 2))
1289</enscript>
1290
1291
1292<syntax>(c-map2 '(OP ...) L1 L2)  →  list</syntax>
1293<syntax>(c-map3 '(OP ...) L1 L2 L3)  →  list</syntax>
1294<syntax>(c-map4 '(OP ...) L1 L2 L3 L4)  →  list</syntax>
1295<syntax>(c-map5 '(OP ...) L1 L2 L3 L4 L5)  →  list</syntax>
1296
1297Like {{c-map1}}, but they accept exactly two, three, four, or five lists respectively.
1298{{OP}} must accept two, three, four, or five extra arguments.
1299If the lists are different lengths, terminates when the shortest list runs out.
1300Analogous to {{map}} from SRFI 1, but they accept a specific number of lists.
1301Added in '''version 0.2.0'''.
1302
1303<enscript highlight="scheme">
1304;; The argument '(1 2) is shortest so the result only has two items.
1305(ck () (c-quote (c-map3 '(c-list) '(a b c) '(1 2) '(x y z))))
1306;; ==> '((a 1 x) (b 2 y))
1307</enscript>
1308
1309
1310<syntax>(c-fold1 '(OP ...) INIT L)  →  result</syntax>
1311
1312Yield a value by repeatedly calling the quoted operation
1313with each item from the list and the previous result.
1314
1315If the list is empty, yields {{INIT}}.
1316Otherwise, the operation is first called with two arguments:
1317the first item of the list, and {{INIT}}.
1318Then, the operation is repeatedly called with the next item of the list and the previous result,
1319until it reaches the end of the list.
1320Yields the final result.
1321
1322Analogous to {{fold}} from SRFI 1, but only accepts one list.
1323'''Prior to version 0.2.0''', this was named {{c-fold}}.
1324
1325<enscript highlight="scheme">
1326(ck () (c-quote (c-fold1 '(c-cons) '(x) '())))
1327;; ==> '(x)
1328(ck () (c-quote (c-fold1 '(c-cons) '(x) '(a b c d e f))))
1329;; ==> '(f e d c b a x)
1330</enscript>
1331
1332
1333<syntax>(c-unfold '(P ...) '(F ...) '(G ...) SEED)  →  list</syntax>
1334<syntax>(c-unfold '(P ...) '(F ...) '(G ...) SEED '(TAIL-GEN ...))  →  list</syntax>
1335
1336Generate a list by recursively "unfolding" from a seed.
1337Analogous to {{unfold}} from SRFI 1.
1338Added in '''version 0.3.0'''.
1339
1340Takes several operations which are called with the seed:
1341
1342* {{(P ... SEED)}} should yield non-{{'#f}} if it is time to stop generating.
1343* {{(F ... SEED)}} should yield an item to be appended to the list.
1344* {{(G ... SEED)}} should yield the next {{SEED}}.
1345* {{(TAIL-GEN ... SEED)}} should yield the tail of the list.
1346  Called with the final {{SEED}} after {{P}} yields non-{{'#f}}.
1347  If omitted, {{'(TAIL-GEN ...)}} defaults to {{'(c-constantly '())}}.
1348
1349<enscript highlight="scheme">
1350(ck () (c-quote
1351        (c-unfold '(c-> '1)                        ; P
1352                  '(c-identity)                    ; F
1353                  '(c-dsub1)                       ; G
1354                  '10                              ; SEED
1355                  '(c-constantly '(BLASTOFF!)))))  ; TAIL-GEN
1356;; ==> '(10 9 8 7 6 5 4 3 2 1 BLASTOFF!)
1357</enscript>
1358
1359
1360<syntax>(c-filter '(OP ...) L)  →  list</syntax>
1361
1362Yields a list by calling the predicate operation on each item in the list,
1363and discarding any item for which the test yields {{'#f}}.
1364Analogous to {{filter}} from SRFI 1.
1365
1366<enscript highlight="scheme">
1367(ck () (c-quote (c-filter '(c-pair?)
1368                          '(a (b . c) 1 (d e) #t))))
1369;; ==> '((b . c) (d e))
1370</enscript>
1371
1372
1373<syntax>(c-remove '(OP ...) L)  →  list</syntax>
1374
1375Opposite of {{c-filter}}.
1376Discards items that pass the test, keeps items that fail the test.
1377Analogous to {{remove}} from SRFI 1.
1378
1379<enscript highlight="scheme">
1380(ck () (c-quote (c-remove '(c-pair?)
1381                          '(a (b . c) 1 (d e) #t))))
1382;; ==> '(a 1 #t)
1383</enscript>
1384
1385
1386<syntax>(c-find '(OP ...) L)  →  item or '#f</syntax>
1387
1388Searches the list for the first item that passes the predicate operation
1389(i.e. the predicate yields a non-{{'#f}} value),
1390then yields that item.
1391Yields {{'#f}} if no item passes the predicate.
1392
1393Analogous to {{find}} from SRFI 1.
1394
1395<enscript highlight="scheme">
1396(ck () (c-quote (c-find '(c-pair?)
1397                        '(a (b . c) 1 (d e) #t))))
1398;; ==> '(b . c)
1399</enscript>
1400
1401
1402<syntax>(c-find-tail '(OP ...) L)  →  pair or '#f</syntax>
1403
1404Searches the list for the first item that passes the predicate operation
1405(i.e. the predicate yields a non-{{'#f}} value),
1406then yields the tail of the list starting with that item.
1407Yields {{'#f}} if no item passes the predicate.
1408
1409Analogous to {{find-tail}} from SRFI 1.
1410
1411<enscript highlight="scheme">
1412(ck () (c-quote (c-find-tail '(c-pair?)
1413                             '(a (b . c) 1 (d e) #t))))
1414;; ==> '((b . c) 1 (d e) #t)
1415</enscript>
1416
1417
1418<syntax>(c-member X L)  →  '#t or '#f</syntax>
1419<syntax>(c-member X L '(OP ...))  →  '#t or '#f</syntax>
1420
1421'''ATTENTION:''' When using the default comparison operator,
1422this CK-macro has [[#pitfalls-of-c-sym-eq|major pitfalls]] that you should be aware of.
1423If you do not require strict R5RS portability,
1424it is recommended to use the comparison operator {{'(c-equal?)}} instead.
1425
1426Searches the list for the first occurance of {{X}},
1427then yields the tail of the list starting with that item.
1428Yields {{'#f}} if the list does not contain {{X}}.
1429
1430Uses {{'(OP ...)}} for comparison,
1431or {{'(c-sym-equal?)}} if the operation is omitted.
1432So by default, {{X}} must be a symbol, list, pair, vector,
1433or nested combination of those things.
1434
1435Same as {{(c-find-tail '(OP ... X) L)}}.
1436Roughly analogous to {{member}} except for the default allowed types.
1437
1438<enscript highlight="scheme">
1439(ck () (c-quote (c-member 'b '(a b c))))
1440;; ==> '(b c)
1441
1442(ck () (c-quote (c-member 'x '(a b c))))
1443;; ==> '#f
1444
1445(ck () (c-quote (c-member '(a b c)
1446                          '((a) (x y z) (a b))
1447                          '(c-u=))))
1448;; ==> '((x y z) (a b))
1449;; Because (c-u= '(a b c) '(x y z)) yields '#t
1450</enscript>
1451
1452
1453<syntax>(c-any1 '(OP ...) L)  →  result or '#f</syntax>
1454
1455Calls the operation on each value in the given list
1456until it finds a result that is not {{'#f}}, then yields that result.
1457Yields {{'#f}} if the predicate yields {{'#f}} for all items in the list,
1458or if the list is empty.
1459
1460Analogous to {{any}} from SRFI 1, but only accepts one list.
1461'''Prior to version 0.2.0''', this was named {{c-any}}.
1462
1463<enscript highlight="scheme">
1464(ck () (c-quote (c-any1 '(c-pair?) '())))
1465;; ==> '#f
1466(ck () (c-quote (c-any1 '(c-pair?) '(a b c))))
1467;; ==> '#f
1468(ck () (c-quote (c-any1 '(c-pair?) '(a (b . c)))))
1469;; ==> '#t
1470
1471(ck () (c-quote (c-any1 '(c-cons 'z) '(a b c))))
1472;; ==> '(1 . a)
1473;; Because (c-cons 'z 'a) yields a value that is not '#f.
1474</enscript>
1475
1476
1477<syntax>(c-every1 '(OP ...) L)  →  result or '#f</syntax>
1478
1479Calls the operation on each value in the given list
1480until it finds a result that is {{'#f}}, then yields {{'#f}}.
1481If the predicate yields a non-{{'#f}} value for every item in the list,
1482this yields the result of calling the predicate on the last item.
1483Yields {{'#t}} if the list is empty.
1484
1485Analogous to {{every}} from SRFI 1, but only accepts one list.
1486'''Prior to version 0.2.0''', this was named {{c-every}}.
1487
1488<enscript highlight="scheme">
1489(ck () (c-quote (c-every1 '(c-pair?) '())))
1490;; ==> '#t
1491(ck () (c-quote (c-every1 '(c-pair?) '(a (b . c)))))
1492;; ==> '#f
1493(ck () (c-quote (c-every1 '(c-pair?) '((a . b) (b . c)))))
1494;; ==> '#t
1495
1496(ck () (c-quote (c-every1 '(c-cons 'z) '(a b c))))
1497;; ==> '(z . c)
1498;; Because all results were non-'#f and (c-cons 'z 'c) was the final operation.
1499</enscript>
1500
1501
1502<syntax>(c-assoc KEY ALIST)  →  pair or '#f</syntax>
1503<syntax>(c-assoc KEY ALIST '(OP ...))  →  pair or '#f</syntax>
1504
1505'''ATTENTION:''' When using the default comparison operator,
1506this CK-macro has [[#pitfalls-of-c-sym-eq|major pitfalls]] that you should be aware of.
1507If you do not require strict R5RS portability,
1508it is recommended to use the comparison operator {{'(c-equal?)}} instead.
1509
1510Searches {{ALIST}} for the first pair whose car matches {{KEY}},
1511then yields that pair.
1512Yields {{'#f}} if no match is found.
1513{{ALIST}} must be an association list, i.e. a list of pairs.
1514
1515Uses {{'(OP ...)}} for comparison,
1516or {{'(c-sym-equal?)}} if {{'(OP ...)}} is omitted.
1517
1518Analogous to {{assoc}} from SRFI 1.
1519
1520<enscript highlight="scheme">
1521(ck () (c-quote (c-assoc 'x '((a . 1) (b . 2) (a . 3)))))
1522;; ==> '#f
1523(ck () (c-quote (c-assoc 'a '((a . 1) (b . 2) (a . 3)))))
1524;; ==> '(a . 1)
1525(ck () (c-quote (c-assoc '(a) '((a . 1) (b . 2) ((a) . 3)))))
1526;; ==> '((a) . 3)
1527</enscript>
1528
1529
1530<syntax>(c-alist-delete KEY ALIST)  →  list</syntax>
1531<syntax>(c-alist-delete KEY ALIST '(OP ...))  →  list</syntax>
1532
1533'''ATTENTION:''' When using the default comparison operator,
1534this CK-macro has [[#pitfalls-of-c-sym-eq|major pitfalls]] that you should be aware of.
1535If you do not require strict R5RS portability,
1536it is recommended to use the comparison operator {{'(c-equal?)}} instead.
1537
1538Removes all pairs in {{ALIST}} whose car matches {{KEY}}.
1539{{ALIST}} must be an association list, i.e. a list of pairs.
1540
1541Uses {{'(OP ...)}} for comparison,
1542or {{'(c-sym-equal?)}} if {{'(OP ...)}} is omitted.
1543
1544Analogous to {{alist-delete}} from SRFI 1.
1545Based on {{c-delete-assoc}} from the original implementation.
1546
1547<enscript highlight="scheme">
1548(ck () (c-quote (c-alist-delete 'a '((a . 1) (b . 2) (a . 3) (c . 4)))))
1549;; ==> '((b . 2) (c . 4)
1550(ck () (c-quote (c-alist-delete '(a) '((a . 1) (b . 2) ((a) . 3)))))
1551;; ==> '((a . 1) (b . 2))
1552</enscript>
1553
1554
1555==== Vector Processing
1556
1557<syntax>(c-vector X ...)  →  vector</syntax>
1558
1559Yields a vector containing the given items.
1560Analogous to {{vector}}.
1561
1562
1563<syntax>(c-list->vector L)  →  vector</syntax>
1564
1565Yields a vector containing the same items as the given list.
1566Analogous to {{list->vector}} from SRFI 43.
1567
1568
1569<syntax>(c-vector->list V)  →  list</syntax>
1570
1571Yields a list containing the same items as the given vector.
1572Analogous to {{vector->list}} from SRFI 43.
1573
1574
1575<syntax>(c-vector-reverse V)  →  vector</syntax>
1576
1577Yields the given vector in reverse order.
1578Similar to {{vector-reverse-copy}} from SRFI 43,
1579but does not take a start or end argument.
1580
1581
1582<syntax>(c-vector-prefix V X ...)  →  list</syntax>
1583
1584Yields the given vector with the extra arguments added to the front.
1585Added in '''version 0.3.0'''.
1586
1587<enscript highlight="scheme">
1588(ck () (c-quote (c-vector-prefix '#(c d) 'a 'b)))
1589;; ==> '#(a b c d)
1590</enscript>
1591
1592
1593<syntax>(c-vector-suffix V X ...)  →  vector</syntax>
1594
1595Yields the given vector with the extra arguments added to the end.
1596
1597<enscript highlight="scheme">
1598(ck () (c-quote (c-vector-suffix '#(a b) 'c 'd)))
1599;; ==> '#(a b c d)
1600</enscript>
1601
1602
1603<syntax>(c-vector-append V ...)  →  vector</syntax>
1604
1605Appends the given vectors.
1606Analogous to {{vector-append}} from SRFI 43,
1607but only accepts two vectors.
1608
1609<enscript highlight="scheme">
1610(ck () (c-quote (c-vector-append)))
1611;; ==> '#()
1612
1613(ck () (c-quote (c-vector-append '#(a b) '#(c d) '#(e f))))
1614;; ==> '#(a b c d e f)
1615</enscript>
1616
1617
1618<syntax>(c-vector-map1 '(OP ...) V)  →  vector</syntax>
1619
1620Yields a vector by calling the quoted operation on each item in the given vector.
1621Analogous to {{vector-map}} from SRFI 43, but only accepts one vector.
1622'''Prior to version 0.2.0''', this was named {{c-vector-map}}.
1623
1624
1625==== Unary Math
1626
1627The CK-macros in this section perform mathematical operations by treating lists as unary numbers.
1628Unary math is pretty slow for large values or complex operations,
1629but it is interesting, portable, and maybe even useful in some cases.
1630
1631Unary numbers are a way of representing non-negative integers as a list of a certain length.
1632For example, the list {{'(a b c d e)}} means the number 5,
1633and the list {{'()}} means the number 0.
1634The contents of the list do not matter, only the length.
1635Negative numbers and non-integral numbers cannot be represented in unary.
1636
1637
1638<syntax>(c-u= U1 U2)  →  '#t or '#f</syntax>
1639
1640Unary equality.
1641Yields {{'#t}} if the two lists have the same lengths,
1642otherwise yields {{'#f}}.
1643
1644<enscript highlight="scheme">
1645(ck () (c-quote (c-u= '(a b c) '(a b c))))
1646;; ==> '#t
1647(ck () (c-quote (c-u= '(1 2 3) '(a b c))))
1648;; ==> '#t
1649(ck () (c-quote (c-u= '(1 2) '(a b c))))
1650;; ==> '#f
1651</enscript>
1652
1653
1654<syntax>(c-u< U1 U2)  →  '#t or '#f</syntax>
1655
1656Unary less-than.
1657Yields {{'#t}} if the first list is shorter than the second list,
1658otherwise yields {{'#f}}.
1659
1660<enscript highlight="scheme">
1661(ck () (c-quote (c-u< '(1 2) '(a b c))))
1662;; ==> '#t
1663(ck () (c-quote (c-u< '(1 2 3) '(a b c))))
1664;; ==> '#f
1665</enscript>
1666
1667
1668<syntax>(c-u<= U1 U2)  →  '#t or '#f</syntax>
1669
1670Unary less-than-or-equals.
1671Yields {{'#t}} if first list is the same length or shorter than the second list,
1672otherwise yields {{'#f}}.
1673
1674<enscript highlight="scheme">
1675(ck () (c-quote (c-u<= '(1 2) '(a b c))))
1676;; ==> '#t
1677(ck () (c-quote (c-u<= '(1 2 3) '(a b c))))
1678;; ==> '#t
1679(ck () (c-quote (c-u<= '(1 2 3 4) '(a b c))))
1680;; ==> '#f
1681</enscript>
1682
1683
1684<syntax>(c-u> U1 U2)  →  '#t or '#f</syntax>
1685
1686Unary greater-than.
1687Yields {{'#t}} if the first list is longer than the second list,
1688otherwise yields {{'#f}}.
1689
1690<enscript highlight="scheme">
1691(ck () (c-quote (c-u> '(1 2 3 4) '(a b c))))
1692;; ==> '#t
1693(ck () (c-quote (c-u> '(1 2 3) '(a b c))))
1694;; ==> '#f
1695</enscript>
1696
1697
1698<syntax>(c-u>= U1 U2)  →  '#t or '#f</syntax>
1699
1700Unary greater-than-or-equals.
1701Yields {{'#t}} if first list is same length or longer than the second list,
1702otherwise yields {{'#f}}.
1703
1704<enscript highlight="scheme">
1705(ck () (c-quote (c-u>= '(1 2 3 4) '(a b c))))
1706;; ==> '#t
1707(ck () (c-quote (c-u>= '(1 2 3) '(a b c))))
1708;; ==> '#t
1709(ck () (c-quote (c-u>= '(1 2) '(a b c))))
1710;; ==> '#f
1711</enscript>
1712
1713
1714<syntax>(c-uzero? U)  →  '#t or '#f</syntax>
1715
1716Unary {{zero?}}.
1717Yields {{'#t}} if the list is empty, otherwise yields {{'#f}}.
1718Same as {{c-null?}}.
1719
1720<enscript highlight="scheme">
1721(ck () (c-quote (c-uzero? '())))
1722;; ==> '#t
1723(ck () (c-quote (c-uzero? '(a))))
1724;; ==> '#f
1725</enscript>
1726
1727
1728<syntax>(c-ueven? U)  →  '#t or '#f</syntax>
1729
1730Unary {{even?}}.
1731Yields {{'#t}} if the given list's length is even
1732(i.e. a multiple of 2), otherwise yields {{'#f}}.
1733
1734<enscript highlight="scheme">
1735(ck () (c-quote (c-ueven? '())))
1736;; ==> '#t
1737(ck () (c-quote (c-ueven? '(a))))
1738;; ==> '#f
1739(ck () (c-quote (c-ueven? '(a b))))
1740;; ==> '#t
1741</enscript>
1742
1743
1744<syntax>(c-uodd? U)  →  '#t or '#f</syntax>
1745
1746Unary {{odd?}}.
1747Yields {{'#t}} if the given list's length is odd
1748(i.e. not a multiple of 2), otherwise yields {{'#f}}.
1749
1750<enscript highlight="scheme">
1751(ck () (c-quote (c-uodd? '())))
1752;; ==> '#f
1753(ck () (c-quote (c-uodd? '(a))))
1754;; ==> '#t
1755(ck () (c-quote (c-uodd? '(a b))))
1756;; ==> '#f
1757</enscript>
1758
1759
1760<syntax>(c-u+ U1 U2)  →  list</syntax>
1761
1762Unary addition.
1763Same as {{c-append}}.
1764This was named {{c-add}} in the original implementation.
1765
1766<enscript highlight="scheme">
1767(ck () (c-quote (c-u+ '(a b) '(c))))
1768;; ==> '(a b c)
1769</enscript>
1770
1771
1772<syntax>(c-u- U1 U2)  →  list</syntax>
1773
1774Unary subtraction.
1775Drops an element from the front of the first list for each element in second list,
1776then yields the remaining list.
1777Negative numbers cannot be represented in unary,
1778so this yields '() if the second list is equal or longer than the first.
1779
1780<enscript highlight="scheme">
1781(ck () (c-quote (c-u- (c-list 'a 'b 'c 'd) '(x y))))
1782;; ==> '(c d)
1783
1784(ck () (c-quote (c-u- (c-list 'a 'b) (c-list 'x 'y 'z))))
1785;; ==> '()
1786;; Because negative numbers cannot be represented in unary.
1787</enscript>
1788
1789
1790<syntax>(c-u* U1 U2)  →  list</syntax>
1791
1792Unary multiplication.
1793Yields a list containing the contents of the first list,
1794repeated once for every item in the second list.
1795
1796Based on {{c-mul}} from the original implementation,
1797except the symbol {{'u}} has no special significance,
1798and result is made from duplicating the first list.
1799
1800<enscript highlight="scheme">
1801(ck () (c-quote (c-u* '(a b) '(c d e))))
1802;; ==> '(a b a b a b)
1803</enscript>
1804
1805
1806<syntax>(c-u/ U1 U2)  →  (list list)</syntax>
1807
1808Unary division.
1809Yields a list of two unary numbers,
1810representing the quotient and the remainder of the division.
1811
1812Given the second list has length {{N}},
1813the quotient will contain every {{N}}th item from the first list,
1814and the remainder will contain the tail of the first list.
1815Division by zero (empty list) is a syntax error.
1816
1817<enscript highlight="scheme">
1818(ck () (c-quote (c-u/ '(a b c d e f g h i j k)
1819                      '(x y z))))
1820;; ==> '((g d a) (j k))
1821;; Because 11 / 3 = 3 with a remainder of 2.
1822</enscript>
1823
1824
1825<syntax>(c-ufactorial U)  →  list</syntax>
1826
1827Unary factorial.
1828If the given list has length zero, yields the list {{'(u)}}.
1829If the given list has length one, yields the given list.
1830Otherwise, yields a list containing items of the given list repeated {{(N-1)!}} times,
1831where {{N}} is the length of the given list.
1832This was named {{c-fact}} in the original implementation.
1833
1834<enscript highlight="scheme">
1835(ck () (c-quote (c-ufactorial '(a b c))))
1836;; ==> '(a b c a b c)
1837;; Because 3! = 6.
1838</enscript>
1839
1840
1841<syntax>(c-udrop L U)  →  list</syntax>
1842
1843Drops up to U items from the front of the given list,
1844where U is a unary number.
1845
1846Same as {{c-u-}}.
1847Analogous to {{drop}} from SRFI 1,
1848but uses unary numbers,
1849and yields the empty list if the list is too short.
1850
1851<enscript highlight="scheme">
1852(ck () (c-quote (c-udrop (c-list 'a 'b 'c 'd) '(x y))))
1853;; ==> '(c d)
1854(ck () (c-quote (c-udrop (c-list 'a 'b) (c-list 'x 'y 'z))))
1855;; ==> '()
1856</enscript>
1857
1858
1859<syntax>(c-utake L U)  →  list</syntax>
1860
1861Yields a list containing up to U items from the front of the given list,
1862where U is a unary number.
1863
1864Analogous to {{take}} from SRFI 1,
1865but uses unary numbers,
1866and yields the entire list if it is too short.
1867
1868<enscript highlight="scheme">
1869(ck () (c-quote (c-utake '(a b c d) '(x y z))))
1870;; ==> '(a b c)
1871(ck () (c-quote (c-utake '(a b) '(x y z))))
1872;; ==> '(a b)
1873</enscript>
1874
1875
1876==== Decimal Integers
1877
1878<syntax>(c-dadd1 N)  →  'N+1 or '#f</syntax>
1879
1880Add 1 to a decimal integer.
1881If 0 <= N <= 15, yields N + 1. Otherwise yields {{'#f}}.
1882Added in '''version 0.3.0'''.
1883
1884<enscript highlight="scheme">
1885(ck () (c-dadd1 '0))
1886;; ==> '1
1887(ck () (c-dadd1 '15))
1888;; ==> '16
1889(ck () (c-dadd1 '16))
1890;; ==> '#f
1891</enscript>
1892
1893The default domain is small because library compilation time increases rapidly
1894the larger the domain is, because it generates a syntax-rules with many branches.
1895You can define an {{add1}} with a larger (or just different) domain
1896using {{c-make-next}} and a list of ''increasing'' integers:
1897
1898<enscript highlight="scheme">
1899(ck () `(define-syntax c-my-add1
1900          ,(c-make-next '(-5 -4 -3 -2 -1 0 1 2 3 4 5))))
1901</enscript>
1902
1903
1904<syntax>(c-dsub1 N)  →  'N-1 or '#f</syntax>
1905
1906Subtract 1 from a decimal integer.
1907If 1 <= N <= 16, yields N - 1. Otherwise yields {{'#f}}.
1908See the notes for {{c-dadd1}}.
1909
1910<enscript highlight="scheme">
1911(ck () (c-dsub1 '16))
1912;; ==> '15
1913(ck () (c-dsub1 '1))
1914;; ==> '0
1915(ck () (c-dsub1 '0))
1916;; ==> '#f
1917</enscript>
1918
1919As with {{c-dadd1}}, you can define a {{sub1}} with a larger (or just different) domain
1920using {{c-make-next}} and a list of ''decreasing'' integers:
1921
1922<enscript highlight="scheme">
1923(ck () `(define-syntax c-my-sub1
1924          ,(c-make-next '(5 4 3 2 1 0 -1 -2 -3 -4 -5))))
1925</enscript>
1926
1927
1928<syntax>(c-du N)  →  list or '#f</syntax>
1929<syntax>(c-du N '(SUB1 ...))  →  list or '#f</syntax>
1930
1931Convert from decimal integers to [[#unary-math|unary integers]].
1932If N is in the domain of {{SUB1}}, yields a list of that many elements,
1933specifically the integers {{(N-1, ..., 0)}}.
1934Otherwise, yields {{'#f}}.
1935
1936{{SUB1}} is any operation that given N yields N-1, where 1 <= N.
1937Defaults to {{c-dsub1}}, which supports 1 <= N <= 16.
1938See the note for {{c-dsub1}} for how to make an operation with a larger domain.
1939
1940<enscript highlight="scheme">
1941(ck () (c-quote (c-du '0)))
1942;; ==> '()
1943(ck () (c-quote (c-du '16)))
1944;; ==> '(15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)
1945(ck () (c-quote (c-du '17)))
1946;; ==> '#f
1947</enscript>
1948
1949
1950<syntax>(c-ud U)  →  integer or '#f</syntax>
1951<syntax>(c-ud U '(ADD1 ...))  →  integer or '#f</syntax>
1952
1953Convert from [[#unary-math|unary integers]] to decimal integers.
1954Given a list of items, yields the list's length as a decimal integer.
1955The contents of the list do not matter, only its length.
1956If the list length is too large for {{ADD1}}, yields {{'#f}}.
1957
1958{{ADD1}} is any operation that given N yields N+1, where 0 <= N.
1959Defaults to {{c-dadd1}}, which supports 0 <= N <= 15.
1960See the note for {{c-dadd1}} for how to make an operation with a larger domain.
1961
1962<enscript highlight="scheme">
1963(ck () (c-ud '()))
1964;; ==> '0
1965(ck () (c-ud '(a b c d e f g h i j k l m n o p)))
1966;; ==> '16
1967(ck () (c-ud '(a b c d e f g h i j k l m n o p q)))
1968;; ==> '#f
1969</enscript>
1970
1971
1972
1973=== Non-portable R5RS Wrappers
1974
1975These are CK-macros that wrap some R5RS procedures that are useful for building macros.
1976Not every R5RS procedure is provided here.
1977If you need other procedures, use [[#ck-wrapper|{{ck-wrapper}}]]
1978to create your own wrappers.
1979
1980These wrappers are considered non-portable because they use ck-wrapper,
1981which is not portable to all R5RS Scheme implementations.
1982See the ck-wrapper docs for portability information.
1983
1984Some R5RS procedures have portable, non-wrapper CK-macro equivalents,
1985which are described in the [[#portable-ck-macros|Portable CK-macros]] section, above.
1986For example, there is no wrapper for {{pair?}} listed below,
1987because {{c-pair?}} is a portable CK-macro listed above.
1988
1989
1990==== General (R5RS Wrappers)
1991
1992<syntax>(c-eqv? X Y)  →  '#t or '#f</syntax>
1993
1994CK-macro wrapper for {{eqv?}}.
1995Added in '''version 0.2.0'''.
1996
1997<syntax>(c-eq? X Y)  →  '#t or '#f</syntax>
1998
1999CK-macro wrapper for {{eq?}}.
2000Added in '''version 0.2.0'''.
2001
2002<syntax>(c-equal? X Y)  →  '#t or '#f</syntax>
2003
2004CK-macro wrapper for {{equal?}}.
2005Added in '''version 0.2.0'''.
2006
2007
2008==== Numbers and Math (R5RS Wrappers)
2009
2010<syntax>(c-number? X)  →  '#t or '#f</syntax>
2011
2012CK-macro wrapper for {{number?}}.
2013Added in '''version 0.2.0'''.
2014
2015<syntax>(c-integer? X)  →  '#t or '#f</syntax>
2016
2017CK-macro wrapper for {{integer?}}.
2018Added in '''version 0.2.0'''.
2019
2020<syntax>(c-= N ...)  →  '#t or '#f</syntax>
2021
2022CK-macro wrapper for {{=}} (equal).
2023Added in '''version 0.2.0'''.
2024
2025<syntax>(c-< N ...)  →  '#t or '#f</syntax>
2026
2027CK-macro wrapper for {{<}} (less than).
2028Added in '''version 0.2.0'''.
2029
2030<syntax>(c-> N ...)  →  '#t or '#f</syntax>
2031
2032CK-macro wrapper for {{>}} (greater than).
2033Added in '''version 0.2.0'''.
2034
2035<syntax>(c-<= N ...)  →  '#t or '#f</syntax>
2036
2037CK-macro wrapper for {{<=}} (less than or equal).
2038Added in '''version 0.2.0'''.
2039
2040<syntax>(c->= N ...)  →  '#t or '#f</syntax>
2041
2042CK-macro wrapper for {{>=}} (greater than or equal).
2043Added in '''version 0.2.0'''.
2044
2045<syntax>(c-max N ...)  →  number</syntax>
2046
2047CK-macro wrapper for {{max}}.
2048Added in '''version 0.2.0'''.
2049
2050<syntax>(c-min N ...)  →  number</syntax>
2051
2052CK-macro wrapper for {{min}}.
2053Added in '''version 0.2.0'''.
2054
2055<syntax>(c-+ N ...)  →  number</syntax>
2056
2057CK-macro wrapper for {{+}} (addition).
2058Added in '''version 0.2.0'''.
2059
2060<syntax>(c-* N ...)  →  number</syntax>
2061
2062CK-macro wrapper for {{*}} (multiplication).
2063Added in '''version 0.2.0'''.
2064
2065<syntax>(c-- N ...)  →  number</syntax>
2066
2067CK-macro wrapper for {{-}} (subtraction).
2068Added in '''version 0.2.0'''.
2069
2070<syntax>(c-/ N ...)  →  number</syntax>
2071
2072CK-macro wrapper for {{/}} (division).
2073Added in '''version 0.2.0'''.
2074
2075<syntax>(c-remainder N1 N2)  →  number</syntax>
2076
2077CK-macro wrapper for {{remainder}}.
2078Added in '''version 0.2.0'''.
2079
2080<syntax>(c-floor N)  →  number</syntax>
2081
2082CK-macro wrapper for {{floor}}.
2083Added in '''version 0.2.0'''.
2084
2085<syntax>(c-round N)  →  number</syntax>
2086
2087CK-macro wrapper for {{round}}.
2088Added in '''version 0.2.0'''.
2089
2090<syntax>(c-exact->inexact N)  →  inexact number</syntax>
2091
2092CK-macro wrapper for {{exact->inexact}}.
2093Added in '''version 0.2.0'''.
2094
2095<syntax>(c-inexact->exact N)  →  exact number</syntax>
2096
2097CK-macro wrapper for {{inexact->exact}}.
2098Added in '''version 0.2.0'''.
2099
2100<syntax>(c-number->string N)  →  string</syntax>
2101<syntax>(c-number->string N RADIX)  →  string</syntax>
2102
2103CK-macro wrapper for {{number->string}}.
2104Added in '''version 0.2.0'''.
2105
2106<syntax>(c-string->number STR)  →  number or '#f</syntax>
2107<syntax>(c-string->number STR RADIX)  →  number or '#f</syntax>
2108
2109CK-macro wrapper for {{string->number}}.
2110Added in '''version 0.2.0'''.
2111
2112
2113==== Pairs and Lists (R5RS Wrappers)
2114
2115<syntax>(c-length L)  →  integer</syntax>
2116
2117CK-macro wrapper for {{length}}.
2118Added in '''version 0.2.0'''.
2119
2120<syntax>(c-list-ref L I)  →  item</syntax>
2121
2122CK-macro wrapper for {{list-ref}}.
2123Added in '''version 0.2.0'''.
2124
2125
2126==== Symbols (R5RS Wrappers)
2127
2128<syntax>(c-symbol? X)  →  '#t or '#f</syntax>
2129
2130CK-macro wrapper for {{symbol?}}.
2131Added in '''version 0.2.0'''.
2132
2133<syntax>(c-symbol->string SYM)  →  string</syntax>
2134
2135CK-macro wrapper for {{symbol->string}}.
2136Added in '''version 0.2.0'''.
2137
2138<syntax>(c-string->symbol STR)  →  symbol</syntax>
2139
2140CK-macro wrapper for {{string->symbol}}.
2141Added in '''version 0.2.0'''.
2142
2143
2144==== Chars and Strings (R5RS Wrappers)
2145
2146<syntax>(c-char? CHAR ...)  →  '#t or '#f</syntax>
2147
2148CK-macro wrapper for {{char?}}.
2149Added in '''version 0.2.0'''.
2150
2151<syntax>(c-char=? CHAR ...)  →  '#t or '#f</syntax>
2152
2153CK-macro wrapper for {{char=?}}.
2154Added in '''version 0.2.0'''.
2155
2156<syntax>(c-string? X)  →  '#t or '#f</syntax>
2157
2158CK-macro wrapper for {{string?}}.
2159Added in '''version 0.2.0'''.
2160
2161<syntax>(c-string CHAR ...)  →  string</syntax>
2162
2163CK-macro wrapper for {{string}}.
2164Added in '''version 0.2.0'''.
2165
2166<syntax>(c-string-length STR)  →  integer</syntax>
2167
2168CK-macro wrapper for {{string-length}}.
2169Added in '''version 0.2.0'''.
2170
2171<syntax>(c-string-ref STR I)  →  char</syntax>
2172
2173CK-macro wrapper for {{string-ref}}.
2174Added in '''version 0.2.0'''.
2175
2176<syntax>(c-string=? STR ...)  →  '#t or '#f</syntax>
2177
2178CK-macro wrapper for {{string=?}}.
2179Added in '''version 0.2.0'''.
2180
2181<syntax>(c-string-ci=? STR ...)  →  '#t or '#f</syntax>
2182
2183CK-macro wrapper for {{string-ci=?}}.
2184Added in '''version 0.2.0'''.
2185
2186<syntax>(c-substring STR START)  →  string</syntax>
2187<syntax>(c-substring STR START END)  →  string</syntax>
2188
2189CK-macro wrapper for {{substring}}.
2190Added in '''version 0.2.0'''.
2191
2192<syntax>(c-string-append STR ...)  →  string</syntax>
2193
2194CK-macro wrapper for {{string-append}}.
2195Added in '''version 0.2.0'''.
2196
2197
2198==== Vectors (R5RS Wrappers)
2199
2200<syntax>(c-vector-length V)  →  integer</syntax>
2201
2202CK-macro wrapper for {{vector-length}}.
2203Added in '''version 0.2.0'''.
2204
2205<syntax>(c-vector-ref V I)  →  item</syntax>
2206
2207CK-macro wrapper for {{vector-ref}}.
2208Added in '''version 0.2.0'''.
Note: See TracBrowser for help on using the repository browser.