Fork me on GitHub
#beginners
<
2022-10-28
>
Jace01:10:23

I would like to build a cross-platform application (desktop, android, and ios) using clojure and clojurescript and I was wondering if anyone knows of any useful starting points like templates or existing repos that I could look at.

walterl01:10:09

Closest I found a few months ago was React Native + cljs, like this example app: https://github.com/JohnDoneth/react-native-web-cljs

popeye14:10:27

Has anyone tried regular expression which matches both url http://abc.def.com https://xyz.def.net

andy.fingerhut14:10:10

Do you mean a regex that matches only one of those two URLs, and no other strings?

andy.fingerhut14:10:24

Or some more general pattern you have in mind?

popeye14:10:36

it is a general pattern

andy.fingerhut14:10:55

Can you describe the general pattern you wish to match?

andy.fingerhut14:10:46

And the short answer to your question is "yes", but I suspect you would like to see the regexes people have used 🙂

popeye14:10:45

http:// or https:// and then website.company.address

andy.fingerhut14:10:21

There are some regexes people suggest for this purpose in this StackOverflow Q&A, but they might require some modification in syntax to be usable in Clojure/JVM or ClojureScript, because when you get fancy enough sometimes regex syntaxes differ a bit between programming languages that have them: https://stackoverflow.com/questions/3809401/what-is-a-good-regular-expression-to-match-a-url

andy.fingerhut14:10:56

So exactly two dots after the // ?

andy.fingerhut14:10:10

Or any number of dots?

popeye14:10:09

i think I will go with starting of https:// and http:// as of now 😄

andy.fingerhut14:10:29

user=> (re-matches #"^(http|https):\/\/(.*)$" "")
["" "http" "foo"]
user=> (re-matches #"^(http|https):\/\/(.*)$" "")
["" "https" "my.company"]

andy.fingerhut14:10:34

Can simplify the regex slightly by getting rid of those backslashes -- habit from me learning regex on Perl many years ago, where that was needed:

user=> (re-matches #"^(http|https)://(.*)$" "")
["" "https" "my.company"]
user=> (re-matches #"^(http|https)://(.*)$" "")
["" "http" "foo"]

andy.fingerhut14:10:19

That will match many strings that contain things after the // that one would not consider a good URL

popeye14:10:28

what if I want atleast one dot

andy.fingerhut14:10:50

This would be one way. The backslash before the dot that has a backslash before it, is because . is interpreted specially inside a regex as "match any one character", unless you put a backslash before it, in which case it means "match only a dot":

user=> (re-matches #"^(http|https)://(.+)\.(.+)$" "")
nil
user=> (re-matches #"^(http|https)://(.+)\.(.+)$" "")
["" "http" "my" "company"]

andy.fingerhut14:10:41

If you want any number of dots, but no consecutive dots, it starts getting a bit longer of a regex to get it right.

popeye14:10:04

I think I need this much as of now 🙂 Thank you

Ben Lieberman14:10:22

I hope this isn't a poor usage of multimethods but I'm trying to learn them doing some image mods and I can't get this right...

(defmulti transform class)
(defmethod transform Integer [b] (invert-bits b))
(defmethod transform Color [b] (grayscale b))
I keep getting an IllegalArgumentException when I pass in e.g. (int 3)

Alex Miller (Clojure team)14:10:37

should be fine, maybe post more code or (pst *e)

Alex Miller (Clojure team)14:10:30

or maybe be aware that defmulti has defonce semantics if you are trying to redefine it at the repl

Ben Lieberman14:10:51

(defn invert-bits [i]
  (bit-and-not 0xff i))

(defn grayscale [cs]
  (let [r (.getRed cs)
        g (.getGreen cs)
        b (.getBlue cs)]
    (/ (reduce + [r g b]) 3)))
This is all my dispatch fns do

Alex Miller (Clojure team)14:10:57

the pst would tell you where the exception is coming from

Ben Lieberman14:10:54

clojure.lang.MultiFn/getFn (MultiFn.java:156)
clojure.lang.MultiFn/invoke (MultiFn.java:229)
day-four/eval7811 (NO_SOURCE_FILE:26)
clojure.lang.Compiler/eval (Compiler.java:7194)
clojure.core/eval (core.clj:3215)
clojure.core/eval (core.clj:3211)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:87)
clojure.core/apply (core.clj:667)
clojure.core/with-bindings* (core.clj:1990)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:87)
clojure.main/repl (main.clj:437)
clojure.main/repl (main.clj:458)
clojure.main/repl (main.clj:368)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:84)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:56)
nrepl.middleware.interruptible-eval/interruptible-eval (interruptible_eval.clj:152)
nrepl.middleware.session/session-exec (session.clj:218)
nrepl.middleware.session/session-exec (session.clj:217)
java.lang.Thread/run (Thread.java:833)

Ben Lieberman15:10:10

This doesn't seem to point to anything except where I evaluated (transform (int 3))

Alex Miller (Clojure team)15:10:56

the code you posted should be fine, I'm wondering if you redefined transform at the repl (and that redefinition didn't actually take place)

Alex Miller (Clojure team)15:10:03

user=> (defmulti transform class)
#'user/transform
user=> (defmethod transform Integer [b] (println "got int" b))
#object[clojure.lang.MultiFn 0x20095ab4 "clojure.lang.MultiFn@20095ab4"]
user=> (transform (int 3))
got int 3
nil
works fine for example

Alex Miller (Clojure team)15:10:44

if that's it, you might try restarting your repl

1
Ben Lieberman15:10:19

Ah yes, that was it. Thanks Alex!

Jing Guo15:10:47

(map (fn [times n]
       (sort (take times (distinct (repeatedly #(rand-int n))))))
  [[10 20] [2 5]])
Hi everyone, I am experimenting with map and fn, however this example does not work and I could not figure out why... I think something like this in CL would work... This is the full function I want to write:
(defn foo []
   (map inc
        (concat (map (apply (fn [times n]
                              (sort (take times (distinct (repeatedly #(rand-int n)))))))
                     [5 33] [2 10]))))

1
Ben Sless15:10:18

You need to destructure the fn arguments in [[times n]]

Ben Sless15:10:45

Or use apply before map

Jing Guo15:10:59

The last line [10 20] [2 5] still does not work

ghadi16:10:27

(map (fn [[times n]]
       (sort (take times (distinct (repeatedly #(rand-int n))))))
     [[10 20] [2 5]])
this indentation should make it clearer @U0306EUQCP6 ^

❤️ 1
1
Jing Guo16:10:30

@U050ECB92 I just updated the code. It now goes into infinite loop

ghadi16:10:46

I can't follow the edits. Can you try the code that I pasted?

Jing Guo16:10:59

@U050ECB92 yes it now works, thank you. So the problem is that I should use [[…]] when there are multiple arguments?

Ben Sless17:10:27

It's when you want to unpack one argument to many

ghadi17:10:39

You have a single argument being passed to the map fn

❤️ 1
ghadi17:10:54

And that argument is a vector of two ints

skylize01:10:09

(fn [[times n]]
  ... )
is sugar for
(fn [m]
  (let [times (m 0)
        n     (m 1)]
     ...))
https://clojure.org/guides/destructuring

❤️ 1
dumrat17:10:52

I got an xml which looks like this:

<Rates type="dictionary">
  <Info type="dictionary">
    <Time type="dateteime">Fri, 28 Oct 2022 16:59:23 GMT</Time>
  </Info>
  <EURUSD type="dictionary">
    <Spot type="dictionary">
      <Pair type="string">EURUSD</Pair>
      <Bid type="double">0.993</Bid>
      <Ask type="double">0.994</Ask>
    </Spot>
  </EURUSD>
</Rates>
What's a standard way to work with such an xml in Clojure? Suppose I want to extract the time, pair, bid and ask values from this. I see a lot of disparate ways (zippers, walkers, specter) etc mentioned in different places. Let me rephrase, what would be the easiest way to do this and what would be a reusable way? For example, I have a lot of xmls like these with different structures and I can think of a use case like this:
(defn get-xml-vals [xml paths] ...)

(get-xml-vals above-xml ["./Rates/Info/Time" "./EURUSD/Spot/Pair" "./EURUSD/Spot/Bid" "./EURUSD/Spot/Ask"]) 
=> [#inst "2022-10-28T16:59:23.000-00.00" "EURUSD" 0.993 0.994]
Which could make me save time. Or is that even possible?

Alex Miller (Clojure team)17:10:25

of course - just need to compose some things together

Alex Miller (Clojure team)17:10:38

there are Clojure libs like org.clojure/data.xml for parsing the xml into Clojure maps

Alex Miller (Clojure team)17:10:53

things like org.clojure/data.zip for traversing those trees

Alex Miller (Clojure team)17:10:29

but you might find it more efficient to use some of the many Java XML libraries and things like XPath to extract values too if you are primarily extracting data of known shape

👍 1
Alex Miller (Clojure team)17:10:44

this is a reasonable example page of doing this with the relevant java apis - https://www.baeldung.com/java-xpath (which are very complete, but also quite tedious)

Alex Miller (Clojure team)17:10:05

it's not a bad idea to first just try to make interop work, then think about how you'd want to describe this op in Clojure and then build the thing in the middle. depending how reusable you want that to be will affect how much effort you put into the middle

👍 1
Ian Fernandez17:10:36

I’m having a problem fetching a dependency

Ian Fernandez17:10:41

Error building classpath. Could not find artifact bouncycastle:bctsp-jdk14:jar:138 in central ((https://repo1.maven.org/maven2/https://repo1.maven.org/maven2/))

hiredman17:10:05

in general "moving to another path" means the old versions stay where they are, and new versions have a different maven coordinate, so while possible, it is unlikely that is the source of your error

hiredman17:10:18

I would be more suspicious of that url

hiredman17:10:31

that isn't the correct url for maven central

Ian Fernandez17:10:46

I’m using a correct mvn repo for sure

hiredman17:10:59

if you look at maven central https://repo1.maven.org/maven2/bouncycastle/bctsp-jdk14/138/ the artifact is there

hiredman17:10:43

it is a correct maven repo, but the name it shows "central" is usual used to refer to the central maven big maven repo at http://maven.org

hiredman17:10:04

the fact that it isn't is likely why the artifact cannot be found

hiredman17:10:01

it seems like in your setup, for whatever reason, central is pointing somewhere else, and that somewhere else may be a valid maven repo, for whatever reason is doesn't have the artifact you are looking for

Ian Fernandez17:10:25

I can point to more than 1 repo?

Ian Fernandez17:10:09

I’ve add to :mvn/repository

hiredman17:10:09

how to do that will depend on whatever tools you are using, so you should consult the documentation (deps.edn, lein, maven, etc)

hiredman17:10:50

you should given your addition some other name

Ian Fernandez17:10:08

it has a ticket for same dependency that I have

hiredman17:10:17

it is possible you are hitting that bug, but I would first try without whatever you are doing to overwrite central

Ian Fernandez17:10:11

Error building classpath. Could not find artifact bouncycastle:bctsp-jdk14:jar:138 in central (https://repo1.maven.org/maven2/)

hiredman17:10:49

you may need to binary search your dependicies then, comment out half, see if starting a repl errors or not

Ian Fernandez17:10:20

Is there any better way instead binary search?

hiredman17:10:21

that will get you to the one that is pulling that in, and you can add an exclusion, and then include the relocated coordinates in your deps

hiredman17:10:16

depending on your setup, if you just have a deps.edn with some deps in it, then the binary search should be the fastest simplest way

hiredman17:10:07

if you are are doing stuff with a lot of aliases, or have a lot of stuff in ~/.clojure/deps.edn then it might be tricky

Ian Fernandez17:10:52

I have a lot of deps

Ian Fernandez17:10:59

this will be tricky

Ian Fernandez17:10:12

a more verbose output for deps.edn would be cool

hiredman17:10:19

sure, but if they are all specified in one place, you just comment the top half, see if a repl will start

hiredman17:10:04

if that works, you know the failing is in the top half, so you comment out the bottom half, and the top quarter and it again

hiredman18:10:11

there are tracing things for tools-deps

hiredman18:10:47

but they output a lot, and I am not sure if they would work if the fetching fails

Alex Miller (Clojure team)18:10:10

I think it's highly likely that the problem here is the bouncycastle relocation

Alex Miller (Clojure team)18:10:48

The url up top for Maven central is a valid Maven repo so I don't think that's an issue

Alex Miller (Clojure team)18:10:39

one hack that might help is actually to generate a pom clj -Spom then use Maven mvn dependency:tree

Ian Fernandez20:10:55

found by binary search

Ian Fernandez20:10:58

took me a lot \

Ian Fernandez17:10:56

I’ve seen that this artifact has moved to other path

Ian Fernandez17:10:02

I’m using clj

Ian Fernandez17:10:21

how can I find the dependency that depends on bouncycastle:bctsp-jdk14:jar:138

Ian Fernandez17:10:37

if my clj -Stree gives me error ?

Kazuki Yokoyama17:10:16

Quick question, why there is no nil punning for the function name?

skylize02:10:18

Nil punning (as a language feature) generally applies to sequences. The cases where it applies to strings mostly derives from strings being seqable. It is usually pretty straightforward to create additional ad-hoc nil-punning, by wrapping something up in a nil check.

(defn name-pun
  "name, but with nil punning"
  [x]
  (when-not (nil? x) (name x)))

(name-pun :foo) ;; "foo"
(name-pun nil)  ;; nil

slipset05:10:20

You could even create a fn:

(defn pun-it [f]
   (fn [x]
     (when-not (nil? x) (f x)))

(def name-pun (pun-it name))
This is probs not “general” enough, since it doesn’t deal with fns which take more than one argument. Have a look at fnil for some additional inspiration.

Kazuki Yokoyama12:10:50

Nice, thank you!