i have following common lisp functions: (aggregate line1 line2)
, (queuer data result)
.
queuer
should push result either values line1
, line2
if have 1st field different, or aggregate of 2 lines if have 1st field equal.
i not know why doesn't change result list.
note: initializing result list (push (pop data) result)
have first element there. 2 lists 1-depth nested lists (("1" "text") ("2" "text") (...))
.
(defun aggregate (line1 line2) (progn (list (nth 0 line1) (nth 1 line1) (nth 2 line1) (concatenate 'string (nth 3 line1) ", " (nth 3 line2)) (concatenate 'string (nth 4 line1) ", " (nth 4 line2))))) (push (pop x) y) (defun queuer (data result) (loop (let ((line1 (pop data)) (line2 (pop result))) (if (equal (first line1) (first line2)) (progn (push (aggregate line1 line2) result) (print "==")) (progn (push line2 result) (push line1 result) (print "<>")))) while data))
thank insights.
if write functions in lisp preferable think 'functionally'. function takes values , returns values. typical rule avoid side effects. function should return result value, not 'modify' variable value.
instead of:
(defparameter *result* '()) (defun foo (a) (push *result*))
use:
(defparameter *result* '()) (defun foo (a result) (push result) result) (setf *result* (foo *result*))
note aggregate
not need progn
.
slightly advanced (don't that):
if have global list:
(defparameter *foo* '())
you can't push onto it, have seen, this:
(defun foo (l) (push 1 l))
if call foo
variable *foo*
unchanged. reason: lisp not pass variable reference, passes value of variable.
but how can pass reference? well, pass reference: cons cell (or structure, vector, clos object, ...):
cl-user 38 > (defparameter *foo* (list '())) *foo* cl-user 39 > (defun foo (ref) (push 1 (first ref))) foo cl-user 40 > (foo *foo*) (1) cl-user 41 > (foo *foo*) (1 1)
now, if @ *foo*
, changed. haven't changed variable. have changed first entry of list.
cl-user 42 > *foo* ((1 1))
but, don't it. program in functional style.
Comments
Post a Comment