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

Last change on this file since 37322 was 37322, checked in by John Croisant, 23 months ago

Updated ck-macros docs for version 0.2.0.

File size: 50.1 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 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: Public Domain
21
22
23'''Table of Contents'''
24[[toc:]]
25
26
27=== Version History
28
29; 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.
30; 0.1.1 (2016-02-07) : Fixed {{c-append}} and {{c-vector-append}} failing when given one argument.
31; 0.1.0 (2016-02-06) : Initial release. Includes version 1.1 (April 2011) of the core {{ck}} macro. Includes many CK-macros.
32
33For more information about what changed in each version,
34see the [[https://gitlab.com/jcroisant/ck-macros/blob/master/CHANGELOG.md|CHANGELOG]].
35
36
37=== What are CK-macros?
38
39CK-macros are Scheme macros written to be compatible with with the core {{ck}} macro.
40
41The core {{ck}} macro is a {{syntax-rules}} macro which implements the CK abstract machine.
42The CK abstract machine is a theoretical model of computation,
43described in the paper "Control Operators, the SECD-Machine, and the Lambda-Calculus"
44by Matthias Felleisen and Daniel P. Friedman.
45But, you don't need to read or understand the paper in order to create or use CK-macros!
46
47Basically, a CK-macro leverages the core {{ck}} macro
48to recursively expand the CK-macros's arguments first,
49before the CK-macro itself is expanded.
50This gives you more control over the macro expansion process,
51allowing you to easily combine simple reusable macros to form more complex macros.
52
53This is very similar to the way Scheme allows you to easily combine simple resuable functions
54({{map}}, {{fold}}, {{cons}}, etc.) to create more complex functions.
55In fact, many useful Scheme functions can be translated to CK-macros,
56allowing you to portably achieve the same effect at macro-expansion time.
57You can even implement "higher-ordered macros" which take a macro as an argument.
58See {{c-map1}} and {{c-compose}} for examples of higher-ordered macros.
59
60CK-macros are not as flexibile, powerful, or efficient as
61CHICKEN's [[/man/5/Module (chicken syntax)|explicit and implicit renaming macros]],
62but CK-macros are much more portable.
63
64* The [[#ck|core {{ck}} macro]] and everything in the
65  [[#portable-ck-macros|Portable CK-Macros]] section
66  are implemented using only standard R5RS features, such as {{syntax-rules}}.
67  This means they will work on any implementation of R5RS or later.
68
69* The [[#ck-wrapper|{{ck-wrapper}} procedure]] and everything in the
70  [[#non-portable-r5rs-wrappers|Non-portable R5RS Wrappers]] section
71  are implemented using
72  [[/man/5/Module (chicken syntax)#explicit-renaming-macros|{{er-macro-transformer}}]],
73  which is not standard R5RS but is available in many Scheme implementations.
74
75
76=== How to write CK-macros
77
78(Note: If you don't care about strict R5RS portability,
79the easiest way to create a CK-macro is with [[#ck-wrapper|{{ck-wrapper}}]].)
80
81Here is a basic template for portable CK-macros:
82
83<enscript highlight="scheme">
84(define-syntax c-foo
85  (syntax-rules (quote)
86    ((c-foo s 'input1 'input2 ...)
87     (ck s output))))
88</enscript>
89
90A CK-macro is just a normal macro that expands to a call to the core {{ck}} macro.
91To be portable, CK-macros are usually written using {{syntax-rules}}.
92But, you can write CK-macros using other macro systems,
93such as CHICKEN's [[/manual/Macros|explicit and implicit renaming macros]],
94as long your macro eventually expands into a call to the core {{ck}} macro.
95
96By convention, the names of CK-macros usually start with "c-",
97to distinguish them from non-CK macros or procedures with similar names.
98But, this naming convention is not required.
99
100CK-macros treat quoting specially, so you should have {{quote}} in the list of literal identifiers (the first argument to {{syntax-rules}}).
101You can also have other literal identifiers if needed.
102
103Every CK-macro's first argument must be the stack, usually called {{s}}.
104The stack is used internally by the core {{ck}} macro while recursively expanding macro arguments.
105Your CK-macro should not touch the stack, only pass it through to the core {{ck}} macro.
106
107Each {{'input}} is an argument passed to your macro.
108Your macro can have any number of input arguments, and they can be named whatever you want.
109They can also be lists or patterns, allowing you to destructure the arguments,
110as is often done with {{syntax-rules}} macros.
111
112The core {{ck}} macro expands the input arguments ahead of time,
113so the arguments will always be quoted values by the time your macro is expanded.
114Usually CK-macros are defined with their input arguments quoted (as above),
115so that you can easily destructure the input to use in your macro.
116You may recall that {{'a}} is translated by the reader to {{(quote a)}}.
117So, the above example is exactly the same as:
118
119<enscript highlight="scheme">
120(define-syntax c-foo
121  (syntax-rules (quote)
122    ((c-foo s (quote input1) (quote input2) ...)
123     (ck s output))))
124</enscript>
125
126When written in this way, it is easier to see that {{input1}} and {{input2}}
127are merely placeholders in the {{syntax-rules}} pattern.
128(This is also why you must tell {{syntax-rules}} that {{quote}} is a literal identifier.
129Otherwise, {{syntax-rules}} would treat {{quote}} as a placeholder, too.)
130
131Your macro should transform the {{input}}s in some way to produce the {{output}},
132which is passed to the core {{ck}} macro.
133The {{output}} must be either:
134
135* A quoted value, such as {{'a}}, {{'(+ 1 2)}}, {{'"foo"}}, {{'42}}, or {{'#t}}.
136* Or, an unquoted call to a CK-macro '''without the s argument''', such as {{(c-cons '+ '(1 2))}}.
137  Nested calls are allowed, such as {{(c-cons '+ (c-list '1 '2))}}.
138
139Quoting is how the core {{ck}} macro knows the difference between a value and a CK-macro call.
140Therefore, '''all values must be quoted''',
141even values which normally do not need to be quoted in Scheme code,
142such as strings, numbers, and booleans.
143
144Eventually, your CK-macro must expand into a call to the core {{ck}} macro
145with a quoted value.
146We say that the macro "yields" this quoted value.
147The quoted value is either used as an argument to another CK-macro,
148or if your CK-macro is the outer-most CK-macro call,
149then the core {{ck}} macro expands into the '''unquoted value'''.
150
151So, if your CK-macro yields the quoted value {{'(+ 1 2)}},
152and it is the outer-most CK-macro (not an argument to another CK-macro),
153the core {{ck}} macro will expand to the unquoted expression {{(+ 1 2)}},
154which would later be evaluated to the number 3.
155(If you want to yield a quoted form as the final result,
156use {{c-quote}} as the outer-most CK-macro.)
157
158See [[http://okmij.org/ftp/Scheme/macros.html#ck-macros|the original article]]
159or [[https://gitlab.com/jcroisant/ck-macros/blob/master/lib/portable.scm|the source code]]
160for many examples of CK-macros.
161
162
163=== Combining CK and non-CK macros
164
165The arguments to a CK-macro must either be a quoted value or a call to a CK-macro
166(i.e. a macro that expands to a call to the core {{ck}} macro).
167Therefore, most non-CK macros and special forms cannot be used as arguments to a CK-macro.
168
169Some non-CK macros can be used in a way that expands into a user-provided expression.
170It is therefore possible for these non-CK macros to be used as arguments to CK-macros,
171as long as they eventually expand into a call to the core {{ck}} macro.
172
173It is possible to write a non-CK macro which invokes a CK-macro via the core {{ck}} macro.
174For example, if you are writing a macro for other people to use,
175you can create a convenience macro, like so:
176
177<enscript highlight="scheme">
178(define-syntax foo
179  (syntax-rules ()
180    ((foo arg1 arg2 arg3)
181     (ck () (c-foo 'arg1 'arg2 'arg3)))))
182</enscript>
183
184Also, it is possible for a CK-macro to expand into a call to a non-CK macro
185as its final result, or as part of the body of its final result.
186For example:
187
188<enscript highlight="scheme">
189(ck () (c-list 'when (c-list '< '1 '2) (c-list 'print '"Yay!")))
190;;; Expands to the expression (when (< 1 2) (print "Yay!")).
191</enscript>
192
193
194=== Troubleshooting
195
196CK-macros push the Scheme macro system in unusual ways,
197so unfortunately they are not very user-friendly.
198
199One common error you may see is, "no rule matches form".
200This often indicates that you forgot to quote a value somewhere.
201As explained in the section [[#how-to-write-ck-macros|How to write CK-macros]],
202all values must be quoted,
203even values which normally do not need to be quoted in Scheme code,
204such as strings, numbers, and booleans.
205
206For example, the code {{(ck () (c-not #t))}} will result in an error like this:
207
208 Syntax error: no rule matches form
209 
210         (ck38782 (((c-not))) #t)
211
212The solution is to quote the {{#t}}, like this: {{(ck () (c-not '#t))}}
213
214
215=== Known issues and limitations
216
217==== Slow compilation
218
219CK-macros are pretty slow to compile,
220because the computation is done at compile time,
221using ''very'' deeply recursive macro expansions.
222
223Non-portable wrappers created with [[#ck-wrapper|{{ck-wrapper}}]]
224are probably somewhat faster than the portable CK-macros created with {{syntax-rules}}.
225But this library prioritizes portability over efficiency,
226so CK-macros are only implemented as wrappers if it is ''impossible''
227to implement them using {{syntax-rules}}.
228
229You could likely improve compilation speed in your own code by
230redefining various CK-macros using {{ck-wrapper}}.
231
232
233==== Pitfalls of c-sym-eq?
234
235{{c-sym-eq?}} has some strange and unexpected behaviors
236because of the way it uses {{let-syntax}}.
237
238* The behavior of {{c-sym-eq?}} is undefined and non-portable
239  when comparing anything except symbols.
240
241* You should not use {{c-sym-eq?}} in any code that expands
242  into a definition (of a variable, procedure, etc.),
243  because that definition will not be visible from outside.
244  This is because definitions that occur within the body of {{let-syntax}}
245  are internal definitions, not global definitions.
246
247For example, this code will not work as expected:
248
249 (ck () (c-list 'define 'x (c-sym-eq? 'a 'a)))
250
251You might expect it to expand to {{(define x #t)}},
252defining a global variable {{x}} with the value {{#t}}.
253But even though {{c-sym-eq?}} seems to be used "inside" the definition,
254the core {{ck}} macro turns things "inside out"
255to eagerly expand macro arguments first.
256So, the definition will actually appear inside of a {{let-syntax}},
257and {{x}} will not be visible from outside.
258
259These pitfalls also affect other macros that use {{c-sym-eq?}} directly or indirectly:
260
261* {{c-sym-equal?}}
262* {{c-member}} with the default comparison operator
263* {{c-assoc}} with the default comparison operator
264* {{c-alist-delete}} with the default comparison operator
265
266It is believed to be impossible to fix {{c-sym-eq?}} in a portable way,
267so it is recommended that you avoid using it or {{c-sym-equal?}} if possible.
268If you don't care about strict R5RS portability,
269you should use the non-portable wrappers {{c-eq?}} and {{c-equal?}} instead.
270
271
272=== ck
273
274<syntax>(ck s 'v)</syntax>
275<syntax>(ck s (op ...))</syntax>
276
277This is the core {{ck}} macro, which implements the CK abstract machine.
278This macro's public interface has two shapes:
279one with a quoted value, and one with a CK-macro call.
280
281; 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)))}}.
282; 'v : 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.
283; (op ...) : A CK-macro call '''without the s argument''', such as {{(c-cons '+ '(1 2))}}.
284Nested calls are allowed, such as {{(c-cons '+ (c-list '1 '2))}}.
285
286
287=== ck-wrapper
288
289<procedure>(ck-wrapper proc)  →  macro transformer</procedure>
290
291Wrap a procedure in a CK-macro, returning a macro transformer
292that can be used with {{define-syntax}} or {{let-syntax}}.
293
294{{ck-wrapper}} requires '''version 0.2.0 or later''' of the ck-macros egg.
295It is considered '''non-portable''' because it depends on
296[[/man/5/Module (chicken syntax)#explicit-renaming-macros|{{er-macro-transformer}}]],
297which is not defined in standard R5RS.
298However, it should work on any Scheme which defines
299{{er-macro-transformer}} in the usual way.
300
301You can wrap any other expression that evaluates to a procedure,
302such as a procedure name, a lambda form, a "let over lambda" expression, etc.
303The expression will be evaluated once,
304when the call to {{ck-wrapper}} is evaluated.
305Therefore, the procedure you are wrapping must be available
306in the syntax environment at macro expansion time.
307(In other words, you should use
308[[/man/5/Module (chicken syntax)#define-for-syntax|{{define-for-syntax}}]],
309[[/man/5/Modules#import-for-syntax|{{import-for-syntax}}]], etc.)
310
311Examples:
312
313<enscript highlight="scheme">
314;;; Import iota from SRFI 1.
315(cond-expand
316  (chicken-4
317   (use-for-syntax (only srfi-1 iota)))
318  (chicken-5
319   (import-for-syntax (only (srfi 1) iota))))
320
321(define-syntax c-iota (ck-wrapper iota))
322
323(ck () (c-quote (c-iota '5)))
324;; ==> '(0 1 2 3 4)
325
326;;; A helper procedure that returns a closure.
327(define-for-syntax (make-adder n)
328  (lambda (x) (+ x n)))
329
330;;; Temporarily define a ck-wrapper around a closure.
331(let-syntax ((c-add2 (ck-wrapper (make-adder 2))))
332  ;; Map c-add2 over the result of c-iota.
333  (ck () (c-quote (c-map1 '(c-add2) (c-iota '5)))))
334;; ==> '(2 3 4 5 6)
335</enscript>
336
337
338=== Portable CK-Macros
339
340The CK-macros in this section are defined using only standard R5RS features,
341such as {{syntax-rules}} and {{let-syntax}}.
342So, these CK-macros will work on any implementation of R5RS or later.
343
344
345==== General
346
347<syntax>(c-quote X)  →  'X</syntax>
348
349Adds an extra level of quotation to the argument.
350This is useful for macros that should expand to a quoted value.
351
352<enscript highlight="scheme">
353;; Without c-quote
354(ck () (c-cons '+ '(1 2)))
355;; Expands to (+ 1 2), which evaluates to the number 3.
356
357;; With c-quote
358(ck () (c-quote (c-cons '+ '(1 2))))
359;; Expands to '(+ 1 2), a quoted list.
360</enscript>
361
362
363<syntax>(c-eval '(OP ...))  →  result</syntax>
364
365Takes a quoted operation and unquotes it,
366allowing the CK machine to expand it.
367Analogous to {{eval}}.
368
369<enscript highlight="scheme">
370(ck () (c-quote (c-eval '(c-cons 'a 'b))))
371;; ==> '(a . b)
372</enscript>
373
374
375<syntax>(c-call '(OP ...) X ...)  →  result</syntax>
376
377Like {{c-eval}}, but adds the given arguments on to the end of the operation.
378Analogous to a lambda call in normal Scheme code.
379
380<enscript highlight="scheme">
381(ck () (c-quote (c-call '(c-cons 'a) 'b)))
382;; ==> '(a . b)
383</enscript>
384
385
386<syntax>(c-apply '(OP ...) X ... '(Y ...))  →  result</syntax>
387
388Like {{c-call}}, but the last argument is a list of more arguments.
389Analogous to {{apply}}.
390
391<enscript highlight="scheme">
392(ck () (c-quote (c-apply '(c-list) 'a '(b) '(c d))))
393;; ==> '(a (b) c d)
394</enscript>
395
396'''Prior to version 0.2.0''', the arguments in the final list required an extra level of quoting.
397
398
399<syntax>(c-compose '((OP-N ...) ... (OP-1 ...)) X ...)  →  result</syntax>
400
401Compose one or more CK-macros and apply them to the arguments.
402Calls the right-most {{OP}} with the arguments {{X ...}},
403then calls the next-right-most {{OP}} with that result, and so on:
404
405 (OP-N ... (OP-2 ... (OP-1 ... X ...)))
406
407{{OP-1}} must accept all the {{X}}s as arguments,
408and the other {{OP}}s must each accept one argument (the result of the previous operation).
409See also {{c-rcompose}}, which is more efficient.
410Added in '''version 0.2.0'''
411
412
413<enscript highlight="scheme">
414(ck () (c-compose '((c-car) (c-cdr)) '(1 2 3)))
415;; ==> 2
416
417;;; Map over a list of lists to see which are not empty.
418(ck () (c-quote (c-map1 '(c-compose '((c-not) (c-null?)))
419                        '((1) () (2 3)))))
420;; ==> '(#t #f #t)
421</enscript>
422
423
424<syntax>(c-rcompose '((OP-1 ...) ... (OP-N ...)) X ...)  →  result</syntax>
425
426Like {{c-compose}}, but the operations are called in the reverse order (left to right).
427This is more efficient than {{c-compose}}.
428Added in '''version 0.2.0'''
429
430
431<syntax>(c-identity X)  →  X</syntax>
432
433Simply yields the value as given.
434Sometimes useful for higher-order macros like {{c-filter}}.
435
436<enscript highlight="scheme">
437(ck () (c-quote (c-identity 'a)))
438;; ==> 'a
439</enscript>
440
441
442==== Boolean Logic
443
444<syntax>(c-not X)  →  '#t or '#f</syntax>
445
446Yields {{'#t}} if the argument is {{'#f}}, otherwise yields {{'#f}}.
447Analogous to {{not}}.
448
449
450<syntax>(c-true X ...)  →  '#t</syntax>
451
452Always yields {{'#t}}, regardless of its arguments.
453May be useful for some higher-order macros.
454Added in '''version 0.2.0'''.
455
456<enscript highlight="scheme">
457;;; Recursively check if two structure have the same length,
458;;; nesting, etc, while ignoring the value of the atoms.
459(ck () (c-compare? '(c-true) '(1 #(2) 3) '(a #(b) c)))
460;; ==> '#t
461</enscript>
462
463
464<syntax>(c-false X ...)  →  '#f</syntax>
465
466Always yields {{'#f}}, regardless of its arguments.
467May be useful for some higher-order macros.
468Added in '''version 0.2.0'''.
469
470
471<syntax>(c-if TEST PASS FAIL)  →  PASS or FAIL</syntax>
472
473Conditional branching.
474If {{TEST}} is {{'#f}}, this yields {{FAIL}}.
475Otherwise it yields {{PASS}}.
476
477Due to the way the CK machine works, both branches will be expanded,
478then the unneeded branch will be discarded.
479If you only want the needed branch to be expanded
480(e.g. because the branches are complex and slow to expand,
481or because it would be an error to expand the unneeded branch),
482use {{c-if*}} instead.
483
484Analogous to
485{{(lambda (test pass fail) (if test pass fail))}}.
486
487<enscript highlight="scheme">
488(ck () (c-quote (c-if (c-pair? '(x))
489                      'pair
490                      'not-pair)))
491;; ==> 'pair
492
493(ck () (c-quote (c-if (c-pair? 'x)
494                      'pair
495                      'not-pair)))
496;; ==> 'not-pair
497</enscript>
498
499
500<syntax>(c-if* TEST 'PASS 'FAIL)  →  PASS or FAIL</syntax>
501
502Similar to {{c-if}}, except that the branches must have an extra level of quoting,
503and only one branch will be expanded.
504This is more similar to how {{if}} behaves, but it is a bit awkward to use.
505
506Analogous to
507{{(lambda (test pass fail) (if test (eval pass) (eval fail)))}}
508
509<enscript highlight="scheme">
510(ck () (c-quote (c-if* (c-pair? '(x))
511                       '(c-car '(x))
512                       ''not-pair))
513;; ==> 'x
514
515(ck () (c-quote (c-if* (c-pair? 'x)
516                       '(c-car 'x)
517                       ''not-pair))
518;; ==> 'not-pair
519</enscript>
520
521
522<syntax>(c-or X ...)  →  item or '#f</syntax>
523
524Yields the first argument that is not {{'#f}}.
525Yields {{'#f}} if all of the arguments are {{'#f}},
526or if there are no arguments.
527
528Roughly analogous to {{or}}, except all arguments are expanded.
529If you only want to expand the arguments that are needed, use {{c-or*}} instead.
530
531
532<syntax>(c-or* 'X ...)  →  item or '#f</syntax>
533
534Similar to {{c-or}}, except that all the arguments must have an extra level of quoting,
535and the arguments will be expanded one at a time until a non-{{'#f}} value is found.
536This is more similar to how {{or}} behaves, but it is a bit awkward to use.
537
538
539<syntax>(c-and X ...)  →  item or '#f</syntax>
540
541If all arguments are not {{'#f}}, yields the last argument.
542If any of the arguments is {{'#f}}, yields {{'#f}}.
543If there are no arguments, yields {{'#t}}.
544
545Roughly analogous to {{and}}, except all arguments are expanded.
546If you only want to expand the arguments that are needed, use {{c-and*}} instead.
547
548
549<syntax>(c-and* X ...)  →  item or '#f</syntax>
550
551Similar to {{c-and}}, except that all the arguments must have an extra level of quoting,
552and the arguments will be expanded one at a time until a {{'#f}} value is found.
553This is more similar to how {{and}} behaves, but it is a bit awkward to use.
554
555
556<syntax>(c-null? X)  →  '#t or '#f</syntax>
557
558Yields {{'#t}} if {{X}} is the empty list, {{'()}}.
559Otherwise yields {{'#f}}.
560Analogous to {{null?}}.
561
562
563<syntax>(c-pair? X)  →  '#t or '#f</syntax>
564
565Yields {{'#t}} if {{X}} is a dotted pair or a non-empty list.
566Otherwise yields {{'#f}}.
567Analogous to {{pair?}}.
568
569
570<syntax>(c-not-pair? X)  →  '#t or '#f</syntax>
571
572Opposite of {{c-pair?}}.
573Analogous to {{not-pair?}} from SRFI 1.
574
575
576<syntax>(c-vector? X)  →  '#t or '#f</syntax>
577
578Yields {{'#t}} if {{X}} is a vector.
579Otherwise yields {{'#f}}.
580Analogous to {{vector?}}.
581
582<enscript highlight="scheme">
583(ck () (c-quote (c-vector? '#(a))))
584;; ==> '#t
585</enscript>
586
587
588<syntax>(c-boolean? X)  →  '#t or '#f</syntax>
589
590Yields {{'#t}} if {{X}} is either {{'#t}} or {{'#f}}.
591Otherwise yields {{'#f}}.
592Analogous to {{boolean?}}.
593
594
595<syntax>(c-sym-eq? X Y)  →  '#t or '#f</syntax>
596
597'''ATTENTION:''' This CK-macro has [[#pitfalls-of-c-sym-eq|major pitfalls]]
598that you should be aware of.
599If you don't require strict R5RS portability, it is recommended to use {{c-eq?}} instead.
600
601Yields {{'#t}} if {{X}} and {{Y}} are the same symbol, otherwise yields {{'#f}}.
602{{X}} should be a symbol.
603{{Y}} can be any value.
604Some Scheme implementations allow {{X}} to be other types,
605but this macro is only portable if {{X}} is a symbol.
606
607Roughly analogous to {{eq?}},
608except it only works (portably) with symbols.
609Based on {{symbol-eq?}} from the original implementation.
610
611
612<syntax>(c-sym-equal? X Y)  →  '#t or '#f</syntax>
613
614'''ATTENTION:''' This CK-macro has [[#pitfalls-of-c-sym-eq|major pitfalls]]
615that you should be aware of.
616If you don't require strict R5RS portability,
617it is recommended to use {{c-equal?}} instead.
618
619Similar to {{c-sym-eq?}}, except it recursively compares
620pairs, lists, and vectors.
621
622Roughly analogous to {{equal?}},
623except it only works (portably) with symbols, pairs, lists, vectors,
624and nested combinations of those things.
625
626
627<syntax>(c-compare? '(OP ...) X Y)  →  '#t or '#f</syntax>
628
629Recursively compares atoms, pairs, lists, or vectors,
630using {{OP}} as the predicate to compare atoms.
631Similar to {{equal?}} but with a custom predicate.
632Added in '''version 0.2.0'''.
633
634{{OP}} will be called with two arguments:
635an atom of {{X}}, and the corresponding atom of {{Y}}.
636In other words, the Nth atom of {{X}} will be compared with the Nth atom of {{Y}},
637descending recursively into nested structures.
638If {{X}} and {{Y}} are themselves atoms, they are compared directly with {{OP}}.
639
640Yields {{'#f}} if {{X}} and {{Y}} have dissimilar structures (length, nesting, type),
641or if {{OP}} yields {{'#f}} for any corresponding atoms of {{X}} and {{Y}}.
642Otherwise yields '#t.
643
644<enscript highlight="scheme">
645(ck () (c-compare? '(c-string-ci=?) '#("a" ("b")) '#("A" ("B"))))
646;; ==> #t
647
648;;; X is a vector with a list, but Y is a list with a vector.
649;;; The structures are dissimilar.
650(ck () (c-compare? '(c-string-ci=?) '#("a" ("b")) '("a" #("b"))))
651;; ==> #f
652
653;;; Can use any predicate. Here, X and Y have same structure,
654;;; and each atom of X is less than the correponding atom of Y.
655(ck () (c-compare? '(c-<) '(1 #(5)) '(2 #(6))))
656;; ==> #t
657
658;;; Can compare atoms directly.
659(ck () (c-compare? '(c-<) '1 '2))
660;; ==> #t
661</enscript>
662
663
664==== List Processing
665
666<syntax>(c-cons X Y)  →  '(X . Y)</syntax>
667
668Yields a pair with the two given arguments.
669Analogous to {{cons}}.
670
671<enscript highlight="scheme">
672(ck () (c-quote (c-cons 'a 'b)))
673;; ==> '(a . b).
674
675(ck () (c-quote (c-cons '+ '(1 2))))
676;; ==> '(+ 1 2).
677
678(ck () (c-quote (c-cons '+ (c-cons '1 (c-cons '2 '())))))
679;; ==> '(+ 1 2).
680</enscript>
681
682
683<syntax>(c-xcons X Y)  →  '(Y . X)</syntax>
684
685Like {{c-cons}}, but exchanges the order of arguments.
686Analogous to {{xcons}} from SRFI 1.
687
688<enscript highlight="scheme">
689(ck () (c-quote (c-xcons 'a 'b)))
690;; ==> '(b . a).
691</enscript>
692
693
694<syntax>(c-list X ...)  →  list</syntax>
695
696Yields a list containing the given items.
697Analogous to {{list}}.
698
699<enscript highlight="scheme">
700(ck () (c-quote (c-list)))
701;; ==> '()
702(ck () (c-quote (c-list 'a 'b 'c)))
703;; ==> '(a b c)
704</enscript>
705
706
707<syntax>(c-car P)  →  item</syntax>
708
709Yields the head of the given pair.
710Analogous to {{car}}.
711
712<enscript highlight="scheme">
713(ck () (c-quote (c-car '(a . b))))
714;; ==> 'a
715
716(ck () (c-quote (c-car '(a b))))
717;; ==> 'a
718</enscript>
719
720
721<syntax>(c-cdr P)  →  tail</syntax>
722
723Yields the tail of the given pair.
724Analogous to {{cdr}}.
725
726<enscript highlight="scheme">
727(ck () (c-quote (c-cdr '(a . b))))
728;; ==> 'b
729
730(ck () (c-quote (c-cdr '(a b))))
731;; ==> '(b)
732</enscript>
733
734
735<syntax>(c-first   L)  →  item</syntax>
736<syntax>(c-second  L)  →  item</syntax>
737<syntax>(c-third   L)  →  item</syntax>
738<syntax>(c-fourth  L)  →  item</syntax>
739<syntax>(c-fifth   L)  →  item</syntax>
740<syntax>(c-sixth   L)  →  item</syntax>
741<syntax>(c-seventh L)  →  item</syntax>
742<syntax>(c-eighth  L)  →  item</syntax>
743<syntax>(c-ninth   L)  →  item</syntax>
744<syntax>(c-tenth   L)  →  item</syntax>
745
746Yields the Nth item of the given list.
747Fails if the list is too short.
748
749Analogous to {{first}} ... {{tenth}} from SRFI 1.
750
751<enscript highlight="scheme">
752(ck () (c-quote (c-first  '(a b c d e f g h i j k))))  ; ==> 'a
753(ck () (c-quote (c-second '(a b c d e f g h i j k))))  ; ==> 'b
754(ck () (c-quote (c-third  '(a b c d e f g h i j k))))  ; ==> 'c
755;;; ...
756(ck () (c-quote (c-tenth  '(a b c d e f g h i j k))))  ; ==> 'j
757</enscript>
758
759
760<syntax>(c-last L)  →  item</syntax>
761
762Yields the last value of the given list.
763Fails if the list is empty or is not a proper list.
764
765Analogous to {{last}} from SRFI 1.
766
767<enscript highlight="scheme">
768(ck () (c-quote (c-last '(a b c))))    ; ==> 'c
769(ck () (c-quote (c-last '(a b . c))))  ; ==> ERROR!
770</enscript>
771
772
773<syntax>(c-last-pair L)  →  pair</syntax>
774
775Yields the last pair of the given list.
776Fails if the list is empty.
777
778Analogous to {{last-pair}} from SRFI 1.
779
780<enscript highlight="scheme">
781(ck () (c-quote (c-last-pair '(a b c))))    ; ==> '(c)
782(ck () (c-quote (c-last-pair '(a b . c))))  ; ==> '(b . c)
783</enscript>
784
785
786<syntax>(c-drop1 L)  →  list</syntax>
787<syntax>(c-drop2 L)  →  list</syntax>
788<syntax>(c-drop3 L)  →  list</syntax>
789<syntax>(c-drop4 L)  →  list</syntax>
790<syntax>(c-drop5 L)  →  list</syntax>
791
792Drops a predefined number of items from the front of the given list.
793Fails if the list is too short.
794See also {{c-udrop}}.
795
796Analogous to {{(drop L N)}} from SRFI 1.
797
798<enscript highlight="scheme">
799(ck () (c-quote (c-drop1 '(a b c d e f g))))  ; ==> '(b c d e f g)
800(ck () (c-quote (c-drop2 '(a b c d e f g))))  ; ==> '(c d e f g)
801(ck () (c-quote (c-drop3 '(a b c d e f g))))  ; ==> '(d e f g)
802(ck () (c-quote (c-drop4 '(a b c d e f g))))  ; ==> '(e f g)
803(ck () (c-quote (c-drop5 '(a b c d e f g))))  ; ==> '(f g)
804</enscript>
805
806
807<syntax>(c-take1 L)  →  list</syntax>
808<syntax>(c-take2 L)  →  list</syntax>
809<syntax>(c-take3 L)  →  list</syntax>
810<syntax>(c-take4 L)  →  list</syntax>
811<syntax>(c-take5 L)  →  list</syntax>
812
813Yields a list containing a predefined number of items from the front of the given list.
814Fails if the list is too short.
815See also {{c-utake}}.
816
817Analogous to {{(take L N)}} from SRFI 1.
818
819<enscript highlight="scheme">
820(ck () (c-quote (c-take1 '(a b c d e f g))))  ; ==> '(a)
821(ck () (c-quote (c-take2 '(a b c d e f g))))  ; ==> '(a b)
822(ck () (c-quote (c-take3 '(a b c d e f g))))  ; ==> '(a b c)
823(ck () (c-quote (c-take4 '(a b c d e f g))))  ; ==> '(a b c d)
824(ck () (c-quote (c-take5 '(a b c d e f g))))  ; ==> '(a b c d e)
825</enscript>
826
827
828<syntax>(c-reverse L)  →  list</syntax>
829
830Yields the given list in reverse order.
831Fails if the list is not a proper list.
832Analogous to {{reverse}}.
833
834<enscript highlight="scheme">
835(ck () (c-quote (c-reverse '(a b c))))
836;; ==> '(c b a)
837</enscript>
838
839
840<syntax>(c-suffix L X ...)  →  list</syntax>
841
842Yields the given list with the extra arguments added to the end.
843
844<enscript highlight="scheme">
845(ck () (c-quote (c-suffix '(a) 'b 'c)))
846;; ==> '(a b c)
847</enscript>
848
849
850<syntax>(c-append L ...)  →  list</syntax>
851
852Appends the given lists.
853Analogous to {{append}}.
854
855<enscript highlight="scheme">
856(ck () (c-quote (c-append)))
857;; ==> '()
858
859(ck () (c-quote (c-append '(+) (c-append '(1) '(2)))))
860;; ==> '(+ 1 2)
861
862(ck () (c-quote (c-append '(define foo) '((+ 1 2)))))
863;; ==> '(define foo (+ 1 2 3))
864</enscript>
865
866
867<syntax>(c-append-map1 '(OP ...) L)  →  list</syntax>
868
869Yields a list by calling the quoted operation on each item in the list,
870then appending the results.
871The operation must be a CK-macro that yields a list.
872The operation may have leading arguments.
873
874Analogous to {{append-map}} from SFRI-1, but only accepts one list.
875'''Prior to version 0.2.0''', this was named {{c-append-map}}.
876This was named {{c-concatMap}} in the original implementation.
877
878<enscript highlight="scheme">
879(ck () (c-quote (c-append-map1 '(c-list 'a 'b) '(1 2))))
880;; ==> '(a b 1 a b 2)
881</enscript>
882
883
884<syntax>(c-map1 '(OP ...) L)  →  list</syntax>
885
886Yields a list by calling the quoted operation on each item in the given list.
887The operation may have leading arguments.
888Analogous to {{map}}, but only accepts one list.
889(See also {{c-map2}} ... {{c-map5}} for versions that accept more lists.)
890'''Prior to version 0.2.0''', this was named {{c-map}}.
891
892<enscript highlight="scheme">
893(ck () (c-quote (c-map1 '(c-cons 'a) '(1 2))))
894;; ==> '((a . 1) (a . 2))
895</enscript>
896
897
898<syntax>(c-map2 '(OP ...) L1 L2)  →  list</syntax>
899<syntax>(c-map3 '(OP ...) L1 L2 L3)  →  list</syntax>
900<syntax>(c-map4 '(OP ...) L1 L2 L3 L4)  →  list</syntax>
901<syntax>(c-map5 '(OP ...) L1 L2 L3 L4 L5)  →  list</syntax>
902
903Like {{c-map1}}, but they accept exactly two, three, four, or five lists respectively.
904{{OP}} must accept the two, three, four, or five extra arguments.
905If the lists are different lengths, terminates when the shortest list runs out.
906Analogous to {{map}} from SRFI 1, but they accept a specific number of lists.
907Added in '''version 0.2.0'''.
908
909<enscript highlight="scheme">
910;; The argument '(1 2) is shortest so the result only has two items.
911(ck () (c-quote (c-map3 '(c-list) '(a b c) '(1 2) '(x y z))))
912;; ==> '((a 1 x) (b 2 y))
913</enscript>
914
915
916<syntax>(c-fold1 '(OP ...) INIT L)  →  result</syntax>
917
918Yield a value by repeatedly calling the quoted operation
919with each item from the list plus the previous result.
920
921If the list is empty, yields {{INIT}}.
922Otherwise, the operation is first called with two arguments:
923the first item of the list, and INIT.
924Then, the operation is repeatedly called with the next item of the list and the previous result,
925until it reaches the end of the list.
926Yields the final result.
927
928Analogous to {{fold}} from SRFI 1, but only accepts one list.
929'''Prior to version 0.2.0''', this was named {{c-fold}}.
930
931<enscript highlight="scheme">
932(ck () (c-quote (c-fold1 '(c-cons) '(x) '())))
933;; ==> '(x)
934(ck () (c-quote (c-fold1 '(c-cons) '(x) '(a b c d e f))))
935;; ==> '(f e d c b a x)
936</enscript>
937
938
939<syntax>(c-filter '(OP ...) L)  →  list</syntax>
940
941Yields a list by calling the quoted operation on each item in the given list,
942and discarding any item for which the test yields {{'#f}}.
943Analogous to {{filter}} from SRFI 1.
944
945<enscript highlight="scheme">
946(ck () (c-quote (c-filter '(c-pair?)
947                          '(a (b . c) 1 (d e) #t))))
948;; ==> '((b . c) (d e))
949</enscript>
950
951
952<syntax>(c-remove '(OP ...) L)  →  list</syntax>
953
954Opposite of {{c-filter}}.
955Discards items that pass the test, keeps items that fail the test.
956Analogous to {{remove}} from SRFI 1.
957
958<enscript highlight="scheme">
959(ck () (c-quote (c-remove '(c-pair?)
960                          '(a (b . c) 1 (d e) #t))))
961;; ==> '(a 1 #t)
962</enscript>
963
964
965<syntax>(c-find '(OP ...) L)  →  item or '#f</syntax>
966
967Searches the list for the first item that passes the predicate operation
968(i.e. the predicate yields a non-{{'#f}} value),
969then yields that item.
970Yields {{'#f}} if no item passes the predicate.
971
972Analogous to {{find}} from SRFI 1.
973
974<enscript highlight="scheme">
975(ck () (c-quote (c-find '(c-pair?)
976                        '(a (b . c) 1 (d e) #t))))
977;; ==> '(b . c)
978</enscript>
979
980
981<syntax>(c-find-tail '(OP ...) L)  →  pair or '#f</syntax>
982
983Searches the list for the first item that passes the predicate operation
984(i.e. the predicate yields a non-{{'#f}} value),
985then yields the tail of the list starting with that item.
986Yields {{'#f}} if no item passes the predicate.
987
988Analogous to {{find-tail}} from SRFI 1.
989
990<enscript highlight="scheme">
991(ck () (c-quote (c-find-tail '(c-pair?)
992                             '(a (b . c) 1 (d e) #t))))
993;; ==> '((b . c) 1 (d e) #t)
994</enscript>
995
996
997<syntax>(c-member X L)  →  '#t or '#f</syntax>
998<syntax>(c-member X L '(OP ...))  →  '#t or '#f</syntax>
999
1000'''ATTENTION:''' When using the default comparison operator,
1001this CK-macro has [[#pitfalls-of-c-sym-eq|major pitfalls]] that you should be aware of.
1002If you don't require strict R5RS portability,
1003it is recommended to use the comparison operator {{'(c-equal?)}} instead.
1004
1005Searches the list for the first occurance of {{X}},
1006then yields the tail of the list starting with that item.
1007Yields {{'#f}} if the list does not contain {{X}}.
1008
1009Uses {{'(OP ...)}} for comparison,
1010or {{'(c-sym-equal?)}} if the operation is omitted.
1011So by default, {{X}} must be a symbol, list, pair, vector,
1012or nested combination of those things.
1013
1014Same as {{(c-find-tail '(OP ... X) L)}}.
1015Roughly analogous to {{member}} except for the default allowed types.
1016
1017<enscript highlight="scheme">
1018(ck () (c-quote (c-member 'b '(a b c))))
1019;; ==> '(b c)
1020
1021(ck () (c-quote (c-member 'x '(a b c))))
1022;; ==> '#f
1023
1024(ck () (c-quote (c-member '(a b c)
1025                          '((a) (x y z) (a b))
1026                          '(c-u=))))
1027;; ==> '((x y z) (a b))
1028;; Because (c-u= '(a b c) '(x y z)) yields '#t
1029</enscript>
1030
1031
1032<syntax>(c-any1 '(OP ...) L)  →  result or '#f</syntax>
1033
1034Calls the operation on each value in the given list
1035until it finds a result that is not {{'#f}}, then yields that result.
1036Yields {{'#f}} if the predicate yields {{'#f}} for all items in the list,
1037or if the list is empty.
1038
1039Analogous to {{any}} from SRFI 1, but only accepts one list.
1040'''Prior to version 0.2.0''', this was named {{c-any}}.
1041
1042<enscript highlight="scheme">
1043(ck () (c-quote (c-any1 '(c-pair?) '())))
1044;; ==> '#f
1045(ck () (c-quote (c-any1 '(c-pair?) '(a b c))))
1046;; ==> '#f
1047(ck () (c-quote (c-any1 '(c-pair?) '(a (b . c)))))
1048;; ==> '#t
1049
1050(ck () (c-quote (c-any1 '(c-cons 'z) '(a b c))))
1051;; ==> '(1 . a)
1052;; Because (c-cons 'z 'a) yields a value that is not '#f.
1053</enscript>
1054
1055
1056<syntax>(c-every1 '(OP ...) L)  →  result or '#f</syntax>
1057
1058Calls the operation on each value in the given list
1059until it finds a result that is {{'#f}}, then yields {{'#f}}.
1060If the predicate yields a non-{{'#f}} value for every item in the list,
1061this yields the result of calling the predicate on the last item.
1062Yields {{'#t}} if the list is empty.
1063
1064Analogous to {{every}} from SRFI 1, but only accepts one list.
1065'''Prior to version 0.2.0''', this was named {{c-every}}.
1066
1067<enscript highlight="scheme">
1068(ck () (c-quote (c-every1 '(c-pair?) '())))
1069;; ==> '#t
1070(ck () (c-quote (c-every1 '(c-pair?) '(a (b . c)))))
1071;; ==> '#f
1072(ck () (c-quote (c-every1 '(c-pair?) '((a . b) (b . c)))))
1073;; ==> '#t
1074
1075(ck () (c-quote (c-every1 '(c-cons 'z) '(a b c))))
1076;; ==> '(z . c)
1077;; Because all results were non-'#f and (c-cons 'z 'c) was the final operation.
1078</enscript>
1079
1080
1081<syntax>(c-assoc KEY ALIST)  →  pair or '#f</syntax>
1082<syntax>(c-assoc KEY ALIST '(OP ...))  →  pair or '#f</syntax>
1083
1084'''ATTENTION:''' When using the default comparison operator,
1085this CK-macro has [[#pitfalls-of-c-sym-eq|major pitfalls]] that you should be aware of.
1086If you don't require strict R5RS portability,
1087it is recommended to use the comparison operator {{'(c-equal?)}} instead.
1088
1089Searches {{ALIST}} for the first pair whose car matches {{KEY}},
1090then yields that pair.
1091Yields {{'#f}} if no match is found.
1092{{ALIST}} must be an association list, i.e. a list of pairs.
1093
1094Uses {{'(OP ...)}} for comparison,
1095or {{'(c-sym-equal?)}} if {{'(OP ...)}} is omitted.
1096
1097Analogous to {{assoc}} from SRFI 1.
1098
1099<enscript highlight="scheme">
1100(ck () (c-quote (c-assoc 'x '((a . 1) (b . 2) (a . 3)))))
1101;; ==> '#f
1102(ck () (c-quote (c-assoc 'a '((a . 1) (b . 2) (a . 3)))))
1103;; ==> '(a . 1)
1104(ck () (c-quote (c-assoc '(a) '((a . 1) (b . 2) ((a) . 3)))))
1105;; ==> '((a) . 3)
1106</enscript>
1107
1108
1109<syntax>(c-alist-delete KEY ALIST)  →  list</syntax>
1110<syntax>(c-alist-delete KEY ALIST '(OP ...))  →  list</syntax>
1111
1112'''ATTENTION:''' When using the default comparison operator,
1113this CK-macro has [[#pitfalls-of-c-sym-eq|major pitfalls]] that you should be aware of.
1114If you don't require strict R5RS portability,
1115it is recommended to use the comparison operator {{'(c-equal?)}} instead.
1116
1117Removes all pairs in {{ALIST}} whose car matches {{KEY}}.
1118{{ALIST}} must be an association list, i.e. a list of pairs.
1119
1120Uses {{'(OP ...)}} for comparison,
1121or {{'(c-sym-equal?)}} if {{'(OP ...)}} is omitted.
1122
1123Analogous to {{alist-delete}} from SRFI 1.
1124Based on {{c-delete-assoc}} from the original implementation.
1125
1126<enscript highlight="scheme">
1127(ck () (c-quote (c-alist-delete 'a '((a . 1) (b . 2) (a . 3) (c . 4)))))
1128;; ==> '((b . 2) (c . 4)
1129(ck () (c-quote (c-alist-delete '(a) '((a . 1) (b . 2) ((a) . 3)))))
1130;; ==> '((a . 1) (b . 2))
1131</enscript>
1132
1133
1134==== Vector Processing
1135
1136<syntax>(c-vector X ...)  →  vector</syntax>
1137
1138Yields a vector containing the given items.
1139Analogous to {{vector}}.
1140
1141
1142<syntax>(c-list->vector L)  →  vector</syntax>
1143
1144Yields a vector containing the same items as the given list.
1145Analogous to {{list->vector}} from SRFI 43.
1146
1147
1148<syntax>(c-vector->list V)  →  list</syntax>
1149
1150Yields a list containing the same items as the given vector.
1151Analogous to {{vector->list}} from SRFI 43.
1152
1153
1154<syntax>(c-vector-reverse V)  →  vector</syntax>
1155
1156Yields the given vector in reverse order.
1157Similar to {{vector-reverse-copy}} from SRFI 43,
1158but does not take a start or end argument.
1159
1160
1161<syntax>(c-vector-suffix V X ...)  →  vector</syntax>
1162
1163Yields the given vector with the extra arguments added to the end.
1164
1165<enscript highlight="scheme">
1166(ck () (c-quote (c-vector-suffix '#(a b) 'c 'd)))
1167;; ==> '#(a b c d)
1168</enscript>
1169
1170
1171<syntax>(c-vector-append V ...)  →  vector</syntax>
1172
1173Appends the given vectors.
1174Analogous to {{vector-append}} from SRFI 43,
1175but only accepts two vectors.
1176
1177<enscript highlight="scheme">
1178(ck () (c-quote (c-vector-append)))
1179;; ==> '#()
1180
1181(ck () (c-quote (c-vector-append '#(a b) '#(c d) '#(e f))))
1182;; ==> '#(a b c d e f)
1183</enscript>
1184
1185
1186<syntax>(c-vector-map1 '(OP ...) V)  →  vector</syntax>
1187
1188Yields a vector by calling the quoted operation on each item in the given vector.
1189The operation may have leading arguments.
1190
1191Analogous to {{vector-map}} from SRFI 43, but only accepts one vector.
1192'''Prior to version 0.2.0''', this was named {{c-vector-map}}.
1193
1194
1195==== Unary Math
1196
1197The CK-macros in this section perform mathematical operations by treating lists as unary numbers.
1198Unary math is pretty slow for large values or complex operations,
1199but it is interesting, portable, and maybe even useful in some cases.
1200
1201Unary numbers are a way of representing non-negative integers as a list of a certain length.
1202For example, the list {{'(a b c d e)}} means the number 5,
1203and the list {{'()}} means the number 0.
1204The contents of the list do not matter, only the length.
1205Negative numbers and non-integral numbers cannot be represented in unary.
1206
1207
1208<syntax>(c-u= U1 U2)  →  '#t or '#f</syntax>
1209
1210Unary equality.
1211Yields {{'#t}} if the two lists have the same lengths,
1212otherwise yields {{'#f}}.
1213
1214<enscript highlight="scheme">
1215(ck () (c-quote (c-u= '(a b c) '(a b c))))
1216;; ==> '#t
1217(ck () (c-quote (c-u= '(1 2 3) '(a b c))))
1218;; ==> '#t
1219(ck () (c-quote (c-u= '(1 2) '(a b c))))
1220;; ==> '#f
1221</enscript>
1222
1223
1224<syntax>(c-u< U1 U2)  →  '#t or '#f</syntax>
1225
1226Unary less-than.
1227Yields {{'#t}} if the first list is shorter than the second list,
1228otherwise yields {{'#f}}.
1229
1230<enscript highlight="scheme">
1231(ck () (c-quote (c-u< '(1 2) '(a b c))))
1232;; ==> '#t
1233(ck () (c-quote (c-u< '(1 2 3) '(a b c))))
1234;; ==> '#f
1235</enscript>
1236
1237
1238<syntax>(c-u<= U1 U2)  →  '#t or '#f</syntax>
1239
1240Unary less-than-or-equals.
1241Yields {{'#t}} if first list is the same length or shorter than the second list,
1242otherwise yields {{'#f}}.
1243
1244<enscript highlight="scheme">
1245(ck () (c-quote (c-u<= '(1 2) '(a b c))))
1246;; ==> '#t
1247(ck () (c-quote (c-u<= '(1 2 3) '(a b c))))
1248;; ==> '#t
1249(ck () (c-quote (c-u<= '(1 2 3 4) '(a b c))))
1250;; ==> '#f
1251</enscript>
1252
1253
1254<syntax>(c-u> U1 U2)  →  '#t or '#f</syntax>
1255
1256Unary greater-than.
1257Yields {{'#t}} if the first list is longer than the second list,
1258otherwise yields {{'#f}}.
1259
1260<enscript highlight="scheme">
1261(ck () (c-quote (c-u> '(1 2 3 4) '(a b c))))
1262;; ==> '#t
1263(ck () (c-quote (c-u> '(1 2 3) '(a b c))))
1264;; ==> '#f
1265</enscript>
1266
1267
1268<syntax>(c-u>= U1 U2)  →  '#t or '#f</syntax>
1269
1270Unary greater-than-or-equals.
1271Yields {{'#t}} if first list is same length or longer than the second list,
1272otherwise yields {{'#f}}.
1273
1274<enscript highlight="scheme">
1275(ck () (c-quote (c-u>= '(1 2 3 4) '(a b c))))
1276;; ==> '#t
1277(ck () (c-quote (c-u>= '(1 2 3) '(a b c))))
1278;; ==> '#t
1279(ck () (c-quote (c-u>= '(1 2) '(a b c))))
1280;; ==> '#f
1281</enscript>
1282
1283
1284<syntax>(c-uzero? U)  →  '#t or '#f</syntax>
1285
1286Unary {{zero?}}.
1287Yields {{'#t}} if the list is empty, otherwise yields {{'#f}}.
1288Same as {{c-null?}}.
1289
1290<enscript highlight="scheme">
1291(ck () (c-quote (c-uzero? '())))
1292;; ==> '#t
1293(ck () (c-quote (c-uzero? '(a))))
1294;; ==> '#f
1295</enscript>
1296
1297
1298<syntax>(c-ueven? U)  →  '#t or '#f</syntax>
1299
1300Unary {{even?}}.
1301Yields {{'#t}} if the given list's length is even
1302(i.e. a multiple of 2), otherwise yields {{'#f}}.
1303
1304<enscript highlight="scheme">
1305(ck () (c-quote (c-ueven? '())))
1306;; ==> '#t
1307(ck () (c-quote (c-ueven? '(a))))
1308;; ==> '#f
1309(ck () (c-quote (c-ueven? '(a b))))
1310;; ==> '#t
1311</enscript>
1312
1313
1314<syntax>(c-uodd? U)  →  '#t or '#f</syntax>
1315
1316Unary {{odd?}}.
1317Yields {{'#t}} if the given list's length is odd
1318(i.e. not a multiple of 2), otherwise yields {{'#f}}.
1319
1320<enscript highlight="scheme">
1321(ck () (c-quote (c-uodd? '())))
1322;; ==> '#f
1323(ck () (c-quote (c-uodd? '(a))))
1324;; ==> '#t
1325(ck () (c-quote (c-uodd? '(a b))))
1326;; ==> '#f
1327</enscript>
1328
1329
1330<syntax>(c-u+ U1 U2)  →  list</syntax>
1331
1332Unary addition.
1333Same as {{c-append}}.
1334This was named {{c-add}} in the original implementation.
1335
1336<enscript highlight="scheme">
1337(ck () (c-quote (c-u+ '(a b) '(c))))
1338;; ==> '(a b c)
1339</enscript>
1340
1341
1342<syntax>(c-u- U1 U2)  →  list</syntax>
1343
1344Unary subtraction.
1345Drops an element from the front of the first list for each element in second list,
1346then yields the remaining list.
1347Negative numbers cannot be represented in unary,
1348so this yields '() if the second list is equal or longer than the first.
1349
1350<enscript highlight="scheme">
1351(ck () (c-quote (c-u- (c-list 'a 'b 'c 'd) '(x y))))
1352;; ==> '(c d)
1353
1354(ck () (c-quote (c-u- (c-list 'a 'b) (c-list 'x 'y 'z))))
1355;; ==> '()
1356;; Because negative numbers cannot be represented in unary.
1357</enscript>
1358
1359
1360<syntax>(c-u* U1 U2)  →  list</syntax>
1361
1362Unary multiplication.
1363Yields a list containing the contents of the first list,
1364repeated once for every item in the second list.
1365
1366Based on {{c-mul}} from the original implementation,
1367except the symbol 'u has no special significance,
1368and result is made from duplicating the first list.
1369
1370<enscript highlight="scheme">
1371(ck () (c-quote (c-u* '(a b) '(c d e))))
1372;; ==> '(a b a b a b)
1373</enscript>
1374
1375
1376<syntax>(c-u/ U1 U2)  →  list</syntax>
1377
1378Unary division.
1379Yields a list of two unary numbers,
1380representing the quotient and the remainder of the division.
1381
1382Given the second list has length {{N}},
1383the quotient will contain every {{N}}th item from the first list,
1384and the remainder will contain the tail of the first list.
1385Division by zero (empty list) is a syntax error.
1386
1387<enscript highlight="scheme">
1388(ck () (c-quote (c-u/ '(a b c d e f g h i j k)
1389                      '(x y z))))
1390;; ==> '((g d a) (j k))
1391;; Because 11 / 3 = 3 with a remainder of 2.
1392</enscript>
1393
1394
1395<syntax>(c-ufactorial U)  →  list</syntax>
1396
1397Unary factorial.
1398If the given list has length zero, yields the list {{'(u)}}.
1399If the given list has length one, yields the given list.
1400Otherwise, yields a list containing items of the given list repeated {{(N-1)!}} times,
1401where {{N}} is the length of the given list.
1402This was named {{c-fact}} in the original implementation.
1403
1404<enscript highlight="scheme">
1405(ck () (c-quote (c-ufactorial '(a b c))))
1406;; ==> '(a b c a b c)
1407;; Because 3! = 6.
1408</enscript>
1409
1410
1411<syntax>(c-udrop L U)  →  list</syntax>
1412
1413Drops up to U items from the front of the given list,
1414where U is a unary number.
1415
1416Same as {{c-u-}}.
1417Analogous to {{drop}} from SRFI 1,
1418but uses unary numbers,
1419and yields empty list if the list is too short.
1420
1421<enscript highlight="scheme">
1422(ck () (c-quote (c-udrop (c-list 'a 'b 'c 'd) '(x y))))
1423;; ==> '(c d)
1424(ck () (c-quote (c-udrop (c-list 'a 'b) (c-list 'x 'y 'z))))
1425;; ==> '()
1426</enscript>
1427
1428
1429<syntax>(c-utake L U)  →  list</syntax>
1430
1431Yields a list containing up to U items from the front of the given list,
1432where U is a unary number.
1433
1434Analogous to {{take}} from SRFI 1,
1435but uses unary numbers,
1436and yields the entire list if it is too short.
1437
1438<enscript highlight="scheme">
1439(ck () (c-quote (c-utake '(a b c d) '(x y z))))
1440;; ==> '(a b c)
1441(ck () (c-quote (c-utake '(a b) '(x y z))))
1442;; ==> '(a b)
1443</enscript>
1444
1445
1446
1447=== Non-portable R5RS Wrappers
1448
1449These are CK-macros that wrap some R5RS procedures that are useful for building macros.
1450Not every R5RS procedure is provided here.
1451If you need other procedures, use [[#ck-wrapper|{{ck-wrapper}}]]
1452to create your own wrappers.
1453
1454These wrappers are considered non-portable because they use ck-wrapper,
1455which is not portable to all R5RS Scheme implementations.
1456See the ck-wrapper docs for portability information.
1457
1458Some R5RS procedures have portable, non-wrapper CK-macro equivalents,
1459which are described in the [[#portable-ck-macros|Portable CK-macros]] section, above.
1460For example, there is no wrapper for {{pair?}} listed below,
1461because {{c-pair?}} is a portable CK-macro listed above.
1462
1463
1464==== General (R5RS Wrappers)
1465
1466<syntax>(c-eqv? X Y)  →  '#t or '#f</syntax>
1467
1468CK-macro wrapper for {{eqv?}}.
1469Added in '''version 0.2.0'''.
1470
1471<syntax>(c-eq? X Y)  →  '#t or '#f</syntax>
1472
1473CK-macro wrapper for {{eq?}}.
1474Added in '''version 0.2.0'''.
1475
1476<syntax>(c-equal? X Y)  →  '#t or '#f</syntax>
1477
1478CK-macro wrapper for {{equal?}}.
1479Added in '''version 0.2.0'''.
1480
1481
1482==== Numbers and Math (R5RS Wrappers)
1483
1484<syntax>(c-number? X)  →  '#t or '#f</syntax>
1485
1486CK-macro wrapper for {{number?}}.
1487Added in '''version 0.2.0'''.
1488
1489<syntax>(c-integer? X)  →  '#t or '#f</syntax>
1490
1491CK-macro wrapper for {{integer?}}.
1492Added in '''version 0.2.0'''.
1493
1494<syntax>(c-= N ...)  →  '#t or '#f</syntax>
1495
1496CK-macro wrapper for {{=}} (equal).
1497Added in '''version 0.2.0'''.
1498
1499<syntax>(c-< N ...)  →  '#t or '#f</syntax>
1500
1501CK-macro wrapper for {{<}} (less than).
1502Added in '''version 0.2.0'''.
1503
1504<syntax>(c-> N ...)  →  '#t or '#f</syntax>
1505
1506CK-macro wrapper for {{>}} (greater than).
1507Added in '''version 0.2.0'''.
1508
1509<syntax>(c-<= N ...)  →  '#t or '#f</syntax>
1510
1511CK-macro wrapper for {{<=}} (less than or equal).
1512Added in '''version 0.2.0'''.
1513
1514<syntax>(c->= N ...)  →  '#t or '#f</syntax>
1515
1516CK-macro wrapper for {{>=}} (greater than or equal).
1517Added in '''version 0.2.0'''.
1518
1519<syntax>(c-max N ...)  →  number</syntax>
1520
1521CK-macro wrapper for {{max}}.
1522Added in '''version 0.2.0'''.
1523
1524<syntax>(c-min N ...)  →  number</syntax>
1525
1526CK-macro wrapper for {{min}}.
1527Added in '''version 0.2.0'''.
1528
1529<syntax>(c-+ N ...)  →  number</syntax>
1530
1531CK-macro wrapper for {{+}} (addition).
1532Added in '''version 0.2.0'''.
1533
1534<syntax>(c-* N ...)  →  number</syntax>
1535
1536CK-macro wrapper for {{*}} (multiplication).
1537Added in '''version 0.2.0'''.
1538
1539<syntax>(c-- N ...)  →  number</syntax>
1540
1541CK-macro wrapper for {{-}} (subtraction).
1542Added in '''version 0.2.0'''.
1543
1544<syntax>(c-/ N ...)  →  number</syntax>
1545
1546CK-macro wrapper for {{/}} (division).
1547Added in '''version 0.2.0'''.
1548
1549<syntax>(c-remainder N1 N2)  →  number</syntax>
1550
1551CK-macro wrapper for {{remainder}}.
1552Added in '''version 0.2.0'''.
1553
1554<syntax>(c-floor N)  →  number</syntax>
1555
1556CK-macro wrapper for {{floor}}.
1557Added in '''version 0.2.0'''.
1558
1559<syntax>(c-round N)  →  number</syntax>
1560
1561CK-macro wrapper for {{round}}.
1562Added in '''version 0.2.0'''.
1563
1564<syntax>(c-exact->inexact N)  →  inexact number</syntax>
1565
1566CK-macro wrapper for {{exact->inexact}}.
1567Added in '''version 0.2.0'''.
1568
1569<syntax>(c-inexact->exact N)  →  exact number</syntax>
1570
1571CK-macro wrapper for {{inexact->exact}}.
1572Added in '''version 0.2.0'''.
1573
1574<syntax>(c-number->string N)  →  string</syntax>
1575<syntax>(c-number->string N RADIX)  →  string</syntax>
1576
1577CK-macro wrapper for {{number->string}}.
1578Added in '''version 0.2.0'''.
1579
1580<syntax>(c-string->number STR)  →  number or '#f</syntax>
1581<syntax>(c-string->number STR RADIX)  →  number or '#f</syntax>
1582
1583CK-macro wrapper for {{string->number}}.
1584Added in '''version 0.2.0'''.
1585
1586
1587==== Pairs and Lists (R5RS Wrappers)
1588
1589<syntax>(c-length L)  →  integer</syntax>
1590
1591CK-macro wrapper for {{length}}.
1592Added in '''version 0.2.0'''.
1593
1594<syntax>(c-list-ref L I)  →  item</syntax>
1595
1596CK-macro wrapper for {{list-ref}}.
1597Added in '''version 0.2.0'''.
1598
1599
1600==== Symbols (R5RS Wrappers)
1601
1602<syntax>(c-symbol? X)  →  '#t or '#f</syntax>
1603
1604CK-macro wrapper for {{symbol?}}.
1605Added in '''version 0.2.0'''.
1606
1607<syntax>(c-symbol->string SYM)  →  string</syntax>
1608
1609CK-macro wrapper for {{symbol->string}}.
1610Added in '''version 0.2.0'''.
1611
1612<syntax>(c-string->symbol STR)  →  symbol</syntax>
1613
1614CK-macro wrapper for {{string->symbol}}.
1615Added in '''version 0.2.0'''.
1616
1617
1618==== Chars and Strings (R5RS Wrappers)
1619
1620<syntax>(c-char? CHAR ...)  →  '#t or '#f</syntax>
1621
1622CK-macro wrapper for {{char?}}.
1623Added in '''version 0.2.0'''.
1624
1625<syntax>(c-char=? CHAR ...)  →  '#t or '#f</syntax>
1626
1627CK-macro wrapper for {{char=?}}.
1628Added in '''version 0.2.0'''.
1629
1630<syntax>(c-string? X)  →  '#t or '#f</syntax>
1631
1632CK-macro wrapper for {{string?}}.
1633Added in '''version 0.2.0'''.
1634
1635<syntax>(c-string CHAR ...)  →  string</syntax>
1636
1637CK-macro wrapper for {{string}}.
1638Added in '''version 0.2.0'''.
1639
1640<syntax>(c-string-length STR)  →  integer</syntax>
1641
1642CK-macro wrapper for {{string-length}}.
1643Added in '''version 0.2.0'''.
1644
1645<syntax>(c-string-ref STR I)  →  char</syntax>
1646
1647CK-macro wrapper for {{string-ref}}.
1648Added in '''version 0.2.0'''.
1649
1650<syntax>(c-string=? STR ...)  →  '#t or '#f</syntax>
1651
1652CK-macro wrapper for {{string=?}}.
1653Added in '''version 0.2.0'''.
1654
1655<syntax>(c-string-ci=? STR ...)  →  '#t or '#f</syntax>
1656
1657CK-macro wrapper for {{string-ci=?}}.
1658Added in '''version 0.2.0'''.
1659
1660<syntax>(c-substring STR START)  →  string</syntax>
1661<syntax>(c-substring STR START END)  →  string</syntax>
1662
1663CK-macro wrapper for {{substring}}.
1664Added in '''version 0.2.0'''.
1665
1666<syntax>(c-string-append STR ...)  →  string</syntax>
1667
1668CK-macro wrapper for {{string-append}}.
1669Added in '''version 0.2.0'''.
1670
1671
1672==== Vectors (R5RS Wrappers)
1673
1674<syntax>(c-vector-length V)  →  integer</syntax>
1675
1676CK-macro wrapper for {{vector-length}}.
1677Added in '''version 0.2.0'''.
1678
1679<syntax>(c-vector-ref V I)  →  item</syntax>
1680
1681CK-macro wrapper for {{vector-ref}}.
1682Added in '''version 0.2.0'''.
Note: See TracBrowser for help on using the repository browser.