-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathsrfi-105-1.5.html
More file actions
2015 lines (1878 loc) · 86 KB
/
srfi-105-1.5.html
File metadata and controls
2015 lines (1878 loc) · 86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!--
SPDX-FileCopyrightText: 2012 Alan Manuel K. Gloria
SPDX-FileCopyrightText: 2012 David A. Wheeler
SPDX-License-Identifier: MIT
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>SRFI 105: Curly-infix-expressions</title>
<meta content="text/html; charset=us-ascii" http-equiv="content-type">
</head>
<body>
<!-- This commented out text is for the brittle SRFI tools -->
<!--
<H1>Title</H1>
Curly-infix-expressions
<H1>Author</H1>
David A. Wheeler, Alan Manuel K. Gloria
<H1>Status</H1>
This SRFI is currently in ``draft'' status.
-->
<h1 id="title">Title</h1>
<p>Curly-infix-expressions</p>
<h1 id="author" id="authors">Authors</h1>
<p><a href="http://www.dwheeler.com">David A. Wheeler</a></p>
<p>Alan Manuel K. Gloria</p>
<h1 id="status">Status</h1>
<p>
This SRFI is currently in ``draft'' status. To see an explanation of
each status that a SRFI can hold, see <a
href="http://srfi.schemers.org/srfi-process.html">here</a>.
To provide input on this SRFI, please
<a href="mailto:srfi minus 105 at srfi dot schemers dot org">mail to
<code><srfi minus 105 at srfi dot schemers dot org></code></a>. See
<a href="../../srfi-list-subscribe.html">instructions here</a> to
subscribe to the list. You can access previous messages via
<a href="mail-archive/maillist.html">the archive of the mailing list</a>.
</p>
<ul>
<li>
Received: <a href="http://srfi.schemers.org/srfi-105/srfi-105-1.2.html">2012/08/22</a></li>
<li>Draft: 2012/08/22-2012/10/22</li>
<li>Revision: <a href="http://srfi.schemers.org/srfi-105/srfi-105-1.3.html">2012/09/03</a></li>
<li>Revision: <a href="http://srfi.schemers.org/srfi-105/srfi-105-1.4.html">2012/09/08</a></li>
<li>Revision: <a href="http://srfi.schemers.org/srfi-105/srfi-105-1.5.html">2012/09/17</a></li>
</ul>
<h1><a name="related-srfis">Related SRFIs</a></h1>
<p>None</p>
<h1><a name="abstract">Abstract</a></h1>
<p>Lisp-based languages, like Scheme, are almost the only
programming languages in modern use that do not support infix notation.
In addition, most languages allow infix expressions to be combined
with function call notation of the form f(x).
This SRFI provides these capabilities, both for
developers who already use Scheme and want these conveniences,
and also for other developers who may choose to use other languages
in part because they miss these conveniences.
Scheme currently reserves <code>{</code>...<code>}</code>
“for possible future extensions to the language”.
We propose that <code>{</code>...<code>}</code> be used
to support “curly-infix” notation as a homoiconic
infix abbreviation,
as a modification of the Scheme reader.
It is an abbreviation in much the same way that
<samp>'x</samp> is an abbreviation for <samp>(quote x)</samp>.
</p>
<p>
A
<a href="#specification"><dfn>curly-infix list</dfn></a>
introduces a list whose visual presentation
is in infix order instead of prefix order.
For example,
<samp>{n > 5}</samp> ⇒ <samp>(> n 5)</samp>,
and
<samp>{a + b + c}</samp> ⇒
<samp>(+ a b c)</samp>.
By intent, there is no precedence, but e.g.,
<samp>{x + {y * z}}</samp>
maps cleanly to
<samp>(+ x (* y z))</samp>.
Forms with mixed infix operators and other complications have
“<var>nfx</var>” prepended to
enable later macro processing, e.g.,
<samp>{4 + 5 * 6}</samp> ⇒
<samp>(nfx 4 + 5 * 6)</samp>.
Also, inside a curly-infix list (recursively),
expressions of the form <samp>f(...)</samp> are simply
an abbreviation for <samp>(f ...)</samp>.</p>
<p>Note that this is derived from the
“<a href="http://readable.sourceforge.net/">readable</a>”
project.
We intend to later submit at least one additional SRFI that will build on
top of this SRFI, but curly-infix-expressions are useful on their own.
</p>
<h1><a name="rationale">Rationale</a></h1>
<p>Lisp-based languages, like Scheme, are almost the only
programming languages in modern use that do not support infix
notation. Even some Lisp advocates, like Paul Graham, admit that
they “don’t find prefix math expressions
natural” (<a href="http://www.paulgraham.com/pypar.html"
rel="nofollow">http://www.paulgraham.com/pypar.html</a>) even after
decades of experience with Lisp-based languages.
Paul Prescod has said, “I have more faith that you could convince
the world to use Esperanto than prefix notation”
(<a href="http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg01571.html" rel="nofollow">http://people.csail.mit.edu/gregs/ll1-discuss-archive-html/msg01571.html</a>).
Infix is not going away; standard mathematical notation uses infix,
infix notation is taught to most people (programmers or not) in school,
and nearly all new programming languages include infix.
</p>
<p>
Adding infix support to Scheme would be a useful convenience for
some existing developers who use Scheme, and it would also
eliminate a common complaint
by developers who currently choose to use other languages instead.
</p>
<p>Scheme currently reserves
<code>{</code>...<code>}</code> “for possible future
extensions to the language”. We propose that
<code>{</code>...<code>}</code> be used to
support “curly-infix” notation as a reader
abbreviation, just as
<samp>'x</samp> is an abbreviation for <samp>(quote x)</samp> and
<samp>(x y z)</samp>
is an abbreviation for
<samp>(x . (y . (z . ())))</samp>.
</p>
<p>This proposal is an extremely <em>simple</em> and
<em>straightforward</em> technique for supporting infix notation.
There is no complex precedence system, all other Scheme
capabilities (including macros and quasiquoting) work unchanged,
any symbol can be used as an infix operation where desired,
and Scheme remains general and homoiconic.
Curly-infix-expressions (also known as c-expressions)
are just a convenient reader abbreviation for infix notation.</p>
<p>At its core, this SRFI provides
the <em>simple</em> curly-infix list,
a list whose visual presentation is in infix order instead of prefix order.
The simple curly-infix list
<samp>{operand-1 operator operand-2 operator operand-3 operator ...}</samp>
is mapped to
<samp>(operator operand-1 operand-2 operand-3 ...)</samp> so that two or
more operands are handled cleanly.
E.g., <samp>{a + b + c}</samp> ⇒
<samp>(+ a b c)</samp>.</p>
<h2><a name="rationale_changereader">Why not macros? Why modify the reader?</a></h2>
<p>Many previous systems have implemented “infix”
systems as a named macro or procedure (e.g., <var>INFIX</var>).
This looks ugly, and it does the wrong thing — the resulting list
always has <var>INFIX</var> at the beginning,
not the actual infix operator, so this
approach can interfere with quoting, macros, and other capabilities.
In particular,
consider the following <var>syntax-rules</var> macro
for function composition:
</p>
<pre>
(define-syntax o
(syntax-rules ()
({f o g}
(lambda args
(f (apply g args))))
({f o g o h o ...}
{(lambda (x)
(f (g x))) o h o ...})))
</pre>
<p>
This example takes advantage of the fact that
<samp>{f o g o h o ...}</samp>
⇒ <samp>(o f g h ...)</samp>.
Infix cannot be implemented as a macro alone,
as the <var>syntax-rules</var> form has
a particular treatment for the pattern.
A macro for infix would very likely confuse
the <var>syntax-rules</var> form.
</p>
<h2><a name="rationale_braces">Why use brace characters for infix?</a></h2>
<p>
There is no perfect character, but braces (aka curly braces) are pretty close.
A key issue is that you want a balanced pair of characters to identify infix,
since you can have infix-in-infix.
The curly braces are visually pleasant pairs, so
it makes sense to use these precious characters on something
extremely common: infix notation.
</p>
<p>
All other character pairs other than braces have serious problems.
Parentheses are already spoken for, of course.
R6RS Scheme already uses up square brackets as a synonym for parentheses.
Angle brackets are already used for comparison.
Paired characters outside the ASCII set have other problems:
some Schemes do not support characters outside the ASCII character set,
such characters are not as well supported by other tools
(and are sometimes corrupted by such tools),
they are more complicated to deal with due to
character encoding problems, and they are harder to enter on many keyboards.
</p>
<p>
In contrast, curly braces are in the ASCII character set and are
already available for this purpose.
They do not have a standardized meaning in any Scheme specification.
There is even a Scheme
<a href="http://trac.sacrideo.us/wg/ticket/468">R7RS ticket #468</a>
that would expressly forbid brackets and curly braces in identifiers;
if accepted (which seems likely at this writing) it would even further
enshrine the notion that braces are special and should be reserved
for some special syntactic purpose other than being in identifiers.
They are also widely available in many other Lisp-derived languages,
such as Common Lisp
(as we’d like this notation to be widely useful across Lisps,
even beyond Scheme).
</p>
<p>
Although curly braces <em>can</em> be used as local Scheme extensions,
there are few Scheme implementations which do so.
On
<a href="http://srfi.schemers.org/srfi-105/mail-archive/msg00063.html">
September 5, 2012, John Cowan posted</a> the
<a href="http://trac.sacrideo.us/wg/wiki/BracketsBraces">results</a>
analyzing the
meanings of square brackets and curly braces in his Scheme test suite
(of 45 Scheme implementations).
Only 2 (Chibi and RScheme) of 45 currently do something
special with braces; “the other implementations treat them
as either synonyms for parentheses, lexical syntax errors,
or identifier characters”.
That is a remarkably small number of Scheme implementations where this
use of curly braces would conflict with some special semantic.
Donovan Kolbly reported that
“RScheme uses braces to delimit C code embedded in Scheme code...
that said, a scanner hack could
easily mode-switch to SRFI-105 interpretation where needed.”
The Chibi extension using braces can be added or removed through a
compile-time option, so not even all Chibi executables have a
conflicting use of brace characters.
</p>
<p>
It’s true that {...} are often used in math for set notation. But
infix notation is far more basic, and common, than sets.
Also, traditional function call notation and infix are helpful when working
with sets, so infix notation is the more important need.
Once you allow neoteric-expressions,
the notation set(...) is a reasonable alternative.
</p>
<h2><a name="rationale_notdifferentsyntax">Why not use a completely different notation inside the expression?</a></h2>
<p>
Some past systems have built infix notations into the reader
in which the infix notation was radically different from normal Lisp notation.
For example, the symbol for procedure calls might change, the names of
variables or procedures might be spelled differently (at least in some cases),
and so on.
The result, in some cases, would be that these notations would
simultaneously lose Lisp’s abilities for
quoting, quasiquoting, and so on, and these notations were
not homoiconic.
It may become impossible to refer to certain symbols, since their
names might include a character that is interpreted as an infix operator.
They can also be confusing; the same symbols (e.g., parentheses) would have
a completely different meaning inside and outside the parentheses.
</p>
<p>
In contrast, this curly-infix-expression proposal avoids these problems.
The lists inside use almost exactly the same syntax inside and outside.
For example, in curly-infix,
<samp>`{,a + ,b}</samp>
maps cleanly to
<samp>`(+ ,a ,b)</samp>,
which works as expected with all macros.
The main difference is that, in a curly-infix expression, the position of
the operator in its surface syntax in a different location (infix)
than its actual final location.</p>
<h2><a name="rationale_noautodetect">Why not autodetect infix?</a></h2>
<p>Some past efforts tried to automatically detect infix operators,
but this turns out to not work well. It’s hard to express
good rules for detecting infix operators, and the rules become too
complex for users (e.g., “punctuation-only symbols”
doesn’t detect “<var>and</var>” or “<var>or</var>”).
And in
any case, if they were automatically detected, an escape mechanism
would be needed anyway -
consider <samp>(map - ns)</samp>
for getting a new list with
the numbers in <var>ns</var> negated.
Allowing the user to expressly notate when
infix was intended, using <code>{</code>...<code>}</code>,
turns out to be far more clearer
and more intuitive. In particular, curly-infix allows the use of
infix with any symbol, whenever you want... and where it’s
not convenient, you don’t need to use it. It is also very
backwards-compatible: Normal lists work normally, and if you want
infix, use <code>{</code>...<code>}</code>.</p>
<h2><a name="rationale_equal">Why use <var>equal?</var> to compare operators in a “simple” curly-infix-list for equality?</a></h2>
<p>
Operators are compared using <var>equal?</var> so that
constructs like <samp>,op</samp> are legal operators,
e.g., <samp>{x ,op y ,op z}</samp>.
Note that unfortunately if the operator construct contains a cycle, it might not terminate
if <var>equal?</var> does not terminate in the presence of cycles.
This was specified this way so that implementers
could use the normal Scheme <var>equal?</var> comparison instead of
having to implement a special comparison operator just for this
particular case.
</p>
<h2><a name="rationale_delimiters">Why must infix operators be delimited?</a></h2>
<p>Curly-infix requires that the infix operators be delimited (e.g., by
spaces). This is consistent with Lisp history and current practice.
Currently, in Lisp, operators are always
delimited in traditional s-expressions (typically by left
parentheses on the left, and by whitespace on the right).
It’s impractical to do otherwise today; most Lisps,
including Scheme, allow and predefine symbols that include characters (like
“<code>-</code>”) that are typically used for infix operators.
If infix operators were not delimited, it would be impractical or
complicated to refer to standard Scheme identifiers.
By requiring delimiters (as is already true for the rest of Scheme),
any procedure may be used as an infix operator, not just a fixed list.
Many developers put space around infix operators even in languages
that don’t require them, so syntactically requiring them is no burden.
In short, it is difficult to allow infix operators
without delimiters, and the visual results are the same as many
real-world uses in other languages, so the result appears quite
customary to typical software developers.</p>
<h2><a name="rationale_noprecedence">Why isn’t precedence part of this SRFI?</a></h2>
<p>Many past “infix” systems for Lisp build in
precedence. However, Lisp systems often process other languages,
and they may freely mix these different languages.
Thus, the same symbol may have different meanings
and precedence levels in different contexts.
The symbol might not even be defined where it is being
used, and allowing precedence definitions would create subtle errors
if files are read in a different order.
If users hook in their own precedence system into a reader, it could
even become difficult to combine code written for different precedence systems.
In short, building precedence into a
Lisp reader creates many complexities.</p>
<p>Yet the complexity of precedence systems is often unnecessary.
In practice, we’ve found that simple infix is all
that’s needed most of the time in Lisp-based languages.
Even in other languages, many developers unnecessarily use
grouping symbols with infix operators to make their order clear.
An examination of two Scheme programs written using curly-infix
(posted 2012-09-14) found that 55/78 (71%) of the top-level
c-expressions do not embed an opening brace; this means that precedence
is irrelevant for more than two-thirds of these top-level c-expressions.
Thus, requiring grouping symbols is less of a
hardship than it might appear.</p>
<p>By intentionally <em>not</em>
building a precedence system into the reader,
a very simple yet useful infix system results.
We don’t need to register procedures, ensure that declarations
of precedence precede their use, gain widespread agreement on some
precedence order, or anything like it.
We also ensure that the notation is clearly homoiconic.</p>
<p>Instead, where precedence is desired, application and library writers
can implement precedence by defining and controlling the scope of an
“<var>nfx</var>” macro or procedure, or by later postprocessing
of that symbol.
Scheme macros are already quite powerful and capable of handling this;
in these cases, <code>{</code>...<code>}</code> provides a more
convenient notation.
The curly-infix approach, instead of trying to manage both infix
and precedence, handles simple cases and then
takes advantage of the existing Scheme scoping rules and macro system for
more complex cases (in the rare cases where they are needed).</p>
<p>Note that curly-infix includes support for unary operators, but again,
they are without precedence.
As a result, they must be grouped separately.
This does not lead to hard-to-read expressions, however.
Examples of simple curly-infix lists combining infix and unary operations
include
<code>{-(x) * -(y)}</code>
and
<code>{-{x} * -{y}}</code>
(the notation is designed so that both work).
</p>
<p>It would be <em>possible</em>
to extend curly-infix to provide a fixed
precedence system (e.g., if an expression is mixed,
attempt to use various precedence rules).
Here is a discussion how this could be accomplished in the future
(should that be necessary), which may also show why such systems were
not proposed in this SRFI.
It is important to understand that
such capabilities would be extensions <em>beyond</em> this SRFI.
It would be best if the precedence rules (if any) were absolutely fixed;
otherwise, subtle bugs would happen if files were read after the
precedence was declared, and code would be hard to combine
if it used different precedence rules.
However, the precedence rules can be fixed while still allowing
arbitrary new symbols, as shown below.
Here is an example of such an extension, called a “math” extension.
In this extension, if a mixed curly-infix list is seen,
it first attempts to apply the “math” ruleset, and only
prepends “nfx” if it does not meet the requirements. In this extension:
</p>
<ol>
<li>All even-numbered parameters must be symbols, there must be an odd number of parameters, and there must be at least five parameters (the minimum to have more than one operator).
</li>
<li>A fixed set of operators is supported, in a fixed order of precedence;
the operators are compared to the table below to determine precedence.
</li>
<li>
If an operator is not in the fixed table, but it is a symbol,
a new symbol is created by
removing from the symbol all “-” surrounded by alphanumerics,
removing all alphanumerics, and then removing all characters not in
an operator of the precedence table; that new symbol is then compared to
the table.
This allows the use of many more operators, e.g.,
“char-ci<=?” would be considered an operator with the
same precedence as “<=”.
If there’s still no match for any operator,
the expression does not meet the “math” ruleset, and
the normal mixed rules are used (<var>nfx</var> is inserted at the front).
</li>
<li>
When the same operator is repeated, the operator simply gains another operand, so {a + b + c * d} is the “+” operator applied to three operands: a, b, and (* c d).
</li>
<li>
Other different operators of the same precedence are interpreted in left-to-right order, so {a + b - c} maps to {{a + b} - c}.
</li>
</ol>
<p>
But there would be substantial arguments about the semantics of
any precedence system.
For example, should there be support for combining different ranged
comparisons, to support notations such as {a < b <= c}?
Should some operators be right-associative, and if so, which ones?
There would also be substantial disagreement on exactly what operators
should be in the precedence table (including which combinations and if
Unicode characters should be included), their order, and whether
the table should be “big” or “small”
(since it is fixed, there are arguments for a larger one).
Below is one possible order, in high-to-low precedence order
(where ... matches 0 or more characters), presuming all is left-to-right;
the point in part is to show that it
would be challenging to get agreement on such a list:
</p>
<ol>
<li>Subscript/down-arrow: sub {Unicode: ↓, ⇓}</li>
<li>Exponentiation/superscript/up-arrow: exp..., **, ^, sup {Unicode: ↑, ⇑}</li>
<li>Multiplication/division: *, /, div..., mod..., quo... {Unicode: ÷, ×}</li>
<li>Addition/subtraction: +, -</li>
<li>Bitwise and: bit...and, log...and, &</li>
<li>Bitwise or/xor: bit...or, log...or, |</li>
<li>Comparison:
<ul>
<li>
Ranged: < , <= , >=, > {Unicode: ≥, ≤, ∋, ∉, ⊄, ⊂, ⊆, ⊃, ⊇}
</li>
<li>Unranged: =, ==, !=, <>, =/=, eq..., in, is {Unicode: ≠, ≈, ≅}</li>
</ul>
<li>Logical conjunction: and {Unicode: ∩, ∧}</li>
<li>Logical/exclusive disjunction: or, xor, eor {Unicode: ∪, ∨, ⊕}</li>
<li>Implication/right arrows/doubled arrows: ->, =>, <->, <=>, -->, ==>, <-->, <==> {Unicode: ↔, ⇔, →, ⇒}</li>
<li>Definition/assignment/left arrow: <-, <--, <==, :=, ::= {Unicode: ≡, ←, ⇐}</li>
</ol>
<p>
Think that is too complicated?
Many other variations are possible.
A “simple math” ruleset could be devised instead,
e.g., perhaps it has a shorter list of built-in operators.
The extant code using curly-infix tends to combine these:
*, /; +, -; < , <= , >=, > =, <>, eq...;
<var>and</var>; and <var>or</var>;
adding exponentiation (e.g., ** and exp...) at a higher precedence level,
and implication (e.g., -> and =>) would make sense for a short list.
(The <> isn’t in many Scheme specifications, but it is odd to omit
it from a precedence list.)
</p>
<p>
The key point is that although this SRFI does not include a precedence system,
one (such as these) could be added later.
If a precedence system were added, all existing code using simple
curly-infix expressions, or 0..2 parameter expressions, would work unchanged.
Even when it’s not, many “nfx” processors would likely generate the
same order in most actual cases.
Since it would be difficult to gain such agreement, and the value of
such a system is doubtful, it is better to provide a much simpler
system that does not include precedence.
Again, any support for precedence is an extension beyond this SRFI.
</p>
<p>At first David A. Wheeler, who started this project,
considered reporting an error if a simple infix
expression isn’t provided.
However, prepending “<var>nfx</var>”
is much more flexible.</p>
<h2><a name="rationale_nfx_undefined">Why is nfx not predefined?</a></h2>
<p>Implementations should not predefine a meaning for <i>nfx</i>,
other than possibly to something that always produces an error
(e.g., raises an exception).
</p>
<p>
If anyone wrote code that depended on some local implementation of nfx,
then by definition it would become implementation-dependent.
Yet the point of the “nfx” macro is to allow application authors
the ability to control what to do in that case,
not to make them unwittingly dependent on an implementation.
</p>
<p>
Of course, an implementation could provide a pre-canned macro that could
be used as a definition of nfx. But in that case, importing the
library would be an explicit act,
easily seen in the code, instead of being hidden.
That way, it is easy to determine when an implementation-dependent
capability is being used.
</p>
<h2><a name="rationale_specialcases">Why are 0, 1, and 2 parameters special?</a></h2>
<p>The empty curly-infix list
<samp>{}</samp> is intentionally mapped to <samp>()</samp>,
as it <em>is</em> an
empty list, and this is the likely user meaning (reducing
unnecessary errors).</p>
<!-- dwheeler says: I think we have to mention n-expressions and t-expressions
here, because they are part of the rationale for these semantics. -->
<p>The one and two parameter cases are defined in part to reduce user error,
and in part to provide better support:
</p>
<ol>
<li>An “escaping”
<samp>{e}</samp> is mapped to <samp>e</samp>
so that <code>{</code>...<code>}</code> can conceptually be used
for grouping:
<samp>{{{a} + {b}}}</samp>
is equivalent to
<samp>(+ a b)</samp>.
It ensures that the neoteric-expression
<samp>f{x}</samp> becomes the likely-intended <samp>(f x)</samp>,
and also makes it easy to use prefix notation; e.g.,
<samp>{ f(x) }</samp> is just another way to write
<samp>(f x)</samp>.
Finally, it also provides an easy escape mechanism
in sweet-expressions for symbols
that would otherwise have other meanings.</li>
<li>The “unary-operation” curly-infix list
<samp>{e f}</samp> ⇒ <samp>(e f)</samp>,
so that
<samp>{- x}</samp> ⇒ <samp>(- x)</samp>,
the likely interpretation, and also so that the neoteric-expressions like
<samp>f{- x}</samp> ⇒
<samp>(f (- x))</samp> are interpreted properly.
</li>
</ol>
<h2><a name="rationale_curlyfooconvention">Why the <var>curly-foo</var> convention?</a></h2>
<p>
We would like to have a convention for users to easily enable curly-infix
everywhere, e.g.,
for the default reader (e.g., <var>read</var>), read-eval-print loop (REPL),
and loader (e.g., <var>load</var>).
Our ideal would be that implementations would
enable curly-infix in their normal
invocation, but some implementers may not want to do that.
For example, if an implementation already uses braces for a
different local extension, they may not want to immediately
switch to curly-infix in their default invocation.
Thus, if implementers choose to not enable curly-infix in their default
reader, a conventional command line name “<var>curly-foo</var>”
is defined for each implementation <var>foo</var> that enables it.
Implementations may have a host of special command-line invocation names,
but presumably one or a few are the usual invocation commands; there
is no requirement to have a curly-foo alternative for a rarely-used
invocation.</p>
<p>There is simply no single option flag (for example) that
everyone could agree on to enable curly-infix.
In practice, we expect that implementations will build this capability
into their default readers and then control it via
some special flag, but we do
not want to mandate exactly how it this capability is turned on or
passed to the reader.</p>
<h2><a name="rationale_marker">Why a marker starting with <var>#!</var> and a letter?</a></h2>
<p>
We would like implementations to always have curly-infix enabled.
However, some implementations may have other extensions
that use <code>{</code>...<code>}</code>.
We want a simple, standard way to identify code that uses curly-infix
so that readers will switch to curly-infix if they need to switch.
This is especially important for those few Scheme implementations that
already use braces for some other purpose.
</p>
<p>
The <var>#!</var> marker prefix was suggested due to its similarity
to other markers.
After all, R6RS and R7RS (draft 6) already use
<var>#!fold-case</var> and <var>#!no-fold-case</var>
as special markers to control the reader.
Using another marker beginning with
<var>#!</var> and a letter allows for a simple, similar-looking marker
for a similar situation.
What’s more, it implies a reasonable convention for reader extensions:
markers that begin with <code>#!</code>, followed by an ASCII letter, should
have the rest read as an identifier (up to a whitespace)
and use that to control the reader.
</p>
<p>
The marker is read up to a whitespace; this is consistent with
<a href="http://trac.sacrideo.us/wg/ticket/447">Scheme R7RS ticket #447</a>.
This makes easy to distinguish between markers if one marker
begins with the same characters as another entire marker.
</p>
<p>
This marker need not interfere with other uses of <var>#!</var>.
<a href="http://srfi.schemers.org/srfi-22/srfi-22.html">SRFI-22</a> supports
<var>#!</var>
followed by space as a comment to the end of the line; this is supported
by several implementations, but this is easily distinguished from this
marker by the space.
Guile, clisp, and several other Lisps support
<code>#!</code>...<code>!#</code>
as a multi-line comment, enabling scripts with mixed languages and
multi-line arguments.
But in practice the <var>#!</var> is almost always
followed immediately by <code>/</code> or <code>.</code>, and other scripts
could be trivially fixed to make that so.
R6RS had a non-normative recommendation to ignore a line that began
with <var>#!/usr/bin/env</var> (without a space), as well
as a <var>#! /usr/bin/env</var> (with a space before the slash),
but this is non-normative;
an implementation could easily implement <var>#!</var> followed by space
as an ignored line, and treat <var>#!</var> followed by
<code>/</code> or <code>.</code> differently.
Thus, implementations could trivially support (simultaneously) markers
beginning with <var>#!</var> followed by a letter
(such as the one to identify curly-infix),
the SRFI-22 <var>#!</var>+space marker as an ignored line,
and the format <var>#!/ ...!#</var> and <var>#!. ...!#</var> as a
multi-line comment.
Note that this SRFI does <em>not</em> mandate support or any particular
semantics for <var>#!fold-case</var>, <var>#!no-fold-case</var>,
the SRFI-22 <var>#!</var>+space convention, or
<var>#!</var> followed by a slash or period;
it is merely designed so that implementations <em>could</em>
implement them all simultaneously.
</p>
<p>
We do not <em>require</em> that applications include this marker.
Our hope is that over time everyone will just support this
natively, making the marker unnecessary, and we do not want to require
that users include an unneeded marker.
</p>
<p>
We recommend that <var>#!curly-infix</var> not be the very first characters
in a file (e.g., put a newline in front of it).
If the file began with <var>#!curly-infix</var>, is made executable,
and then execution is attempted,
this might confuse some systems into trying to run the
program <var>srfi-105</var>.
</p>
<p>By intent, this SRFI (including the enabling mechanism)
doesn’t use or interact with any module system at all
(including the R6RS and R7RS module systems). This is because some
implementations won’t have a module system (or at least not a
standard one). Curly-infix is an intentionally simple mechanism
that can be built into even trivial Scheme implementations.
Mandating module support is unnecessary and might inhibit its
adoption.</p>
<h2><a name="rationale_marker_105">Why the marker <var>#!curly-infix</var>?</a></h2>
<p>
There were two competing alternatives:
<var>#!srfi-105</var> and <var>#!curly-infix</var>.
</p>
<p>
The
<a href="http://srfi.schemers.org/srfi-105/mail-archive/msg00027.html">
<var>#!srfi-105</var> was recommended during discussion of SRFI-105</a>,
in part because it makes it clear where more information can be gathered.
Also, it suggests that <code>srfi-</code> should be
the namespace for SRFIs, a plausible convention.
</p>
<p>
However, <var>#!curly-infix</var> marker
has the advantage of being more obvious about what is being enabled.
Modern search engines make it easy to find where information is, using
either naming convention.
Finally, if this capability were accepted into future Scheme specification,
its name would not need to change.
</p>
<h2><a name="rationale_racketinfixconvention">What about the Racket “infix convention”?</a></h2>
<p><a href=
"http://docs.racket-lang.org/guide/Pairs__Lists__and_Racket_Syntax.html">
Racket allows a notation called the “infix convention”
with the form “<code>(a . operation . b)</code>”</a>. An
advantage of this alternative is that it does not use the braces,
so it might be easier to implement in Schemes which already define
<code>{</code>...<code>}</code> in a local extension. However, the Racket “infix
convention” has many problems:</p>
<ul>
<li>The Racket infix convention is much longer and more awkward
than curly-infix notation. In the Racket infix convention, every
infix operator adds 6 characters. Infix operations are a very
common operation, so convenience matters. An expression like
<samp>(1 . + . 2)</samp>
is far longer, and less convenient, than
<samp>{1 + 2}</samp>.</li>
<li>It doesn’t look like other languages or math. A human
notation should be maximally understandable to people given what
they already know.
The notation <samp>{a + b}</samp>
is much more similar to the standard notation
“a + b” than
<samp>(a . + . b)</samp>.</li>
<li>It is easy to make mistakes. If you forget a “<code>.</code>”
somewhere, you end up with the wrong result, and possibly without an
error being flagged. This notation also
makes it harder to see improper lists; improper lists are important
but rare, so it’s good to make them obvious.
In contrast, the Racket infix convention
makes improper lists hard to distinguish.
The Racket documentation even goes out of its way to emphasize that
infix convention use is unrelated to improper lists... which
suggests that they are easily confused.</li>
<li>Without <code>{</code>...<code>}</code>, <samp>{x}</samp> is no longer useful as an escape mechanism
for sweet-expressions (a notation that builds on curly-infix). An
alternative would be to use <samp>(. x)</samp> as an escape mechanism,
but at that point dots-in-lists become busy and confusing.</li>
<li>Racket’s implementation, according to its documentation,
does not allow multiple operations,
e.g.,
<samp>(a . + . b . + . c . + . d)</samp>.
That could be added,
but using them makes the Racket infix convention even more
unwieldy. For example, compare
<samp>(a . + . b . + . c . + . d)</samp>
to
<samp>{a + b + c + d}</samp>.</li>
<li>Even Racket users don’t use this convention often. Its
documentation says that “Racket programmers use the infix
convention sparingly—mostly for asymmetric binary operators
such as <var><</var> and <var>is-a?</var>”.
The documentation does not say why,
but its extra length and awkwardness may be part of the reason.
In any case, the fact that the Racket documentation recommends that it
be used “sparingly” does not encourage wider adoption.</li>
</ul>
<p>In short, cases where infix notation would be useful are
extremely common, so its notation should be convenient.
The Racket “infix convention” may be the
next-best notation for infix notation after curly-infix, but
it’s next-best, and we should strive for the <em>best</em>
available notation for such a common need.
Curly-infix does not <em>conflict</em> with the
Racket infix convention; implementations could implement both.
We recommend that an implementation that
implements the Racket infix convention should also allow multiple
operands and use curly-infix semantics for them, pretending that
<samp>. op .</samp>
is a single parameter.
In that case,
<samp>(a . + . b . + . c)</samp>
would map to
<samp>(+ a b c)</samp>,
and
<samp>(a . + . b . * . c)</samp>
would map to
<samp>(nfx a + b * c)</samp>.
Note that the existence of the Racket “infix
convention” is additional evidence of the <em>need</em> for a
standard infix convention; many have separately created mechanisms
to try to provide infix support.</p>
<h2><a name="rationale_racket_infix_plt">What about the Racket infix.plt package?</a></h2>
<p>
The
<a href="http://planet.racket-lang.org/display.ss?package=infix.plt&owner=soegaard"> “Infix Expressions for PLT Scheme” package by
Jens Axel Søgaard</a>,
called here the “Racket infix.plt” package,
provides an infix notation for PLT Scheme (now called Racket).
The
<a href="http://planet.racket-lang.org/package-source/soegaard/infix.plt/1/0/planet-docs/manual/index.html">manual for the Racket infix.plt package</a>
lists a number of examples and constructs.
</p>
<p>
In this approach, the 3-character sequence “@${“ begins an infix expression,
which switches to a completely different language that
ends with a matching “}”.
The <a href="http://planet.racket-lang.org/package-source/soegaard/infix.plt/1/0/parser.ss">parser.ss source code</a> defines the grammar of this
language as follows:
</p>
<pre>
<e> :== <num>
| <id> variable reference
| <e> [ <args> ] application
| { <args> } list construction
| <e> + <e> addition
| <e> - <e> subtraction
| <e> * <e> multiplication
| <e> / <e> division
| <e> ^ <e> exponentiation
| - <e> negation
| ( <e> ) grouping
<id> An identifier begins with a letter,
and is optionally followed by series of letters, digits or underscores.
An underscore is converted to a -. Thus list_ref will refer to list-ref.
<num> A number is an non-empty series of digits,
optionally followed by a period followed by a series of digits.
</pre>
<p>
This grammar is incomplete; infix.plt also supports (per its documentation
or source code):
</p>
<pre>
<e> OP <e> comparison. OP is <, <=, =, <>, >,=, > (and Unicode)
<e> := <e> assignment
<e> ; <e> sequence
(λ ids . expr) anonymous function
√<e> square root (Unicode character)
¬<e> logical not
</pre>
<p>
Differences in this approach, which some may see as advantages, are that
infix operators need not be separated by whitespace,
it provides precedence of * and / over + and -,
and it builds in a simple assignment statement if you want it.
Like many infix notations (including curly-infix), for many expressions
the infix.plt package is a far clearer notation than the
traditional s-expression.
</p>
<p>
However, there are many negatives to the infix.plt approach:
</p>
<ol>
<li>
Because it has a fixed built-in grammar,
only a few fixed symbols can be used as infix operators.
For example, <samp>and</samp> and <samp>or</samp>
are not supported as infix operators, yet they are commonly
used in infix position in other languages.
Similarly, it does not support the many other
procedures that might be useful in infix position, such as
<samp>char-ci>?</samp> and <samp>eq?</samp>.
This demonstrates a basic problem with only allowing a fixed set
of infix operators in a notation: Scheme (like all Lisps) allows for easy
creation of new procedures and macros.
An infix notation should make it easy to <em>use</em> those
procedures and macros, in whatever position is most natural,
and even if they have not been defined yet.
</li>
<li>Because it has a precedence system, it is necessarily less homoiconic
when precedence is used.
Note that curly-infix supports precedence via <var>nfx</var>, and
a built-in precedence system <em>could</em> be added later
if this was desired by the community.
</li>
<li>There seems to be no provision for Scheme capabilities
such as quoting and quasiquoting; a quasiquoted variable does not seem to
be allowed.
</li>
<li>
Many variables and operators cannot be referred to, and some that can be
must be spelled differently (and thus inconsistently).
Identifiers (which are also used for function names) must
“begin with a letter, and is optionally followed by series of letters,
digits or underscores. An underscore is converted to a -”.
Thus, it is not possible to call procedures with names like
“char=?”.
Similarly, variables with “*” or other such symbols
embedded in them cannot be referenced.
In short, many identifiers are inaccessible in this notation, either
as variables or as procedure names.
The approach does allow references to variable names with “-”
embedded in them,
but the names must be spelled differently (and thus inconsistently)
by replacing every “-” with “_”.
Thus, variables like “list-ref” must
be spelled as “list_ref” inside the infix.plt notation.
This approach also
makes it impossible to refer to variables with underscores in them.
These are fundamental side-effects of not requiring infix operators
to be delimited,
and cannot be changed without a significant change to the notation.
</li>
<li>
The notation is completely different and inconsistent
with the surrounding Lisp notation.
The curly braces {...} are suddenly used for list creation operation,
square brackets x[...] are used for function application, and
(...) is used for grouping (not for list creation).
This can create confusion, since the same symbol can have a completely
different meaning, and that confusion could easily lead to
hard-to-find errors.
</li>
</ol>
<p>
Note that an implementation could support both curly-infix and
the Racket infix.plt package simultaneously.
</p>
<p>
Like the Racket “infix convention”,
the infix.plt package does demonstrate that there is a <em>need</em> for
an infix notation that can be used in Scheme.
</p>
<h2><a name="rationale_six">What about Gambit’s “Scheme Infix eXtension (SIX)”?</a></h2>
<p>
The Gambit reader includes a notation called the
<a href="http://www.iro.umontreal.ca/~gambit/doc/gambit-c.html#Scheme-infix-syntax-extension">“Scheme Infix eXtension (SIX)”</a>
that supports infix notation. SIX expressions begin with a backslash.</p>
<p>Like curly-infix, SIX is a reader extension.
But SIX has a number of problems compared to curly-infix:
</p>
<ul>
<li>SIX has a long, complex grammar, requiring users to remember a complex grammar, and requiring a far more complex implementation. Curly-infix, by contrast, is extremely simple.</li>
<li>SIX is inflexible. It only supports a fixed set of operators, and
users cannot easily use other operators inside its notation.
SIX even defines a small set of types and control structures
which cannot be extended.
People can easily create new operations;
it’s important that an infix system
be able to immediately use them.</li>
<li>SIX does not generate standard Scheme expressions, and thus it does
not interact well with macros and quoting.
SIX generates special markers when given infix expressions, and they
must then be processed later for use.
For example, in SIX, using an infix <samp>+</samp> in the input
generates <samp>six.x+y</samp>, not <samp>+</samp>, in the read result.
This means that macros may have to be specially designed to work with SIX.
In contrast, in curly-infix, <samp>{x + y}</samp> actually
generates <samp>(+ x y)</samp>, so curly-infix works in a better
way with other macros and with quoting rules.</li>
</ul>
<p>
Like the Racket “infix convention” and Racket infix.plt package,
SIX does demonstrate that there is a <em>need</em> for
an infix notation that can be used in Scheme.
</p>
<p>A system could simultaneously implement curly-infix and SIX.
However, curly-infix is far simpler, is more flexible (e.g., by allowing
arbitrary symbols), and works much more easily with macros and quoting.
Thus, we believe that curly-infix is the better system and more
appropriate for standardization across Scheme implementations.</p>
<h2><a name="rationale_guile">What about Guile 1.4’s “reading infix” module?</a></h2>
<p><a href="http://gnuvola.org/software/guile/doc/index.html">Guile 1.4.x
at gnuvola.org</a> is self-described as a
“(somewhat amicable) fork from the official Guile”.
It includes
<a href="http://gnuvola.org/software/guile/doc/Reading-Infix.html">support
for reading infix expressions</a>.