Calling a function with arguments in lists - clojure

i have a function that takes 3 arguments
(defn times-changed-answer [rid qid csv-file] ...some code)
that counts for a user with (record-id) rid how many times he changed his answer with (question-code) qid. The data is in csv-file.
It works and i have tested it for multiple users.
Now i want to call this function for all users and for all questions.
I have a list of rids and a list of qids.
(def rid-list '(1 2 4 5 10)
(def qid-list '(166 167 168 169 180 141)
How could i call this function on all users for all questions?
The lists are of different length and the third argument (the file) is always the same.

I'd use for list comprehension - it depends on what result you expect
here; here e.g. [rid qid result] is returned for all of them:
(for [rid rid-list
qid qid-list]
[rid qid (times-changed-answer rid quid csv-file)])
If you want to have this in a map, you could e.g. reduce over that.

Related

Common Lisp Applying Regex-like Patterns to Keys in PLIST

I am wondering if it is possible to apply Regex-like pattern matching to keys in a plist.
That is, suppose we have a list like this (:input1 1 :input2 2 :input3 3 :output1 10 :output2 20 ... :expand "string here")
The code I need to write is something along the lines of:
"If there is :expand and (:input* or :output*) in the list's keys, then do something and also return the :expand and (:output* or :input*)".
Obviously, this can be accomplished via cond but I do not see a clear way to write this elegantly. Hence, I thought of possibly using a Regex-like pattern on keys and basing the return on the results from that pattern search.
Any suggestions are appreciated.
Normalize your input
A possible first step for your algorithm that will simplify the rest of your problem is to normalize your input in a way that keep the same information in a structured way, instead of inside symbol's names. I am converting keys from symbols to either symbols or lists. You could also define your own class which represents inputs and outputs, and write generic functions that works for both.
(defun normalize-key (key)
(or (cl-ppcre:register-groups-bind (symbol number)
("^(\\w+)(\\d+)$" (symbol-name key))
(list (intern symbol "KEYWORD")
(parse-integer number)))
key))
(defun test-normalize ()
(assert (eq (normalize-key :expand) :expand))
(assert (equal (normalize-key :input1) '(:input 1))))
The above normalize-key deconstructs :inputN into a list (:input N), with N parsed as a number. Using the above function, you can normalize the whole list (you could do that recursively too for values, if you need it):
(defun normalize-plist (plist)
(loop
for (key value) on plist by #'cddr
collect (normalize-key key)
collect value))
(normalize-plist
'(:input1 1 :input2 2 :input3 3 :output1 10 :output2 20 :expand "string here"))
=> ((:INPUT 1) 1
(:INPUT 2) 2
(:INPUT 3) 3
(:OUTPUT 1) 10
(:OUTPUT 2) 20
:EXPAND "string here")
From there, you should be able to implement your logic more easily.

create an empty list of list in scheme(racket)

I am a beginner in Scheme so I apologize if it's a really basic question for you.
I am trying to create an empty list of lists which will be filled afterwards. The correct way to implement this is using objects but I need to do it using a list.
Suppose we have a university department and students. Each student has some specific fields such as name, gpa etc. These fields are determined by the user so the number of fields is unknown. At the end, we have something like we have in database structures:
create a table(table-name is given by the user as a parameter) with the columns(again, given by the user).
visually speaking, list of lists should look like this:
table-name---name1---name2---name3---...
-----------------field11----field21---field31--....
-----------------field12----field22---field32--....
.......
after creating the list, I should have the ability to insert records into it.
Just define a variable :
(define student-list '())
So student-list is the empty list. You can add whatever you want to it. Imagine you want add a student. You can just add it to the empty list :
(set! student-list (cons '(name phone-number etc) student-list))
You're just assigning to student-list a new value, which is the previous value of list (the empty list) and the new list you want. And, with the same code, you can add another student.
In Scheme, you don't have to determine the number of fields directly : list are dynamic structures. With (list stg stg2), you can create a list which is '(stg stg2). But you have another operator : cons. This function let you add something to a list : (cons 'stg3 (list stg stg2)), and you got the list '(stg3 stg stg2). You added a field and you don't had to "declare" a field or something like that. It's not a fixed array like in C. And if you have a list of list, each list can have a not defined number of fields. So, for example.
(define student-list)
;;; This is your first empty list.
(define (add-student ids)
(set! student-list (cons ids student-list)))
;;; ids is the list of name, etc. of student
;;; you want to insert in the student-list.
This code define a global variable and change it with the data you give to the function add-student. And this can be anything. '(name phone gpa) or '(name gpa), etc. However, if you want to pass a list to a function ((define (add-student students ids)) for instance, with students the list of all students), you can't use set!. You'll have to use set-car! and set-cdr!.
As said in comments, you don't have to set a list of nil elements, and complete them after. You can just have an empty variable, and fill it with your data when they come.
Edit : With the above code, I'm doing some side effect. But you have another way : in Scheme, everything has a return value. When you're doing (+ 1 2), you'll have the return value of 3. So if you do (list (+ 1 2) (+ 1 4)), you'll have a list '(3 5). So a function has a return value too. In above code, return value is #void, cause set! doesn't have return value. However, you can directly return the list you want. To do it, you can just remove the set!.
(define (add-student-second students ids)
(cons ids students))
So if you're doing (add-student-second '((name1)) (name2)), you'll got ((name2) (name1)) as a return value. You just have to treat your data as you want after that.

How to use pprint-newline properly?

I am trying to print a sequence such that neither the whole sequence is printed on one line, nor is each element of the sequence printed on its own line. E.g.
[10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29]
I found pprint-newline in the documentation which indicates that allows me to determine how the newline gets printed. Unfortunately, I cannot find any examples on how it is to be used in conjunction with pprint, and the doc string doesn't to offer much insight:
-------------------------
clojure.pprint/pprint-newline
([kind])
Print a conditional newline to a pretty printing stream. kind specifies if the
newline is :linear, :miser, :fill, or :mandatory.
This function is intended for use when writing custom dispatch functions.
Output is sent to *out* which must be a pretty printing writer.
pprint specifies an optional second argument for the writer, which is by default set to *out*. However, I am not sure how to 'send' pprint-writer to *out* in this case, e.g. something like the example below doesn't appear to work
(clojure.pprint/pprint [1 2 3 4] (*out* (clojure.pprint/pprint-newline :miser)))
While Guillermo explained how to change the dispatch for pretty-printing in general, if all you want to do is printing one collection differently, that's possible, too.
For example, using cl-format (after (use '[clojure.pprint :as pp)):
(binding [pp/*print-pretty* true
pp/*print-miser-width* nil
pp/*print-right-margin* 10]
(pp/cl-format true "~<[~;~#{~a~^ ~:_~}~;]~:>~%" '[foo bar baz quux]))
Set *print-right-margin* as you wish.
You don't have to use format for this. The format directives can be translated to their respective pretty-printer functions, if you want. Explanation of the format string: ~< and ~:> establish a logical block. Inside the block, there are three sections separated by ~;. The first and last section are your prefix and suffix, while the elements are printed in the middle section, using ~#{ and ~}. For each element, the element is printed using ~a, followed by a space, if needed, and a conditional fill-style newline.
(In CL, the format string could be simplified to "~<[~;~#{~a~^ ~}~;]~:#>~%", but that doesn't seem to work in Clojure 1.5.)
As the help says, the function is intended for use for custom dispatch functions.
In order to change the behavior of the pprint for sequences you need to provide a new dispatch function for clojure.lang.ISeq.
The current dispatch function for sequences you can find in clojure/pprint/dispatch.clj
(use-method simple-dispatch clojure.lang.ISeq pprint-list)
...
(defn- pprint-simple-list [alis]
(pprint-logical-block :prefix "(" :suffix ")"
(print-length-loop [alis (seq alis)]
(when alis
(write-out (first alis))
(when (next alis)
(.write ^java.io.Writer *out* " ")
(pprint-newline :linear)
(recur (next alis)))))))
Since printing is dispatched according to data type overriding seems to be the way to go.
See the source code for ideas.

Lisp, add new list to db in "for" loop, why returning NIL?

I wonder, how can I print in LISP each new value from loop "for" in new list, which each time creates by calling the function.
I have created the func:
(defun make (id name surname) (list :id id :name name :surname surname) )
Here I created the global variable:
(defvar *db* nil)
And here I defined the func for adding each new value to store it in db:
(defun add (cd) (push cd *db*))
So, I'm able to add each new data to db, like that:
(add (make 0 "Oleg" "Orlov" ) )
To look the content of my db , I can use:
*db*
So, I wonder how to put each new record-list to db using "for" loop, I print values in "for" loop in lisp like this:
(loop for i from 1 to 10 do ( ... ))
If , I use:
(loop for i from 0 to 10 do (add (make i "Oleg" "Orlov") ) )
If you read db using *db* you will see, that all evelen records were added, but after calling the last line, you will get NIL result in return.
Why do I catch NIL result, not T and what does it mean?
Thanks, best regards!
Every form in Lisp evaluates to something.
If a form you type in doesn't return a value, it will evaluate to NIL by default (otherwise, it evaluates to the value(s) it returns). Your loop doesn't actually return a value itself; it just performs 10 assignments (each of the intermediate expressions do return a value, but you don't collect and return them). Therefore, that code will return NIL.
If you haven't done so already, check out chapter 3 of Practical Common Lisp, in which Peter Seibel goes step-by-step through creating a simple database. It might give you some insights into the basics of how Lisp works. The specific question you ask (why forms return NIL by default, and what it means specifically in the context of Common Lisp) is answered in chapter 2 of the same book
As for how you would explicitly cause your loop to emit the list of items it added to *db*, try the following
(loop for i from 1 to 10
for elem = (make i "Oleg" "Orlov")
do (add elem)
collect elem)

how to create a list in LISP and accepting elements of list from user?

how to create a list in LISP and accepting elements of list from user?
Use the read function to read user input. For example:
[6]> (list (read) (read))
joe
moe
(JOE MOE)
joe and moe are my input lines, terminated by a newline (pressing Enter). The list function creates a new list.
If you want to read the elements of a list of unknown length, you could do it like this (takes input until NIL) [CL]:
(loop for read = (read)
while read collect read)
Alternatively, the easiest possibility actually is:
(read)
Because the user may enter (foo bar baz 1 2 3) here, too.