Fork me on GitHub
#beginners
<
2021-07-02
>
vinurs03:07:55

hello, i hava a java file in src/java/vinurs/utils named http://hellojava.java and in lein project.clj i set :java-source-paths ["src/java"] :prep-tasks ["javac" "compile"] in my src/clj/app/core.clj i import it (:import (vinurs.utils HelloJava)) then when i in shell run lein repl, it output

Caused by: java.lang.ClassNotFoundException: vinurs.utils.HelloJava
then i have to comment the import (:import (vinurs.utils HelloJava)) in core.clj then run lein repl, this time it compile the java file to .class this time i restore the import , then run lein repl it works ok

vinurs03:07:55

everytime i add a java file, i should do like this? comment the import?then lein javac, then import it?

hiredman03:07:05

It is because of the order of your prep tasks

vinurs03:07:57

@hiredman how to resolve this problem?

Pradeep B03:07:37

maybe by moving :prep-tasks first in the sequence.

hiredman03:07:40

No, sorry, I was misremembering but my guess is you have an issue like what is described here https://github.com/technomancy/leiningen/blob/master/doc/MIXED_PROJECTS.md#interleaving-compilation-steps

vinurs03:07:26

thanks, this is what i need

olaf08:07:48

Cljs+Reagent. A simple menu div that append an event listener to the document and decide if the document click is inside or outside the component. I expect the handler to be called first, but the output is "second" and then "first". Why? Is caused from the re-rendering that add the component on-click listener multiple times?

(defn menu [mouse-pos]
  (r/with-let [!menu-ref (atom nil)
               handler   (fn [evt]
                           (console-log "first")
                           (when (and @!menu-ref
                                      (not (.contains @!menu-ref
                                                      (.-target evt))))
                             (console-log "outside")))
               _         (.addEventListener js/document "click" handler)]
    [:div.UI-menu {:style {:top  (:y mouse-pos)
                           :left (:x mouse-pos)}
                   :ref #(reset! !menu-ref %)
                   :on-click #(console-log "second")}
     "Adjust Diameter"]
    (finally
      (.removeEventListener js/document "click" handler))))

lepistane10:07:33

Hello, i've got general question about security. So i have a website and i would like traffic to be encrypted/hidden even for the client. Basically web app will know how to de-crypt it. I've never done this, i never heard about this, i dont think this is practice. Basically i want website to be usable but all traffic that it receives is hidden/unreadable/encrypted Is there a way for this to be done?

delaguardo10:07:01

Typically using https protocol should be enough.

dgb2310:07:47

I was thinking of https too but: > So i have a website and i would like traffic to be encrypted/hidden even for the client.

dgb2310:07:58

makes me suspcious

dgb2310:07:20

Either the client can read the data or not. A web application is open to the client.

lepistane11:07:49

Yeah that makes sense. Like even if i do some voodoo JS functions that will decrypt that voodoo are still available for reading. Oki guys thanks

Apple11:07:59

what's the point of communication, perhaps you mean client(human) cannot read but client(program) can read?

dgb2311:07:09

@UP82LQR9N that would have been the idea it seems. However, simply not sending the data they shouldnt be able to read is the only robust solution and is typically less work than trying to obfuscate. The visibility (authorization) logic has to live somewhere anyways.

lepistane12:07:23

weirdly i just want client to see the data they way i present it but not be able to read the data from response in json.

lepistane12:07:33

maybe obfuscate route is the way to go since authorization is solved. client won't see what i don't want him to see, but i want him to see data only via website if he calls api directly to receive jiberish that only website can read

lepistane12:07:26

hopefully it makes sense what i am asking

dgb2312:07:14

well you can use something like messagepack or some other binary format. but those things wont help if they are technically adept. a CSRF token can at least give you some control over who can read from your API. I guess if you are just worried about cosmetics, then just put your stuff into a binary format, they typically have some good performance characteristics too.

lepistane13:07:57

makes sense, thanks

noisesmith17:07:22

in terms of security, the client has full access to the js vm, and controls that vm implementation, there's nothing you can do that actually hides anything reliably in client code

noisesmith17:07:39

obfuscation is possible but can't be relied on

max minoS11:07:51

I'm trying to multiply all digits in a number together (e.g. 729 => 7 2 9), and so far I have

(->> digits
    str
    seq
    (map Integer/parseInt)
    (reduce *))
but I see that I cant do those functions to a sequence, which returns (\7 \2 \9), what does this mean?

tws11:07:00

those are literal chars. try doing (map #(Character/getNumericValue %) s)) instead

tws11:07:44

also, you don’t need to seq a string. they have that abstraction on them already.

👍 4
max minoS11:07:51

is the Character/ a default library that I can always call without requiring?

pithyless11:07:14

Integer and Character are both classes from java.lang (which is available by default in CLJ)

pithyless11:07:59

there's also a different way of splitting a string you should be aware of:

user=> (seq (str 123))
(\1 \2 \3)

user=> (clojure.string/split (str 123) #"")
["1" "2" "3"]

pithyless11:07:54

In the first example you get back java Characters (the slashes are the giveaway); in the latter you get back strings (where you can then call Integer/parseInt )

max minoS12:07:27

thank you so much, I've used the clojure.string/split before but I seq being used a lot when I google so I thought it might be better

pithyless12:07:40

The two are semantically different (and both have their place). When you split a string, you're saying split this one string into a collection of smaller, disjoint strings. When you seq you are iterating over a sequence (iterating over a string returns it's characters one-by-one).

pithyless12:07:44

I think Brave Clojure probably gives a much better explanation :) https://www.braveclojure.com/core-functions-in-depth/

🙏 4
noisesmith17:07:05

seq is called implicitly many places in clojure, including map and reduce

noisesmith17:07:27

user=> (map str "hello")
("h" "e" "l" "l" "o")

noisesmith17:07:42

> you don’t need to seq a string. they have that abstraction on them already @U1Z392WMQ almost - any clojure.core sequential function calls seq for you

noisesmith17:07:25

usually, you only need to call seq in your own code when using interop with something outside clojure, or when you need the behavior of empty meaning nil which means false

👍 2
practicalli-john13:07:30

I have a project that will use AWS Dynamo to hold some key-value pairs, so wondering what recommendations people had on using it from Clojure. The value can be a string and I guess I can map between a keyword and what ever AWS Dynamo uses. https://github.com/Taoensso/faraday seems to be a common choice to access the AWS Dynamo API It seems pretty straightforward. Any thumbs up for this approach or other alternatives people have found useful. Thank you.

bigos15:07:08

I use clj to create a library jar. how do I use that jar in and based java project?

bigos15:07:52

i tried to copy generated jar but do not know how to use it on java side. the documentation is a bit confusing

alexmiller15:07:54

Java only runs bytecode, so you need some hook into compiled Clojure. there are several ways to do this:

alexmiller15:07:38

• pre-compile your Clojure code into bytecode with classes with static methods, then call into those • use the https://clojure.github.io/clojure/javadoc/clojure/java/api/Clojure.html to start the Clojure runtime, load vars, and invoke them (compiles dynamically from Clojure source) • other variants of the above, but those are the most common

bigos15:07:56

i do not understand such vague details, my apologies. i use deps.edn https://github.com/bigos/Pyrulis/blob/master/Clojure/deps.edn

bigos15:07:17

clj -X:jar :jar csvreport.jar

bigos15:07:54

then i copy the jar file to the libs folder of netbeand based project and add the jar in netbeans properties

bigos15:07:23

i do not know how to import the code and use it on java side

bigos15:07:14

you say precompile clojure into bytecode

bigos15:07:40

looking into the jar file doe not show similar content to other java jars

bigos15:07:52

it just contins raw clojure files

alexmiller15:07:54

yeah, if you read the depstar docs, you need to AOT compile the jar as well by specifying :compile-ns etc

alexmiller15:07:56

what code do you want to run?

bigos15:07:58

i want to run simple clojure hello world and point it on java side

bigos15:07:28

I have noticed the deps.edn that i follow has changed, should I update it?

alexmiller15:07:31

sorry, don't know the answer to that

alexmiller15:07:59

what existing function do you want to run? I'm trying to be less vague for you

bigos15:07:22

thank you for being honest 🙂 it is complex and requires patience

bigos15:07:05

i have updated deps.edn and will try compiling again keeping your suggestions in mind. I may have more specific questions later

bigos15:07:39

(ns sgs.lidlcsvreport) (defn foo "I don't do a whole lot." [x] (prn x "Hello, World!"))

bigos15:07:03

this is my clojure code that i want run on java side

bigos15:07:31

hopefully it will let me escape from the insanity of java type system

alexmiller16:07:02

if you don't want to aot compile, you can use the Clojure Java API to load and compile this on the fly

bigos16:07:55

[email protected]:~$ clj --help| grep Version Version: 1.10.1.727 [email protected]:~$ java -version java version "1.8.0_162" Java(TM) SE Runtime Environment (build 1.8.0_162-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.162-b12, mixed mode)

bigos16:07:15

for the old java i use, which one is better?

alexmiller16:07:17

import clojure.java.api.Clojure;
import clojure.lang.IFn;
...

// (require 'sgs.lidlcsvreport)
IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read("sgs.lidlcsvreport"));

// (sgs.lidlcsvreport/foo "HI")
IFn foo = Clojure.var("sgs.lidlcsvreport", "foo");
foo.invoke("HI");

alexmiller16:07:38

on the Java, doesn't matter, anything ≥ Java 1.8 is fine

alexmiller16:07:05

(that version is pretty old and missing a lot of security fixes though fyi)

bigos16:07:27

there is nothing I can do about the decade of compromise 🙂

bigos16:07:48

hopefully, it that works we can gradually make progress

bigos16:07:13

if I import clojure, how do I add clojure to the project?

bigos16:07:54

i can copy a jar file in the project lib folder and add the jar to project proprties

alexmiller16:07:16

if I understood correctly, you're building an uber jar that will include clojure

bigos16:07:44

ah, so how do i import that uberjar into clojure?

alexmiller16:07:27

an uberjar is the code from a project + all the code from its dependencies. in this case, the dependency includes clojure (which is just pulled in as a library)

alexmiller16:07:43

so the uberjar you build in your project includes your project's code and clojure itself

alexmiller16:07:28

if you did need to include clojure, it's on Maven Central like everything else - groupId= org.clojure, artifactId = clojure, latest version = 1.10.3

bigos16:07:41

clj -X:uberjar :jar ./lidlcsvreport.jar :main-class sgs.lidlcsvreport

bigos16:07:27

now the sgs has 'lidlcsvreport$fn__140.class' lidlcsvreport.clj 'lidlcsvreport$foo.class' lidlcsvreport__init.class 'lidlcsvreport$loading__6738__auto____138.class'

bigos16:07:06

how do i import that on java side

alexmiller16:07:58

the code I posted above

bigos16:07:27

i will try it, we are on something because java ide tries to be helpful about the package

bigos16:07:19

ide complains saying class interface or enum expected

alexmiller16:07:57

are the Clojure classes in your jar?

alexmiller16:07:19

if not, then you have a jar, not an uberjar and you will need to include Clojure as a dependency

bigos16:07:09

clj -X:uberjar :jar ./lidlcsvreport.jar :main-class sgs.lidlcsvreport i have tried that, what options i am missing

bigos16:07:22

the project deps.edn has alias for deploy

bigos16:07:29

should i try that?

alexmiller16:07:55

I don’t think so

alexmiller16:07:11

Sorry, I need to step away for a bit

bigos16:07:51

no problem 🙂

bigos16:07:17

import clojure.java.api.Clojure; now ide says it is unused import

bigos16:07:44

IFn require = Clojure.var("clojure.core", "require"); has the error

bigos16:07:52

IFn require = Clojure.var("clojure.core", "require");

bigos16:07:21

code compiles

bigos16:07:31

import clojure.java.api.Clojure; import clojure.lang.IFn; import sgs.lidlcsvreport$foo;

bigos16:07:52

what do I do about the foo?

bigos16:07:46

i think I am making progress now. than you very much for your help

hiredman17:07:27

what you do about the foo is you remove the import, use Clojure.var to reference it like alex has above

Yosevu Kilonzo18:07:57

Hello! Is there an idiomatic way to thread data through converging functions similar to https://ramdajs.com/docs/#converge?

// JavaScript

const data = { a: 3, b: 4 }

pipe(
  converge(add, [prop('a'), prop('b')]),
  fn2,
  fn3
)
This is what I have:
(+ (:a data) (:b data)) // 7
And I want to do something like:
;; Clojure

(def data {:a 3 :b 4})

(-> data
    (something :a :b +)
    fn2
    fn3)

indy19:07:11

Something like (apply converge-fn ((juxt f g h) input))

dpsutton19:07:47

(defn something [x fns f] (apply f ((juxt fns) x))

3
noisesmith15:07:38

that should be (apply juxt fns) in there I think

dpsutton15:07:21

Ah yeah. Good point

Yosevu Kilonzo19:07:33

Ah, thanks indy and dpsutton. I'll experiment with that!

sova-soars-the-sora19:07:44

apply and juxt seem to be super powerful

tws20:07:36

how do people perform benchmarking?

tws20:07:16

I see

Aliases in the deps.edn file can also be used to add optional dependencies that affect the classpath:

{:aliases
 {:bench {:extra-deps {criterium/criterium {:mvn/version "0.4.4"}}}}}
Here the :bench alias is used to add an extra dependency, namely the criterium benchmarking library.

You can add this dependency to your classpath by adding the :bench alias to modify the dependency resolution: clj -A:bench.
from https://clojure.org/guides/deps_and_cli but do you just run clj -A:bench and do stuff from a repl? Not sure how to integrate this from my REPL driven approach. right now it seems easier to require criterium and have some rich comment forms. (using CIDER/emacs)

seancorfield20:07:49

Yes, criterium's README should show examples of how to run from a REPL -- which you could do from a Rich Comment Form in a source file.

seancorfield20:07:21

(! 738)-> clj -A:bench
Downloading: criterium/criterium/maven-metadata.xml from clojars
Clojure 1.10.3
user=> (require '[criterium.core :refer [bench quick-bench]])
nil
user=> (bench (reduce + (range 10000)))

seancorfield20:07:36

(time passes)

Evaluation count : 549420 in 60 samples of 9157 calls.
             Execution time mean : 107.444260 µs
    Execution time std-deviation : 5.941988 µs
   Execution time lower quantile : 101.784873 µs ( 2.5%)
   Execution time upper quantile : 125.506758 µs (97.5%)
                   Overhead used : 8.115184 ns

Found 6 outliers in 60 samples (10.0000 %)
	low-severe	 2 (3.3333 %)
	low-mild	 4 (6.6667 %)
 Variance from outliers : 40.1884 % Variance is moderately inflated by outliers

phronmophobic20:07:17

I've found the clojure-goes-fast blog posts generally helpful, http://clojure-goes-fast.com/blog/

tws20:07:46

sorry, @U04V70XH6 i wasn’t clear. i know how to do it, but my execution feels clunky, so wondering how others run any periodic benchmarks.

tws20:07:28

thanks, I’ll stick with RCF for now.

seancorfield20:07:51

Yup, RCFs in the code is how I'd deal with this.

tws20:07:27

is it weird to have criterium in your deps.edn :deps if it’s only used for RCF? Or is there another way to get it on the classpath?

ghadi20:07:48

put it in an alias and add the alias when you are developing or benchmarking

3
seancorfield20:07:59

I think a lot of folks have a :dev alias that adds in all sorts of dev-only tooling (Polylith encourages that approach: :dev for dev-only stuff, :test for test-only stuff, so you start your REPL with clj -A:dev:test or similar)

greg20:07:42

It looks like it is possible to have a multi-arity anonymous function. How to call anonymous fn with 1 arg from the one with no args?

(defn fun []
  (fn 
    ([] :call-anon-with-random)
    ([x] {:x x})))

; expected:
((fun))    ; => {:x :random}
((fun) :A) ; => {:x :A}

alexmiller20:07:56

I think you mean def there (or you don't need the fn part)

greg20:07:25

This is simplified example, I want to use higher-order function and create a (fn) with optional argument

alexmiller20:07:43

there is no magic here - if you want to invoke a thing, you either need the instance or a name to refer to it

alexmiller20:07:26

you can use & to make optional arguments and then parse the args and handle both cases

phronmophobic20:07:36

What about?

(def fun
  (fn my-fn
    ([] (my-fn :random))
    ([x] {:x x})))

(fun) ;; {:x :random}
(fun 42) ;; {:x 42}
(my-fn) ;; Unable to resolve symbol: my-fn in this context

👍 3
greg20:07:54

this is it

simple_smile 3
greg21:07:05

actually I realised that I can call defn from another defn as well

(defn fun []
  (defn anon
    ([] (anon :random))
    ([x] {:x x})))
but yours way is better. I didn't know that fn can have a name 😄

😁 3
tws21:07:18

defn is just shorthand or the long-form fn invocation. ps. that’s a first for me, seeing a todo in the source.

Clojure 1.10.3
user=> (source defn)
(def
...
defn (fn defn [&form &env name & fdecl]
...
;;todo - restore propagation of fn name
...

Elias Elfarri21:07:13

Hello, I need help with using the chestnut template. I've been able to develope in re-frame and cljs with figwheel and i wanted to take it a step further and try to connect it to some sort of backend. So i setup a chestnut project, how ever i am very unexperienced with compojure/ring and everything todo with server side stuff. So i really need help with setting up extra routes with compojure in said environment. There is a route.clj that has the following code in it:

(defn home-routes [endpoint]
  (routes
   (GET "/" _
     (-> "public/index.html"
         io/resource
         io/input-stream
         response
         (assoc :headers {"Content-Type" "text/html; charset=utf-8"})))
   (resources "/")))
I would like to add extra routes to it and thought that i could just do that by adding another GET just like this:

Elias Elfarri21:07:28

(defn home-routes [endpoint]
  (routes
   (GET "/" _
     (-> "public/index.html"
         io/resource
         io/input-stream
         response
         (assoc :headers {"Content-Type" "text/html; charset=utf-8"})))
   (GET "/bar" [] ("Please Work"))
   (resources "/")))
But this, does unfortunately not work. Does anyone here know why or what i am doing wrong here? I basically want to be able to access a link "localhost:10555/bar", but nothing really shows up when i do this.

sova-soars-the-sora21:07:02

Hi @moelfarri good job so far. You need to return a "ring response map" from your server which takes the form

{:status 200
 :headers {"Content-Type" "text/html"}
 :body "Your string or HTML here."
}
In the GET above yours that works already, you can see it is threading together index.html and a function called response and associating into that map the key :headers You can rearrange this a bit so it's more convenient to write new routes. There is a defroutes macro that you can use to define new routes rather than operating each one as a new io/resource. Let me see if I can find a brief example for you.

sova-soars-the-sora21:07:23

This page might help (and hopefully not confuse you) https://github.com/ring-clojure/ring/wiki/Concepts#requests This page about using Compojure ought to be very helpful to you @moelfarri https://learnxinyminutes.com/docs/compojure/

Elias Elfarri10:07:14

Thank you for the response!! I'll take a look at the material 🙂