On Fri, 01 Nov 1996 23:34:35 -0800 Lu wrote: >Vladimir Nesterovsky wrote: >> On Sun, 27 Oct 1996 04:13:05 -0800, - Lu wrote >> >rosie wrote: ..... How can I multiply all numbers inside strings by 2?? >> >> there are 14 paths and 12 pigs. >> >> How can there be 24 ducks? >> >> >This is one way. (I am sure there are many other ways) >> >> It may be >> (defun mult2 ( strng ) >> (strlgather >> (mapcar >> '(lambda(s / n) >> (if(zerop(setq n(atof s))) s >> (rtos (* n 2)))) >> (strlparse strng " ")) ;; parse by spaces >> " ")) ;; gather back with spaces >> >> Have fun, > >Thanks. You guys amaze me. :-) I have never taken the time to learn >the usage of LAMBDA and MAPCAR. It's really simple. (lambda(x)(* x x)) is just the same as '((x)(* x x)) (note the quote) or (defun temp_func(x)(* x x)). The only difference, I guess, is that it may be virtualized after (vmon), but now at modern times all the memory is virtual anyway (defun will also spoil your name space). QUOTE is a function that returns its argument UNEVALUATED. When LISP sees ((x)(* x x)) in your code (w/out quote), it tries to evaluate the expression, and whilst it's a list, LISP thinks it's user function call, like (doit 1 2 3). In the latter DOIT is SYMbol that evaluates to list(== user function) and that's OK, but in the former ((x)...) the first argument isn't SYM at all, so you'd get BAD FUNCTION error with this code. LISP wants to evaluate everything so before passing it on to MAPCAR, it will evaluate ((x) (* x x)), but (x) is not a function, hence the error. Now, you don't want to evaluate this right away, only to pass it as argument to MAPCAR (see later), so you use quote to pass it AS IT IS, UNEVALUATED. It's like you've being typing it yourself at keyboard while executing the MAPCAR over and over again. Now for MAPCAR. It's a function that needs 1. quoted-sym OR quoted-lambda OR quoted-user-function-list 2. some list 3... optional more lists Let's say we call it with (mapcar 'myfunc mylist) The result will be LIST of RESULTS of calling MYFUNC with each element of MYLIST. For example (defun mysqr(x)(* x x)) (mapcar 'mysqr (list 1 2 3 4)) would return (1 4 9 16) Again MYSQR is quoted here, because MAPCAR is expecting it as such. MYSQR expects one numeric argument and that's what it gets. If I would call it like (MAPCAR 'MYSQR (list 1 2 "3")) LISP would try to build a list of results like [1] (list (mysqr 1) (mysqr 2) (mysqr "3")) and I would get BAD ARGUMENT TYPE error at "3". Note again that if you'd write this expression [1] yourself, MYSQR is again QUOTED-SYM of previously defined user-function that evaluates to some list, having it's first argument as a list too, so at this point LISP acknowledges such a list as user function and tries to evaluate it, substituting you real arguments for the fake arguments from its arguments-list. SO if you just want some function to be used in MAPCAR and if you don't want it stay around not being used anywhere else, you may use LAMBDA. It's a function that creates kind of ANONYMOUS FUNCTION and returns it QUOTED, just like DEFUN does (only defun creats NAMED function that stays in environment). MAPCAR is great in that it don't need to know OF HOW MUCH LENGTH a data-list is. It doesn't care. It just runs to the end of it, as at run-time it will be known. So you, at writing-time (like compile-time in compiled languages, like C etc), don't have to know the exact length of your data-list, and IT'S GREAT! It lets you deal with variable-length data easily, and all the real data is such. So I can (mapcar 'mysqr '(1 2 3)) or I can (mapcar 'mysqr '(1 2 3 4 5)), whatever. There's something more. Let's say I have this function that SUMs all its arguments. It's a '+, as I may call (+ 1 2) or (+ 1 2 3) etc. Now when I write (mapcar '+ '(1 2 3) '(4 5 6)) it's equivalent to (list (+ 1 4) (+ 2 5) (+ 3 6)) I can also write (mapcar '+ '(1 2 3)'(4 5 6)'(7 8 9)), equal to (list (+ 1 4 7)(+ 2 5 8)(+ 3 6 9)) etc. So we have another flexibility here. Of course I am responsible to provide my callable function with the appropriate number of arguments fed by MAPCAR, because else I'll get TOO MANY/FEW ARGUMENTS error when LISP will be eventually evaluating this. So what I do here, is 1. take a string apart and build a list of 'words' == substrings separated by " " (using my STRLPARSE function == STRing to List PARSE) 2. For each of words apply some function and build up the list of results - that's a MAPCAR 3. Use LAMBDA to make this function. It will try to ATOF every word. If it was not convertible, 0.0 will be returned, so I just return the original word string (and if it was real 0 there, then if multiplied by some # it will be 0 again), BUT if it's a number, I multiply it by 2 and make it string again (here DIMZIN and LUPREC will come into place). 4. Now I have list of words where each number was multiplied by 2. 5. Just gather it back by STRLGATHER using space as a glue string. Isn't it a simple way of thinking? Forget about all those counters, setq's and so on. Just operate upon your lists of data! Take it apart, apply some function, combine it back - voila! It's all done on a new level of operating. The system cares about all this indexing stuff, and you're relieved to do some essential work and creative thinking. ====================