aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cppawk-cons.1166
-rw-r--r--cppawk-include/cons-priv.h44
-rw-r--r--testcases-cons24
3 files changed, 222 insertions, 12 deletions
diff --git a/cppawk-cons.1 b/cppawk-cons.1
index a4d766d..fa286b9 100644
--- a/cppawk-cons.1
+++ b/cppawk-cons.1
@@ -493,6 +493,17 @@ or
it is to be understood as a variable that was not assigned, and
therefore evaluates to the undefined value.
+In this library, whenever the input to a function is a list, it
+is required to be a proper list unless otherwise noted.
+A proper list is terminated by the specific atom
+.B nil
+rather than some other atom. If a library function which requires
+proper lists detects an improper list, execution will terminate
+with a diagnostic.
+
+Other input conditions are diagnosed, such as a negative argument where a
+non-negative integer is expected.
+
.SS Macro \fInil\fP
.bk
.B Syntax:
@@ -1600,6 +1611,161 @@ returns a list similar to
butlast(list(1, 2, 3), 15) -> nil
.ft R
+.SS Function \fIreverse\fP
+.bk
+Syntax:
+
+.ft B
+ reverse(\fIx\fP)
+.ft R
+
+The
+.B reverse
+function returns the reverse of list
+.IR x :
+a list containing the same items as
+.I x
+but in the opposite order.
+
+.SS Function \fIiota\fP
+.bk
+Syntax:
+
+.ft B
+ iota(\fIx\fP, \fIy\fP[, \fId\fP])
+.ft R
+
+The
+.B iota
+function produces a list of numbers starting from
+.I x
+and ending in
+.IR y .
+
+The optional
+.I d
+argument (delta) specifies the increment step size between
+consecutive numbers. It defaults to one, if
+.I y
+is greater than
+.IR x ,
+negative one otherwise.
+
+When the value of
+.I y
+is surpassed, the production stops. If the value of
+.I y
+occurs, it is included in the list. The value
+.I y
+being surpassed means that the next value of the sequence
+lies on the other side of
+.I y
+compared to the previous value of the sequence. That
+next value is excluded from the sequence, and the
+sequence terminates.
+
+If
+.I x
+is greater than
+.IR y ,
+then a descending sequence is generated, if the value of
+.I d
+is negative.
+
+In all other situations, the following requirements apply:
+
+If
+.IB x " == "
+.IR y ,
+then
+.B iota
+returns
+.BI list( x )
+regardless of the value of
+.IR d .
+
+Furthermore,
+.B iota
+function returns the empty list
+.B nil
+in the following situations:
+
+The
+.B iota
+function unconditionally returns the empty list
+.B nil
+in the following situations:
+
+.IP 1.
+.BR d " == "
+.BR 0 .
+
+.IP 2.
+.BR x " <= " y " && " d " <"
+.BR 0 .
+
+.IP 3.
+.BR x " > " y " && " d " >"
+.BR 0 .
+.PP
+
+To ensure maximum accuracy when fractional range limits and/or delta are used,
+the successive values of the sequence are calculated by by a
+multiplication-and-displacement calculation relative to an internal counter
+which increments in steps of 1 starting from 0, not by repeatedly accumulating
+the value of
+.I d .
+
+That is to say, for example,
+.B "iota(2.5, 10, 0.3)"
+collects the initial value of 2.5 into the output list, and then
+subsequent values are produced by the calculation
+.B "i * 0.3 + 2.5"
+for values of the internal variable
+.I i
+being 1, 2, ... and not by initializing an accumulator to 1, and then
+repeatedly adding 0.3 to that accumulator.
+
+The test for whether the value of
+.I y
+occurs in the sequence (and is therefore included) uses the
+.B ==
+operator and therefore absolute floating-point precision. Depending
+on the choices of
+.I x
+and
+.IR d ,
+a value that is very close to
+.I y
+may be attained, which is not recognized as equal. If all three values
+.IR x ,
+.I y
+and
+.I d
+have exact representations in the floating-point system, and the
+difference between
+.I x
+and
+.I y
+is a multiple of
+.I d
+then
+.I y
+will be attained.
+
+.B Examples:
+
+.ft B
+ iota(1, 1) -> (1)
+ iota(1, 3) -> (1 2 3)
+ iota(1, -1) -> (1 0 -1)
+ iota(1, 3, 0.25) -> (1 1.25 1.5 1.75 2 2.25 2.5 2.75 3)
+ iota(3, 1, -0.25) -> (3 2.75 2.5 2.25 2 1.75 1.5 1.25 1)
+ iota(1, 3, -1) -> nil
+ iota(2.5, 2.5, 0) -> (2.5)
+ iota(2.5, 2.5, -1) -> (2.5)
+.ft R
+
.SH "SEE ALSO"
cppawk(1)
diff --git a/cppawk-include/cons-priv.h b/cppawk-include/cons-priv.h
index 55790d1..97d410d 100644
--- a/cppawk-include/cons-priv.h
+++ b/cppawk-include/cons-priv.h
@@ -786,23 +786,43 @@ function __butlast(__lst, __n,
return (__i in __circbuf) ? __list_end(__circbuf[__i]) : __nil
}
-function __iota(__from, __to, __step,
- __i, __out)
+function __iota(__from, __to, __delta,
+ __out, __i, __val)
{
__out = __list_begin();
if (__from < __to) {
- if (!__present(__step))
- __step = 1
- if (__step > 0)
- for (__i = __from; __i <= __to; __i += __step)
- __out = __list_add(__out, __i)
+ if (!__present(__delta))
+ __delta = 1
+
+ if (__delta <= 0)
+ return __nil;
+
+ __i = 0
+ __val = __from
+
+ while (__val <= __to) {
+ __out = __list_add(__out, __val)
+ __i++
+ __val = __from + (__i * __delta)
+ }
+ } else if (__from > __to) {
+ if (!__present(__delta))
+ __delta = -1
+
+ if (__delta >= 0)
+ return __nil;
+
+ __i = 0
+ __val = __from
+
+ while (__val >= __to) {
+ __out = __list_add(__out, __val)
+ __i++
+ __val = __from + (__i * __delta)
+ }
} else {
- if (!__present(__step))
- __step = -1
- if (__step < 0)
- for (__i = __from; __i >= __to; __i += __step)
- __out = __list_add(__out, __i)
+ return __list(__from)
}
return __list_end(__out)
diff --git a/testcases-cons b/testcases-cons
index 6b7751d..9962970 100644
--- a/testcases-cons
+++ b/testcases-cons
@@ -649,3 +649,27 @@ nil
3
(1)
nil
+--
+35:
+$cppawk '
+#include <cons.h>
+
+BEGIN {
+ print sexp(iota(1, 1))
+ print sexp(iota(1, 3))
+ print sexp(iota(1, -1))
+ print sexp(iota(1, 3, 0.25))
+ print sexp(iota(3, 1, -0.25))
+ print sexp(iota(1, 3, -1))
+ print sexp(iota(2.5, 2.5, 0))
+ print sexp(iota(2.5, 2.5, -1))
+}'
+:
+(1)
+(1 2 3)
+(1 0 -1)
+(1 1.25 1.5 1.75 2 2.25 2.5 2.75 3)
+(3 2.75 2.5 2.25 2 1.75 1.5 1.25 1)
+nil
+(2.5)
+(2.5)