I've noticed in most programming languages there seems to be an asymmetry in defining functions for powers and roots. Newlisp too seems to follow this arrangement. There is the SQRT function but no general ROOT function. We have the POW function for general powers but no dedicated SQ function for squaring. First I will start with arguing for simple enhancements to SQRT. I would like to see sqrt take a vector list and return the length of the vector. So (sqrt '(1 2 3)) returns 3.741... In addition to this I would like the function to take an optional 2nd vector and return the n-dimensional distance between them. So (sqrt '(1 2 3) '(3 4 5)) would return 3.464... Making these changes would allow basic vector operations and incorporate finding distance between points without having to write a dedicated function.
A suggested SQ function takes a number x and multiplies it by itself preserving type. If x is a vector then its elements are squared and then summed. If there are two vectors then the difference between the two are calculated and the sum of the squares is performed on that. Now we have the quadrance operation that can be used in place of distance to get rid of having to call square roots in some algorithms.
We balance the POW function with the ROOT function that takes the y root of a number x. If no root y is supplied then it defaults to 3 which makes it a very handy cube root function.
The following code provides an implementation of these ideas if you want to try them out
Code Select
; Return true if v is a vector. A vector is a list of
; numbers that has at least one number in it.
(define ( vector? v )
(and (list? v)
(> (length v))
(for-all number? v)))
; Take the vector x square its elements and then sum them.
(define (sqsum x)(apply add (map mul x x)))
; Subtract vector y from vector x.
(define (vsub x y)(map sub x y))
; Take the square root of a number.
; If an integer or float use the sqrt function.
; If a vector return the length of the vector.
; If two vectors return the distance between the vectors.
(define ( sr x y )
(if y (setq x (vsub y x)))
(sqrt (if (vector? x)
(sqsum x)
x
)))
(constant 'sqrt sr) ;redefine sqrt function to act like sr function
; Square a number.
; If an integer use the * function.
; If a float use the mul function.
; If a vector return the quadrance of the vector.
; If two vectors return the quadrance between the vectors.
(define ( sq x y )
(if y (setq x (vsub y x)))
(if (vector? x)
(sqsum x)
((if (integer? x) * mul) x x)))
; Take the y root of x.
; If no y then the cube root is returned.
(define ( root x (y 3) )
(if (= y 2)
(sr x)
(pow x (div 1 y))))
I had one more idea to suggest; allow REVERSE to take a second list and perform a reverse append operation as in (reverse '(1 2 3) '(4 5 6)) -> (1 2 3 6 5 4) and (reverse "cat" "dog") -> "catgod" .