beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Hagenek 2020-12-08T00:16:24.105100Z

Hi everyone! When solving Advent of Code day 3, At around 20 minutes in, Lambdaisland uses a symbol called input->map, this does not work for me. https://www.youtube.com/watch?v=wXVDfzxeZ-o&ab_channel=LambdaIsland . Is it his own macro? Here is my code that gives the error:

(defn sled-down [input]
  @(first
    (drop-while 
     (complement reduced?)
     (iterate sled [(input->map input) 0 0 0]))))

2020-12-08T00:18:55.105700Z

https://youtu.be/wXVDfzxeZ-o?t=1143 on line 16

Hagenek 2020-12-08T00:20:40.106800Z

Ahh thank you, missed that he changed that. Time for bed!āœŒļøNot used to using -> in function names

2020-12-08T00:21:01.107300Z

it's surprising that it doesn't return a hash-map

2020-12-08T00:22:07.107800Z

oh, it's a different kind of "map" (as if the two we have aren't enough)

Ronny Li 2020-12-08T01:11:09.108400Z

Hi, I've seen some reitit handlers extract the following keys fromĀ `request`:

{:keys [path-params query-params body-params]}
Yet when I inspect my request map I only see
:query-string
:path-params
:body
Does anyone know the reason for this discrepancy? Am I on the wrong version of reitit? I'm usingĀ `[metosin/reitit "0.5.10"]`

2020-12-08T01:21:49.109900Z

It will depend on the middleware you modifying the request before it gets to your handler

2020-12-08T01:22:21.110600Z

I think body-params comes from some kind json parsing middleware

2020-12-08T01:23:11.111700Z

You can also have form-params which comes from the middleware that parses the body as an encoded form post

Felix M 2020-12-08T02:54:29.113500Z

Hi, what's the difference between Reagent and Re-frame? When would you either or both to build SPAs? thanks

Ronny Li 2020-12-08T20:51:02.151Z

I'll slightly re-word what Sean said, Reagent is basically React and Reframe is basically Redux.

Ronny Li 2020-12-08T20:51:41.151200Z

This means that for simple stuff you only need Reagent but if at any point you start having headaches when managing app state then you should consider Reframe

šŸ™ 1
Ronny Li 2020-12-08T03:18:58.113600Z

Thank you so much! That makes a lot more sense.

seancorfield 2020-12-08T03:32:01.117400Z

@heyhey I'm no expert -- I don't do any cljs -- so I'm basing this on just reading the respective websites for those two projects: re-frame is a reactive framework built on top of Reagent -- Reagent is a low-level wrapper around React. We looked at doing some cljs work back in 2013/2014 and the choice then was Om or Reagent and we built an SPA with both. We liked Reagent a lot more. My understanding is that re-frame is a higher-level approach that makes building more complex SPAs easier than with just Reagent (in the same way that Redux brings structure to React apps to help manage dataflow better). There are #reagent and #re-frame channels here if you want to ask more in-depth questions.

šŸ‘ 1
scythx 2020-12-08T05:23:23.118600Z

Has anybody ever tried to deploy clojure-webapp on cpanel?

evocatus 2020-12-08T09:15:02.120100Z

If I need to, let's say, calculate sum of even numbers between 1 and 1000 I would do it like this:

(->> (range 1 1000)
     (filter even?)
     (reduce +)
)

evocatus 2020-12-08T09:18:21.120700Z

But what if I need to do the same for numbers that are either divisible by 3 or divisible by 5?

evocatus 2020-12-08T09:19:21.122Z

Is there a better way than checking for this complex condition at once?

evocatus 2020-12-08T09:20:55.123100Z

Like

(or #(zero? (rem % 3))
    #(zero? (rem % 5)))

Ben Sless 2020-12-08T09:30:03.123200Z

First you can abstract it a little by using some-fn:

(doc some-fn )
-------------------------
clojure.core/some-fn
([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps])
  Takes a set of predicates and returns a function f that returns the first logical true value
  returned by one of its composing predicates against any of its arguments, else it returns
  logical false. Note that f is short-circuiting in that it will stop execution on the first
  argument that triggers a logical true result against the original predicates.

šŸ˜® 1
Ben Sless 2020-12-08T09:30:37.123400Z

Then you can define a little helper:

(defn divisible? [n] (fn [k] (zero? (rem k n))))

Ben Sless 2020-12-08T09:30:56.123600Z

Already you can create something like:

(some-fn (divisible? 3) (divisible? 5))

Ben Sless 2020-12-08T09:32:26.123800Z

if you want to go one level further you can take any number of divisors:

(defn divisible-by-either? [xs] (apply some-fn (map divisible? xs)))

Ben Sless 2020-12-08T09:33:27.124Z

Then you'd write

(->> xs (filter (divisible-by-either? [3 5])) (reduce +))

evocatus 2020-12-08T09:38:56.124300Z

Thanks! some-fn is killer

Ben Sless 2020-12-08T09:40:37.124500Z

You're welcome. Be sure to say hi to her evil twin, every-pred

(doc every-pred )
-------------------------
clojure.core/every-pred
([p] [p1 p2] [p1 p2 p3] [p1 p2 p3 & ps])
  Takes a set of predicates and returns a function f that returns true if all of its
  composing predicates return a logical true value against all of its arguments, else it returns
  false. Note that f is short-circuiting in that it will stop execution on the first
  argument that triggers a logical false result against the original predicates.

Daniel Stephens 2020-12-08T11:09:40.127500Z

Hi all, Is there a way to get clojure.java.jdbc to return LocalDates/Instants rather than the java.sql.Timestamp/Date values? I have an issue where I store a BCE date correctly but it pulls it back flipped to a positive value. 0000-01-01 local dates gets stored as 0001-01-01 BC postgres date correctly, gets read as 0001-01-01 java.sql.Date wrongly.

(query "SELECT CAST(date_col AS VARCHAR) FROM table")
=> [{:date_col 0001-01-01 BC}]


(query "SELECT date_col FROM table")
=> [{:date_col #inst "0001-01-01T00:00:00.000-00:00"}]

^ techincally this is a java.sql.Date but as it extends java.util.Date clojure formats it as an instant, either way it's lost the ERA.

Daniel Stephens 2020-12-08T11:10:58.127600Z

I'm on 'latest stable' 0.7.11 but not sure if it's this library or an underlying one that gets it wrong

souenzzo 2020-12-08T11:12:30.128Z

Maybe ask in #sql channel

šŸ‘ 1
Chris 2020-12-08T13:56:03.131100Z

Hi all, how can I run a single clojure file with a dependency? I have the following file:

(require '[hickory :as h])

(defn run
  []
  (->> (slurp "some.html")
       h/parse
       h/as-hickory
       :content
       first
       :content
       (filter #(= (:tag %) :body))))

(println (run))
And Iā€™m trying to run it using:
clj -Sdeps "{:deps {hickory {:mvn/version \"0.7.1\"}}}" script.clj
However, I get:
Could not locate hickory__init.class, hickory.clj or hickory.cljc on classpath

Chris 2020-12-08T13:56:41.131600Z

I tried changing the first line to:

(ns script
  (:require [hickory :as h]))

Chris 2020-12-08T13:56:46.131800Z

But it did not change anything

Chris 2020-12-08T13:59:25.132400Z

Sorry, I found my mistake šŸ¤¦ I had to do (require '[hickory.core :as h])

2020-12-08T14:02:37.133Z

According to the README for the hickory project, the namespace to require is called hickory.core, not hickory. Try changing that in your require form.

Chris 2020-12-08T14:11:19.133400Z

Yes, that was my mistake, everything works fine now! Thanks!

Felix M 2020-12-08T14:48:18.136200Z

@seancorfield thank you, that's exactly the overview I needed. So, Re-frame is a framework built on top of Reagent, along the lines of Next.js for React. Got it.

Miles R. 2020-12-08T19:16:40.139100Z

Hi! I'm an electrical engineer looking to pick this up for some SPA hobby projects. Primary development experience is in windows desktop applications in C++ and C#, as well as far less relevant 8 bit embedded applications

šŸ‘‹ 2
Miles R. 2020-12-08T19:18:45.140700Z

I have a skeletonized project established in IntelliJ (2018.3.6 Ultimate Edition) using Cursive and Leiningen, I want to eventually deploy it using something like heroku but coming from byte level shenanigans at my current job there's a lot to take in all at once

Miles R. 2020-12-08T19:47:05.143700Z

to keep things simple starting out I've created a new project using the command lein new luminus {project name} +re-frame that builds and runs fine when I set it to run the -main segment from my .core project file, after that I point firefox at the correct page and it returns this message saying I haven't compiled my clojurescript yet:

Miles R. 2020-12-08T19:49:10.144900Z

popping over to the terminal in my IDE I try running the suggested command and it returns that 'lein' is not recognized

phronmophobic 2020-12-08T20:12:31.145900Z

does it work if you type the command wherever you typed in: lein new luminus {project name} +re-frame?

Miles R. 2020-12-08T20:14:08.148700Z

I put that command back together from the new project wizard where it decompiles it into separate project name, template, and template settings fields, my IntelliJ definitely is running lein under the hood I'm just not sure how to access that directly

2020-12-08T20:14:10.148900Z

whatā€™s the idiomatic way to efficiently (i.e. binary search) a sorted vector for a value?

(let [sorted-vec (vec (sort [10 2 0 99 -18 72 10]))
  ...?)
(contains? sorted-vec n) works, but itā€™s not efficient

Miles R. 2020-12-08T20:14:25.149200Z

anyways I managed to successfully deploy: http://kobold.xyz/

Miles R. 2020-12-08T20:14:44.149600Z

(It's empty but hey that it works at all is pretty promising)

šŸ¤˜ 1
phronmophobic 2020-12-08T20:17:22.149800Z

depending on the use case, the idiomatic solution might be to use a different data structure. this stack overflow solution also looks reasonable, https://stackoverflow.com/questions/8949837/binary-search-in-clojure-implementation-performance#8950240

2020-12-08T20:18:10.150100Z

yeah, I tried the Java interop way, but got some cast exceptions between Integer and Long, and kind of gave up on it. decided to see if there was a more built-in, idiomatic way

phronmophobic 2020-12-08T20:19:42.150300Z

would sorted-set work for your use case?

phronmophobic 2020-12-08T20:21:47.150500Z

there are also a dozen data structures listed at https://www.clojure-toolbox.com/ that perform well for different use cases

2020-12-08T20:22:21.150800Z

thank you, will have a look. and yeah, in this particular case, sorted-set would work, so thatā€™s a good point

2020-12-08T21:06:46.151400Z

regarding contains? above, that should be instant, and only look for the index by position, not the value held

2020-12-08T21:10:12.151800Z

also, with a sorted-set you can use subseq / rsubseq to iterate in a way that takes advantage of the binary tree implementation (eg. using the branching to quickly find the first item > your start-key)

2020-12-08T21:12:15.152100Z

demo of the contains? issue:

user=> (let [sorted-vec (vec (sort [:c :a :b :d]))] (contains? sorted-vec 0))
true

2020-12-08T21:12:26.152300Z

that is true because there is an item at index 0

2020-12-08T21:14:17.152500Z

You need to run two things. Server is runned by lein run while you also need to run client hot code reloading compliation, which is in your case likely lein figwheel (I am using Shadow-cljs for that.)

2020-12-08T21:15:23.152700Z

It works that server is serving HTML and JS file from resources directory, and JS is created there by running lein figwheel. When you build production version, it will build production version of JS and package everything inside uberjar so the server can serve it.

Miles R. 2020-12-08T21:38:35.154700Z

Basic question, how do I serve up the favicon.ico as part of the slug? the normal HTML method results in a 404 when attempting to access it

2020-12-08T21:41:03.156300Z

@milesred42 typically I have made a middleware that short-circuited all requests for "/favicon.ico" regardless of parent with a resource response containing the correct image file

2020-12-08T21:41:27.156900Z

there might be something premade for this...

2020-12-08T21:42:38.157500Z

this stack overflow answer is about the same as what I did https://stackoverflow.com/a/51978184

Miles R. 2020-12-08T21:42:56.157900Z

kk, i'll look into that

2020-12-08T21:43:54.158600Z

of course this means you need to have a "favicon.ico" file, most likely in your resources/ folder so that it will be present in your packed jar

Miles R. 2020-12-08T21:44:47.159500Z

yeah it's already in resources/public/ so it should be pretty easy to redirect those requests

2020-12-08T21:45:04.159800Z

it's not a redirect, it's an override of your routing handler

2020-12-08T21:45:23.160200Z

I mean, you could also define favicon.ico as a route, that's just less idiomatic

2020-12-08T21:48:45.161600Z

@milesred42 also, depending on how you deploy (and what kind of site / level of usage you are expecting) you might have a reverse proxy or CDN setup anyway, and in that case it's easier to just define the favicon statically and ignore it in clojure world

2020-12-08T22:28:51.162200Z

is there a way to constrain the size of the thread pool used for future and deref ? or does one need to use this approach (`set-agent-send-off-executor!`)? https://stackoverflow.com/questions/11316737/managing-agent-thread-pools-in-clojure#comment108769284_11322660

2020-12-08T22:31:03.162700Z

deref doesn't use a threadpool

2020-12-08T22:31:27.162800Z

ah, right, itā€™s just waiting for the future to finish

phronmophobic 2020-12-08T22:31:36.163Z

you could also create your own future that uses whatever executor your want. the clojure.core code wouldn't be that hard to modify:

(defn future-call 
  "Takes a function of no args and yields a future object that will
  invoke the function in another thread, and will cache the result and
  return it on all subsequent calls to deref/@. If the computation has
  not yet finished, calls to deref/@ will block, unless the variant
  of deref with timeout is used. See also - realized?."
  {:added "1.1"
   :static true}
  [f]
  (let [f (binding-conveyor-fn f)
        fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)]
    (reify 
     clojure.lang.IDeref 
     (deref [_] (deref-future fut))
     clojure.lang.IBlockingDeref
     (deref
      [_ timeout-ms timeout-val]
      (deref-future fut timeout-ms timeout-val))
     clojure.lang.IPending
     (isRealized [_] (.isDone fut))
     java.util.concurrent.Future
      (get [_] (.get fut))
      (get [_ timeout unit] (.get fut timeout unit))
      (isCancelled [_] (.isCancelled fut))
      (isDone [_] (.isDone fut))
      (cancel [_ interrupt?] (.cancel fut interrupt?)))))
  
(defmacro future
  "Takes a body of expressions and yields a future object that will
  invoke the body in another thread, and will cache the result and
  return it on all subsequent calls to deref/@. If the computation has
  not yet finished, calls to deref/@ will block, unless the variant of
  deref with timeout is used. See also - realized?."
  {:added "1.1"}
  [& body] `(future-call (^{:once true} fn* [] ~@body)))

2020-12-08T22:31:39.163200Z

I guess amend that to ā€œcontrol the number of threads used to execute futuresā€

phronmophobic 2020-12-08T22:32:40.163600Z

you could even modify it to allow for an executor to be passed in if you wanted something like multiple thread pools

2020-12-08T22:32:53.164Z

I've never used set-agent-send-off-executor! or any of the via functions

2020-12-08T22:33:42.164800Z

I use executors a fair bit, and deref works on java Futures just fine

phronmophobic 2020-12-08T22:33:42.164900Z

or you could interop with an implementation of executor directly, https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executor.html

2020-12-08T22:35:56.165300Z

do you have a sample code snippet, by chance?

2020-12-08T22:36:05.165600Z

trying to understand what I need to change to use those instead

2020-12-08T22:36:35.166100Z

reading Clojure Applied, and it talks about using Java thread pools but doesnā€™t show an example of how to use them along with Clojure futures

dpsutton 2020-12-08T22:36:44.166400Z

future submits to Executors.newCachedThreadPool so i don't believe there's any way to constrain the number of spawned threads using that macro

2020-12-08T22:40:39.166800Z

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executors.html has a bunch of static methods for creating different kinds of executors

2020-12-08T22:41:32.167300Z

when you schedule work do be done on an executorservice you often get back a https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html which deref supports

2020-12-08T22:41:39.167500Z

a clojure future is just a wrapping of dynamic var binding plus .submit of an fn to an executor - check out the source of future-call which the future macro uses, it's pretty small

2020-12-08T22:48:14.167700Z

thanks, all. I have some reading to do