Fork me on GitHub
#beginners
<
2023-03-13
>
Patrick05:03:44

Hi everyone! I've started to get my feet wet in clojure web development and have made a simple CRUD+auth site using compojure, hiccup, next.jdbc, and buddy-auth. I've used the session backend for buddy-auth and I'm wondering how I can implement some kind of "stay logged in" functionality? My session auth uses username and password which I wrote a little salting and hashing function to store. Do I use cookies? If so, what are some best practices?

James06:03:31

Yes, using cookies is how id do it, for this id look at following: Use an HttpOnly cookie: Set the "HttpOnly" flag to prevent client-side scripts from accessing the cookie. This helps prevent cross-site scripting (XSS) attacks. Set an expiration time: Set an expiration time for the cookie to control how long the user should stay logged in. Storing a session ID in the cookie: Instead of storing the username and password in the cookie, store a session ID. Renew the cookie on every request: When the user makes a request, renew the expiration time of the cookie to keep the user logged in. To implement these best practices in your web application, you can modify your Buddy auth configuration to use cookies instead of session storage. You can use the wrap-authentication middleware from Buddy to create and verify the session ID.

(require '[buddy.auth :refer [wrap-authentication]])

(def auth-config
  {:authenticators
   {:session
    (buddy.auth.strategies.session/session-authenticator
     (fn [username password]
       (your-salting-and-hashing-function username password))
     {:redirect-uri "/login"
      :unauthorized-handler #(your-unauthorized-handler)})}})

(def app
  (-> routes
      (wrap-authentication auth-config)))

Alejandro Buffery11:03:00

Hi, I am tired of OOP and i would like to learn web development with clojurescript. I am a complete newbee with clojure, learned basics of lisp long time ago. I am having a hard time trying to figure out what to do and the path to follow. I hear about reagent-reframe, but that is not compatible with modern react, etc. Online courses, books, etc seem outdated, incomplete, etc I hear about helix, but not ready. I hear about figwheel easier, but shadow better. I know nothing about all of this, or any other, I only read about it when skimming some posts. I will be glad to get ideas in order to have a planned route of less pain to learn from scratch and setup from scratch. My goals: • learn clojurescript from scratch (book?) • good/easy computer setup to work with clojure • seamlessly use react ecosystem and npm packages when needed My current setup: • mac m1 • vscode • if emacs provides a better setup/experience i am willing to learn it, provided a light, quick and easy learning source to follow Thanks !

lassemaatta11:03:57

It's easy to get stuck on "analysis paralysis"; trying to find the optimal tools and libraries with no (real or imagined) downsides. I'd suggest just choosing something (shadow + reagent + reframe is a nice combo) to get started and when you get some experience it's easier to evaluate things properly.

pez11:03:06

Hi! It's indeed a scattered image when researching these things without prior knowledge. I agree with @U0178V2SLAY about diving in. I also agree about shadow-cljs + reagent + re-frame. Don't know where you found that Figwheel would be easier than shadow, but it doesn't ring true to me. Figwheel is simpler, maybe that's what you read? As for computer setup, I am a maintainer of Calva, and we have made it our goal to try make it as easy as we can to setup things for Clojure and ClojureScript development. In theory you should be able to be hacking on a ClojureScript app by: 1. Installing Calva in VS Code 2. Get a copy of this project template: https://github.com/PEZ/shadow-bare-bones to your computer 3. Follow the 3-4 steps mentioned there That project template uses shadow-cljs and reagent. So no re-frame there, but I think it makes sense to add that to the mix later, when you know how it feels without it. Calva also has an introduction to Clojure the language, so you might want to open a separate VS Code window and issue the command Calva: Fire up the Getting Started REPL. It is a REPL-driven interactive intro to Calva and to Clojure. I hope this helps! For Calva support, feel super welcome to join the #calva channel. calva

❤️ 2
practicalli-johnny12:03:44

https://clojurescript.org/reference/documentation is a complete language reference http://funcool.github.io/clojurescript-unraveled/ is a nice guide to the ClojureScript language ( which is 99% the same as Clojure, except for a few limitations of the JavaScript host platform). As Clojure & ClojureScript language are almost identical, any good Clojure book or exercises can help to learn ClojureScript The big difference of course between Clojure & ClojureScript is the host (Java or JavaScript) and the type of applications & services built Pick an editor you are most familiar with to minimize the initial learning load, there are many to choose from https://practical.li/clojure/clojure-editors/. Clojure aware editors have the same core functionality, so initial choice is not that important. Shadow-cljs is effectively built on top of node.js and therefore more integrated. Assumes that node.js is well understood and significant use of JavaScript npm packages will be used Read the user guide in detail to avoid common issues when starting https://shadow-cljs.github.io/docs/UsersGuide.html Figwheel is a simple approach and doesn't require node.js, so ClojureScript applications can be built without JavaScript. Figwheel does enabled use of npm packages via bundle though. As with any language, there are a wide range of choice for libraries to help build apps and many types of apps that can be built (UI / full-stacl / backend). Most common ClojureScript front-end is reagent which takes a react.js like approach. re-frame builds upon reagent and supports the building of more complex UIs and stateful workflows.

kennytilton12:03:41

Are you programming the Web now with a different stack? If so, what would that be? Regarding learning CLJS specifically, actually any good Clojure or CLJS tutorial will be fine to get started, since they are so similar. I always recommend Brave Clojure and Clojure Koans. Why is "modern React" a requirement? Once you settle on re-frame vs Reagent vs Helix vs ___, you should be able to find a "quick start" Hello world project you can get running in a few minutes. For the Web I use figwheel.main, for React Native https://github.com/PEZ/rn-rf-shadow. I would recommend ClojureDart/Flutter, but that is about as OO as it gets. If you do not mind the underlying framework being OO while you code Clojure, give that stack a look.

Alejandro Buffery13:03:11

Thanks for so top notch welcoming answers. Maybe i did read that figwheel is simpler, I skimmed the info trying to get a sense of bearings in an ocean. Calva is a great starting point knowing I can tip toe my first steps. I will take the advice of starting-off with shadow + reagent + reframe. I am with Flutter+React currently, was evaluating Svelte, and hoping that CLJS will offer a brighter-more stable future. I do not know the implications in CLJS of not supporting “modern React” (future proofing?), some posts I saw seemed to mention that it was a problem/inconvenience, so naively guessed it must be. I’ll checkout also Unraveled and Brave Clojure. Thanks, Thanks, Thanksss !!!

🙏 2
kennytilton14:03:06

Good choices! Staying current with React is tough because it keeps evolving, but CLJS frameworks can insulate us from much of that. The thing to remember is that there are other ways to build UIs besides React's unique mechanisms. I would avoid framework lock-in, anyway. Hey, if Flutter is on the table, check out #clojuredart, and even my nascent wrapper, https://github.com/kennytilton/flutter-mx. They both liberate Flutter/Dart devs from most of the OO grief.

pez15:03:40

Last time I checked ClojureDart didn't have a REPL story. If that is still the case, for learning ClojureScript purposes, I think it is better to start with an option where Interactive Programming can be employed.

kennytilton15:03:14

Well, with turnaround in a couple of seconds, in those rare circumstances where I need to explore REPL-like, I just add the expression to my main function and save. For learning, I still say just use the best Clojure tutorial we can find. Once the itch to Build Something(tm) cuts in, well, as I said, I never use CLJS (or JS, for that matter) at a prompt. Am I weird?

Stuart17:03:21

I've found having a repl open for doing re-frame can be handy, I often have a bunch of debug (rf/dispatch-sync [:foo]) type statements for playing around, setting state, resetting pages etc. Inside a comment block.

kennytilton20:03:37

Sounds brilliant, @U013YN3T4DA! Real re-frame mastery using it to mess with dominos interactively and within the r/f rules. Has that been written up?

pez20:03:44

I do a bit of that in this demo: https://www.youtube.com/watch?v=hQIltSac-gs

👀 2
kennytilton22:03:37

Very nice, @U0ETXRFEW. You live code better than I!

pez23:03:38

Sounds like you didn’t check the demo that made me record this one. 😀

kennytilton00:03:44

Ah, I asked in a comment on the video about the live bug that stopped the first demo. I'll see if I can find it....

Alejandro Buffery02:03:05

I am certainly interested in Clojuredart in order to work more in one world. My first understanding is that Clojuredart is ready to some degree, not sure how far it goes from a usability standpoint. I will start slowww, my plan is when I have a foothold on basic Clojure to try Reagent-Reframe, and after Clojuredart. My fear of looking soon at Clojuredart is stumbling over stones and with insufficient knowledge of how to wade the river at different crossings. I have started reading Brave Clojureee !

Alejandro Buffery02:03:31

Have you had a look by chance at https://www.unison-lang.org/, it is a different beast than Clojure, yet also with an interesting REPL like approach and property-based testing. It caught my eye, and made me wonder if Clojure flexibility would make this type of distributed computing paradigm easier in some way.

kennytilton04:03:31

"I will start slowww, my plan is when I have a foothold on basic Clojure to try Reagent-Reframe, and after Clojuredart." Good plan. CLJD is pretty solid, tho. "It caught my eye, and made me wonder if Clojure flexibility would make this type of distributed computing paradigm easier in some way." Unison reminds me of #C7Q9GSHFV Electric Clojure after a quick scan. Maybe @U09K620SG has some thoughts?

🙏 2
Alejandro Buffery07:03:42

Thanksss, you made my day knowing CLJD is solid to use ! Hyperfiddle I get what it is, yet I do not quite understand/grasp part of the explanations, most probably due to my lack of knowledge. I believe part of the success of Hyperfiddle may well be in Dustin adding in the mix teaching/communication to breakup the concepts from abstract/technical terms to more mundane street user terms, many times explained with simple image/slide, similar to easy going online courses/materials. Produce material for technical people that want to know how things work (probably because they have to explain it to somebody after) and material for non-technical people that simply want to know how to get things done. If the explanations of Hyperfiddle is on one side and maybe React, for example, on the other, readers find something familiar to them, React, and may find easier the parallelisms and advantages when directly comparing. The style of the contents seems leaned to convince technical people, the sauce of success may be more in finding ways for non-technical people to clearly see the benefits. A good measure for the viability is how many non-technically inclined people get it or not. For non-technical people the benefits tend to be two: money (while React pays can not change) and/or less work/easier (in which case will ask the technical people to losen up to change because it is easier). I guess Dustin is well aware, and simply the day only has 24 hours.

👍 4
🙂 2
pez10:03:00

I happen to know that the Electric Clojure team are eager to figure out how the project should be described. It is still a moving target, though, when it comes to a lot of implementation and Dx. That said, I haven't picked up that they are after the distributed computing use cases. It is more about making reactive programming work seamlessly and with extreme performance over the client/server barrier. Also, just to clear some of the confusion up, Electric Clojure and Hyperfiddle are different things.

🙏 2
Dustin Getz11:03:55

Ty for the feedback @U04T3JCE9GX! You're right and we're working on streamlined materials. I have @U0ETXRFEW’s ELI5 summary in front of me right now 🙂

Dustin Getz11:03:49

@U0PUGPSFR IIUC, Unison is not reactive which in my opinion is a huge mistake for the long term (you'd probably agree?). In the medium term it may see some success but I think ultimately it will be eclipsed by reactive paradigm which is more universal. I am not actually sure what Unison's killer app is. AFAIK all the cloud architectures map better to reactive graphs (kubernetes dependency orchestration, distributed processes, data workflows etc)

2
Dustin Getz11:03:48

> I haven't picked up that they are after the distributed computing use cases We have some hypotheses, Electric in theory is a distributed state management layer that turns AWS into a seamless data fabric, eclipsing kubernetes etc, but lets not get ahead of ourselves, history is filled with grand ambitions of dead projects

kennytilton13:03:50

Thx for the clarification, @U09K620SG. I just saw their contrast with "the idea that a program is a thing that describes what a single OS process does, on a single computer." and got to thinking about how Electric smooths over the awkward boundary between server and client.

Alejandro Buffery15:03:48

Thanksss Dustin. Currently on the Unison landing page is “Say where you want computations to run and it happens*”.* Behold, I am no expert, my understanding is that Unison is not reactive per se, but if the computation that is running and distributed is, then I guess reactivity is one of its possibilities. Unison is also focused on avoiding people producing and running code/test duplications via function signatures having a hash. That, or they are trying to get rid of half the devs around the World 😅 For me Unison and Electric have different scopes / possible use cases. Unison does not have, that I know, a killer app, they are working now on having a cloud microservice (see roadmap) Unison has a very easy+clear road map and has nice communication and materials that can be improved from some perspectives, but quite nice nevertheless. For the broad public they both have an Achilles heel, most people do not like (do not know? never introduced to? so foreign to FP?) Clojure and Haskell like language (sense of academic background) This I guess you have a feeling of from some feedback regarding syntax. So if Clojure be it, and for many many good reasons, I guess the saying “its not what you do but the way that you do it” is quite important to get across. A Typescript, Python, project could more easily get away with doing worse ‘the way that you do it’. For example Vue material is better than React material (currently improved), yet React gets away with it because it uses JS/TS. Those are just my two very naive cents, from some body that knows quiteee less, and seen toooo much 😅, put special effort/resources/heart into “the way”

👍 2
M J11:03:53

Im using a re-com selection list, any ideas how to target the checked items to give them a different class? I want list-group-item to have a different class when it is checked or selected..

[selection-list :src (at)
    :class (selection-list-style)
    :hide-border? true
    :model          selections
    :choices        multi-select-items
    :label-fn       :label
    :as-exclusions? false
    :multi-select?  (:allow_multiple settings)
    :disabled?      false
    :required?      false
    :parts {:list-group {:class (list-group-style)}
            :list-group-item {:class (list-group-item-style )} 
            :checkbox {:class (list-group-checkbox-style {:color (:buttons_color theme-data)})}
            :radio-button {:class (list-group-radio-btn-style {:color (:buttons_color theme-data)})}}
    :on-change      (fn [value]
                      (reset! selections value)

                      (reset! new-session false))]

pooriaTaj12:03:08

Hi , I have searched around for a while inorder to find a practical way to create List in clojure using java interop , But to no avail. Does any one know the syntax? Actually what I am trying to do is to use the .addAddress method of the ClientNetworkConfig of HazelCast , and it returns this error

class java.util.ArrayList cannot be cast to class [Ljava.lang.String; (java.util.ArrayList and [Ljava.lang.String; are in module java.base of loader 'bootstrap')

lispyclouds13:03:08

it seems the function youre trying to call takes a array of strings and not an arraylist. [Ljava.lang.String is the name for an array. the [L.

lispyclouds13:03:57

try (into-array String [your things])

j4m3s14:03:53

Hey there! I was wondering how I could do dispatch on executable name ? (`argv[0]` for those familiar with C). I have a use case that looks a bit like busybox which is a single binary and it dispatches based on the executable it's called with. 🙂 I googled this but haven't found in either java or clojure.

Alex Miller (Clojure team)14:03:52

isn't the executable always java?

j4m3s14:03:46

Well, if you compile with GraalVM's native-image, the exe name is not java (but probably is java wrapped ?)

j4m3s14:03:38

Otherwise, I would dispatch on the jar name

Alex Miller (Clojure team)14:03:51

in Java 9+, you can get the current process and it's info, which I presume could be used to get to this stuff

(.get (.command (.info (java.lang.ProcessHandle/current))))

Alex Miller (Clojure team)14:03:36

user=> (.get (.command (.info (java.lang.ProcessHandle/current))))
"/Users/alex.miller/.jenv/versions/openjdk64-11.0.13/bin/java"

j4m3s14:03:54

neat! That was exactly what I was looking for. Do you think it's gonna work differently on graal or it should be the same api-wise ?

Alex Miller (Clojure team)14:03:36

one way to find out! :)

j4m3s14:03:09

Haha will take a look at it. I'll try it out and get back to you with the results 🙂 Thanks for everything.

Eldath Ray15:03:39

Hi everyone. Just learned Clojure, such a beautiful language (compared to other LISP-s 😉 )! But I still miss those pattern matching features in other FP languages. I googled https://github.com/clojure/core.match which supposed to support matching on defrecord. But the following code didn't work:

(defrecord Ident [name])
=> user.Ident
(def id (->Ident "id"))
=> #'user/id
(match [id]
       [(Ident. name)] :ident)
Unexpected error (AssertionError) macroexpanding match at (/tmp/form-init5295265289282886137.clj:1:1).
Invalid list syntax name in (Ident. name). Valid syntax: [[:default :guard] [:or :default] [:default :only] [:default :seq] [:default :when] [:default :as] [:default :<<] [:default :clojure.core.match/vector]]
(match [id]
       [(->Ident name)] :ident)
Unexpected error (AssertionError) macroexpanding match at (/tmp/form-init5295265289282886137.clj:1:1).
Invalid list syntax name in (->Ident name). Valid syntax: [[:default :guard] [:or :default] [:default :only] [:default :seq] [:default :when] [:default :as] [:default :<<] [:default :clojure.core.match/vector]]
seems the syntax is correct according to https://github.com/clojure/core.match/wiki/Deftype-and-defrecord-matching. Am I misused the library, or this feature (matching on defrecord) has been retracted leaving an outdated document? Any suggestions are appreciated! 😺

andre15:03:39

I don't much about core.match, but pattern matching is not very common in Clojure. And neither are records... maps are preferred, usually. For some context, Rich talks a little bit about pattern matching https://gist.github.com/reborg/dc8b0c96c397a56668905e2767fd697f#why-no-pattern-matching. I don't want to hijack your thread and make this a records vs maps conversation since you asked specifically for core.match help, but glad to help if you want some suggestions on how to refactor this to use maps and maybe ditch core.match

José Javier Blanco Rivero16:03:53

Records are also maps, so ¿does this make sense for you?:

(match [id] [{:name (_ :guard string?)}] :ident)

pppaul17:03:06

do you specifically want to do pattern matching on records?

pppaul17:03:42

match documents are not out of date, the library hasn't changed much over the past 5-10 years. it's hard to tell what your pattern matching is trying to do, José thinks you want to use a guard, but you could also be trying to do a transformation (not as likely). you really have to read all of the wiki for basic usage, and be very careful about syntax, and even vary naming. don't name your symbols something that could be in the environment including clojure core names. I name all my symbols with "?" as first char, and I never use that style outside of pattern matching.

👍 2
pooriaTaj15:03:05

Hi i am trying to use the java library of hazelcast and hazelcast jet to write a pipeline Where I have problems is writing pipelines requires you to be able to write java lambda expressions Since clojure fns are not usable in this case I wonder if there is a work around to use lambda expressions

(-> (.readFrom hz-pipeline (TestSources/itemStream 10))
      (.withoutTimestamps)
      (.filter  (fn [x]
                  (odd? x)))
      (.setName "Filter odd numbers")
      (.writeTo (Sinks/logger)))

pooriaTaj15:03:23

; Execution error (IllegalArgumentException) at hermes.van-buren.positions.hazelcast.core/eval14584 (form-init7721897086252744905.clj:132).
; No matching method filter found taking 1 args for class com.hazelcast.jet.impl.pipeline.StreamStageImpl

pooriaTaj15:03:27

The error I receive is this

pooriaTaj15:03:54

I have looked into this for writing java lambda expressions but have no clue how to implement it

seancorfield16:03:44

@U02JS8BDHB9 Can you provide a link to the Hazelcast docs for this filter() method?

seancorfield16:03:55

You're likely going to need to reify whatever interface filter() is expecting and provide an implementation that way.

seancorfield17:03:42

Ah, so you'll need to reify com.hazelcast.function.PredicateEx and implement enough of the methods there that the .filter() call needs. Probably test() and testEx().

seancorfield17:03:39

I remember Hazelcast being kind of a PITA to work with from Clojure because it has so many custom types and doesn't rely on the modern Java stuff (the SAM stuff that hiredman mentioned in response to your cross-post to #C03S1KBA2)

seancorfield17:03:10

Ah, PredicateEx extends Predicate which is standard Java... So, yeah, try to implement just testEx() and test() and see if that's enough to satisfy filter().

seancorfield17:03:45

(reify com.hazelcast.function.PredicateEx (test [_ x] (odd? x)) (testEx [_ x] (odd? x)))
Something like that... I don't have the Hazelcast library to hand to verify whether that will be enough.

pooriaTaj19:03:54

Thanks , I have actually implemented test and its accepted by filter , but when submitted to the hazelcast cluster it results in this error

com.hazelcast.jet.JetException: Class containing the lambda probably missing from class path, did you add it using JobConfig.addClass()?: com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassCastException: cannot assign instance of java.lang.invoke.SerializedLambda to field com.hazelcast.jet.impl.pipeline.transform.MapTransform.mapFn of type com.hazelcast.function.FunctionEx in instance of com.hazelcast.jet.impl.pipeline.transform.MapTransform
        at com.hazelcast.jet.impl.util.ExceptionUtil.handleSerializedLambdaCce(ExceptionUtil.java:214)
        at com.hazelcast.jet.impl.execution.init.CustomClassLoadedObject.deserializeWithCustomClassLoader(CustomClassLoadedObject.java:68)
        at com.hazelcast.jet.impl.JobCoordinationService.deserializeJobDefinition(JobCoordinationService.java:1116)
        at com.hazelcast.jet.impl.JobCoordinationService.lambda$submitJob$2(JobCoordinationService.java:250)
        at com.hazelcast.jet.impl.JobCoordinationService.lambda$submitToCoordinatorThread$54(JobCoordinationService.java:1306)
        at com.hazelcast.jet.impl.JobCoordinationService.lambda$submitToCoordinatorThread$55(JobCoordinationService.java:1327)
        at com.hazelcast.internal.util.executor.CompletableFutureTask.run(CompletableFutureTask.java:64)
        at com.hazelcast.internal.util.executor.CachedExecutorServiceDelegate$Worker.run(CachedExecutorServiceDelegate.java:217)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:829)
        at com.hazelcast.internal.util.executor.HazelcastManagedThread.executeRun(HazelcastManagedThread.java:76)
        at com.hazelcast.internal.util.executor.HazelcastManagedThread.run(HazelcastManagedThread.java:102)
Caused by: com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassCastException: cannot assign instance of java.lang.invoke.SerializedLambda to field com.hazelcast.jet.impl.pipeline.transform.MapTransform.mapFn of type com.hazelcast.function.FunctionEx in instance of com.hazelcast.jet.impl.pipeline.transform.MapTransform
        at com.hazelcast.internal.serialization.impl.SerializationUtil.handleException(SerializationUtil.java:111)
        at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:277)
        at com.hazelcast.jet.impl.execution.init.CustomClassLoadedObject.deserializeWithCustomClassLoader(CustomClassLoadedObject.java:66)
        ... 11 more
Caused by: java.lang.ClassCastException: cannot assign instance of java.lang.invoke.SerializedLambda to field com.hazelcast.jet.impl.pipeline.transform.MapTransform.mapFn of type com.hazelcast.function.FunctionEx in instance of com.hazelcast.jet.impl.pipeline.transform.MapTransform
        at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2076)
        at java.base/java.io.ObjectStreamClass$FieldReflector.checkObjectFieldValueTypes(ObjectStreamClass.java:2039)
        at java.base/java.io.ObjectStreamClass.checkObjFieldValueTypes(ObjectStreamClass.java:1293)
        at java.base/java.io.ObjectInputStream.defaultCheckFieldValues(ObjectInputStream.java:2512)
        at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2419)
        at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
        at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:489)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:447)
        at java.base/java.util.ArrayList.readObject(ArrayList.java:929)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1046)
        at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2357)
        at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
        at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)

pooriaTaj19:03:56

at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:489)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:447)
        at java.base/java.util.HashMap.readObject(HashMap.java:1466)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1046)
        at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2357)
        at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
        at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
        at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2496)
        at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2390)
        at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
        at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:489)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:447)
        at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:92)
        at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:85)
        at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:44)
        at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:271)
        ... 12 more

23:00:15.155 [ WARN] [c.h.j.i.JobCoordinationService] [127.0.0.1]:5701 [dev] [5.2.2] null
com.hazelcast.jet.JetException: Class containing the lambda probably missing from class path, did you add it using JobConfig.addClass()?: com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassCastException: cannot assign instance of java.lang.invoke.SerializedLambda to field com.hazelcast.jet.impl.pipeline.transform.MapTransform.mapFn of type com.hazelcast.function.FunctionEx in instance of com.hazelcast.jet.impl.pipeline.transform.MapTransform
        at com.hazelcast.jet.impl.util.ExceptionUtil.handleSerializedLambdaCce(ExceptionUtil.java:214)
        at com.hazelcast.jet.impl.execution.init.CustomClassLoadedObject.deserializeWithCustomClassLoader(CustomClassLoadedObject.java:68)
        at com.hazelcast.jet.impl.JobCoordinationService.deserializeJobDefinition(JobCoordinationService.java:1116)
        at com.hazelcast.jet.impl.JobCoordinationService.lambda$submitJob$2(JobCoordinationService.java:250)
        at com.hazelcast.jet.impl.JobCoordinationService.lambda$submitToCoordinatorThread$54(JobCoordinationService.java:1306)
        at com.hazelcast.jet.impl.JobCoordinationService.lambda$submitToCoordinatorThread$55(JobCoordinationService.java:1327)
        at com.hazelcast.internal.util.executor.CompletableFutureTask.run(CompletableFutureTask.java:64)
        at com.hazelcast.internal.util.executor.CachedExecutorServiceDelegate$Worker.run(CachedExecutorServiceDelegate.java:217)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:829)
        at com.hazelcast.internal.util.executor.HazelcastManagedThread.executeRun(HazelcastManagedThread.java:76)
        at com.hazelcast.internal.util.executor.HazelcastManagedThread.run(HazelcastManagedThread.java:102)
Caused by: com.hazelcast.nio.serialization.HazelcastSerializationException: java.lang.ClassCastException: cannot assign instance of java.lang.invoke.SerializedLambda to field com.hazelcast.jet.impl.pipeline.transform.MapTransform.mapFn of type com.hazelcast.function.FunctionEx in instance of com.hazelcast.jet.impl.pipeline.transform.MapTransform
        at com.hazelcast.internal.serialization.impl.SerializationUtil.handleException(SerializationUtil.java:111)
        at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toObject(AbstractSerializationService.java:277)
        at com.hazelcast.jet.impl.execution.init.CustomClassLoadedObject.deserializeWithCustomClassLoader(CustomClassLoadedObject.java:66)
        ... 11 more
Caused by: java.lang.ClassCastException: cannot assign instance of java.lang.invoke.SerializedLambda to field com.hazelcast.jet.impl.pipeline.transform.MapTransform.mapFn of type com.hazelcast.function.FunctionEx in instance of com.hazelcast.jet.impl.pipeline.transform.MapTransform
        at java.base/java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2076)
        at java.base/java.io.ObjectStreamClass$FieldReflector.checkObjectFieldValueTypes(ObjectStreamClass.java:2039)
        at java.base/java.io.ObjectStreamClass.checkObjFieldValueTypes(ObjectStreamClass.java:1293)
        at java.base/java.io.ObjectInputStream.defaultCheckFieldValues(ObjectInputStream.java:2512)
        at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2419)
        at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
        at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:489)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:447)
        at java.base/java.util.ArrayList.readObject(ArrayList.java:929)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1046)
        at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2357)
        at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
        at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:489)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:447)
        at java.base/java.util.HashMap.readObject(HashMap.java:1466)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at java.base/java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1046)
        at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2357)
        at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
        at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
        at java.base/java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2496)
        at java.base/java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2390)
        at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2228)
        at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1687)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:489)
        at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:447)
        at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:92)
        at com.hazelcast.internal.serialization.impl.defaultserializers.JavaDefaultSerializers$JavaSerializer.read(JavaDefaultSerializers.java:85)
        at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.read(StreamSerializerAdapter.java:44)
        at com.hazelcast.intern

seancorfield19:03:48

Ah, now memories of using Hazelcast are coming back to me... Yeah, it requires these things to be serializable so you have to have an actual class -- you can't just use reify for things.

pooriaTaj19:03:02

So I reify and generate class in a separate namespace?

pooriaTaj19:03:17

and then instantiate that function type from that namespace

pooriaTaj19:03:40

I have seen this on github

(ns connectors.f01
  (:gen-class
    :implements [java.io.Serializable com.hazelcast.jet.function.DistributedFunction]))

(defn -apply [this input]
  (str input))

seancorfield19:03:33

Yeah, you end up with lots of :gen-class stuff and then you have to ensure it's AOT-compiled onto the classpath before running your own code. It gets pretty nasty.

pooriaTaj19:03:22

Ye i saw some use the compile function before actually passing the function in the pipeline

pooriaTaj19:03:19

Isn't there any easier solution then ? Maybe do some polyglot java and clojure stuff to cover prerequisite for passing fns into it?

pooriaTaj19:03:57

We are persistant on using clojure with hazel cast but if it's this much pain in the butt , I guess I'll have to convince my boss .

seancorfield19:03:10

What's painful is that you end up with a gen-class wrapper like that for each function of any sort you need to pass into Hazelcast code... I wonder if anyone has created a Hazelcast wrapper library that makes this easier? I don't think there was last I looked but there might be now. Yeah, writing these things in Java and calling into Clojure code via the Java API might also work.

pooriaTaj19:03:55

There was some stuff on github , something like a university project but was too specific. There is another library but its not much of a deal since it does not cover jet , and only hazel cast it self.

seancorfield19:03:51

Was this one of the blog posts you saw about hz/jet and Clojure? http://blog.hellonico.info/posts/clojure/jet/

pooriaTaj19:03:57

yes thats what I saw , but its too specific , I pretty much need to implement many of the transformers and aggregators and the mini types they require my self so it's not that much of a help anyways

seancorfield19:03:47

Was the runa-labs library one you looked at? It hasn't been updated for 9 years at this point (Runa has long since dissolved I think -- that was Amit Rathore's company, back when I got started with Clojure).

pooriaTaj19:03:53

There is another issue with hazel cast with clojure, but I don't know if its relevant to clojure . LSP servers break down when auto completing the class paths , there also seems to be a lot of mutual classes between different hazelcast packages like com.hazelcast.jet/hazelcast-jet-kafk

pooriaTaj19:03:17

with com.hazelcast/hazelcast-client or com.hazelcast/hazelcast it self

pooriaTaj19:03:46

And I have seen some inconsitencies with docs , some classes do not reside where the doc says they do like IMap

pooriaTaj19:03:20

I actually kept getting no class def found exceptions when using calva and vs code when I looked for auto complete path suggestions

pooriaTaj19:03:01

Yes I have checked runa labs

pooriaTaj19:03:22

but it was too deprecated to be usable , I think it worked with pre version 4 releases of hazelcast

seancorfield19:03:45

Yeah, I first encountered Hazelcast at a Bay Area Java meetup I used to attend (a decade ago!) and thought it might be excellent for some stuff at work but we abandoned it pretty quickly -- and now I'm remembering why! It was just too painful to use from Clojure 😕

pooriaTaj19:03:13

Damn , its a shame since it could fit together perfectly with clojure if there were a good library

pooriaTaj19:03:11

Thanks anyways though.

seancorfield19:03:11

I suspect someone could create a nice library that relied heavily on macros to generate code so you have stuff like (defpredicateex odd [x] (odd? x)) and have it produce all the gen-class code behind the scenes but I suspect there aren't many people trying to use Hazelcast with Clojure at this point...?

Casey Schultz15:03:34

Hey everybody, I'm very new to programming (1yoe) after a career change. I don't have a degree, but boot camped my way to a job. I was laid off recently and have been learning clojure in my new free time. I'm working through Clojure for the Brave and True. I would love suggestions on books or videos to help my learning! Also am I crazy for learning this with so little experience?

kennytilton16:03:36

Clojure is actually better for noobs than other languages. The consistency and simplicity make for a smaller skill set to be mastered before you can start coding in anger. Got a hobby project in mind? That to me is the key. Either way, have fun!

❤️ 8
Casey Schultz16:03:46

A good friend of mine and mentor is a clojurian and is building a reservation website. We will be working on that together. Then I'd like to explore a little pet project I've wanted to do for a while. Thanks for the input.

practicalli-johnny16:03:24

All my Clojure books and 100+ hours of video content is freely available (and continually improve upon) at https://practical.li/ Although if you are working on a project with a mentor, then I assume that will cover a lot

👍 4
❤️ 4
pppaul17:03:39

a general purpose programming language should never end up in the category of being crazy to learn, unless it's something like a joke language. even if you don't end up using clojure/lisp, having some knowledge as to what it's good at and bad at should help you. there are problems where lisp is near the best tool for the job, but problems don't generally tell you how they should be solved. so experience is good. though, I personally find that I need a problem to solve before I play around with tools. for books, SICP is one of the better books on learning about what lisp is good at, and rich hickeys YouTube videos on explaining clojure help show what clojure was originally very good at. (It's good at more things now)

❤️ 2
xbrln19:03:43

Getting clojure from Russ Olsen is a great first Clojure book !

👍 2
Δημήτριος Φκιαράς17:03:13

Hello, any help installing this library (https://github.com/Element84/clj-gdal#usage-) with leiningen? I added the clojars reference to my project but I am getting this error: “Syntax error compiling at (src/klv_emmiter/dsm.clj:1:1). namespace ‘gdal.band’ not found” when trying to evaluate the namespace form. Do I need to install java gdal package first?

seancorfield17:03:42

I just tried in a new project and got this error trying to (require 'gdal.band):

Native library load failed.
java.lang.UnsatisfiedLinkError: no gdalconstjni in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib
Syntax error (UnsatisfiedLinkError) compiling def at (band.clj:107:1).
'int org.gdal.gdalconst.gdalconstJNI.GDT_Unknown_get()'
so perhaps you're getting that error and that causes the error you reported?

❤️ 2
seancorfield17:03:31

Ah, per the README: • The Java library downloaded from Maven still requires that you have GDAL 2.x compiled on your system, as it references libraries which GDAL builds.

seancorfield17:03:59

So it sounds like you need to download/build the native libraries it is depending on...?

Δημήτριος Φκιαράς18:03:59

Thank you! I did read that, but got confused by the statement “Java GDAL 1.11 library (included)“.

Δημήτριος Φκιαράς18:03:50

That means that in every machine I want to run my project, I will have to install that library? Is there any way to pack it in my jar file?

seancorfield18:03:06

No idea what the license for the native stuff might allow or disallow.

❤️ 2
seancorfield18:03:18

I think that statement just means that the Java wrapper for the native stuff is included, but it doesn't distribute the native GDAL stuff (perhaps because it needs to be built specifically for various platforms, perhaps because the licensing is not compatible with distribution).

sheluchin17:03:47

Given a date, how can I get the boundaries of the date's week of the year?

Akiz19:03:24

Something like this?

(require '[clj-time.core :as t])
(let [date (t/now)
            day-no (dec (t/day-of-week date))]
        [(t/minus date (t/days day-no))
         (t/plus date (t/days (- 6 day-no)))])
=>
[#object[org.joda.time.DateTime 0x1db45f48 "2023-03-13T19:40:59.722Z"]
 #object[org.joda.time.DateTime 0x7c649799 "2023-03-19T19:40:59.722Z"]]

R.A. Porter20:03:21

Using just interop:

(let [today (LocalDate/now)]
  [(.with today ChronoField/DAY_OF_WEEK 1)
   (.with today ChronoField/DAY_OF_WEEK 7)])

sheluchin20:03:48

@UBRV1HXPD thank you, that's pretty straight forward to follow.

👍 2
sheluchin20:03:58

@U01GXCWSRMW could you explain that one a bit? Looks like a pretty elegant solution.

R.A. Porter20:03:55

It’s using the underlying Java time libraries - https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html And ChronField from java.time.temporal. It will, of course, only work if you’re running atop Java. Won’t work for Clojurescript, for example.

sheluchin20:03:29

@U01GXCWSRMW I find java.time very difficult to get familiar with. Not sure how to approach absorbing it. Every time I have to do something with it slightly outside the usual stuff, it's always a big time sink.

(require '[cljc.java-time.local-date :as ld])            
(require '[cljc.java-time.temporal.chrono-field :as cf]) 
(let [dt (ld/now)]                                       
  [(ld/with dt cf/day-of-week 1)                         
   (ld/with dt cf/day-of-week 7)])))                     
works nice; thanks!

R.A. Porter20:03:36

You might also look at tick. When I add a date/time library to my Clojure code, that’s always my preference. https://github.com/juxt/tick

2
sheluchin20:03:46

I'd prefer to learn java.time first but if I ever give up I'll try tick lol

Tyler Nisonoff21:03:35

Not sure if this falls in beginner, but I'm a beginner to AOT compilation! I recently had a prod application (that was AOT compiled) fail with:

...
Execution error (NoSuchFieldError) at clojure.tools.analyzer.jvm.utils__init/load (REPL:259).
__thunk__0__
The only change in this deploy was some package upgrades. It seems that clojure.tools.analyzer.jvm is being pulled in by core.async , so dont see any direct deps for it -- and im not using directly in my code But asking here because I'm at a bit of a loss of how to investigate it -- have not been able to repro by building the uberjar and running it locally.

hiredman21:03:13

at work we've dropped back to a previous core.async release before https://github.com/clojure/core.async/commit/1252c589fa2e43a8320c786b41e83d079e025bf2 (ASYNC-248)

Tyler Nisonoff21:03:34

wow would have had no idea!! Thank you so much

hiredman21:03:45

the other way to work around it, at least with core.async, is to require clojure.core.async.impl.ioc-macros somewhere early in your aot process, forcing it and its dependencies to aot compile before the expansion of the go macro would load it

Tyler Nisonoff21:03:23

and guessing not AOT compiling will work as well? considering just getting rid of AOT compilation

Tyler Nisonoff21:03:51

are you using 1.5.648 for core.async?

hiredman21:03:30

not aot compiling would I think also avoid it, but I am not 100% sure, I've only reproduced it with aot compilation

🎉 2
Alex Miller (Clojure team)22:03:03

fyi, I am working on this issue in the compiler

❤️ 4
phill00:03:38

I think the above bug link was intended to be https://clojure.atlassian.net/browse/ASYNC-249 (not 234)

👍 2