This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-03-26
Channels
- # announcements (1)
- # autochrome-github (1)
- # babashka (9)
- # beginners (112)
- # bristol-clojurians (2)
- # calva (26)
- # cider (10)
- # clj-kondo (31)
- # cljs-dev (40)
- # clojure (114)
- # clojure-austin (1)
- # clojure-dev (112)
- # clojure-europe (22)
- # clojure-germany (5)
- # clojure-italy (1)
- # clojure-nl (2)
- # clojure-norway (1)
- # clojure-spec (10)
- # clojure-uk (96)
- # clojurescript (39)
- # core-logic (5)
- # datomic (40)
- # fulcro (34)
- # graphql (17)
- # jobs (3)
- # kaocha (4)
- # leiningen (10)
- # luminus (1)
- # malli (3)
- # meander (44)
- # midje (2)
- # off-topic (40)
- # pathom (5)
- # re-frame (8)
- # reitit (8)
- # ring (3)
- # ring-swagger (4)
- # shadow-cljs (83)
- # spacemacs (96)
- # tools-deps (16)
- # vim (4)
- # xtdb (15)
- # yada (20)
raspberry pi question: I’m trying to setup an IDE where I run emacs on my mac, edit the files locally (mapped to a local volume), and have cider connect to the repl on the pi over the local net. 1. is this kind of setup known to work? 2. should I install lein on the pi or is there a better approach?
I’ve installed azul jdk 11 on the pi and am able to locally edit files via emacs at this point.
if you can avoid using lein, it will be much less overhead - if you need CIDER you can add nrepl as a project dep and start up an nrepl server in a temporary -main
- you'll need to override the host it listens on by default it's local only
otherwise you can make an uberjar with all your deps in it with lein, then start it up in an ssh session with rlwrap java -cp my-uber.jar clojure.main
- you get a less featureful repl but use less system resources on the pi
I don’t think I need lein. Not really sure what the minimum is, do I need to install clojure on the pi? From googling this there were references to installing lein which I supposed installs clojure.
sorry if this is confusing, I’m very much a noob and have only ever run clojure locally on my mac.
The idea of what’s required remotely vs locally confuses me.
you don't need clojure, clojure is a java library and will be in your jar
I expect to use Cider to connect to a remote repl.
then you need to add nrepl as a dep to your project, and start an nrepl server
it's a small amount of code at least
and you'll need to change the :host of the server to 127.0.0.1
I’m confused about how the repl gets run on the pi. There must be some sort of clojure interpreter that needs to be installed on the pi, right?
or does all the clojure stuff occur on the local mac and then get sent over to the pi via the CIDER nrepl connection?
as java bytecode?
That’s the point of the nrepl server. It listens for commands n runs them in your java/clojure process on the pi and sends them back to emacs
clojure itself is a bytecode compiler
it's a jar, java runs it if you ask it to
ok, so to make sure I understand, I only need java on the pi.
right - and you can have a git checkout or a jar or both to provide the code for java to execute
lol, I’m starting with a very limited understanding of the architecture! I guess I should read up on nrepl and cider before I ask more questions.
or just send everything over the repl
cider is great for features, but it adds a lot of complexity too once you do something sufficiently unusual - doing this without cider is much easier
ok, so the simplest thing is not to use cider? I think I’ve only ever used cider for local clojure. so I’ll edit the clojure files in emacs but not use cider? Any links to what I should read about that?
anything that works in a file (with very few exceptions) works when sent to a repl
you can literally dump every namespace into the repl (as long as you get the dependency order of namespaces right) and it will work
a part that confuses me (a lot of this confuses me) is that it seems that something should be listening on the pi for the connection from the mac.
right, it runs sshd by default so you can ssh in
and then you can start a repl inside ssh
how do I start a repl in the pi, I thought that was accomplished via lein or something similar. Not by java which is all I thought I needed on the pi.
inf-clojure
is a socket-repl client for emacs you can use instead of cider
again, sorry for the confusion. this must be difficult. If I’m developing locally on my mac, editing source files there, and then evaluating on the pi, then surely something must run on the pi to pass instructions over to the JVM, no?
My best guess of the architecture: 1. edit the files on the mac via emacs (which has the effect of updating the files locally on the pi since they are network mapped) 2. use emacs minor mode to connect to an nrepl on the pi (I thought this meant cider but seemingly it does not) 3. evaluating sexp in emacs passes the sexp over to the nrepl running on the pi, somehow it’s interpreted to java bytecode there and run on the pi jvm.
I've always simply ssh'd into the pi and ran Clojure and emacs from there
that might be the simplest solution until I get a better understanding of the components involved here. I’ll need to watch some youtubes on nrepl I think!
Thanks everyone for bearing with my ubernoob questions.
What’s the rationale between using ::keyword
vs. :keyword
? What conventions drive using one or the other?
The ::keyword
form is the fully qualified namespace form?
::
means "auto-resolve" the keyword. ::foo/bar
will use the namespace alias foo
to resolve it, ::bar
will use the current namespace.
(ns some.example
(:require [fuselier :as foo]))
::foo/bar ;=> :fuselier/bar
::bar ;=> :some.example/bar
thanks!
Why would you store keywords inside namespaces?
@ordoflammae The keywords aren't "stored" inside a namespace. :foo/bar
is just a "qualified keyword". There doesn't have to be a foo
namespace.
The ::
syntax uses namespaces (and aliases) to resolve the qualified name, but that's the only connection.
Qualified keywords are used heavily with clojure.spec
so reading the rationale and/or guide for that will probably help explain it https://clojure.org/about/spec and https://clojure.org/guides/spec
But qualified keywords are useful outside of Spec too.
For example, next.jdbc
produces result sets with qualified keywords identifying the columns, where the table name is used as the qualifier (if available). So a SQL query that joins a person
table and an address
table, for example, and both tables might have id
as their primary key -- and you'd get a result set where the rows have :person/id
and :address/id
so you can tell them apart.
You can also see them used here https://clojure.org/reference/multimethods
So I started a little side project playing around with Clojure just because I kinda liked my impression of how Rich Hickey cut his jibsail, because I had enjoyed working with Scheme in college, and because I was more than a little burned out on Android Java development And now I’m iteratively building a web app on a live, running server through an REPL This is more fun programming than I’ve had in years.
Welcome to the community :) and have fun!
Similar story here. I've had no more lisp exposure than browsing through SICP, but that and a couple of Rich Hickey talks had seeded the idea of trying Clojure some day. After a bit of a break from dev work I started playing with Clojure last week, to see if I could still find programming fun rather then tedious. And so far I really have. It's refreshing. I'm just working my way through a book or two and some small scale exercises for now, but I have a few interesting projects in mind.
Isnt’ everything starting with :
a keyword?
I saw it here: https://clojurians.slack.com/archives/C03S1L9DN/p1585198253017000 On second look, this seems Hiccup syntax. Still don't know what it does though.
DatePicker is React component written in JS and you need to tell Reagent it should be converted from React component to Reagent
Hi folks, I have a question that feels easy, but has eluded me so far.
I want to check if a given datetime is within the hours of 8am and 8pm in the relevant timezone, using Java 8 time (`clojure.java.time`).
As far as I can tell, I can easily check whether it is within 8-8 in my local timezone using instances of time/local-time
; however, I am stuck on how to compare within the target timezone
I have this:
(defn outside-valid-hours? [timezone timestamp]
(let [timestamp-tz (time/with-zone (time/zoned-date-time timestamp) timezone)
event-time (time/local-time timestamp-tz timezone)
valid-start (time/local-time 8)
valid-end (time/local-time 20)]
(< valid-start event-time valid-end)))
But whatever I try I can only seem to specify the start and end dates at 8-8 local timeOr this (time/zoned-date-time (time/local-date timestamp-tz) (time/local-time 8) timezone)
I'd reach for TDD in this case. TDD would force you to state your expectations, and let you solve them one-by-one. Test cases could also make it easier to help you, as others can then get something to test against. It doesn't have to be a lot:
(defn plus [x y])
(assert (= 2 (plus 1 1)))
(assert (= 10 (plus 5 5)))
Thanks @U3X7174KS - I have some simple tests, but still stuck on where to go beyond that
For e.g.
(is (outside-valid-hours? "Etc/GMT+3" "2020-01-01T03:03:51.302Z"))
(is (outside-valid-hours? "Etc/GMT+3" "2020-01-01T19:03:51.302Z"))
(is (not (outside-valid-hours? "Etc/GMT+3" "2020-01-01T13:03:51.302Z")))
(is (not (outside-valid-hours? "Etc/GMT+3" "2020-01-01T07:03:51.302Z")))
Is it possible to write a test that specifically tests a timezone conversion? In the situation that I'm unable to make a larger function work, I try to test smaller concepts. I often discover having misunderstood some term, abstraction or concept.
For clojure cli, what does the S
prefix (i.e. sDeps
)stand for? I couldn’t find info for some of these commands in docs.
which are you not finding?
I think everything should be doc'ed in clj -h
or man clj
the list of commands are documented, i mean that I couldn’t find any specific mention of what the prefix stood (which made it harder for me to remember)
Hi pals, I'm currently reading Clojure for the Brave and True and found myself stuck trying to understand what lazy sequences are, I've looked at some articles on the internet but the concept still feels foggy to me, can somebody explain it in more human-like language, thanks in advance!
I wrote this once, trying to explain lazy sequences to someone. See if this helps. https://gist.github.com/Hindol/e6eba6bbc27289985ea7a5d242629d87
I can try. “Lazy” means basically “on demand evaluation”. For example, (range)
returns a lazy sequence of all integers starting at zero and going up. If you tried to evaluate that, it’ll run forever, but you can execute (take 5 (range))
and you’ll get back (0 1 2 3 4)
, because range
is lazy — it only evaluates as many values as it needs to satisfy what’s being asked for.
That’s over-simplified, of course, but conceptually, that’s the idea. It’s a way to work with large or infinite sequences using only finite resources.
Thanks! 🙂
Talking about Clojure for the Brave. Is the code there generally considered idiomatic?
I’d say in general, but if there’s any specific thing you have questions about feel free to ask.
e,g, the way the hobbit bothering code uses destructuring on part & remaining, and recur to get the equivalent of a car/cdr recursion (kinda)
Do you happen to have a link? Haven’t looked at that chapter in a while.
on: (let [[part & remaining] remaining-asym-parts] (recur remaining (into final-body-parts (set [part (matching-part part)]))))
Yeah, I’d say that’s reasonably idiomatic. There might be other approaches that would also be idiomatic, but that looks like something I might write.
recur
is how Clojure works around the lack of tail-call optimization in the JVM, so it’s commonly used in that sort of scenario.
Yep, still getting to grips with that. But it suddenly hit me that the destructuring & rest thing is equivalent of car/cdr
So I now feel the urge to try translating some tree and graph walking lisp into loop/recur
I wrote this once, trying to explain lazy sequences to someone. See if this helps. https://gist.github.com/Hindol/e6eba6bbc27289985ea7a5d242629d87
Thanks hindol, that's a pretty clean explanation!
@phil634 If you're looking for just car/cdr functionality in the recur, like processing elements one at a time (e.g. (set [part (matching-part part)])
), I think it can be more idiomatic to use a reduce
over your collection.
(reduce (fn [coll part]
(into coll #{[part (matching-part part)]})
remaining-asym-parts)
Also gives you a chance to factor out the function into something reusable. loop/recur
is relatively speaking pretty manual, so if you can get away with cleaner/more readable methods with sequence functions I think it's generally more preferredI remember reading that the gson object can be reused after serializing. But that made it sound ominously like it wasn’t thread safe
I'll do a quick test, why not
this sleeps between processing one value and processing the next, I think that makes the gson object get used concurrently
user=> (map deref (mapv (fn [v] (future (.toJson gson (cons "1" (lazy-seq (do (Thread/sleep 1000) [v])))))) (range 100)))
("[\"1\",0]" "[\"1\",1]" "[\"1\",2]" "[\"1\",3]" "[\"1\",4]" "[\"1\",5]" "[\"1\",6]" "[\"1\",7]" "[\"1\",8]" "[\"1\",9]" "[\"1\",10]" "[\"1\",11]" "[\"1\",12]" "[\"1\",13]" "[\"1\",14]" "[\"1\",15]" "[\"1\",16]" "[\"1\",17]" "[\"1\",18]" "[\"1\",19]" "[\"1\",20]" "[\"1\",21]" "[\"1\",22]" "[\"1\",23]" "[\"1\",24]" "[\"1\",25]" "[\"1\",26]" "[\"1\",27]" "[\"1\",28]" "[\"1\",29]" "[\"1\",30]" "[\"1\",31]" "[\"1\",32]" "[\"1\",33]" "[\"1\",34]" "[\"1\",35]" "[\"1\",36]" "[\"1\",37]" "[\"1\",38]" "[\"1\",39]" "[\"1\",40]" "[\"1\",41]" "[\"1\",42]" "[\"1\",43]" "[\"1\",44]" "[\"1\",45]" "[\"1\",46]" "[\"1\",47]" "[\"1\",48]" "[\"1\",49]" "[\"1\",50]" "[\"1\",51]" "[\"1\",52]" "[\"1\",53]" "[\"1\",54]" "[\"1\",55]" "[\"1\",56]" "[\"1\",57]" "[\"1\",58]" "[\"1\",59]" "[\"1\",60]" "[\"1\",61]" "[\"1\",62]" "[\"1\",63]" "[\"1\",64]" "[\"1\",65]" "[\"1\",66]" "[\"1\",67]" "[\"1\",68]" "[\"1\",69]" "[\"1\",70]" "[\"1\",71]" "[\"1\",72]" "[\"1\",73]" "[\"1\",74]" "[\"1\",75]" "[\"1\",76]" "[\"1\",77]" "[\"1\",78]" "[\"1\",79]" "[\"1\",80]" "[\"1\",81]" "[\"1\",82]" "[\"1\",83]" "[\"1\",84]" "[\"1\",85]" "[\"1\",86]" "[\"1\",87]" "[\"1\",88]" "[\"1\",89]" "[\"1\",90]" "[\"1\",91]" "[\"1\",92]" "[\"1\",93]" "[\"1\",94]" "[\"1\",95]" "[\"1\",96]" "[\"1\",97]" "[\"1\",98]" "[\"1\",99]")
oh right, thanks
same result
oh in comparison to gson above, right
that's easy to adjust with a custom serializer of course, perhaps a clojure Gson serdes with good clojure defaults would be worth making