Clojure - How to put a list and a function inside a defn function - function

I am a newbie and making some exercises. How can I put a def with a list of sentences and a randomizer function inside a defn function? How does that work?
(def list["test1", "test2", "test3"]) - works fine
(rand-nth list) - works fine
How do I put it inside a function defn?
Thanks for help.

IIUC you just want to reimplement rand-nth, no?
(defn wrapped-rand-nth [a-list]
(rand-nth a-list))
If you want the list to be static (non-changing)
(defn randomize []
(rand-nth ["test1" "test2" "test3"]))
works, but it creates the vector upon each call, a better way is to
(let [the-list ["test1" "test2" "test3"]]
(defn randomize []
(rand-nth the-list)))

Related

why is this racket code giving me a function call error?

i am working through this online book //htdp.org/2021-11-15/Book/index.html to learn the racket.as i progressed through the book i came across this code - this isnt my code and all it had asked of me was to change the ... with a string which i did - check below - first one is from the site - second one is the one i modified with strings as as specifed
(define current-color ...)
(define next-color
(if (string=? "green" current-color) "yellow" ...))
(define current-color "red")
(define next-color
(if (string=? "green" current-color) "yellow" "amber"))
and when i run it i get this error
(next-color "green")
function call: expected a function after the open parenthesis, but found a variable
am i missing something please help me out
next-color, defined as:
(define next-color
(if (string=? "green" current-color) "yellow" "amber"))
is variable, not function, so you can't call it like this: (next-color "green"). If you want to get its value, just type into REPL:
> next-color

Unable to extract value based on keys from a .CLJ file

I have gotten JSON info from an open API using
(def station-info (clj-http.client/get statinfo {:as :json}))
I have spit that information into a .clj file defined as si. It's content look like this:
{:stations [{:station_id "1755", :name "Aker Brygge", :address "Aker Brygge",
:lat 59.91118372188379, :lon 10.730034556850455, :capacity 33}
{:station_id "1101", :name "Stortingstunellen", :address "RÃ¥dhusgata 34",
:lat 59.91065301806209, :lon 10.737365277561025, :capacity 24}]}
When I call the function (map :station_id (:stations si)) it returns an empty list "()".
But if I define a function with the same info in the REPL and then use the same function, it works!
Very strange.
EDIT: Fixed it by turning the string from the file into a data structure:
(def si-data-structure (edn/read-string (slurp si)))
Your function is right, so your data must be wrong. In particular, you will surely find that (:stations si) is also empty. Look at the si variable and see if it really contains what you expect: is it a map? Is :stations one of its keys?
I Fixed it by turning the string from the file into a data structure:
(def si-data-structure (edn/read-string (slurp si)))

Javascript spread operator in Clojurescript?

I am trying to achieve the following javascript code in clojurescript:
const a = {
"foo": "bar",
//...
};
let b = {
...a,
//^ what is the clojurescript equivalent for this?
"newprop": 10,
};
I have tried to assoc-in, thinking it would behave like a clojure map, with no success...
To provide you with another option, you can use goog.object to interact with JavaScript objects in ClojureScript. The following code will work:
(require 'goog.object)
(def a #js {:foo "bar"})
;; Modify `a` inline
(goog.object/set a "newprop" 10) ;; In JS, this is equivalent to a.newprop = 10
If you want to do a shallow copy of a and modify that value, you can use clone (which will behave like the spread operator).
;; Shallow copy a
(def b (goog.object/clone a))
;; Modify the cloned object
(goog.object/set b "newprop" 10)
There's a neat library you can use though to interact with JavaScript objects if you need to do it often: https://github.com/binaryage/cljs-oops
My question was not clear enough, I had an object defaultProps coming from an external js library. My goal was to create a new instance of this js object and extending it with new props, and feeding it back to a js function expecting a js object. There was more to it than I first foresaw. I finally managed to do it with some juggling with js->clj and clj->js:
(def b
(clj->js (assoc (js->clj a) "newprop" 10)))
Thank you for your answers!
(def a {:foo "bar"})
(def b (assoc a :newProp 10))
This is really just combining two maps together. That can be done with merge:
(def a {"foo" "bar"}) ; Emulating the constant
(def b {"newprop" 10})
(def c (merge a b)) ; {"foo" "bar", "newprop" 10}

How to pass an array into Hoplon from a Castra backend

If I am trying to an array into the index.cljs.hl page how do I go about using the array in Clojurescript. I found that I can use:
(loop-tpl :bindings [single-data rpc/test-vector]
(h2 single-data))
In the hLisp part but if I want to use the array above where the html tag is I seem to run into problems. The array in the rpc.cljs page is as follows
(defc= test-vector ["Good" "Man" "Shoe"])
And I have tried using map without the data and just an array and it works:
(defn build-list
[]
(map #(h2 %) ["one" "two" "three"]))
But then if I try and use the array it no longer works and I have no clue why.
(defn build-list
[]
(map #(h2 %) rpc/test-vector))
Cheers
If you put '#rpc/test-vector' with the last example it works.
Cheers

Clojure - How to apply a different function to each column?

I'm new to Clojure and playing with it for fun.
I'm reading a CSV file and want to apply a different function to each column. What is an elegant (both concise and readable) way to do this?
I have explored two approaches:
Working on a vector of rows:
for each row...
(def row-1 ["John", "24"])
...I want to apply a different function to each element, and obtain this result:
["John", 24]
The function I want to use are:
(def converters-1 [identity, read-string])
Is there a simple way to apply the converters-1 functions to the row-1 elements?
Working on a map:
With this method I start by turning each row into a map:
(def row-2 {:name "John", :age "24"})
Edit: And I want to obtain this map:
{:name "John", :age 24}
The converters are also stored in a map:
(def converters-2 {:name identity, :age read-string})
Is there a simple way to apply the right converters to the row-2 elements?
I will be interested to read solutions for both approaches.
In the end I will put the data into a map. I'm just not sure whether I want to do the conversions before or after getting this map.
Use map for sequences; use merge-with for maps.
user=> (map #(% %2) converters-1 row-1)
("John" 24)
user=> (merge-with #(% %2) converters-2 row-2)
{:name "John", :age 24}
(map #(%1 %2) converters-1 row-1)
;; ("John" 24)
if (def row-2 {:name "John", :age "24"}) (it's an integer in your example)
(for [x (keys converters-2)] ((converters-2 x) (row-2 x)))
;; ("John" 24)
I found a solution for the map approach, but it's less elegant than Diego's solution with vectors.
(into {} (map (fn [[k v]]
[k ((converters-2 k) v)]
) row-2))
Is there a simpler solutions for this map-approach?
Am I missing a core function that would simplify it?
Edit: reading Diego's edit, I could also use keys:
(into {} (map #(
[% ((converters-2 %) (row-2 %))] ; the key, and the converted value
) (keys row-2)))
But I prefer the previous solution, because it does not need the comment: it is obvious what happens to the key, and to the value. Plus, in this solution I only need to write row-2 once.
Edit 2: If I write (converters-2 k identity), then I only need to indicate the columns who need a transformation. For the other columns (like :name here) identity is the default converter. That is an advantage, compared to the vector approach.
Edit 3: I found a another solution for the map approach, using update-in:
(reduce #(update-in %1 [%2] (converters-2 %2)) row-2 (keys row-2))
Well, now that it's written, to my novice eyes it's harder to read and understand.
So far the vector solution is still best. I'll keep my eyes open for a better map solution; it might come in handy some day.