Fork me on GitHub
#beginners
<
2020-05-25
>
radicalmatt02:05:06

I'm interested in playing around with compile a bit, but in my repl I am finding that I need to modify the "java.class.path" system property so the namespace I want to pass to compile can be found. How can I add my src folder to the classpath inside my repl session?

dpsutton02:05:40

the src directory should be on the classpath by default unless you have manually set a different set of paths. in lein it will be :src-paths ["src"] and in deps.edn it will be :paths ["src"]

radicalmatt02:05:05

I'm just messing around in the repl, not using a lein project

radicalmatt02:05:48

do I need to explicitly source that deps.edn file when starting a repl?

dpsutton02:05:49

{:paths ["src" "classes"]} needs to be in a deps.edn. and check (doc compile)

dpsutton02:05:09

not sure what "source" means here. but you should run clj from a directory with that deps.edn file yes

radicalmatt02:05:07

I was using clojure and not clj which I guess caused the deps.edn to not be picked up

dpsutton02:05:01

i don't believe that's your issue. here's the source of clj:

~/p/a/acl ❯❯❯ cat (which clj)
#!/usr/bin/env bash

if type -p rlwrap >/dev/null 2>&1; then
  exec rlwrap -r -q '\"' -b "(){}[],^%#@\";:'" clojure "[email protected]"
else
  echo "Please install rlwrap for command editing or use \"clojure\" instead."
  exit 1
fi

dpsutton02:05:31

which is almost incomprehensible to me but the important pieces are exec rlwrap ... clojure "[email protected]"

radicalmatt02:05:22

I actually at the same time (in order to actually get clj) removed the aptitude installed clojure I had and opted for the direct install from the clojure site - that bumped the version as well :shrug:

dpsutton02:05:47

ohh. i think that package is a very old and not what you want clojure 🙂

factorhengineering04:05:16

Hey there. Quick question. If I want to write a program that locks out a lot of buttons on the keyboard, and even mouse or touchpad presses (this is for a program for a very young child), is that even doable in CLJS, or should I use Clojure? I would really rather learn CLJS since other things I want to write in the future would benefit from that language.

factorhengineering04:05:44

Is there a standard way of turning a CLJS program into a desktop executable? I think I've heard of Electron or something that wraps a JS program into a desktop app, and I think Atom is a text editor that is written in JS and uses just that to become a desktop app...but is there something more straightforward for CLJS?

krzyzowiec04:05:21

@factorhengineering Not really, although there is another option. You could just write a web app that works from the browser. You'll be able to disable any key presses you like, and just enable a "kiosk mode", either through a https://addons.mozilla.org/en-US/firefox/addon/modern-kiosk/ or https://thegeekpage.com/how-to-setup-chrome-kiosk-mode-in-windows-10/. I think that would be the simplest approach. Otherwise you would probably need to look at Electron or doing JavaFX in Clojure.

krzyzowiec04:05:36

Now that I check, there are some https://github.com/Gonzih/cljs-electron on github. I'd say the browser-based approach would be easiest, but up to you ofc.

factorhengineering04:05:43

@krzyzowiec Oooh. Kiosk mode. Sounds interesting. I will have to look into that.

factorhengineering05:05:26

I wouldn't need to reject the three-finger salute, just single keys and whatever combinations a couple of baby hands could bang out.

seancorfield05:05:59

(we had a cat that manually dialed 9-1-1 on a speaker phone so don't underestimate what damage a baby can do 🙂 )

factorhengineering05:05:14

@krzyzowiec I just looked up Firefox Kiosk mode and apparently it's easy to launch (and you do so with the target address specified), though you can't simple toggle into it from an already-running firefox.

factorhengineering05:05:23

and you need to Alt-F4 to exit.

krzyzowiec05:05:36

Oh neat, didn’t know firefox had it built-in too. Yeah I would go that route just to avoid adding another layer of stuff to deal with.

factorhengineering05:05:52

Great tip. I think I would be out of luck with it to block the Windows key though. 😕

krzyzowiec05:05:06

Yeah you couldn’t do that with a browser alone. I haven’t used Windows in a long time, but I’d imagine you would need some third party software or registry tweaks for that.

factorhengineering05:05:17

That's getting complicated. Maybe I should make that program #2 on my list instead of #1, and let it be the reason I try Clojure after getting the CLJS program done.

krzyzowiec05:05:01

Easy to turn off/on. I remember using stuff like this back when I was gaming on Windows.

krzyzowiec05:05:48

Sure that makes sense.

krzyzowiec05:05:44

Although you’d probably have similar issues babyproofing a native app. You’d probably want to use the Windows kiosk mode instead.

factorhengineering05:05:16

Cool. I would be sending this to my sister who also has a young'un too, though. Don't really want to make her 'adjust' her computer. 😉

sergey.larionov07:05:57

Hello, can somebody help me to find a good way to do a search please? I have a list of pairs `(def input ((-10 -9) (-10 -8) (-10 -7)))` and I have a function `(defn calculate [input] ... )`. And I want to find a pair which when passed to the `calculate` function will return result `X`. Only thing that comes to mind right now is to make a function that woud apply  calculated on a pair and return both the pair and the result and then search over that

dpsutton07:05:07

(filter (fn [pair] (= X (apply calculate pair))) pairs) will give you the ones that satisfy that. you can then take the first of that

ordnungswidrig07:05:35

Or e.g. (-> (map #(apply calculate %)) (filter #{X}))

ordnungswidrig07:05:56

apply takes the args as a list and calls the functions with these args. (filter #{X})` takes advantage from the fact, that a set (created with the #{x y z} syntax) is a function that evaluates to true of called with a member element.

sergey.larionov08:05:31

@dpsutton @ordnungswidrig Thanks! Exactly what I was looking for

sergey.larionov09:05:13

(println (first (filter (fn [pair] (= X (apply calculate pair))) all-input))) if all-input is lazy-seq will it run calculate for each of all-input or will drop out on the first found?

jason35810:05:17

It's usually faster to test this in REPL than to ask and wait for the answer:

user=> (println (first (filter odd? (iterate inc 0))))
1
nil
user=>

didibus10:05:19

It'll stop after the first it find

sergey.larionov10:05:05

Yeah I got it from the @ answer, sorry for the lazy question

allaboutthatmace178910:05:44

The docs for empty? say to use seq for checking if something is not empty. I get why this is better than (not (empty ,,,)) , but are there situations when you would want to use seq over the more descriptive not-empty (which is (when (seq coll) coll) - i.e. the same but also preserves the collection type)?

joshua.mcquistan13:05:20

I'm thinking about which I would use and I think it would depend on the context of the surrounding code. Whichever would increase readability. My default would be to use not-empty but if I cared more about it being a sequence then I'd use that

steiner304413:05:56

hello,everyone. I'm learning java stream now,and I want to use stream like clojure,but I meet someting I can't understand,can somebody check my code? here is my clojure code

(reduce (fn [r x]
                     (assoc r x
                            (inc (get r x 0)))) {} (range 0 99))
here is my java code
Map<Integer,Integer> m = Stream.iterate(1,x->x+1).limit(100).reduce(new HashMap<Integer,Integer>(),(r,x)->{
		int count = Optional.ofNullable(r.get(x)).orElse(0) + 1;
		r.put(x,count);
		// later delete return
		return r;
	    });
and then,throw many errors:sweat_smile:

steiner304413:05:56

hello,everyone. I'm learning java stream now,and I want to use stream like clojure,but I meet someting I can't understand,can somebody check my code? here is my clojure code

(reduce (fn [r x]
                     (assoc r x
                            (inc (get r x 0)))) {} (range 0 99))
here is my java code
Map<Integer,Integer> m = Stream.iterate(1,x->x+1).limit(100).reduce(new HashMap<Integer,Integer>(),(r,x)->{
		int count = Optional.ofNullable(r.get(x)).orElse(0) + 1;
		r.put(x,count);
		// later delete return
		return r;
	    });
and then,throw many errors:sweat_smile:

didibus18:05:08

It works for me

didibus18:05:11

What error do you get

didibus18:05:41

Wait, do you mean the Clojure version doesn't work or the Java one?

cdimara23:05:20

It seems like there are methods to do everything you need.

cdimara23:05:27

You just have to keep googling to figure out how to do it.

cdimara23:05:27

Also keep types out of it as much as possible. Let java do the type work for you if it can.

cdimara23:05:57

also: there's a clojure function to count distinct things in a collection: frequencies https://clojuredocs.org/clojure.core/frequencies

steiner304400:05:44

@ can you show me your code and your openjdk version?

didibus00:05:11

Sorry I didn't try the Java one. I meant the Clojure code worked for me.

steiner304401:05:33

can you try it? here is the code

import static java.lang.System.out;
import java.util.stream.*;
import java.util.stream.Collectors;
import static java.util.stream.Collectors.reducing;
import java.util.Optional;
import java.util.List;
import java.util.Arrays;
import java.util.Map;
import java.util.HashMap;
import static java.util.Arrays.asList;

class Main {
    public static void main(String[] args) {
	// test reduce with lambda

	Map<Integer,Integer> res = new HashMap<>();
	Map<Integer,Integer> map = Stream.iterate(1,x->x+1).limit(100).reduce(res,(m,x)-> {
		int count = Optional.ofNullable(m.get(x)).orElse(0) + 1;
		m.put(x,count);
		return m;
	    });


    }

}

didibus01:05:19

I did not try the Java code. I just tried this:

(reduce (fn [r x]
          (assoc r x
                 (inc (get r x 0)))) {} (range 0 99))

phil63419:05:09

To my great excitement, I just found the cl-format function. I assuming I'm confident with Common Lisp formatting, is there any reason not to use it?

phil63419:05:12

Context is porting and then refactoring some simple text games from Common Lisp, noughts and cross and stuff like that, as a learning exercise.

alexmiller19:05:36

No reason. There are a few features not implemented but it’s pretty close I think

didibus19:05:32

I love cl-format 😋. I've been wanting to take a jab at adding the missing features but never did also cant sign the CA so :man-shrugging:

didibus19:05:18

I also thought it be nice to extend on it to support associative as input as well. Though that would be going beyond what cl supports I believe.

didibus19:05:10

I think all it's missing is allowing arbitrary functions in the format.

phil63406:05:46

OK cool thanks 🙂

scotto21:05:38

Hi there, folks - I’m struggling with a sticky wicket of the map function. I have a couple of functions that work well, but I need to massage the data to get what I want.

(defn all-keys-scored [state]
  (map #(key-scoring state %) [:p :g :o])
  )
(all-keys-scored data1)
=> (-1.7277318877806633 -1.1886085959005304 1.621003101827997)
But what I’d really like to have is something like:
(all-keys-scored data1)
=> {:p -1.7277318877806633, :g -1.1886085959005304, :o 1.621003101827997)
Can someone please give me a kick in the right direction? 😎

smith.adriane21:05:09

maybe something like:

(defn all-keys-scored [state]
  (into {} (map (juxt identity #(key-scoring state %)))  [:p :g :o]))
;; or
(defn all-keys-scored [state]
  (into {} (map #(do [% (key-scoring state %)]))  [:p :g :o]))

scotto21:05:16

Oh, I hadn’t thought of wrapping it in a do.

smith.adriane21:05:48

i’m not sure it’s a good idea, but i do it sometimes and I’m not sure it’s a bad idea ¯\(ツ)

scotto21:05:19

Honestly, I’d like to get the key result out of the max of this series, so I’ll be doing the following to the result: (key (apply max-key val ... ))

smith.adriane21:05:22

you could also do:

(defn all-keys-scored [state]
  (into {} (map #(vector % (key-scoring state %)))  [:p :g :o]))

smith.adriane21:05:18

if you only care about the max value, I might consider using some sort of reduce

smith.adriane21:05:40

which may be what max-key does

scotto21:05:50

OK, I’m just going with

(defn all-keys-scored [state]
  (key (apply max-key val (into {} (map #(vector % (key-scoring state %))) [:p :g :o])))
  )
… and calling it a day. Thanks @!

factorhengineering23:05:07

@dpsutton Hey. Hope you're around to see this. I finally just finished all the steps in your https://github.com/dpsutton/asg-ignite-presentation/blob/master/shadow-cljs.org

factorhengineering23:05:31

(after a lot of detours to learn Emacs things)

factorhengineering23:05:52

but I see nothing when I point a browser at http://localhost:3000/

factorhengineering23:05:50

I also got of whole lot of dependency updating (maybe because it was the first time I've run anthing like this?), and "Build completed. (158 files, 157 compiled, 2 warnings, 35.92s)"

factorhengineering23:05:54

and the following errors:

factorhengineering23:05:11

------ WARNING #1 - :undeclared-ns --------------------------------------------- File: [...]\src\app\main.cljs:12:4 -------------------------------------------------------------------------------- 9 | [:h1 "hi"]])(ns app.main) 10 | 11 | (defn ^:dev/after-load start [] 12 | (r/render [app] ----------^--------------------------------------------------------------------- No such namespace: r, could not locate r.cljs, r.cljc, or JavaScript source providing "r" -------------------------------------------------------------------------------- 13 | (.getElementById js/document "app"))) 14 | 15 | (defn ^:export init 16 | [] --------------------------------------------------------------------------------

factorhengineering23:05:37

------ WARNING #2 - :undeclared-var -------------------------------------------- File: [...]\src\app\main.cljs:12:4 -------------------------------------------------------------------------------- 9 | [:h1 "hi"]])(ns app.main) 10 | 11 | (defn ^:dev/after-load start [] 12 | (r/render [app] ----------^--------------------------------------------------------------------- Use of undeclared Var r/render -------------------------------------------------------------------------------- 13 | (.getElementById js/document "app"))) 14 | 15 | (defn ^:export init 16 | [] --------------------------------------------------------------------------------

seancorfield23:05:04

@factorhengineering Line 9 in that file looks wrong.

seancorfield23:05:32

Also, if that is really your ns form, you are not requiring whatever that r alias is supposed to be.

seancorfield23:05:10

What are the first nine lines of app\main.clj?

factorhengineering23:05:05

That was it! Somehow '(ns app.main)' got stuck on the end of that line. Strange.

factorhengineering23:05:33

My browser now says hi. It's been a journey to this point. Thanks.

factorhengineering23:05:49

Now I can finally start tinkering... 😄

factorhengineering23:05:15

I wish it had complained about line 9 instead of line 12 in those warning messages!

factorhengineering23:05:07

Is it normal for cmd to never give me my cursor back after running that?

factorhengineering23:05:19

must have to Ctrl-c it?

wls23:05:37

I have what I suspect is a very basic namespace issue, and I can't seem to make headway. Either I can't get a fully qualified var name to resolve, meaning it wants a :require in my (ns ...). Or, I get a Cyclic load dependency. Basically, I've got a low-level module that does socket I/O, and I've got a high level module that does application stuff. So each module needs to know about the other, and the code works fine if I jam everything into one name space, though it makes no functional sense to do so. Conceptually:

(ns xyzzy.low-level ...)

; Invoked when socket activity happens -- need to let the high-level know
(defn invoked-by-some-callback [packet] (xyzzy.high-level/please-handle-this (decode packet)))

(defn send-packet-to-client [packet] ...mechanisms to push bits out over a socket... )


(ns xyzzy.high-level ...)

(defn please-handle-this [map] ...does something application related... )

; Something needs to be told to the client -- have the low-level do it
(defn letTheClientKnow [foo] (xyzzy.low-level/send-packet-to-client (encode foo)))
Ideally, because I want to call out the tight-coupling, I'd like to use the fully qualified names. I'd be okay with even using :refer to grab just the method I need. And it'd be great to keep all low-level things together, and all high-level things together. My first false (?) assumption was that namespaces just kept names apart, each modules would be "compiled", and a runtime all the symbols would be resolvable; I suspect there's more to the story.

dpsutton23:05:41

Your terminal will keep running a program until it’s done. Which command are your running?

dpsutton23:05:09

@wls often a handler is passed in and invoked on each socket message

wls23:05:34

@dpsutton - Digging a little deeper, I'm accepting a pile of websocket connections; these have a handler attached (much like you suggest). And that's working, I can use it to examine the packet contents, etc. But now I want to act on the contents of the packet, calling the higher level code. This creates a conflict, if the higher level module wants to hand data to the low-level for distribution back to a client. So the call sequence is: 1) Socket sends. 2) Callback fires. 3) Can dispatch to higher level. 4) Higher level makes some decision. 5) Higher level wants to send message back. 6) Higher goes to invoke low-level call... except I never get this far because each namespace "includes" the other (which I know is wrong). Any docs / blogs / or Google-queries you might suggest?

dpsutton00:05:39

It should be simple to write out to the socket the response from your handler

wls00:05:50

I think we're talking past each other. If I put all the code in the same namespace, everything works. Sockets, handler, application, you name it. What I'm trying to do now is better organize all those functions, putting similar things into their own name spaces. That's where the problem is happening.

wls00:05:24

There's something I'm not groking about the the way the name spaces work. I figure it simply would be to prevent naming collisions, say with third party libraries. So all I'm trying to do is bring into scope something from one name space into another and vice-versa. But things are acting like it's "including" the files (I know that's not what's happening). At the moment, I'm trying to make a third namespace where I can put the common stuff... this isn't ideal, but I want to see if it helps me understand the problem better. I also thought (erronously?) that you could always specify a full name space whether you refered / used it or not. e.g., I can do Java interop like

(java.util.UUID/randomUUID)
without any issue. So I'm confused why my own classes don't work the same way. Like I said, I'm missing something very basic in my education.

wls00:05:14

(for anyone else jumping in and following along): I've just spoken with several developers who found parallels in the way NodeJS and Java imports works for similar cross-dependencies. The idea seems to be that it's not just module A and module B, but the cross-boundary logic should go into module C. It's a different way of looking at the design, and (in theory) it turns the circular dependency into a tree. While this may mean re-thinking some function names, it looks like a way out of this hole.

dpsutton23:05:17

This way neither knows of the other

dpsutton23:05:24

And one place composes the two together