views:

361

answers:

4

Hello everyone,

I have a few questions concerning Lists, classes and variables in clojure.

  1. This may seem quite stupid but how do I access elements in a List ?

I'm coding a program that allows you to manipulate a phonebook; You can add an entry, delete one or print the information about one. This leads me to two questions :

  1. Is there a way to create a class "entry" that would contain "name" "adress" "phone number" variables ? or is that impossible in clojure (and functional programming in general ?) If I can't have a List of objects containing that information, how would I go about this task ?

  2. I was thinking of having a function that reads user input to know what the user wants to do (add entry, delete entry or print info) then calls the appropriate function to do that which calls back the first function when it's done. Is passing as a parameter the List of entries to each function the right thing to do ?

+5  A: 

Have you considered buying the book Programming Clojure? A pdf version is only $21 US. Well worth the money in my opinion.

Todd Stout
I second this, especially with no FP experience.
Rayne
I thirdify this. Going though the book right now. Excellent resource.
seth
+5  A: 

This may seem quite stupid but how do I access elements in a List ?

(nth coll index)

For example:

(nth [1 2 3 4] 2) ; -> 3 (since it uses zero-based indexing)

Is there a way to create a class "entry" that would contain "name" "adress" "phone number" variables ? or is that impossible in clojure (and functional programming in general ?) If I can't have a List of objects containing that information, how would I go about this task ?

It's possible in Clojure, but unidiomatic. In Clojure, the basic abstraction for data entities are maps, not classes (except for some corner cases where direct interoperation with Java frameworks is needed). So you would just use a map:

(def entry {:name "x" :address "y" :phone-number "z"})

To access the item's name, you either use

(:name entry)

or

(get entry :name)

The former works only when the keys of the map are keywords, the latter works with all types of key.

So for your example, your data model (the phonebook) would be a seq (say, a list or a vector) of such maps.

I was thinking of having a function that reads user input to know what the user wants to do (add entry, delete entry or print info) then calls the appropriate function to do that which calls back the first function when it's done. Is passing as a parameter the List of entries to each function the right thing to do?

Since your model consists of only one main data structure (the phone book seq), passing it as an arg is certainly an appropriate way to design your functions. If you expect to have more kinds of top-level containers (i.e. for a more real world application), I'd recommend looking into the Application Context Pattern, which will look a bit intimidating at first (at least it did for me, and it contains a lot of Clojure-specific jargon), but is well worth the effort to learn.

pmf
I think a struct would better suit his purpose than a map.
Rayne
Thanks a lot, very helpful info
JoOb
+1  A: 
(entry :name)

will also work as well when accessing a map. So you have three ways of accessing an element of a map by using the keyword:

(entry :name)

or

(:name entry)

or

(get entry :name)

where

(def entry {:name "x" :address "y" :phone-number "z"})

As Rayne mentioned, the second form is only possible if the key is a keyword. You can use the other "short" form with keys of other types:

user=>(def my-map {"a" "b" "c" "d"})
user=>(my-map "c")
"d"
user=>(get my-map "a")
"b"
Pinochle
+1  A: 

For part one of your question, if you will be accessing the items in your list with (nth ...) you may consider using a vector. Vectors are not like arrays in other languages. for instance chopping them and adding new elements to the end are also efficient in addition to numerical indexing. Under the hood the arrays are actually very similar to maps.

best of all arrays are functions of an index:

 (def a [1 2 3 4])
 (a 2) ==> 3

for parts 2 and 3 pmf's answer cover them very nicely.

Arthur Ulfeldt
+1 for showing that vectors are functions too!
Bart J