Page 1 of 1


Posted: Tue Oct 21, 2003 3:50 pm
by eddier

Code: Select all

; initialize data
(load "technology-survey-2003-04.dat")

; init values
(setq k 0)
(map (lambda (x)
  (let ((i (inc 'k)) (j 0))
    (map (lambda (y) (set (symbol (string "a-" i "-" (inc 'j)))
                  (if (integer? y) 0 '()))) x)))
     (first data)))

(set (symbol "r") 0)
(println r)

In the above code I get the error
symbol expected in function set: nil
The error is in the set right before the println because if I remove (set (symbol "r") 0), I get no error.


Posted: Tue Oct 21, 2003 10:11 pm
by Lutz
there seems to be a closing paraenthesis efter '(first-data))', which doesn't have an opening, but I don't know if this is related to the error.

Can you supply some fake data to try the whole thing?

I suppose 'data' is a list of lists of lists?


Posted: Tue Oct 21, 2003 10:40 pm
by Lutz
When taking out the addtional parenthesis and with:

(set 'data '(((1 2 3)(2 4 5)) ((6 7 8)(9 10 11))))

it runs fine and creates the symbols:

a-1-1 a-1-2 a-1-3 a-2-1 a-2-2 a-2-3

I guess the it takes one of the 'set' as a multiple argument 'set', because of the additional parenthesis.


Posted: Tue Oct 21, 2003 11:07 pm
by Lutz
I fixed a bug, when balancing parenthesis. The next version will report the error correctly as a 'missing parenthesis' error and point to the additional closing parenthesis before the 'set' statement in the error message.


Posted: Wed Oct 22, 2003 1:37 pm
by eddier
That must have been it. I played with the code a while and then started from scratch and everything worked fine the second time around.

I usually don't miss parenthesis since emacs highlights them as you type them.

I'm trying to convert some outdated python code to lisp to tally the results of our surveys. New survey changes broke the old code. An interpreter like lisp is ideal for throwing in conditionals to break out data by fields. However, keeping tallies in lists of lists of lists is a bit harder than I thought it would be. This part was easier in python (a[j] += 1) vs ??? That's why I'm creating all those variables. Some of them are counts and others are lists of strings (comments). If you know an easier method, I'm game :)

The Vice President has given the go ahead for a cgi program and surveys on the Web next time around. We will have a codes to make sure people have filled out a survey and also not allow them to take a survey twice. The hard part is to convince them the surveys are still anonymous.


Posted: Wed Oct 22, 2003 2:20 pm
by Lutz
With only a few hundred variables to update you could try association lists and do something like the following:

(set 'lst '((a 1)(b 2)(c 3)))
(replace-assoc 'b lst (list 'b (+ 1 (last $0)))) => ((a 1)(b 3)(c 3))
lst => ((a 1)(b 3)(c 3))

Or work with the plain list of values:

(set 'lst '(1 2 3 4))
(replace-nth 1 lst (+ $0 1)) => '(1 3 3 4)
lst => '(1 3 3 4)

The symbol stuff will probably be faster on bigger arrays, you might encapsulate the symbol-mangling stuff in some functions, like shown in 'array.lsp' in the distribution, but for more dimensions: like

(inc-array MyArray 1 4 2 value) ;; same as: MyArray[1][4][2] += value


Posted: Wed Oct 22, 2003 2:39 pm
by eddier
Thanks for the ideas

(inc-array MyArray 1 4 2 value) ;; same as: MyArray[1][4][2] += value

I will create a function inc-array as this will clean upthings considerably.

After carefully reviewing the number of surveys I have, the plain list of values may be the best solution. Just read one survey at a time and a have a list for each question in the survey.

My inc-array will then be just
(inc-array q1 pos value)

Posted: Wed Oct 22, 2003 2:55 pm
by eddier
Thanks for the ideas Lutz!

I can work with the plain list of values. I will just have a list q1, q2, ..., qn for each survey question. I can first use a conditional expression on (question n, position i) to determine break downs. If the condition is meet, the code can pull out the comments and record them separately. Then I can use the inc-array function:

Code: Select all

(define (inc-array quest choice)
  (replace-nth choice quest (+ $0 1)))
to tally the scores.

I'm getting like Micro$oft, making things too complicated. Thanks again!


Posted: Thu Oct 23, 2003 2:16 pm
by Lutz
I wonder if it is time to substitute 'nth' and 'replace-nth' with multi-dimensional versions. You could enter a variable number of index parameters and the functions would automatically go into deeper nested lists (arrays). Indices would be zero-based like before. It also would round out the existing set of matrix fnctions: invert, multiply and transpose (indispensable doing statistics).

The old 'nth' and 'replace-nth' have the index as the first parameter, which doesn't make them suited for simple expansion, maintaining compatibility with old code. So the substitutes would carry a new name. After some versions the old once would be eliminated.

How about:

(set-array myarray 2 4 3 expr) ; 3-dmensional replace
(get-array myarray 2 3 4) ; 3-dimensional nth

or: 'set-mat' , 'get-mat' (for matrix)

any ideas for names (short but informing)


Posted: Thu Oct 23, 2003 4:13 pm
by eddier
How are you going to know if expr is not an index in
(set array myarray 2 4 3 expr)

expr might be an integer.

Taking after
a[j] = r
r = a[j]

(set[] myarray Index_ list expr)
(get[] myarray index_list)

(array myarray index_list) => gets the value at index list
(array myarray index_list expr) => puts the value at index list

What do you think?


Posted: Thu Oct 23, 2003 4:28 pm
by eddier
I just realized that you can tell if something is an expression because it is the last argument in the list.