create an empty list of list in scheme(racket) - list

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.

Related

finding member in nested lists netlogo

i'm trying to solve a problem in netlogo that has me stuck for a while now. i've got two lists (of turtles i've collaborated with and of "successful"/"unsuccessful" judgments). the two lists are mapped like so [[(turtle 10) "successful"] [(turtle 11) "unsuccessful"] with the following:
let general-history (map list collaborators my-success)
where the collaborators are the who numbers and my-success is a string (either "successful" or "unsuccessful")
now, i would like to check whether a turtle has, in its general-history list, at least one successful and one unsuccessful collaborator, to be able to proceed. this is where i've gotten to:
ifelse not empty? general-history and member? "successful " last general-history and member? "unsuccessful" last general-history
i know this is wrong because last here implies that i'll be looking only at the last list of general-history (i.e., [] [] [this one]). what i want it to do is assess whether there are at least two lists (one with "successful" as index 1 and one with "unsuccessful" as index 1) in the whole general-history nested list.
would foreach work better here or is it possible to still use member? but with some kind of element + list indexing? thank you very much for the help!
If I have understood your question correctly, you can use map to create a list of all the last items (success or not) and then apply member? to that list. Here is a complete model example that constructs some test data and the applies this approach.
to testme
clear-all
; create some test data
create-turtles 10
let collaborators sort n-of 3 turtles
let list-both (map list collaborators (list "yes" "no" "no"))
print list-both
; check condition
print member? "yes" map last list-both
end

Filtering or matching in nested list

My data structure was original a big Map. But I read that we should not use too big maps, to not run out of atoms. So my new data structure looks like that.
countries = [[{'name', 'Germany'}, {'code', 'DE'}], [{'name', 'Austria'}, {'code', 'AT'}]]
I want to make a filter_by/3 method, to filter this nested list for the country list by attributes name or code
Should I transform the Tuples to Maps or is there another way to filter this?
You could use a list of maps. Maps are very performant when retrieving elements, especially when the keys in a map are very few.
In your example:
countries = [%{name: "Germany", code: "DE"},
%{name: "Austria", code: "AT"}]
Note that even if you'll use thousands of such maps in a list, you'll never run out of atoms since :name and :code will always be the only two allocated atoms (since each atom is exactly is value, so writing :a and :a is like writing 3 and 3).
Once you have a similar list in place, you can filter it with a function like:
def filter_by(countries, key, value) do
Enum.filter(countries, fn(country) -> country[key] == value end)
end
filter_by(countries, :code, "AT")

clojure - add item to nested set

Say I have a set like this:
#{#{"a"} #{"b"} #{"c"}}
Say I wanted to updated the middle set to make s become:
#{#{"a"} #{"be"} #{"c"}}
How would I achieve this?
(-> #{#{"a"} #{"b"} #{"c"}} (disj #{"b"}) (conj #{"be"}))
=> #{#{"a"} #{"be"} #{"c"}}
(of course there's no ordering in sets, it could well be shown in any order).

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)

Prolog Insert list as element into another List

In my program my P = [0,1,2] I want to store it into another LIST, because P will keep changing in a loop so I want to store P into a LIST, so my LIST will be like below :
eg.
LIST = [[0,1,2],[3,4,5],[6,7,8]]
create_list([],[]).
create_list(G, [H|G]).
This is what I did, create_list(P,LIST). I not sure how to do it as it keep return me no. But I am pretty sure I can get different P because I am able to print them out each time P changed.
You need to create a predicate that receives the item (list in this case) you want to append to another input list, and this would give you a new list with the which has all the items of your input list plus the new item.
So, it would be something like:
create_list(Item, List, [Item|List]).
Initially the input List would be an empty list ([]), so you might call it
create_list([0,1,2], [], List1),
create_list([3,4,5], List1, List2),
create_list([6,7,8], List2, List).
This will result in List instantiated with [[0,1,2],[3,4,5],[6,7,8]]