I decide to publish my library with the functions I found useful.
//http://en.feautec.pp.ru/SiteNews/funlib_lsp
renewed versions of "dofile" and "rawk", list grouping and other small stuff...
It could be nice to have the 'lesser' and 'greater' functions on a system level. I have seen that somebody has it as '--' and '++'.
It improves readability and also it could be faster because we pass only 1 parameter (++ x), not two (+ x 1).
Something like this:
(+ 1 (rand (- (factorial len) 1)))
Would look like this:
(++ (rand (-- (factorial len))))
Lutz, how do you like it?
----------------
'group' on a system level would be nice too :-))
Jeremy Dunn proposed: (group lst n bool)
;; This function performs a multiple slice on a given list
;; One supplies a list and an integer n. The list is broken into a list of sublists of
;; length n. If n is negative the list items are collected going from the end of the list
;; to the beginning. If the optional bool argument is supplied then remaining elements are
;; included in the result.
;; (group '(1 2 3 4 5 6 7) 3) -> ((1 2 3)(4 5 6))
;; (group '(1 2 3 4 5 6 7) 3 true) -> ((1 2 3)(4 5 6)(7))
;; (group '(1 2 3 4 5 6 7) -3 true) -> ((1)(2 3 4)(5 6 7))
(define (group lst n bool , len num rep rem start)
(setq num (abs n))
(if (< n 0)
(reverse (map reverse (group (reverse lst) num bool)))
(= n 0)
nil
(begin
(setq len (length lst)
rep (/ len num)
rem (% len num)
start '()
)
(if (< num len)
(begin
(dotimes (x rep)
(setq start (cons (slice lst (* x num) num) start)))
(if (and bool (> rem 0))
(setq start (cons (slice lst (* num rep) rem) start)))
(reverse start))
(list lst)))))
taken from here:
http://www.alh.net/newlisp/phpbb/viewtopic.php?t=765
---------------------
Dmi: Could you please give me an example for 'group-by'? Thank you!
Fanda
group-by works like this:
call-log is (date time duration client)
...and I slightly format the console output
> call-log
((2005 10 1 9 4 20 1 "User1")
(2005 10 1 17 5 31 19 "Kassa3")
(2005 10 1 18 15 44 13 "Kassa6")
(2005 10 2 12 9 55 2 "Kassa6")
(2005 10 2 14 58 44 5 "Kassa6")
(2005 10 2 17 17 47 2 "User2")
(2005 10 2 17 19 28 3 "User2")
(2005 10 2 17 52 45 3 "User1"))
> (group-by call-log '(-1) '(0 1 2 3 4 5 6))
((("User2") ((2005 10 2 17 17 47 2) (2005 10 2 17 19 28 3)))
(("Kassa6") ((2005 10 1 18 15 44 13)
(2005 10 2 12 9 55 2)
(2005 10 2 14 58 44 5)))
(("Kassa3") ((2005 10 1 17 5 31 19)))
(("User1") ((2005 10 1 9 4 20 1) (2005 10 2 17 52 45 3))))
> (group-by call-log '(0 1 2 3) '(6 7))
(((2005 10 2 17) ((2 "User2") (3 "User2") (3 "User1")))
((2005 10 2 14) ((5 "Kassa6")))
((2005 10 2 12) ((2 "Kassa6")))
((2005 10 1 18) ((13 "Kassa6")))
((2005 10 1 17) ((19 "Kassa3")))
((2005 10 1 9) ((1 "User1"))))
So, for my 'call-log' list, I can to group by client, or by day+hour, or whatever else...
Next, having the grouped list, I can get a complex statistics by any parameter.
If base list have a complex structure, for ex.:
(((year month day) (hour min sec) duration client)......)
then I can simply use 'map' to preprocess it like this:
(group-by (map (fn (x) (append (x 0) (x 1) x)) call-log) '(0 1 2 3) (-2 -1))
(modification of the last example)
'dofile' function is now havy tested in a real life.
Bugfixed and compatible with newlisp 8.7.0 or greater.
Improved 'group':
care about group length may not be greater than list length
can group from the end if group length is negative
Introduced 'group-all' - like a 'group' but not truncates the rest slice if it's not full.
Introduced 'ecase' - 'case', that evaluates e key arguments.
Introduced 'append-one' - nondestructive append one non-list element to the list.
since the last post I've collected a nice set. here is it:
//http://en.feautec.pp.ru/store/libs/
a brief list:
(global 'dofile 'dostring 'rawk 'rcase 'inc-p 'dec-p 'group 'group-all
'group-by 'try 'lesser 'greater 'append-one 'ecase 'ifempty 'dirname
'push-end 'file-tree 'newlisp-version 'int10 'doc)
Here is a pair of newLisp macros that implements Fanda's '++' and '--' ideas.
If passed an integer or an integer expression, the '++' macro increments the integer or expression value by 1 or by the value of the optional second parameter. For example:
>(++ 1)
2
>(++ (+ 1 2 3))
7
>(++ (+ 1 2 3) 5)
11
If passed a symbol, '++' increments the symbol's value and returns the updated value. For example:
>(set 'var 1)
1
>var
1
>(++ var)
2
>var
2
>(++ var 2)
4
>var
4
The '--' macro behaves similarly. Here are the macros:
(define-macro (++ _a _b)
(if (symbol? _a)
(set _a (+ (eval _a) (or _b 1)))
;else
(+ (eval _a) (or _b 1)) ))
(define (-- _a _b)
(if (symbol? _a)
(set _a (- (eval _a) (or _b 1)))
;else
(- (eval _a) (or _b 1)) ))
++ and -- now in funlib.lsp
Thanks!
Small improvement to ++:
_b must be evaluated before usage, to allow something like:
(++ var (length something))
(define-macro (++ _a _b)
"(++ a b) - increment a by b. a can by either a symbol or a value"
(if (symbol? _a)
(set _a (+ (eval _a) (or (eval _b) 1)))
(+ (eval _a) (or (eval _b) 1)) ))
Also I found some (documented) note about (inc):
(inc 'sym value) - with second argument, always converts sym to a float despite both arguments may be integers.
If I use 'sym as an integer argument in the dynamic library calls, after calling (inc 'sym 1) it becames unusable for that.
So ++ can be well integer-only replacement.
(funlib.lsp updated)
And, finally, a version w/o macro:
(define (++ _a01 _b01)
"(++ int-a int-b) - increment int-a by int-b. int-a can be either a symbol or a value"
(if (symbol? _a01)
(set _a01 (+ (eval _a01) (or _b01 1)))
(+ (eval _a01) (or _b01 1))))
(define (p++ _a01 _b01)
"(p-- int-sym int-num) - post-increment int-sym by int-num"
(let (_old (eval _a01))
(++ _a01 (or _b01 1))
_old))
> (set 'a 1)
1
> (++ 'a)
2
> a
2
> (p++ 'a 2)
2
> a
4