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
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).
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.
it's not only pointless, it sort of suggests that things are okay, at least at a cursory glance
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?
read-string
?
Wow, okay! Thanks 🙂
far more preferable to use clojure.edn/read-string
for this type of thing.
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.
@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
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
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.
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...
This may be the easiest one to call? static CascadingStyleSheet readFromString(String sCSS, ECSSVersion eVersion)
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.
Here's the ECSSVersion
class: https://javadoc.io/static/com.helger/ph-css/6.2.3/com/helger/css/ECSSVersion.html
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.
(it's a static
field so, again, no object instance to worry about)
Ok, imma try this out.
Oh my gosh! It worked!
That javadoc comes in super handy too.
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.
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=>
Wow, that produces a gnarly-looking result.Sure does, but at least it’s something. Now I just gotta coerce all this into the format I want.
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.
You might find bean
helpful to pick apart Java objects that you get back from stuff like this:
user=> (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=> (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=> (map keys *1)
((:allDeclarations :allSelectors :class :declarationCount :selectorCount :sourceLocation))
user=> (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=>
I love how it’s called bean lol
"Java Beans" are a thing 🙂
oh man, just searched. Beans everywhere!
So I dug a bit further:
user=> (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=> (count *1)
1
user=> (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=> (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=> (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=>
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.
Wowza.
Writing my own parser seems a lot more within reach now…
You mean two for loops?
Yeah, you can do something like this (defn [] ((for [i (x)] i)(for [j (x)] j)))
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))
@c.westrom the "x" variable part must differ? you use "i" and "j", while i'm using same "x" for both.
I don’t think that matters.
The local variable only applies within the parens at least for the for
macro.
idk, but only 1 "for" that's executed
If that doesn’t work, try wrapping both for loops in a single paren.
only the latter for
how todo that?
Like this ((for)(for))
(defn asdf
((for [x (take 4(range 10))]
'do this)
(for [x (drop 4(range 10))]
'do that)))
You can also turn the result into other data types. You can also pass the result of those loops as arguments to another function.
no cannot
it's result in error
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 resultI 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)))
For exercises for a complete beginner, is 4Clojure the best place to start (and finish) before attempting anything else?
It’s a good place to start
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.
It's nota clojure specific site though.
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.
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?