Fork me on GitHub
#beginners
<
2022-09-08
>
cvetan00:09:25

(defn find-sports
  [url]
  (def sports [])
  (let [sport (parse-xml url)
        tag (:tag sport)
        sports []]
    (if sport
      (cond
        (= tag :urlset)
          (doseq [mm (map get-content (:content sport))]
            (let [location (:loc mm)
                  segments (count (str/split location #"/"))]
              (when (= 4 segments)
                (conj sports location)))))
      (println (str "Unable to process url")))
    )
  sports)

cvetan00:09:43

I tried using conj but appearantly that does not work

Jon Boone00:09:56

Which seq are you trying to iterate over?

cvetan00:09:07

this one map get-content (:content sport)

seancorfield00:09:33

doseq is intended for side-effects; it returns nil

seancorfield00:09:34

Clojure has immutable data. conj doesn't modify sports -- it returns a new data structure with location added to it. Do not use def inside a function -- it always defines a global value.

seancorfield00:09:44

You probably want to look at loop -- but bear in mind it is not like loops in other languages: it produces a single value at the end, when you no longer recur back to the top of the loop.

seancorfield00:09:03

Also @UG8V3094J for the future, we try to encourage everyone to use threads in most of the channels here: make a single post with your question and then reply in a thread to that providing all the details. Thanks.

✔️ 1
👍 1
cvetan00:09:49

what could be alternative

cvetan00:09:08

is there any way to collect values in doseq ?

Martin Půda03:09:14

Can you please provide some example data and expected result? Also, add a definition of get-content and parse-xml (or name of the library for these functions).

Jaro Drenčák11:09:24

As pointed out by Martin, please try to describe what would you like to achieve. The reason why I am asking for it is quite simple. I am missing in your code something I am calling "functional programming pattern" and consideration of data immutability.

cvetan10:09:25

I am using luminus framework and I wrote down some functions to map some values based on database values and some other input. The thing is I pull id, and some other attribute from database because I need id for foreign key in stuff I am mapping. However when I return value from hugsql and try to dump it with pprint to inspect if everything works right, value is not dumped on console but rather I get this and I don't know how to use it:

#function[livescore-scrapper.db.core/eval16313/f--16221--auto----16340]

cvetan10:09:09

and I have db query function like this:

-- :name get-sport-reference :? :*
SELECT id, url
FROM sports
ORDER BY url;

cvetan10:09:49

I need to check if there is matching, I tried with using filter function, but I get error because I do not know how to use/evaluate this

cvetan10:09:55

and if I try it like this to suround that db call with parenthesis I get following error:

Execution error (ClassCastException) at livescore-scrapper.db.core/eval16300$fn (core.clj:11).
class mount.core.DerefableState cannot be cast to class clojure.lang.IFn (mount.core.DerefableState is in unnamed module of loader clojure.lang.DynamicClassLoader @78c1a023; clojure.lang.IFn is in unnamed module of loader 'app')

cvetan10:09:35

if anyone can explain what I am doing wrong, I would much appreciate it, I am doing this for colledge project, and I am fairly new to clojure.

pavlosmelissinos12:09:23

Can you post any of your code?

pavlosmelissinos12:09:45

It would help to have a way to reproduce your problem

pavlosmelissinos12:09:36

Without looking at any code it looks like you're printing a function, so you do need to call it but maybe not in the way you've tried so far. Have you managed to run SQL queries with hugsql on its own? Outside the context of luminus I mean. If not, you might want to check out the examples on their documentation and try out a few.

cvetan20:09:22

you are right

cvetan20:09:42

I needed to start luminus with (mount/start) in repl

cvetan20:09:53

after that my functions ran as expected

cvetan20:09:07

so I expect that in regular flow with web app running all should be good

2FO15:09:26

Hello, How can I do repl driven dev inside comment blocks. I'm using #spacemacs and given the following code I'd like to render the request map inside the block, however it only returns nil. My steps: 1. Cider jack in , ' 2. Evaluate the buffer , e b 3. Create a new request by refreshing the page at localhost:8080 4. Evaluate the comment block , e f

(ns min.core
  (:require [ring.adapter.jetty :as j]))

(defn handler [request]
  (def request request)
  {:status 200
   :body "hello"})

(def server
  (j/run-jetty (var handler) {:port 8080 :join? false}))

(comment
  (request)) ;; => nil

Nick Cellino15:09:28

The issue might be that you're trying to evaluate the comment form which will evaluate to nil and I think you want to evaluate “request”

1
🙏 1
Nick Cellino15:09:52

Separate issue but it also looks like you're trying to call request as a function in your comment block which I assume is not what you intend

Nick Cellino15:09:52

Not sure what the eMacs or cider command is as I don't use those but can you put your cursor on “request” and do some “evaluate current form” or “evaluate current word” command or something like that?

dpsutton15:09:55

(setq clojure-toplevel-inside-comment-form t) can help with the top level comment stuff

2FO15:09:29

@U03RD9KKKRS I just tried that, the unwrapped version returns nil as well

(comment
  request) ;; => nil

dpsutton15:09:52

you need to evaluate request not (comment request)

1
🙏 1
ChillPillzKillzBillz15:09:29

Is there something equivalent to exec() https://realpython.com/python-exec/ in python in Clojure?

pavlosmelissinos16:09:28

Why do you ask though? Running arbitrary code can be dangerous and there are often better ways to achieve your goal, e.g. with https://clojure.org/reference/reader#tagged_literals you can annotate an edn file to run custom logic that you, the developer, control (instead of the user).

ChillPillzKillzBillz16:09:38

I would like to do something like following: Assuming a label "x" I want to execute (def var_x (func x 2)) The var_x bit needs to change dynamically as the label changes. The labels are eventually going to come from a list. But after executing the code, I'd like to access each of them using the literals var_<label1>, var_<label2> .....

pavlosmelissinos16:09:43

Do you really have to include the label in the name of the binding?

ChillPillzKillzBillz16:09:26

yes I am trying out sicmutils, and I am trying to define named mathematical literals... it helps if I can access by name.

pavlosmelissinos16:09:48

Ah, I see. I was prepared to suggest representing your "vars" as a collection of maps (e.g. [{:label x, :data (func x 2)} {:label y, :data (func y 2)} ...]) which is simpler than running eval but in your case it's probably not enough (and you're in control of the code that runs so eval is probably ok).

ChillPillzKillzBillz16:09:50

yeah I am just trying to define some algebraic variables... hence the arbitrary labels... so if I wanted to define a (math) function f(x,y,z) = x^2 + y/z then it helps to have x,y,z as defined vars

👍 1
ChillPillzKillzBillz12:09:03

For anyone interested in this problem, I solved it using macros. As shown below.

(defmacro def-literal-number [label]
  (->> label
       (list 'symbol)
       (list 'e/literal-number)
       (list 'def (symbol label))))
To create a new literal-number, all that is needed is a call to (def-literal-number "x")

ghadi15:09:26

eval, the E in REPL

☝️ 1
Abhi Saxena19:09:29

Hi Clojurians, Have a question on using if condition under let binding, I have below function: (defn get-chart-info [a b c flag] (let [target-value (get-target-total a) act1-vs-target (get-tip-diff a target-value) act2-vs-target (get-tip-diff a target-value) act3-vs-target (get-tip-diff a target-value)] (merge act1-vs-target act1-vs-target act1-vs-target))) I want to execute only certain statements under let based on the flag and accordingly only merge what I have evaluated above, what's the way to do this in Clojure

Bob B20:09:15

the exact intent is a little unclear to me, but what you could do is put a, b, and c in a collection and then map whatever needs to be done with flag over that to decide which ones to include/build maps from, and then potentially apply merge to that collection of maps

Abhi Saxena21:09:29

I should have put it in a better way, the idea is just to perform only certain bindings based on the flag

seancorfield22:09:53

@U03TDQ043GA Since merge allows you to pass nil for an argument and it treats it as an empty hash map, you could guard each expr in the let with when:

act1 (when some-cond (get-tip-diff a target-value))

seancorfield22:09:28

That will only call get-tip-diff when some-cond is truthy, and it will bind act1 to either that result or nil.

👍 1
seancorfield22:09:49

nil-punning is your friend here

Abhi Saxena03:09:05

thanks Sean for your help.

cvetan22:09:57

can someone recommend me some webscrapper library in clojure for javascript based websites? I need to extract some data from one website, which uses javascript datatables, which are rendered async after page load.

rickheere06:09:35

I've used frontend ewe testing tools to do these kinds of things in the past. I used Cypress just in normal JavaScript. But there is also this tool https://github.com/clj-commons/etaoin in clojure but I've never used it