funlib.lsp - my function's library

Started by Dmi, November 03, 2005, 03:34:19 PM

Previous topic - Next topic

Dmi

I decide to publish my library with the functions I found useful.

http://en.feautec.pp.ru/SiteNews/funlib_lsp">//http://en.feautec.pp.ru/SiteNews/funlib_lsp

renewed versions of "dofile" and "rawk", list grouping and other small stuff...
WBR, Dmi

Fanda

#1
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">http://www.alh.net/newlisp/phpbb/viewtopic.php?t=765



---------------------



Dmi: Could you please give me an example for 'group-by'? Thank you!



Fanda

Dmi

#2
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)
WBR, Dmi

Dmi

#3
'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.
WBR, Dmi

Dmi

#4
since the last post I've collected a nice set. here is it:

http://en.feautec.pp.ru/store/libs/">//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)
WBR, Dmi

Sammo

#5
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)) ))

Dmi

#6
++ and -- now in funlib.lsp



Thanks!
WBR, Dmi

Dmi

#7
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)
WBR, Dmi

Dmi

#8
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
WBR, Dmi