0

I want to create a nested map.

The function implementation I have is the following:

(defn thefunction [something value]

;;"something" is for i.e: (something2 something3) ;it's a seq, could have more values.

;;here I want the code to create a map like this >> {:something2 {:something3 value}}

I don't know how to implement it to get the map above. I'm new at clojure.

Thanks.

4
  • You could use assoc-in for this: (assoc-in nil [:foo :bar] 1) => {:foo {:bar 1}}. Commented Oct 1, 2018 at 20:22
  • @TaylorWood I want to access the value using (get-in theMap [:something2 :something3]) but it returns nil because its saving {something2 {something3 value}} instead of {:something2 {:something3 value}} Commented Oct 1, 2018 at 20:35
  • @AgustínP. Welcome to Stack Overflow, I'm really glad you made the jump from watching to posting. Did you know you can format your code snipets just by putting four spaces at the start of the line? also it make it easier to answer if you include an example call to the function you are writing, as well as what you think the output would look like. That way I don't guess the wrong desired output. Commented Oct 1, 2018 at 20:51
  • @marco.m there's nothing wrong with homework questions. It's how the question is asked. Commented Oct 2, 2018 at 0:16

2 Answers 2

1

There's an assoc-in function in clojure.core you can use for this. assoc-in takes an associative data structure (e.g. map, vector), a key-path sequence, and a value to associate at the end of the nested path.

In your case there's no pre-existing structure to associate into, but that's fine because assoc-in uses assoc internally which will create a map if the first argument is nil:

(assoc nil :foo 1)
=> {:foo 1}

So you can define your function in terms of assoc-in with nil as its first argument:

(defn the-function [something value]
  (assoc-in nil something value))

And for example if your something sequence consists of symbols:

(the-function '(something2 something3) 'value)
=> {something2 {something3 value}}

(the-function (map str (range 4)) :foo)
=> {"0" {"1" {"2" {"3" :foo}}}}

I want to access the value using (get-in theMap [:something2 :something3]) but it returns nil

Typically you'll see Clojure map literals use keyword keys, although many other types will also work fine, and they can be mixed:

(the-function [:foo "bar" 'baz] \z)
=> {:foo {"bar" {baz \z}}}

You could convert your input sequence into keywords either before you call your function (or inside it if you want to enforce keyword-keys for all callers).

(the-function (map keyword '(something2 something3)) 'value)
=> {:something2 {:something3 value}}
(get-in *1 (map keyword '(something2 something3)))
=> value
Sign up to request clarification or add additional context in comments.

Comments

0

Unlike many languages, clojure allows you to use collection literals as the return value of a function with no extra overhead, so for example a function to create a nested map could be as simple as

(defn i-make-a-nested-map []
 {1 {:a {:b 2}}})

and that can use arguments to the function anywhere in there:

(defn i-make-a-nested-map [I'm-a-function-argument]
 {1 {:a {:b I'm-a-function-argument}}})

so your question very nearly contains it's own answer where you wrote:

(defn thefunction [something value]
    {:something2 {:something3 value}})

There are useful function for manipulating keywords if you need to add the numbers to the end of the keyword passed in. They are name str and keyword

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.