beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
2021-02-06T00:14:55.088400Z

If the mutating Java methods called via swap! are not synchronized in some other way, they can run concurrently if multiple concurrent swap! calls are made, and they will garble the mutable state. The atom is not helping anything

2021-02-06T00:17:06.088600Z

I am pretty sure that for most programming languages, it is possible to define either or both of an operational or denotational semantics. Strachey in the 1960s devised one of the first denotational semantics, and he did it for an imperative language (something like Algol of the time, but it could have been C).

👀 1
2021-02-06T00:17:34.088800Z

I have the rough idea that you have to work a bit harder to define a denotational semantics for mutable languages, but I'm no authority on the matter.

blak3mill3r 2021-02-06T01:33:06.091500Z

it's not only pointless, it sort of suggests that things are okay, at least at a cursory glance

zackteo 2021-02-06T02:19:30.093100Z

How do I convert this - "[1, 2, 3, 5, 7, 11, 13, 17, 19, 23]\n" to a clojure vector? Is there a simple way to do this?

dorab 2021-02-06T02:34:40.093400Z

read-string?

zackteo 2021-02-06T02:53:05.093700Z

Wow, okay! Thanks 🙂

dpsutton 2021-02-06T03:57:57.094400Z

far more preferable to use clojure.edn/read-string for this type of thing.

West 2021-02-06T05:42:43.100700Z

Hey guys, so I’m trying to leverage a https://github.com/phax/ph-css, but I really am not comfortable with OOP at all. I’m trying to leverage this library but don’t know how classes and methods work in Java, let alone how to use them in Clojure. So I know that methods work like functions. Sometimes you need to create an object from another data type using (new ClassName). When I try to run line 20 I get an error: No matching method readFromString found taking 1 args for class com.helger.css.reader.CSSReader What that tells me is that I didn’t properly call the method I’m looking for, though I don’t think I’m in the wrong place. I need help understanding what exactly is going wrong here.

seancorfield 2021-02-06T05:48:55.101500Z

@c.westrom I looked over that repo and it took me a while to find a link to the API JavaDocs for it... https://javadoc.io/doc/com.helger/ph-css/latest/index.html

seancorfield 2021-02-06T05:50:23.102Z

For the CSSReader class, this is the direct link https://javadoc.io/static/com.helger/ph-css/6.2.3/com/helger/css/reader/CSSReader.html

West 2021-02-06T05:51:48.103900Z

It looks like it takes 3 arguments.

static CascadingStyleSheet --- readFromString(String sCSS, Charset aFallbackCharset, ECSSVersion eVersion)
Read the CSS from the passed String using a byte stream.

seancorfield 2021-02-06T05:51:51.104Z

If you look for readFromString you'll see eight possible signatures (yikes!) and they all take a String as the first argument (sort of expected) but they all take at least one extra argument... some take more than one extra...

seancorfield 2021-02-06T05:53:22.104500Z

This may be the easiest one to call? static CascadingStyleSheet readFromString(String sCSS, ECSSVersion eVersion)

seancorfield 2021-02-06T05:54:24.105700Z

At least they are static methods so you don't have to worry about creating an object instance to work from -- Clojure functions all compile down to static methods, so think of static methods as just plain ol' functions.

seancorfield 2021-02-06T05:55:31.106700Z

Here's the ECSSVersion class: https://javadoc.io/static/com.helger/ph-css/6.2.3/com/helger/css/ECSSVersion.html

seancorfield 2021-02-06T05:56:37.107800Z

So maybe the easiest thing to pick there is LATEST, so you can add (com.helger.css ECSSVersion) to your :import clause and then use ECSSVersion/LATEST as the second argument.

seancorfield 2021-02-06T05:56:59.108300Z

(it's a static field so, again, no object instance to worry about)

West 2021-02-06T05:57:28.108700Z

Ok, imma try this out.

West 2021-02-06T05:59:03.109Z

Oh my gosh! It worked!

West 2021-02-06T05:59:36.109700Z

That javadoc comes in super handy too.

West 2021-02-06T06:01:56.112100Z

Ok, so it wasn’t the syntax or the OO concepts. It was really just me not knowing how to use the docs. Also it was a static method, kinda like most of the http://java.io stuff.

seancorfield 2021-02-06T06:04:08.112700Z

seanc@DESKTOP-30ICA76:~/clojure$ clj -Sdeps '{:deps {com.helger/ph-css {:mvn/version "6.2.3"}}}'
Clojure 1.10.2
user=> (import '(com.helger.css ECSSVersion) '(com.helger.css.reader CSSReader))
com.helger.css.reader.CSSReader
user=> (CSSReader/readFromString "h1 {color: blue;}" ECSSVersion/LATEST)
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See <http://www.slf4j.org/codes.html#StaticLoggerBinder> for further details.
#object[com.helger.css.decl.CascadingStyleSheet 0x73ab3aac "[CascadingStyleSheet@0x73ab3aac: importRules=[]; namespaceRules=[]; rules=[[CSSStyleRule@0x2e140e59: selectors=[[CSSSelector@0x49a71302: members=[[value=h1; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=1; endLine=1; endColumn=2]; lastTokenArea=[beginLine=1; beginColumn=1; endLine=1; endColumn=2]]]]; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=1; endLine=1; endColumn=2]; lastTokenArea=[beginLine=1; beginColumn=1; endLine=1; endColumn=2]]]]; declarations=[[[CSSDeclaration@0x5cd61783: property=color; expression=[members=[[value=blue; optimizedValue=blue; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]]; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]; important=false; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=5; endLine=1; endColumn=9]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]]]; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=1; endLine=1; endColumn=2]; lastTokenArea=[beginLine=1; beginColumn=17; endLine=1; endColumn=17]]]]; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=1; endLine=1; endColumn=2]; lastTokenArea=[beginLine=1; beginColumn=17; endLine=1; endColumn=17]]]"]
user=&gt;
Wow, that produces a gnarly-looking result.

West 2021-02-06T06:09:55.113300Z

Sure does, but at least it’s something. Now I just gotta coerce all this into the format I want.

West 2021-02-06T06:11:15.114700Z

I was able to instantiate a class within Clojure before (if the REPL serves me right) so maybe I can experiment with other libraries now.

seancorfield 2021-02-06T06:13:05.115800Z

You might find bean helpful to pick apart Java objects that you get back from stuff like this:

user=&gt; (bean *1)
{:fontFaceRuleCount 0, :supportsRuleCount 0, :ruleCount 1, :allRules [#object[com.helger.css.decl.CSSStyleRule 0x2e140e59 "[CSSStyleRule@0x2e140e59: selectors=[[CSSSelector@0x49a71302: members=[[value=h1; sourceLocation=[firstTokenArea=[beginLine=1; ... lots more stuff ...
user=&gt; (map bean (:allRules *1))
({:allDeclarations [#object[com.helger.css.decl.CSSDeclaration 0x5cd61783 "[CSSDeclaration@0x5cd61783: property=color; expression=[members=[[value=blue; optimizedValue=blue; sourceLocation=[firstTokenArea=[beginLine=1; ... lots more stuff ...
;; but we can see what "shape" these things are:
user=&gt; (map keys *1)
((:allDeclarations :allSelectors :class :declarationCount :selectorCount :sourceLocation))
user=&gt; (bean (:allDeclarations (first *2)))
{:class com.helger.commons.collection.impl.CommonsArrayList, :clone [#object[com.helger.css.decl.CSSDeclaration 0x5cd61783 "[CSSDeclaration@0x5cd61783: property=color; expression=[members=[[value=blue; optimizedValue=blue; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]]; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]; important=false; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=5; endLine=1; endColumn=9]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]"]], :empty false}
user=&gt;

West 2021-02-06T06:13:45.116100Z

I love how it’s called bean lol

seancorfield 2021-02-06T06:15:47.116400Z

"Java Beans" are a thing 🙂

West 2021-02-06T06:17:00.117Z

oh man, just searched. Beans everywhere!

seancorfield 2021-02-06T06:17:16.117200Z

So I dug a bit further:

user=&gt; (seq (:allDeclarations (first *3)))
(#object[com.helger.css.decl.CSSDeclaration 0x5cd61783 "[CSSDeclaration@0x5cd61783: property=color; expression=[members=[[value=blue; optimizedValue=blue; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]]; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]; important=false; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=5; endLine=1; endColumn=9]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]"])
user=&gt; (count *1)
1
user=&gt; (bean (first *2))
{:class com.helger.css.decl.CSSDeclaration, :expression #object[com.helger.css.decl.CSSExpression 0x6fd5717c "[members=[[value=blue; optimizedValue=blue; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]]; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]"], :expressionAsCSSString "blue", :important false, :property "color", :sourceLocation #object[com.helger.css.CSSSourceLocation 0x7e2f86e6 "[firstTokenArea=[beginLine=1; beginColumn=5; endLine=1; endColumn=9]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]"]}
user=&gt; (bean (:expression *1))
{:allMembers [#object[com.helger.css.decl.CSSExpressionMemberTermSimple 0x45d6ef73 "[value=blue; optimizedValue=blue; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]"]], :allSimpleMembers [#object[com.helger.css.decl.CSSExpressionMemberTermSimple 0x45d6ef73 "[value=blue; optimizedValue=blue; sourceLocation=[firstTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]]"]], :class com.helger.css.decl.CSSExpression, :memberCount 1, :sourceLocation #object[com.helger.css.CSSSourceLocation 0x3f29e26 "[firstTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]"]}
user=&gt; (map bean (:allMembers *1))
({:class com.helger.css.decl.CSSExpressionMemberTermSimple, :clone #object[com.helger.css.decl.CSSExpressionMemberTermSimple 0x3b05a99b "[value=blue; optimizedValue=blue]"], :optimizedValue "blue", :sourceLocation #object[com.helger.css.CSSSourceLocation 0x2c43eb8 "[firstTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]; lastTokenArea=[beginLine=1; beginColumn=12; endLine=1; endColumn=15]]"], :value "blue"})
user=&gt;

seancorfield 2021-02-06T06:18:59.118300Z

This is kinda typically of heavily OO Java stuff: deeply nested trees of objects instead of just plain data like Clojure would use. Everything I'm calling bean on is a Java object that could just be data in Clojure.

West 2021-02-06T06:21:09.118500Z

Wowza.

West 2021-02-06T06:21:57.119300Z

Writing my own parser seems a lot more within reach now…

West 2021-02-06T06:54:48.120400Z

You mean two for loops?

West 2021-02-06T06:56:12.122900Z

Yeah, you can do something like this (defn [] ((for [i (x)] i)(for [j (x)] j)))

2021-02-06T06:56:49.123500Z

Hello can we do 2 "for" loops within 1 defn?

(defn asdf
  (for [x (take 4(range 10))]
      'do this)
  (for [x (drop 4(range 10))]
      'do that))

2021-02-06T06:59:41.124400Z

@c.westrom the "x" variable part must differ? you use "i" and "j", while i'm using same "x" for both.

West 2021-02-06T06:59:55.124600Z

I don’t think that matters.

West 2021-02-06T07:00:40.126Z

The local variable only applies within the parens at least for the for macro.

2021-02-06T07:01:00.126700Z

idk, but only 1 "for" that's executed

West 2021-02-06T07:01:18.127100Z

If that doesn’t work, try wrapping both for loops in a single paren.

2021-02-06T07:01:24.127300Z

only the latter for

2021-02-06T07:01:44.127800Z

how todo that?

West 2021-02-06T07:01:46.127900Z

Like this ((for)(for))

West 2021-02-06T07:02:02.128100Z

(defn asdf
  ((for [x (take 4(range 10))]
      'do this)
  (for [x (drop 4(range 10))]
      'do that)))

West 2021-02-06T07:03:10.129100Z

You can also turn the result into other data types. You can also pass the result of those loops as arguments to another function.

2021-02-06T07:19:49.129400Z

no cannot

2021-02-06T07:20:21.129600Z

it's result in error

2021-02-06T07:22:57.131300Z

Actually the code is like this

(defn asdf
  (println "hello")

  (for [x (take 4(range 10))]
      'do this)

  (println "world")
  (for [x (drop 4(range 10))]
      'do that))
so the result will be "hello" 1st loop for result "World" 2nd loop for result

2021-02-06T07:31:44.132600Z

I knew it, because take & drop return a lazy seq, only the last of the lazy seq returned use dorun will force it to run https://clojuredocs.org/clojure.core/dorun

(defn asdf
  (println "hello")

  (dorun (for [x (take 4(range 10))]
      'do this))

  (println "world")
  (dorun (for [x (drop 4(range 10))]
      'do that)))

theVastSilence 2021-02-06T15:08:17.134900Z

For exercises for a complete beginner, is 4Clojure the best place to start (and finish) before attempting anything else?

alexmiller 2021-02-06T15:31:08.136Z

It’s a good place to start

2021-02-06T15:31:34.137Z

4Clojure is using an old version of Clojure IIRC. I also quite like solving problems in Codewars. YOu can start at the easy 8KYU puzzles and work your way up. The nice thing is when you solve it you get to see other peoples solutions voted by Best Practice, I've learned a lot from solving them using my rubbish clojure and then learning much nicer ways of solving the problems and finding functions I didn't know existed.

2021-02-06T15:32:15.137300Z

It's nota clojure specific site though.

Corin (CWStra) 2021-02-06T18:48:30.141300Z

I'm trying to use clojure.spec.test.alpha/check in a cljs repl, but I constantly get an error about needing to require clojure.test.check and clojure.test.check.properties before calling it, even though I did that. Is there a way to make sure the namespaces are properly imported? (find-ns 'clojure.test.check) returns an object, and likewise for properties.

Corin (CWStra) 2021-02-06T18:52:21.143100Z

The https://cljs.github.io/api/cljs.spec.test.alpha/check for check uses exists? as a check for the imports, but that returns nil whenever I run it for a namespace. Is that significant, or is that just macro vs. non-macro thing?