Replace string with a regex containing a variable without macro - clojure

I need to delete some contents at the end of a string (eq_code) using Clojure.
I want to implement a regex initialized by a variable (get-in vector [3 1]).
Maybe macro would have helped me.
Here is the code :
(reset! atom_code (clojure.string/replace eq_code #(str (get-in vector [3 1])) ""))
The error is :
IllegalArgumentException Invalid match arg: project.core$interpreted_lang_while$fn__4457#7ac4b7c5 clojure.string/replace (string.clj:102)
Is there a way to replace a substring without using macro ?
For example using a function that return a regex.

https://clojuredocs.org/clojure.string/replace
replace match parameter (second arg) can't be a function.
The solution is to construct the pattern from your dynamic value:
user> (def data [["a" "b"] ["c" "d"]])
#'user/data
user> (clojure.string/replace "mama" (re-pattern (get-in data [0 0])) "")
"mm"
and also: vector is the core function, so try not to shadow it by using it as a var name (though it's not actually what is wrong with your solution)

I think the problem is that vector is a clojure function, and I am guessing that you have some data named vector that is causing the compiler confusion.
Could you please update your question with sample data and desired output?

Related

Pass abstract/null variables into functions Clojure

I have a function that i need to take in a word and im trying to make a variable x the sorted version of word variable. Im not sure how i go about doing this... i am trying to pass it in as a parameter for a function but not working.
How do i pass in a "word" and make a variable within the function equal to a sorted version of "word" so i have two copies, the original word and the x version of word. So i can then go on to pass into a map i need to create.
(for [wordset '("one" "two" "three" "FouR" "wot" "Rheet" "nope" "#")]
(transform2 wordset))
(defn transform2 [word x]
(let [x (sort-string (str/lower-case word))]
(prn x)))
(defn sort-string [s]
(apply str (sort s)))
This is the error im getting back
CompilerException java.lang.RuntimeException: Unable to resolve symbol: x in this context, compiling:(NO_SOURCE_PATH:108:1)
This expression is doing nothing for you:
(for [wordset '("one" "two" "three" "FouR" "wot" "Rheet" "nope" "#")]
(transform2 wordset))
You are not placing this anywhere where the return value will be used. A for is not like an imperative for loop in other languages. It just creates a sequence and returns it, it is not modifying anything.
Also you should use vectors and prefer keywords, in general:
[:one :two :three :whatever]
Though that would change the semantics of what you're doing, so maybe you have strings coming in from somewhere else and need to use them? Otherwise, don't use strings yourself as identifiers: that's what keywords are for.
As for your other questions, it's not quite clear what you mean. You say you'd like to make a variable, but it's not clear what you mean by this, as the code you have isn't doing anything along those lines.
Your transform2 accepts two arguments but you're passing only one. Try removing the x argument like below. Also, you may want to reverse the order you create the functions because they need to be defined before being used. (You may also use declare.)
(defn sort-string [s]
(apply str (sort s)))
(defn transform2 [word]
(let [x (sort-string (clojure.string/lower-case word))]
(prn x)))
(for [wordset '("one" "two" "three" "FouR" "wot" "Rheet" "nope" "#")]
(transform2 wordset))
Result will be:
"eno"
"otw"
"eehrt"
"foru"
"otw"
"eehrt"
"enop"
"#"

How can I evaluate "symbol" and "(symbol 1)" with the same name?

I want to get following results when I evaluate edit-url and (edit-url 1).
edit-url --> "/articles/:id/edit"
(edit-url 1) --> "/articles/1/edit"
Is it possible to define such a Var or something?
Now, I use following function, but I don't want to write (edit-url) to get const string.
(defn edit-url
([] "/articles/:id/edit")
([id] (str "/articles/" id "/edit")))
Thanks in advance.
If those behaviors are exactly what you want, print-method and tagged literals may be used to imitate them.
(defrecord Path [path]
clojure.lang.IFn
(invoke [this n]
(clojure.string/replace path ":id" (str n))))
(defmethod print-method Path [o ^java.io.Writer w]
(.write w (str "#path\"" (:path o) "\"")))
(set! *data-readers* (assoc *data-readers* 'path ->Path))
(comment
user=> (def p #path"/articles/:id/edit")
#'user/p
user=> p
#path"/articles/:id/edit"
user=> (p 1)
"/articles/1/edit"
user=>
)
edit-url will either have the value of an immutable string or function. Not both.
The problem will fade when you write a function with better abstraction that takes a string and a map of keywords to replace with words. It should work like this
(generate-url "/articles/:id/edit" {:id 1})
Clojure is a "Lisp 1" which means that is has a single namespace for all symbols, including both data scalars and functions. What you have written shows the functionally of both a string and a function but for a single name, which you can do in Common Lisp but not Clojure (not that a "Lisp 2" has its own inconveniences as well).
In general this type of "problem" is a non issue if you organize your vars better. Why not just make edit-url a function with variable arity? Without arguments it returns something, with arguments it returns something else. Really the possibilities are endless, even more so when you consider making a macro instead of a function (not that I'm advocating that).

Clojure- Amending code for different functionality

This line of code:
dates (distinct (map (keyword :cobdate) data))
had to be amended to this line of code
dates (distinct (map #(get % "cobdate") data))
in order to use in the way I required
Could anyone tell me how to convert this line of code:
grouped-by-token (group-by :severity data)
in order to make the same conversion?
The first argument to group-by is a function. :severity, in your third sample, is being used as a function, because keywords can be treated as functions: (:severity {:severity 1}) ;; => 1.
Because strings cannot be treated as functions, you must use the alternate syntax to extract the value.
grouped-by-token (group-by #(% "severity") data)

clojure: how to get values from lazy seq?

Iam new to clojure and need some help to get a value out of a lazy sequence.
You can have a look at my full data structure here: http://pastebin.com/ynLJaLaP
What I need is the content of the title:
{: _content AlbumTitel2}
I managed to get a list of all _content values:
(def albumtitle (map #(str (get % :title)) photosets))
(println albumtitle)
and the result is:
({:_content AlbumTitel2} {:_content test} {:_content AlbumTitel} {:_content album123} {:_content speciale} {:_content neues B5 Album} {:_content Album Nr 2})
But how can I get the value of every :_content?
Any help would be appreciated!
Thanks!
You could simply do this
(map (comp :_content :title) photosets)
Keywords work as functions, so the composition with comp will first retrieve the :title value of each photoset and then further retrieve the :_content value of that value.
Alternatively this could be written as
(map #(get-in % [:title :_content]) photosets)
A semi alternative solution is to do
(->> data
(map :title)
(map :_content))
This take advances of the fact that keywords are functions and the so called thread last macro. What it does is injecting the result of the first expression in as the last argument of the second etc..
The above code gets converted to
(map :_content (map :title data))
Clearly not as readable, and not easy to expand later either.
PS I asume something went wrong when the data was pasted to the web, because:
{: _content AlbumTitel2}
Is not Clojure syntax, this however is:
{:_content "AlbumTitel2"}
No the whitespace after :, and "" around text. Just in case you might want to paste some Clojure some other time.

Clojure Parse String

I have the following string
layout: default
title: Envy Labs
What i am trying to do is create map from it
layout->default
title->"envy labs"
Is this possible to do using sequence functions or do i have to loop through each line?
Trying to get a regex to work with and failing using.
(apply hash-map (re-split #": " meta-info))
user> (let [x "layout: default\ntitle: Envy Labs"]
(reduce (fn [h [_ k v]] (assoc h k v))
{}
(re-seq #"([^:]+): (.+)(\n|$)" x)))
{"title" "Envy Labs", "layout" "default"}
The _ is a variable name used to indicate that you don't care about the value of the variable (in this case, the whole matched string).
I'd recommend using clojure-contrib/duck-streams/read-lines to process the lines then split the fields from there. I find this method is usually more robust to errors in the file.