Re: SETF and variable issues in Self Similar program.



In article
<1568e9f0-aa4e-460a-bacb-70911622d0fe@xxxxxxxxxxxxxxxxxxxxxxxxxxx>,
Eric <ericbelcastro@xxxxxxxxx> wrote:


Some comments about the general style of your code below:


;;list-a-scale just creates a list of ordered integers from n up to x
;;(I already wrote a count-up function and will probably just use a
;;modified version of that in the final code)
;;
;;(defun count-up (n)
;; (cond ((= n 1) (list 1))
;; (t (append (count-up (- n 1)) (list n)))))

APPEND is always a warning sign. APPEND in recursive
functions supposed to be inefficient. APPEND creates
a fresh list - always. Your code is maximum inefficient,
since you append a long list to a list with a single item.

Rethink it.

;;
;;symbol-scroll scrolls the list to the left or right
;;reorder-by-n takes every n element of the list, and returns a new
;;list - which sounds similar to what I want, but it's not.
;;
;;The given portion of the code here creates listx1 listx2 .... listxn
;;automatically - these lists contain all numbers that are equivalent
;;in the final structure - and they will be called while *countera* is
;;being decremented in the final function and translated to the final list.
;;
;;create-ssarray is the part that I am concentrated on now - r1 is the ratio
;;of similarity, sp1 is the starting point for that ratio (it can start
;;anywhere instead of at just 1), slength is the length of the list
;;(1 2 3 4...). Everything works perfectly for ratios
;;2,3,6,etc. but not for many other ratios as the pattern I am using is
;;faulty, and I know why. I just have to start over.

(setf *numratios* 1)
(setf clm 0)
(setf *counta* 0)

Global variables should always be written as *foo*. Variables
are introduced by DEFPARAMETER. Hint: DEFPARAMETER allows
a comment string.

(defparameter *foo* 'bar
"*FOO* is the prototypical variable")


(defun ordered-union (x y)
(append x (remove-if #'(lambda (k) (member k x))
y)))

I would give x and y more descriptive names. Add a comment.

(defun foo (bar)
"the function foo does..."
ghsdf)

Any good Common Lisp allows you to look up the documentation string
with a key combination. Also many implementations will
show you the arglist when you press space after a function
or if you press some key combination. You want then
variable names that are readable. Otherwise you
would see (setclm n) - what does it mean? You likely will
not remember what the function does after a week not looking
at the code.


(defun create-ssarray (slength r1 sp1)
(let* ((original-list-t (list-a-scale 1 slength))
(new-list-1 (symbol-scroll (- sp1 1)
(reorder-by-n (ceiling (/ slength r1))
original-list-t))))
(setf ssarray (build-array (list original-list-t new-list-1)))
(setf *original-list* (list-a-scale 1 slength))
(create-sublists ssarray)))

I would not even guess what the function does. It is not descriptive
enough. Any Lisp compiler (also interactive) would also complain
that ssarray is not known to be a variable - it is not introduced
in this function. Using global variables like *original-list*
is also not a good idea. Rule: avoid global variables.


(defun create-sublists (array)
(incf *counta*)
(set (car (symbol-bundle 2 (list 'listx *counta*)))
(listrec (pick-array 0 clm (+ *numratios* 1) array :down) 1))
(cond ((check-length *counta*) nil)
(t (setf clm (setclm *counta*)) (create-sublists array))))

Again it is not clear what this does.
You definitely need more documentation.

I also put either examples in the documentation or write tests.

(defun append-foo (list)
"Append the symbol foo to the end of the input list."
(append list (list 'foo)))

; (append-foo '(1 2 3))
; -> (1 2 3 FOO)

Any good Lisp editor lets you execute the code in the comment.
A typical thing would to select the code with a double click
and press eval-region. Sometimes you also can place the
cursor at the end or the beginning of a form and press enter.
Even if the form is in the comment.
Sometimes I just use the editor and no listener.
The code is in the editor buffer and example calls are in the comments.
When I develop the function, I execute the code in the comment to
see if it works. If the tests get more complicated, I write tests
and execute those from forms in the comments.


(defun listrec (listx n)
(if (equal n 1)
(setf listg (remove-duplicates (ordered-union listx (pick-array 0 (- (nth n listx) 1) (+ *numratios* 1) ssarray :down))))
(setf listg (remove-duplicates (ordered-union listg (pick-array 0 (- (nth n listg) 1) (+ *numratios* 1) ssarray :down)))))
(cond ((null (nth (+ n 1) listg)) listg)
(t (listrec listg (+ n 1)))))

Again you set a symbol not defined in the function (listg). You really should
use the compiler for development. Find out what the keychord your
editor has for 'compile defun'. The you can have the cursor somewhere in
the function and the editor will pick the whole function, compile
it with the compiler and present any output. The compiler would
complain about free variables, missing arguments, ... and many
similar errors. If you have a good compiler, you even might get
style warnings or efficiency hints.


(defun check-length (n)
(if (equal n 1) (equal (length listx1) (length *original-list*))
(equal (length (append-lists n)) (length
*original-list*))))

Somehow I find above function not intuitive. You are using global variables.
Don't do that.


(defun append-lists (n)
(cond ((equal n 0) nil)
(t (append (symbol-value (car (symbol-bundle 2 (list 'listx n))))
(append-lists (- n 1))))))

Again, a recursive append. Again some access to an outside datastructure.


(defun setclm (n)
(let ((listo (sort (append-lists n) '<)))
(- (find-if #'(lambda (x) (null (equal x (nth (- x 1) listo))))
*original-list*) 1 )))


Again a global variable used.

I think you should write your code in small pieces that work independently.
Avoid side effects. Make each function a little 'module' which
takes input (only the arglist, no global variables) and create
output. Make them easily testable - independently. Each function
should have a clear and documented purpose. Make them easy
to combine.

Rewrite the functions. Do it again. Until you like what you see.
Especially for beginners with Lisp it is important to experiment
and to try out alternatives. Lisp is very good for interactively
designing implementations of algorithms. You can change it and
test it immediately. Also reading some books on basic usage
of Lisp lets you learn from others - SICP, PAIP, Lisp (3rd Edition,
Winston/Horn, Practical Common Lisp, ...
It takes some time, but suddenly it will all fit together.

If you read and understand AMOP, even enlightenment is possible. ;-)



;;I am thinking about doing it by creating a positional-list that contains
;;the positions in the list that need replaced by 1 2 3 4 5...
;;
;;(positional-list (mapcar #'(lambda (x) (+ (mod (* x r1) slength) 1))
;; (list-a-scale 0 slength)))
;;
;;I would then need to take this positional-list and a *original-list* of (1
2 3...)
;;
;;(setf *original-list* (list-a-scale 1 slength))
;;
;;integers in counting order and say (with code) take the first number from
;;counting-list and put it in a new list in the position that is the first
number
;;in positional-list. Then take the second number from counting list and put
it
;;in a new list in the position that is the second number in position-list,
etc.
;;
;;I am trying to do this with nth mapcar and replace now...maybe using an
empty
;;vector filled with 0s (build-array) and putv and then converting back to
list
;;would be better, don't know.
;;
;;Regardless, thank you everyone for so much help. I'll try to educate
myself
;;and not be such a needy little boy.

--
http://lispm.dyndns.org/
.



Relevant Pages

  • Re: Some advice for a lisp newb
    ... > So they could be global variables, which would get them out of the ... > parameter lists so one could focus attention on the parameter that is ... (defun shortest-path (start end net) ... (defun bfs (queue) ...
    (comp.lang.lisp)
  • Re: How does #last do it?!?!
    ... The fact that last does not slow down with larger lists ... (defun last-long(iter) ... APPEND is a function without side effects. ... LAST will not use recursion. ...
    (comp.lang.lisp)
  • SMUTIL - What is a Dot Context Error [1/2]
    ... (DEFUN ISTENSE (NODE ARG) ... ;;BUILD CONSTRUCTS AN OSS OR AN RSS FROM ITS ARGUMENTS. ... (SETQ %PROPS '(NEGATIVE= REFER= ... ;;CARTESIAN PRODUCT OF N LISTS GIVEN AS ARGUMENTS. ...
    (comp.lang.lisp)
  • Re: Some advice for a lisp newb
    ... (defun shortest-path (start end net) ... (parent a child-list (b c)) ... Lisp's built-in lists are singly linked, ... My vote goes for an alternative - that programmers from a C ...
    (comp.lang.lisp)
  • Re: eval in bash vs macro in lisp
    ... The first element is the symbol "defun", ... The last two elements are nil, ... is used to end lists. ... The whole thing is a tree formed from pairs. ...
    (comp.lang.lisp)