This page contains the description of the following commands s2p_inner, scanstring, search-in-path, select, selectq, send, send-error, send-super, seq_to_array, seq_to_list, sequential_let, SequentialLet, sequential_seq, set, set_bep, setfn, setcoef, setq, set_to_one, set_theta, set_val, shch, shift_theta, show-functions, show-oblist, signum, simpsw, sin, sincos, singleton_seq, sinh, size, skip_unwanted, slambda, Slambda, slet, Slet_to_sequential_let, sort1, sort2, spanstring, splines, sqrt, sref, sset, step, stratom, string, string-to-list, string_to_number, stringp, strlen, sub, sub_inf, sub_line, sublist, subsets_seq, subst, subst3, substitute, substring, substring-eq, subtypep, super-itsoft, symbol, symbolp, synonym, system,
This function calls parse_s2p in order to read a file (foo.s3p if the first argument is foo, and the second is 3). We have then a vector of frequencies f[i] and a p × p matrix S[i]. Endymion writes, in the file foo.inner, for each i a line containing: the norm of row k, for every k, and the angle in degree between rows k and i, and the same for the rows. If the matrix is inner, norms should be one, and angles should be ninety degrees. In the case p=2, a file foo.inner1 is constructed. It contains for a certain number of values of W=exp(i.φ), the mean value of the scalar product of the two rows of the matrix, assuming that non-diagonal elements have been multiplied by W.
The scanstring function takes two or three arguments: two objects that can be coerced into a string and an integer (the default value is zero). It considers each character at position i in the first string, starting at n, and returns the index of the first character that is in the second string. It returns () if not possible. The function could be defined as
(defun scanstring (a b . c) (if c (setq c (car c)) (setq c 0)) (tag found (let (s1 s2 n1 n2 ok) (setq s1 (string-to-list a)) (setq s2 (string-to-list b)) (setq n1 (length s1)) (setq n2 (length s2)) (for (i c 1 (- n1 1)) (when (member (nth i s1) s2) (exit found i))) ())))
Example
[Endymion] (scanstring "abcd" "sbe") 1 [Endymion] (scanstring "abcd" "efg") () [Endymion] (scanstring "abcd" ".a" 1) () [Endymion] (scanstring "abc" "defghc") 2 [Endymion] (scanstring "foo" "") () [Endymion] (string 123e20) 1.23e+22 [Endymion] (scanstring 123e20 "+-.e") 1 [Endymion] (scanstring 123e20 "+-.e" 3) 4 [Endymion] (scanstring 123e20 "+-.e" 5) 5
The search-in-path function takes three arguments. It constructs a sequence of file names, as described below, and checks if this is the name of a file that can be opened for reading. If such is the case, the first valid name is returned. Otherwise, () is returned.
Here dir should be a string or a list of names, ext is a list of names, while file is a simple name (a name is a string or a symbol, it can also be a fsymbol). Non-names in dir or and ext are ignored. If ext is (), no extension is considered (note that, if ext is a list that contains no valid name, the list of file names is empty, and the result is ()). For each x in the list dir, for each y is the list ext, the concatenation of x, file and y is considered. In general, a directory ends with a slash, and an extension starts with a dot, but this is irrelevant to search-in-path
[Endymion] (traceval (search-in-path '("A" "A/B/" 12) "foo" '(".x" ".y"))) --> (search-in-path '(A A/B/ 12) foo '(.x .y)) --> '(A A/B/ 12) <-- (A A/B/ 12) --> foo <-- foo --> '(.x .y) <-- (.x .y) probefile Afoo.x--> failed probefile Afoo.y--> failed probefile A/B/foo.x--> failed probefile A/B/foo.y--> failed <-- () () [Endymion] (traceval (search-in-path '("A" "A/B/" 12) "foo" ())) --> (search-in-path '(A A/B/ 12) foo ()) --> '(A A/B/ 12) <-- (A A/B/ 12) --> foo <-- foo --> () <-- () probefile Afoo--> failed probefile A/B/foo--> failed <-- () () [Endymion] (setq dir "/usr/local/lib/texmf/web2c/") /usr/local/lib/texmf/web2c/ [Endymion] (search-in-path dir "plain" '(".fmt")) /usr/local/lib/texmf/web2c/plain.fmt
Like selectq below, but uses equal and member instead of eq and memq.
The two macros selectq and select take at least two arguments. Each argument but the first is a clause, a list of the form (v b1 ... bm). The first argument is evaluated. This gives some quantity X. Then all clauses are considered, one after the other. If a clause matches, then quantities b1 ... bm are evaluated in order. If no clause matches, the result is (). In the case where v is a list, the clause matches if X is in the list (the test is done via memq for selectq, and member for select). In the case where v is not a list, the clause matches if X is v (the test is done via eq for selectq, and equal for select), or if this is the last clause and v is true.
The expansion of selectq is something like (let ((#:system:lambda var)) (cond ...)), where let and cond are macros that are expanded.
[Endymion] (defun f (x) (select (car x) (1 (print "one")) [Endymion] ((2 3 4 5) (print "small") (cdr x)) [Endymion] (("a" "b" "c") (print "1 char") x) [Endymion] (true (print "true")) [Endymion] (true (print "unrecognised")))) f [Endymion] (defun fq (x) (selectq (car x) (1 (print "one")) [Endymion] ((2 3 4 5) (print "small") (cdr x)) [Endymion] ((a b c) (print "1 char") x) [Endymion] (true (print "true")) [Endymion] (true (print "unrecognised")))) fq [Endymion] (defun g (x) (f (list x x))) g [Endymion] (list (g 0) (g 1) (g 2) (g 6) (g "a")(g "A") (g true) (g false)) unrecognised one small unrecognised 1 char unrecognised true unrecognised (unrecognised one (2) unrecognised (a a) unrecognised true unrecognised) [Endymion] (defun g (x) (fq (list x x))) ** Redefinition of function : g g [Endymion] (list (g 0) (g 1) (g 2) (g 6) (g 'a)(g 'A) (g true) (g false)) unrecognised one small unrecognised 1 char unrecognised true unrecognised (unrecognised one (2) unrecognised (a a) unrecognised true unrecognised) [Endymion] (getdef 'f) (defun f (x) ((#:system:lambda 1 (g1) (if (equal g1 '1) (print one) (if ( member g1 '(2 3 4 5)) (progn (print small) (cdr x)) (if (member g1 '(a b c)) (progn (print 1 char) x) (if (equal g1 'true) (print true) (print unrecognised)))))) (car x))) [Endymion] (getdef 'fq) (defun fq (x) ((#:system:lambda 1 (g2) (if (eq g2 '1) (print one) (if (memq g2 '(2 3 4 5)) (progn (print small) (cdr x)) (if (memq g2 '(a b c)) (progn ( print 1 char) x) (if (eq g2 'true) (print true) (print unrecognised)))))) ( car x))) [Endymion] (selectq) selectq : wrong number of arguments : 0 this should be at least 2 [Endymion] (select 0 (1 . 2)) selectq : not a list : (1 . 2)
The macros could be defined as
(dmd selectq (x . l) (selectq-expander x l true)) (dmd select (x . l) (selectq-expander x l false)) (defun selectq-expander(myvar l sw) (let ((var (gensym)) (res ())) (while (consp l) (let ((x (car l)) (test) w cl) (setq l (cdr l)) (setq cl (cdr x) x (car x)) (setq w (list var (list 'quote x))) (cond ((null x) ()) ((and (consp x) sw) (setq test (cons 'memq w))) ((consp x) (setq test (cons 'member w))) ((and (eq x 'true) (null l)) (setq test true)) (sw (setq test (cons 'eq w))) (true (setq test (cons 'equal w)))) (when test (setq res (cons (cons test cl) res))))) `(let ((,var ,myvar)) (cond ., (nreverse res)))))
The send function takes at least two arguments, say f, a1, a2, etc. It calls getfn with three arguments, the first argument is the type (computed via type-of) of the second argument a1, the first argument f and (). Assume for instance that the type is #:foo:bar, and the first argument is first. In this case, the result is either #:foo:bar:first, #:foo:first or (). If the result is a function, this function is called; if the result is (), send-error is called with two arguments, f and the list of remaining arguments. The function could be defined as:
(defun send (f a1 . args) (let ((type (type-of a1))) (let ((fun (getfn type f ()))) (if fun (apply fun (cons a1 args)) (send-error fun (cons a1 args))))))
Example
[Endymion] (defun #:cons:first (x) (car x)) #:cons:first [Endymion] (defun #:symbol:first (x) (packagecell x)) #:symbol:first [Endymion] (defun #:vector:first (x) (vref x 0)) #:vector:first [Endymion] (defun #:foo:first (x) (vref x 1)) #:foo:first [Endymion] (send 'first '(1 2 3)) 1 [Endymion] (send 'first '#:a:b:c) #:a:b [Endymion] (send 'first '#[A B C]) A [Endymion] (send 'first '#:foo:bar:#[A B C]) B [Endymion] (send 'first "foo" "bar") send : undefined method : (first (foo bar)) [Endymion] (defun send-error x (car x)) ** Redefinition of function : send-error send-error [Endymion] (send 'first "foo" "bar") first [Endymion] (send 'first '(foo) '(bar)) #:cons:first : wrong number of arguments : 2 this should be 1
The send-error command takes any number of arguments, and provokes an error. You can redefine it. It is used in the case where send does not find the adequate method.
[Endymion] (send-error 1 2 3 4 5) send : undefined method : (1 2 3 4 5) [Endymion] (defun send-error x (error 'Send "undefined method" x)) ** Redefinition of function : send-error send-error [Endymion] (send-error 1 2 3 4 5) Send : undefined method : (1 2 3 4 5)
The send-super function behaves like the send function. It constructs a function that depends on the type of a1. Assume that this type is #:a:b:c:d:e and the second argument is f. Then send will consider the following symbols #:a:b:c:d:e:f, #:a:b:c:d:f, #:a:b:c:f, #:a:b:f, and #:a:f, namely the symbol f in some package pack, take the first function in this list, and apply it to the arguments ai. The send-super function assumes that its first argument is one of these packages, and starts the research after this package. Typically, this allows recursive send, using as first argument the package where the previous send found the method. In the case where no method is found the senderror function is called. The function could be defined as:
(defun send-super (pk f a1 . args) (unless (typep a1 pack) (error 'send-super "not a subtype" a1)) (let ((type (packagecell pk))) (let ((fun (getfn type f ()))) (if fun (apply fun (cons a1 args)) (send-error fun (cons a1 args))))))
Example
[Endymion] (defun #:a:f (x) "a") #:a:f [Endymion] (defun #:a:b:f (x) "b") #:a:b:f [Endymion] (defun #:a:b:c:f (x) "c") #:a:b:c:f [Endymion] (defun #:a:b:c:d:e:f (x) (cons "e" (send-super '#:a:b:c:d 'f x))) #:a:b:c:d:e:f [Endymion] (send 'f '#:a:b:c:d:e:#[]) (e . c) [Endymion] (send 'f '#:a:b:c:d:#[]) c [Endymion] (send-super '#:a:b:c:d 'f '#:a:b:c:#[]) send-super : not a subtype : (#:a:b:c:d #:a:b:c:#[]) [Endymion] (send-super '#:a:b:c 'f) send-super : wrong number of arguments : 2 this should be at least 3 [Endymion] (send-super '#:a:b:c '1 '#:a:b:c:#[]) send : undefined method : (1 (#:a:b:c:#[]))
This function puts the content of the sequence in the array. If the array has N dimensions, each element of the sequence must be a list of size N+1, the value followed by the indices. Otherwise, you will get an error message of the form: N arguments expected.
(1) x:=makearray(u,hash, all,all,all); (1) <ARRAY: u> (2) seq_to_array([],u); seq_to_array : not an array : u (3) seq_to_array(0,x); seq_to_array : not a sequence : 0 (4) seq_to_array([1],x); #:feval:seq_to_array : wrong number of arguments : 0 this should be 2 (5) seq_to_array([[10,11,12],[14,15,16]],x); (5) <ARRAY: u> (6) array_to_list(x); (6) [[10, 11, 12], [14, 15, 16]] (7) x[11,12]; (7) 10
This function converts a sequence into a list. It could be defined as seq_to_list(x):=let(L=[], while not endofseq(x) do newl(L, popseq(x)), reverse(L)). The function may signal an error in case it can deduce that the loop nevers ends. See makeseq for examples.
The Slet construction is the symbolic let, substitutions are done in parallel; in the case of SequentialLet substitutions are done in order from left to right: there is no difference between Slet([a=b], Slet([c=d],e)) and SequentialLet([a=b,c=d],e). In both cases, you need Seval to evaluate the expression. The function Slet_to_sequential_let tries to convert from the first case to the second one. When you say sequential_let([a=b,c=d],e), the is transformed into slet([a=b], slet([c=d],e)), expanded, and converted in a SequentialLet, see examples.
(1) [a,b,c] := [1,2,3]; (1) 3 (2) slet(a=x,slet(b=y,f(a,b,c))); (2) Slet([a = x], Slet([b = y], f(a, b, 3))) (3) Slet_to_sequential_let(%); (3) SequentialLet([a = x, b = y], f(a, b, 3)) (4) Slet_to_sequential_let(a+b); (4) 3 (5) A:=slet([a=b,b=a+b], [a,b]); (5) Slet([a = 2, b = 3], [a, b]) (6) Seval(%); (6) [2, 3] (7) sequential_let([a=b,b=a+b], [a,b]); Macro expansion -> sequential_let([a = b, b = a + b], [a, b]) Macro expansion <- Slet_to_sequential_let(Slet([concat(a) = b], let([a = concat(a)], Slet([concat(b) = a + b], let([b = concat(b)], [a, b]))))) (7) SequentialLet([a = 2, b = 2 + a], [a, b]) (8) Seval(%); (8) [2, 4]
This function creates a sequence, formed by concatenation of the arguments that should be sequences.
(1) A:=sequential_seq(1...5, [a,b,c], permutation([u,v,w])); (1) <UninitializedSequence: SEQ, <vector: <UninitializedSequence: interval, 1 ... 5>, <UninitializedSequence: list, [a, b, c]>, < UninitializedSequence: permutation, [u, v, w]>>> (2) B:=makeseq(A); (2) <InitializedSequence: SEQ, <vector: <InitializedSequence: interval, 1, 5, 1>, <InitializedSequence: list, [a, b, c]>, <InitializedSequence: permutation, [u, v, w], 1, <InitializedSequence: list, [[v, w], [w, v] ]>>>> (3) seq_to_list(B); (3) [1, 2, 3, 4, 5, a, b, c, [u, v, w], [u, w, v], [v, u, w], [w, u, v], [v, w, u], [w, v, u]]
This function is the Lisp equivalent of the symbolic construction object[index]:=value. In some cases, an error is signaled, saying that the object is not an array. If the object is a vector, the function behaves like vref; if the object is a polynomial, it sets the coefficient of degree index. For the case of splines see splines, for the case of pwfunctions see #:pw:alloc_function.
The setfn function takes three arguments. If Endymion is compiled in parano mode, this function signals an error. If type is neither defun, dmd, or a valid integer, the funtion returns (). Otherwise it defines name without checks and returns this. In the example that follows, we use getdef in order to get a valid address. If the type is defun or dmd, the code should be a list: number of arguments, argument list, then body. In the case of B, it is impossible to call the function, since (x y) matches no number.
[Endymion] (getdef 'car) (ds car 2 134778784) [Endymion] (setfn 'CAR 2 134778784) CAR [Endymion] (CAR '(1 2 3)) 1 [Endymion] (CAR 'foo) CAR : not a list : foo [Endymion] (setfn 'CDR 'x 134778784) () [Endymion] (setfn 'A 'defun '(2 (x y) (list x y))) A [Endymion] (getdef 'A) (defun A (x y) (list x y)) [Endymion] (setfn 'A 'defun '(2 (x x x) (list x))) A [Endymion] (A 1 2) (()) [Endymion] (setfn 'B 'defun '((x y) (list x))) B [Endymion] (B) B : wrong number of arguments : 0 this should be x or y [Endymion] (setfn 'C '2 13477878) C [Endymion] (C) C : wrong number of arguments : 0 this should be 1 [Endymion] (C 1) Segmentation fault
The set function takes two arguments. The first argument should be a symbol, it sets its cell value to the second argument. There is no essential difference between (set 'foo 'bar) and (setq foo 'bar). See also setq
[Endymion] (set 'foo' bar) bar [Endymion] (setq f 'a g 'a) a [Endymion] (set (if (eq foo 'bar) 'f 'g) 'c) c [Endymion] (list f g) (c a) [Endymion] (set (if (eq foo 'bar1) 'f 'g) 'b) b [Endymion] (list f g) (c b) [Endymion] (set 'foo 2) 2 [Endymion] (set foo 2) set : not a variable : 2
The setq special form takes an even number of arguments, a variable and a value. Variables vi are not evaluated. Values wi are evaluated, the result is put in the value of vi. The return value of setq is the last value evaluated (or () if no argument is given).
Some variables are special, in that there is a function associated to it that checks that validity. This function must take 0 or 1 argument (here, if the case of f, we use the #:system:nb-args trick). See description of arg: the (arg) form returns the list of arguments. If this is empty, the function is called without arguments. Otherwise (arg 1) is the first argument. The function makegetset converts an ordinary symbol to a get/set one. This cannot be reverted. You can change the value of the function, but it must take 0 or 1 arguments.
[Endymion] (setq x 1 y (list x x) z (list x y)) (1 (1 1)) [Endymion] x y z 1 (1 1) (1 (1 1)) [Endymion] (setq x y z) setq : wrong number of arguments : 3 this should be even [Endymion] (setq true false) setq : not a variable : true [Endymion] (setq ibase -1) ibase : argument out of bounds : -1 [Endymion] (setq 1 2) setq : not a variable : 1 [Endymion] (defun f (#:system:nb-args -101) &nobind [Endymion] (if (arg) (if (memq (arg 1) '(a b c)) (setq y (arg 1)))) y) f [Endymion] (setq y 'a) a [Endymion] (setq y 'b) b [Endymion] (f 1 2) f : wrong number of arguments : 2 this should be at most 1 [Endymion] (makegetset 'f) f [Endymion] f b [Endymion] (setq f 'c) c [Endymion] (setq f 'd) c [Endymion] (let ((f 3)) f) c [Endymion] (let ((f 'b)) f) b [Endymion] (defun f (x) x) defun : Cannot redefine : f [Endymion] (defun f (#:system:nb-args -101) &nobind [Endymion] (if (arg) (if (memq (arg 1) '(a b c d)) (setq y (arg 1)))) y) ** Redefinition of function : f f [Endymion] (setq f 'd) d
The split-path function takes as argument a pathname (either an object of type pathname, or something that can be converted to a pathname, for instance a string or a symbol), like "foo/bar.gee" and returns the three parts as a list (here foo, bar, gee). If the argument is "$XAUTHORITY", or ~foo, the pathname is expanded. See pathname for examples.
The show-functions function takes no argument; it returns (). It has as side effect to print all symbols that have a functional value.
The show-oblist function shows the oblist, the list of all symbols. Symbols that have no cval, no plist and no fval are not printed. Otherwise, you will see a long list with items like the following.
errsxt1 cval: list or string too short plist: () fval: () symbolp cval: _undef_ plist: () fval: 134793200 lmargin cval: lmargin plist: () fval: 134863968 foo cval: _undef_ plist: () fval: (1 (x) x)
This function returns the sign of x; this is x divided by its absolute value (0 for 0, 1 for a positive number, -1 for a negative number).
[Endymion] (signum 'foo) signum : not a number : foo [Endymion] (signum -2/3) -1 [Endymion] (signum 1.5) 1 [Endymion] (signum 0) 0 [Endymion] (signum #C(1 2)) [0.894427190999916i+0.447213595499958]
The simpsw variable can be false, all or true (all other values are converted to true). It controls what happens if the simplifier is called directly, or in case of an unknown function call like f(x,y). If the value is false, nothing special happens. If the value is true or all, subexpressions are simplified (recursively), in particular, arithmetic operators are evaluated again. If all, a bit more is done. This needs to be completed
(1) s:=(x+y)^2; 2 (1) (x + y) (2) expop:=2; (2) 2 (3) f(x):=[g(x), simpsw]; (3) <FUNCTION: f> (5) f(s); 2 (5) [g((x + y) ), FALSE] (6) let(simpsw=true,f(s)); 2 2 (6) [g(x + y + 2 x y), TRUE] (7) let(simpsw=all,f(s)); 2 2 (7) [g(x + y + 2 x y), all]
The functions sin, cos, tan are the basic trigonometric functions; the functions sinh, cosh, tanh are the hyperblic equivalents; the functions sincos and shch compute and return the sine and cosine. These functions take as argument a real or complex number, in double precision or more. Recall that 1.L0 is a quad precision number, 1.D0 is an octuple precision number, and 1.B0 is a bigfloat.
[Endymion] (sin 1.0) 0.841470984807897 [Endymion] (cos 1.0) 0.54030230586814 [Endymion] (sincos 1.0) (0.841470984807897 . 0.54030230586814) [Endymion] (tan 1.0) 1.5574077246549 [Endymion] (sinh 1.0) 1.1752011936438 [Endymion] (cosh 1.0) 1.54308063481524 [Endymion] (tanh 1.0) 0.761594155955765 [Endymion] (shch 1.0) (1.1752011936438 . 1.54308063481524) [Endymion] (sin #C(3. 4.)) [-27.0168132580039i+3.85373803791938] [Endymion] (sin 0.3141592653589793238462643383279L1) 0.502884196681097564023329420182208L-30 [Endymion] (sin 0.3141592653589793238462643383279d1) 0.502884197169399375105820974944592307816406286209589712822920458701D-30 [Endymion] (sin 0.3141592653589793238462643383279b1) 0.50288419e-30 [Endymion] (sin 0.3141592653589793238462643383279l0) 0.309016994374947424102293417182771L0 [Endymion] (sin 0.3141592653589793238462643383279D0) 0.309016994374947424102293417182771231730888608493015813543415010079D0 [Endymion] (sin 0.3141592653589793238462643383279b0) 0.309016994374947424102293417182771231730e0
This function returns a sequence of length one, containing x.
(1) x:=singleton_seq(25); (1) <UninitializedSequence: single, 25> (2) y:=makeseq(x); (2) <InitializedSequence: single, 25> (3) popseq(y); (3) 25 (4) endofseq(y); (4) TRUE
This function returns the size of its argument. This is the degree of a polynomial, the length of a vector, a string, a list, etc.
(1) size(#vector(1,2,3)); (1) 3 (3) size(#PD_s z^3); (3) 3 (9) let(x=size(#PFD_s z^3+z^-1), [#car(x), #cdr(x)]); (9) [- 1, 3]
This is like Slambda, but the first argument is unevaluated (if it is a list, the elements of the list are unevaluated, otherwise a list with a single element is created). In fact, slambda(x,B) expands to let(x=X,Slambda(x,b)), where X evaluates to a symbol whose name is x.
There is no function, no operator, no macro called Slambda, but the symbol is declared to be used with two arguments. When you say f(x,y) and the operator is not a function, the simplifier will be called; it can reject the operator, or apply it, or construct the expression applyq(f,x,y). When you say lambda(x,x+y)(1), the compiler creates a Lisp function and applies to the number 1. When you say Slambda([x],x+y)(1), the simplifier creates an expression, and applies it, application is done via subst(x=1,x+y): Note that, if you replace the integer by a string, then addition will complain; in the case of a symbolic lambda, you may get a `typecheck failure'. (see subst for details).
(1) [a,b,c]:=[1,2,3]; (1) 3 (2) F:=slambda([a,b], f(a,b,c,d)); Macro expansion -> slambda([a, b], f(a, b, c, d)) Macro expansion <- let([b = concat(b), a = concat(a)], Slambda([a, b], f(a,b,c,d))) (2) Slambda([a, b], f(a, b, 3, d)) (3) F:=subst(d=D,F); (3) Slambda([a, b], f(a, b, 3, D)) (4) F(u,v); (4) f(u, v, 3, D) (5) F(u,v,w); Slambda : length of list not 3 : [a, b] (6) subst(g=F, [ g, g(u,v) ]); (6) [Slambda([a, b], f(a, b, 3, D)), f(u, v, 3, D)] (7) Slambda(1,2,3); Slambda : wrong number of arguments : 3 this should be 2
There is the same relationship between let, slet and Slet as between lambda, slambda and Slambda (see above). The first argument of slet should be a list of equalities (a single equality is accepted). The macro creates a Slet where the names in the LHS of the equalities are left unevaluated. In fact slet(a=b,c) becomes Slet(A=b,let(a=A,c)); this is then evaluated: b and c are evaluated as usual, and A evaluates to a. You must call Seval explicitly if you want the Slet to be evaluated.
(1) [a,b,c] := [1,2,3]; (1) 3 (2) F:=slet(a=b,g(a,b,c,d)); Macro expansion -> slet(a = b, g(a, b, c, d)) Macro expansion <;- Slet([concat(a) = b], let([a = concat(a)], g(a, b, c, d))) (2) Slet([a = 2], g(a, 2, 3, d)) (3) G:=slet([a=b,u=v],g(a,b,c,d)); Macro expansion -> slet([a = b, u = v], g(a, b, c, d)) Macro expansion <- Slet([concat(a) = b, concat(u) = v], let([a = concat(a), u = concat(u)], g(a, b, c, d))) (3) Slet([a = 2, u = v], g(a, 2, 3, d)) (4) subst(d=D,F); (4) Slet([a = 2], g(a, 2, 3, D)) (5) Seval(%)+ Seval(G); (5) g(2, 2, 3, D) + g(2, 2, 3, d)
The expression (sort1 x) is equivalent to (#:feval:generic_sort x 'compare)
The expression (sort2 x) is equivalent to (#:feval:generic_sort (append x ()) 'number)
The scanstring function takes two or three arguuments: two objects that can be coerced into a string and an integer (the default value is zero). It considers each character at position i in the first string, starting at n, and returns the index of the first character that is not in the second string. It returns () if not possible. The function could be defined as
(defun spanstring (a b . c) (if c (setq c (car c)) (setq c 0)) (tag found (let (s1 s2 n1 n2 ok) (setq s1 (string-to-list a)) (setq s2 (string-to-list b)) (setq n1 (length s1)) (setq n2 (length s2)) (for (i c 1 (- n1 1)) (unless (member (nth i s1) s2) (exit found i))) ())))
Example
[Endymion] (spanstring "abcd" "ab") 2 [Endymion] (spanstring "abcb" "ab") 2 [Endymion] (spanstring "abcd" "aabbccdd") () [Endymion] (spanstring "abcd" "bcd" 1) () [Endymion] (spanstring "abcd" "bcd" 0) 0 [Endymion] (spanstring "foo" "") 0 [Endymion] (spanstring 123.456 "123456789") 3 [Endymion] (spanstring -123.456 "123456789") 0 [Endymion] (spanstring 123.456e20 "123456789") 1 [Endymion] (spanstring 123.456e20 "123456789" 2) 7 [Endymion] (string 123.456e20) 1.23456e+22
A spline object is a piece-wise polynomial function. It is represented internally by an array of size N (the function spline_size returns the size), containing a ppoly; this is an array of 6 numbers, a, b, A, B, C, D. On the interval [a,b], the value of the function f(x) is A+Bt+Ct2+Dt3, where t=x-(a+b)/2. The coefficients are complex, the bounds are real. When the spline is read or printed, ten numbers are read: a, b, RA, IA, RB, IB, RC, IC, RD, ID (where R and I and the real an imaginary parts). Of course a must be less than b, and the upper bound of one interval must be the lower bound of the next one. You can use getcoef, this returns one coefficient as a vector of size 6. You can use setcoef to modify the coefficients; the last argument is a vector containing a, b, A, B, C, D. Of course, you cannot modify the bounds, so that a vector of size 4 with A, B, C, D works as well. The function make_splines takes as argument a list or vector of N+1 numbers, and creates the zero spline.
[Endymion] (make_splines #[1.2 1.3 1.4 1.5 ]) #PSp 3 1.2 1.3 0 0 0 0 0 0 0 0 1.3 1.4 0 0 0 0 0 0 0 0 1.4 1.5 0 0 0 0 0 0 0 0 [Endymion] (setq sp #PSp 2 1.66 1.77 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 [Endymion] 1.77 1.99 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.10) #PSp 2 1.66 1.77 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2 1.77 1.99 2.3 2.4 2.5 2.6 2.7 2.8 2.9 2.1 [Endymion] (splines_size sp) 2 [Endymion] (getcoef sp 1) #[1.77 1.99 [2.4i+2.3] [2.6i+2.5] [2.8i+2.7] [2.1i+2.9]] [Endymion] (setcoef sp 0 #[1.66 1.77 #C(1.3 -1.4) #C(1.5 -1.6) #C(1.7 -1.8) [Endymion] #C(1.9 -2.0)]) #[1.66 1.77 [-1.4i+1.3] [-1.6i+1.5] [-1.8i+1.7] [-2i+1.9]]
In symbolic mode, the printed result is a bit different. A splines behaves like an array, in that you can use a[b] or a[b]:=c instead of getcoef(a,b) or setcoef(a,b,c). The last argument can be a list instead of a vector.
(1) sp; (1) <spline: <ppoly: 1.66, 1.77, 1.3 - 1.4 %i, 1.5 - 1.6 %i, 1.7 - 1.8 %i, 1.9 - 2 %i>(<ppoly: 1.77, 1.99, 2.3 + 2.4 %i, 2.5 + 2.6 %i, 2.7 + 2.8 %i, 2.9 + 2.1 %i>)> (2) sp[1]; (2) <vector: 1.77, 1.99, 2.3 + 2.4 %i, 2.5 + 2.6 %i, 2.7 + 2.8 %i, 2.9 + 2.1 %i> (3) sp[1]:=[1.77, 1.99, #C(2.3,-2.4), 3, 4, 0]; (3) [1.77, 1.99, 2.3 - 2.4 %i, 3, 4, 0]
You can get the value of a splines by using the pol-eval function. The second argument must be a real number. If it is outside the range of the splines, the value is ().
[Endymion] (pol-eval sp 1.769) [1.391963728i+1.3137436184] [Endymion] (pol-eval sp 1.7701) [2.1452909440721i+2.0540112444329] [Endymion] (pol-eval sp 0) () [Endymion] (pol-eval sp #C(0 1)) pol-eval : not a real number : [i]
The lisp function requires a number, and returns the square root; the symbolic function is more general. In non-trivial cases, power(n,1/2) is computed.
(1) sqrt(1000); (1) 31.6227766016838 (2) sqrt(100); (2) 10 (3) sqrt(-100); (3) 10 %i (4) sqrt(#C(11 12.3)); (4) 3.70818096084138 + 1.65849511254828 %i (5) [sqrt (x), sqrt(1/x), sqrt(x^2), (sqrt(x))^2, sqrt(a*b) ]; [ |-- ] [ |- 1 | 2 |---] (5) [\|x, ---, \|x , x, \|a b] [ |- ] [ \|x ]
The sref function takes two arguments: a string and a number. It returns the character of the string at the given position.
[Endymion] (sref 'foo 0) sref : non string argument : foo [Endymion] (sref "foo" 1.5) sref : not a fixnum : 1.5 [Endymion] (sref "foo" -1) sref : argument out of bounds : -1 [Endymion] (sref "foo" 4) sref : argument out of bounds : 4 [Endymion] (catenate (list (sref "bar" 0) (sref "bar" 2) [Endymion] (sref #"BAR" 0)(sref #"BAR" 2))) brBR
The sset function takes three arguments: a string, a number, and a character. It sets the character in the string at the given position. It returns the character. If x is a string (#:feval:array1 x n) is the same as (sref x n) and (#:feval:arrstore x cn idx) is the same as (sset x idx cn). Symbolic notations are x[n] and x[idx]:=cn so that decrement(x[0],32); replaces the first character of x by its uppercase equivalent (if it is a lowercase letter).
[Endymion] (sset 'foo 0 #/a) sset : non string argument : foo [Endymion] (sset "foo" 1.4 #/a) sset : not a fixnum : 1.4 [Endymion] (sset "foo" -1 #/a) sset : argument out of bounds : -1 [Endymion] (sset "foo" 3 #/a) sset : argument out of bounds : 3 [Endymion] (sset "foo" 1 1.2) sset : not a fixnum : 1.2 [Endymion] (sset "foo" 1 -2) sset : argument out of bounds : -2 [Endymion] (sset "foo" 1 1000) sset : argument out of bounds : 1000 [Endymion] (setq x "foo" Z #"FOO") FOO [Endymion] (sset x 0 #/a) 97 [Endymion] (sset Z 0 1000) 1000 [Endymion] x aoo [Endymion] Z ϨOO
The construction 1...10 step 3 is explained here.
If the argument of stratom is not a character string, it is returned unchanged. Otherwise it is converted to an atom (a number if possible, a symbol otherwise).
Inside a symbolic macro you can use string(x), this converts the argument in a string, see the compiler.
The string function takes one argument, and converts it to string. If the argument is a string or a wide-string, the argument is returned. Otherwise, it is converted like catenate (note that catenate always returns a new string). Integers and floating point numbers can be converted. Rational numbers and BigFloat cannot be converted. Lists and vector of codes can be converted (see example).
[Endymion] (setq x1 "foo" x2 #"bar") foo [Endymion] (eq x1 (string x1)) true [Endymion] (eq x2 (string x2)) true [Endymion] (eq x1 (catenate x1)) () [Endymion] (eq x2 (catenate x2)) () [Endymion] (equal x1 (catenate x1)) true [Endymion] (equal x2 (catenate x2)) true [Endymion] (string -10) -10 [Endymion] (string 10) 10 [Endymion] (string 1234567890) 1234567890 [Endymion] (string 12345678901) string : non string argument : 12345678901 [Endymion] (string 12345/678901) string : non string argument : 12345/678901 [Endymion] (string 'foo) foo [Endymion] (string '#:foo:bar) bar [Endymion] (string '123.l0) 123.L0 [Endymion] (string '123.d0) 123.D0 [Endymion] (string '(100 101 102)) def [Endymion] (string '(1000 1010 1020)) string : syntax error : bad list of ASCII codes [Endymion] errexp 1000 [Endymion] (catenate #"" '(1000 1010 1020)) Ϩϲϼ [Endymion] (catenate #"" '(1000 -1010 1020)) catenate : syntax error : bad list of Unicode codes [Endymion] errexp -1010 [Endymion] (string #:string:#[100 101 102]) def [Endymion] (string #:string:#[100 -101 102]) string : syntax error : bad list of ASCII codes [Endymion] errexp -101 [Endymion] (string #:string:#[1000 1010 1020]) string : syntax error : bad list of ASCII codes [Endymion] (catenate #"" #:string:#[1000 1010 1020]) Ϩϲϼ
The string-to-list command takes an argument and converts it to a wide-string. It returns the list of Unicode numbers of the string. Note that explode returns also a sequence of integers, the UTF8 representation of the string.
[Endymion] (setq x (catenate #"" "José")) José [Endymion] (explode x) (74 111 115 195 169) [Endymion] (string-to-list x) (74 111 115 233) [Endymion] (string-to-list "José") (74 111 115 233) [Endymion] (string-to-list '(100 110 300 400)) (100 110 300 400) [Endymion] (string-to-list '(100 110 300 400 x)) string-to-list : syntax error : bad list of Unicode codes
This function takes as argument a string s and two integers i, j. The string s, starting at position i, with at most j characters is converted to a rational number or an integer.
[Endymion] (string_to_number "12345/e" 1 3) 234 [Endymion] (string_to_number "1437/5678e2" 1 7) 437/567 [Endymion] (string_to_number "1437/5678e2" 1 20) 437/5678 [Endymion] (string_to_number "1-437/5678e2" 1 7) -437/56 [Endymion] (string_to_number "1-437/5678e2" 1 -5) 0 [Endymion] (string_to_number "1-437/5678e2" 1 5) div : division by zero : -437 [Endymion] (string_to_number "1-437/5678e2" 1 1/5) string_to_number : bad arguments : 1-437/5678e2 [Endymion] (string_to_number 12 1 15) string_to_number : bad arguments : 12
The stringp function takes one argument. It returns its arguments if it is a string, it returns () otherwise.
[Endymion] (stringp 'foo) () [Endymion] (stringp '(foo)) () [Endymion] (stringp #[(foo)]) () [Endymion] (stringp "(foo)") (foo) [Endymion] (stringp #"José") José
The strlen function takes an argument and returns the number of characters of the argument converted to a string. See the function string for how the argument can or cannot be converted into a string. The function can be defined as follows:
(defun strlen (x) (length (string-to-list x)))
Example
[Endymion] (strlen "foo") 3 [Endymion] (strlen '#:foo:bar:geee) 4 [Endymion] (strlen '12345) 5 [Endymion] (strlen '-12.3) 5 [Endymion] (strlen #"José") 4 [Endymion] (strlen 3/4) strlen : non string argument : 3/4
The procedure takes two integer arguments, where k is between 1 and n. It returns the sequence of all ordered lists of length k of numbers between 0 and n-1. The length of this sequence is the number of combinations between the two arguments; hence can be large.
(1) subsets_seq(10, 2);; subset : argument out of bounds : 10 (2) subsets_seq(3,6); (2) <UninitializedSequence: subset, 3, 6> (3) s:=makeseq(%); (3) <InitializedSequence: subset, 3, 6> (4) seq_to_list(s); (4) [[0, 1, 2], [0, 1, 3], [0, 1, 4], [0, 1, 5], [0, 2, 3], [0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [0, 4, 5], [1, 2, 3], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], [1, 4, 5], [2, 3, 4], [2, 3, 5], [2, 4, 5], [3, 4, 5]]
The sub function computes the difference between its two arguments. The effect of (- 1 2 3) is the same as (sub 1 (+ 2 3)). Note that the symbolic reader considers a-b-c as (a-b)-c, not a-(b+c).
See subst below.
The Lisp subst function takes three arguments. It replaces all occurences of the second argument by the first in the last. The result shares as many elements are possible with the initial list. The function can be defined as
(defun subst (a b l) (if (equal b l) a (if (atom l) l (let ((la (subst a b (car l))) (ld (subst a b (cdr l)))) (if (and (eq la (car l)) (eq (ld (cdr l)))) l (cons la ld))))))
Examples. Look carefully: #1 is the part of L1 that was initially shared, #7 is the sublist (1 2) that was not shared, and #3 is the substituted expression.
[Endymion] (subst '(x y z) 'a '(a c (d a))) ((x y z) c (d (x y z))) [Endymion] (setq l '(1 2)) (1 2) [Endymion] (setq L1 '(a b #.l ((a b #.l) (1 2) . a))) (a b (1 2) ((a b (1 2)) (1 2) . a)) [Endymion] (cirprint (list L1 (subst '(1 2) 'a L1))) ((a b #1=(1 2) ((a . #5=(b #1#)) #7=(1 2) . a)) (#3=(1 2) b #1# ((#3# . #5#) #7# . #3#))) ((a b (1 2) ((a b (1 2)) (1 2) . a)) ((1 2) b (1 2) (((1 2) b (1 2)) (1 2) 1 2)))
The symbolic function substitute performs a similar job, but the result of the substitution is simplified again. Both subst(a=b,c) and subst3(a,b,c) replace a by b in c. The first argument of the symbolic subst function can be a list or a set of equalities. In this case, multiple substitutions are done in parallel. Finally, sublist(A,B,c) replaces Ai by Bi in c, where Ai and Bi are the corresponding elements in the lists A and b. For some strange reason, you cannot replace a list by an integer, and vice-versa. You have to set the variable $substnoerr to a non-false value in order to remove this check.
(1) subst(a=b,[a,b,<<a,b,a=b, f(a), a^2, a+b, a(10)>>]); 2 (1) [b, b, <<b, b, b = b, f(b), b , 2 b, b(10)>>] (2) subst(<<a=b,b=a>>, [ a,b, a+b, a*b, a^b] ); a (2) [b, a, a + b, a b, b ] (3) subst3(a,b, [a,b]); (3) [b, b] (4) substitute(b,a, [a,b,a+b,a-b]); (4) [b, b, 2 b, 0] (5) sublist([a,b,c],[A,B,C], f(a,b)); (5) f(A, B) (6) subst([1]=0, [[1], [1,2], [1,2,3]]); subst : typecheck failure in substitution : [1] = 0 (7) let(#:endymion:substnoerr=true, subst([1]=0, [[1], [1,2], [1,2,3]])); (7) [0, [1, 2], [1, 2, 3]]
The substring function takes two or three arguments: a string (or anything that can be coerced to a string via string) and two integers. The last argument can be omitted, a large value will be used instead. The result is a string, obtained by removing the n1 first characters, and taking at most n2 characters of the result. The function could be defined as follows.
(defun substring (strg n1 . n2) (let ((S (string-to-list strg))) (setq S (nthcdr n1 S)) (if n2 (setq S (firstn (car n2) S))) (if (eq (type-of strg) 'wstring) (catenate #"" S) (catenate S))))
Example
[Endymion] (substring "abcde" 0 3) abc [Endymion] (substring "abcde" 1 2) bc [Endymion] (substring "abcde" 2) cde [Endymion] (substring "abcde" 9 2) [Endymion] (substring "José" 2 2) sà [Endymion] (substring #"José" 2 2) sé
The substring-eq function takes three, four, or five arguments, a string, an integer, a string, an integer (default value is zero), and an integer (default value is infinity). The function compares the first string (starting at the first index), with the second string (starting at the second index). If four arguments are given, as many characters as possible are tested. If five arguments are given, the last argument is the number of characters to test (the result is false if this number is too large). The function could be defined as:
(defun substring-eq (s1 n1 s2 . x) (let ((n2 0) len) (if x (setq n2 (car x) x (cdr x))) (setq s1 (nthcdr n1 (string-to-list s1))) (setq s2 (nthcdr n2 (string-to-list s2))) (if x (setq len (car x)) (setq len (length s1)) (when (≤ (length s2) len) (setq len (length s2)))) (if (and s1 s2 (≤ len (length s1)) (≤ len (length s2))) (equal (firstn len s1) (firstn len s2)) ())))
Example
[Endymion] (substring-eq "foobar" 0 "gezu" 0 0) true [Endymion] (substring-eq "foobar" 0 "gezu" 0 1) () [Endymion] (substring-eq "abcde" 2 "xcdef" 1) true [Endymion] (substring-eq "abcde" 2 "xcdef" 1 2) true [Endymion] (substring-eq "abcde" 2 "xcdef" 1 3) true [Endymion] (substring-eq "abcde" 2 "xcdef" 1 4) () [Endymion] (substring-eq '#:a:foo 1 '#:b:oops) true [Endymion] (substring-eq '#:a:foo 1 '#:b:oops 1) () [Endymion] (substring-eq '#:a:foo 1 '#:b:oops 1 1) true [Endymion] (substring-eq '#:a:foo 1 '#:b:oops 1 2) ()
The subtypep function takes two types as arguments, it returns true if the first one is a subtype of the second. If returns false if one of the arguments is not a symbol. It returns true if the first argument, its packagecell, the packagecell of is packagecell, etc, is equal to the second argument. The function could be defined as:
(defun subtypep (type L) (if (or (not (symbolp type)) (not (symbolp L))) () (if (null L) true (while (and type (neq type L)) (setq type (packagecell type))) (if type true false))))
Example
[Endymion] (subtypep 'foo 1) () [Endymion] (subtypep 1 'foo) () [Endymion] (subtypep '#:a:b:c '#:a:b:c) true [Endymion] (subtypep '#:a:b:c '#:a:b) true [Endymion] (subtypep '#:a:b:c '#:a) true [Endymion] (subtypep '#:a:b:c ()) true [Endymion] (subtypep '#:a:b '#:a:b:c) () [Endymion] (subtypep '#:a '#:a:b:c) () [Endymion] (subtypep () '#:a:b:c) ()
The function super-itsoft behaves like itsoft. It applies a given function to the list a. This function is computed as follows. First, the itsoft list (the value of #:sys-package:itsoft) is considered; all items are discarded, until finding p, which is also discarded. After that, itsoft is called, with arguments f and a, but with this smaller itsoft list. For an example of use, see itsoft.
The synonym function takes two arguments. If these two arguments are symbols, it copies the functional value of the second in the first and returns the first argument. Otherwise it does nothing, and returns ().
[Endymion] (defun F1 (x) (CAR x)) F1 [Endymion] (F1 0) eval : undefined function : CAR [Endymion] (synonym 'F2 'F1) F2 [Endymion] (synonym 'CAR 'car) CAR [Endymion] (F2 0) car : not a list : 0 [Endymion] (getdef 'F2) (defun F2 (x) (CAR x)) [Endymion] (getdef 'CAR) (ds CAR 2 134779088) [Endymion] (synonym 'car 0) () [Endymion] (synonym 1 'car) ()
The symbol function takes two arguments, a pakage (a symbol) and a name (a symbol or a string); it constructs and returns a symbol whose name is formed by these components.
[Endymion] (setq pk '#:foo:bar) #:foo:bar [Endymion] (symbol pk 'toto) #:foo:bar:toto [Endymion] (packagecell (symbol pk 'toto)) #:foo:bar [Endymion] (string (symbol pk 'toto)) toto [Endymion] (symbol pk "toto") #:foo:bar:toto [Endymion] (symbol 123 "toto") symbol : not a symbol : 123 [Endymion] (symbol pk 456) symbol : non string argument : 456
The symbolp function returns true if its argument is a symbol and false otherwise.
[Endymion] (symbolp 'foo) true [Endymion] (symbolp 'ibase) true [Endymion] (symbolp 'true) true [Endymion] (symbolp '"true") () [Endymion] (symbolp '("true")) ()
The system function takes no argument; it returns the name of the system on which Endymion is running. Example
[Endymion] (system) linux [Endymion] (type-of (system)) string
back to home page © INRIA 2005, 2006 Last modified $Date: 2009/01/08 17:43:30 $