summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib.c26
-rw-r--r--tests/012/callable.tl23
-rw-r--r--tests/012/iter.tl4
-rw-r--r--txr.135
4 files changed, 86 insertions, 2 deletions
diff --git a/lib.c b/lib.c
index 03e6efb8..086041a0 100644
--- a/lib.c
+++ b/lib.c
@@ -8333,6 +8333,7 @@ INLINE val do_generic_funcall(val fun, struct args *args_in)
case BUF:
carray:
default:
+ dfl:
bug_unless (args->argc >= ARGS_MIN);
args_normalize_least(args, 3);
@@ -8364,6 +8365,31 @@ INLINE val do_generic_funcall(val fun, struct args *args_in)
fun = cdr(binding);
}
break;
+ case NUM:
+ case BGNUM:
+ args_normalize_least(args, 1);
+
+ switch (args->fill) {
+ case 0:
+ callerror(fun, lit("missing required arguments"));
+ case 1:
+ return ref(args->arg[0], fun);
+ default:
+ callerror(fun, lit("too many arguments"));
+ }
+ case RNG:
+ if (opt_compat && opt_compat <= 288)
+ goto dfl;
+ args_normalize_least(args, 1);
+
+ switch (args->fill) {
+ case 0:
+ callerror(fun, lit("missing required arguments"));
+ case 1:
+ return sub(args->arg[0], fun->rn.from, fun->rn.to);
+ default:
+ callerror(fun, lit("too many arguments"));
+ }
case COBJ:
if (fun->co.cls == hash_cls) {
bug_unless (args->argc >= ARGS_MIN);
diff --git a/tests/012/callable.tl b/tests/012/callable.tl
new file mode 100644
index 00000000..0f0e9327
--- /dev/null
+++ b/tests/012/callable.tl
@@ -0,0 +1,23 @@
+(load "../common")
+
+(mtest
+ [0 '(1 2 3)] 1
+ [1 '(1 2 3)] 2
+ [2 '(1 2 3)] 3)
+
+(mtest
+ [0 "abc"] #\a
+ [1 "abc"] #\b
+ [2 "abc"] #\c)
+
+(mtest
+ [0..1 '(1 2 3)] (1)
+ [1..3 '(1 2 3)] (2 3))
+
+(mtest
+ [0..0 "abc"] ""
+ [0..2 "abc"] "ab"
+ [-1..: "abc"] "c")
+
+(test (mapcar [callf list* 2 0 1 3..:] '((A B C X) (D E F Y) (G H I Z)))
+ ((C A B X) (F D E Y) (I G H Z)))
diff --git a/tests/012/iter.tl b/tests/012/iter.tl
index 9b1db6f5..1b1bfd1e 100644
--- a/tests/012/iter.tl
+++ b/tests/012/iter.tl
@@ -49,7 +49,7 @@
"D01" "D02" "D03" "D04" "D05" "D10" "D11" "D12" "D13" "D14" "D15"
"E01" "E02" "E03" "E04" "E05" "E10" "E11" "E12" "E13" "E14" "E15"
"F01" "F02" "F03" "F04" "F05" "F10" "F11" "F12" "F13" "F14" "F15")
- [maprod append "A".."F" ["00".."99" 1..11]]
+ [maprod append "A".."F" [1..11 "00".."99"]]
("A01" "A02" "A03" "A04" "A05" "A06" "A07" "A08" "A09" "A10" "B01"
"B02" "B03" "B04" "B05" "B06" "B07" "B08" "B09" "B10" "C01" "C02"
"C03" "C04" "C05" "C06" "C07" "C08" "C09" "C10" "D01" "D02" "D03"
@@ -58,7 +58,7 @@
"F06" "F07" "F08" "F09" "F10"))
(test
- [mapcar identity [0..10 3 6]] (3 4 5))
+ [mapcar identity [3..6 0..10]] (3 4 5))
;; iterating from fixnum to bignum was rejected in up to txr-269.
(test (each ((x fixnum-max..(* 5 fixnum-max))) (return 42)) 42)
diff --git a/txr.1 b/txr.1
index 18b60420..c88e06a3 100644
--- a/txr.1
+++ b/txr.1
@@ -13816,6 +13816,15 @@ operates on a string argument.
It returns the leftmost matching substring, or else
.codn nil .
+Structure objects are callable if they implement the
+.code lambda
+method.
+
+Integers and ranges are callable like functions. They take one argument,
+which must be a sequence or hash. An integer selects the corresponding
+element position from the sequence, and a range extracts a slice of
+its argument.
+
.B Example 1:
.verb
@@ -13878,6 +13887,26 @@ substring
within the argument
.strn abcd .
+.B Example 5:
+
+.verb
+ [1 "abcd"] -> #\eb
+
+ ["abcd" 1] -> #\eb
+.brev
+An integer used as function indexes into sequence.
+This produces the same result as when the sequence is used
+as a function with an integer argument.
+
+.B Example 6:
+
+.verb
+ [1..3 '(a b c d)] -> (b c)
+ ['(a b c d) 1..3] -> (b c)
+.brev
+
+A range used as a function extracts a slice of its argument.
+
.SS* Special Variables
Similarly to Common Lisp, \*(TL is lexically scoped by default, but
also has dynamically scoped (a.k.a "special") variables.
@@ -91611,6 +91640,12 @@ of these version values, the described behaviors are provided if
is given an argument which is equal or lower. For instance
.code "-C 103"
selects the behaviors described below for version 105, but not those for 102.
+.IP 288
+Integers and ranges callable like functions are a new feature introduced
+after \*(TX 288. The latter, callable ranges, are a breaking change;
+certain expressions with a range in the function position interpreted
+the range as a sequence. Using this compatibility value disables ranges being
+callable, restoring the old behaviors.
.IP 283
In \*(TX 283 and older versions, the
.meta flags