Fork me on GitHub
#beginners
<
2020-12-09
>
st3fan03:12:00

Hmm unexpected … (clojure.set/subset? #{} #{:a :b}) => true

st3fan03:12:16

Is that something from set theory? Empty set is always a subset of another set?

dpsutton03:12:45

Ever element of it is in the other set

dpsutton03:12:20

It’s vacuously true. An easy way to think of it is to list a counter example. Name an element that is in the empty set that is not in your other set

seancorfield03:12:47

@st3fan empty sets of things often have surprising behavior at first glance. (and) ; true, (or) ; nil for example.

st3fan03:12:22

Interesting

seancorfield03:12:35

Similarly,

user=> (some some? [])
nil
user=> (every? some? [])
true

seancorfield03:12:57

The latter is often more surprising, given the docstring says "Returns true if (pred x) is logical true for every x in coll, else false." because no elements are logical true.

seancorfield03:12:38

And it can be confusing that (every? nil? []) is of course also true -- so every element is nil and not-nil at the same time 🙂

seancorfield03:12:45

But it is true because there are no elements in [] for which the predicate isn't "logical true".

Mark McWiggins05:12:18

Is there a way to evaluate a symbol to use as a keyword? For example, if I have '("A" "some data")

dpsutton05:12:41

can you give a literal example of what you want to accomplish? is some data a map with keywords and you have a string and you want to look up the value at that keyword entry?

Mark McWiggins05:12:11

Never mind I found it: (keyword (first '("A" "some data")) gives me what I want: A:

Old account07:12:59

Hi, What is the idiomatic way to convert :two-word keyword to Two Word strings?

Pavel Klavík08:12:48

You can also use this library for similar conversions: https://clj-commons.org/camel-snake-kebab/.

6
dpsutton07:12:38

str it, split on "-", map capitize, and then join it back together with a string

✔️ 3
dpsutton07:12:16

(->> (str/split (name :two-words) #"-") (map str/capitalize) (str/join " "))

dpsutton07:12:09

this often comes up when converting keywords into display items in a UI. You can probably create a better regex to match on underscores and some other common separators if applicable

Lyderic Dutillieux12:12:12

Hey guys, Why does : (first {:a 1, :z 2}) return [:a 1] (val (first {:a 1, :z 2})) return 1 BUT (val [:a 1]) throw a ClassCastException instead of returning 1 as the two statements above would suggest ?

Lyderic Dutillieux13:12:28

I guess it has to do with the underlying types (PersistentVector vs Map), But wouldn't it be more consistent to have val being equivalent to second in case of a vector with 2 elements ? Same thing for key and first

andy.fingerhut14:12:47

I believe (class (first {:a 1, :z 2}) is a MepEntry class, not PersistentVector, and that key and val have special behavior for MapEntry objects that they do not have for regular vectors.

andy.fingerhut14:12:55

MapEntry objects have a default printed representation that looks like a two-element vector, and I believe operations that you can do on a vector also work on a MapEntry, e.g. nth, first, second, assoc.

andy.fingerhut14:12:13

But the converse is not true -- some operations like key and val work on MapEntry, but not on vectors.

noisesmith19:12:57

it's kind of funny that this works

user=> (conj (first {:a 1}) :b)
[:a 1 :b]

noisesmith19:12:13

I think it auto-promotes to persistent vector

andy.fingerhut20:12:14

yes, many operations that work on persistent vectors also work on MapEntry, but return an object with class clojure.lang.PersistentVector, not clojure.lang.MapEntry.

chrisblom13:12:28

yes its because of the underlying types

chrisblom13:12:31

user=> (type (first {:a 1}))
clojure.lang.MapEntry
user=> (type [:a 1])
clojure.lang.PersistentVector

👍 3
chrisblom13:12:34

clojure has many examples where you can use a generic (second) or specific (val) function

chrisblom13:12:13

the specific functions are usually more performant

Chinmay Dalal16:12:45

i'm trying to get the sums of all possible pairs of numbers in a vector between i and i-25

(let [subv (subvec v (- i 25) i)
        a (transient [])]
    (for [b subv
          c subv
          :when (> c b)]
      (conj! a (+ b c)))
    (persistent! a))

Chinmay Dalal16:12:58

where v is the input vector

Chinmay Dalal16:12:12

why does this return an empty vector?

hiredman16:12:05

For is not a loop

hiredman16:12:33

That also isn't a correct usage of transients

hiredman16:12:04

That is "bashing in place"

Chinmay Dalal16:12:51

does that mean i have to use loop and handle indices manually?

dpsutton16:12:56

i think if you just use the for loop without the transient you have exactly what you want: a collection of (+ b c) when (> c b). you don't need to accumulate this into another collection if the for builds this collection in the first place

dpsutton16:12:41

you're building a collection and then for each element in that collection putting it into another collection. just use the first collection without the unnecessary extra collection

Chinmay Dalal16:12:27

cool, but now those sums are in vectors

Chinmay Dalal16:12:37

turns out i dont need a vector at all

Chinmay Dalal17:12:01

(let [subv (subvec v (- i 25) i)]
        
    (for [b subv
          c subv
          :when (> c b)]
      (+ b c)))
is enough

Chinmay Dalal17:12:34

it returns a list which i then turn into a vector

dpsutton17:12:00

you need random access to this collection?

dpsutton17:12:48

i'm wondering why you need a vector instead of the lazy sequence that is returned

Chinmay Dalal17:12:15

uhh idk actually

Chinmay Dalal17:12:31

i'll go forward with the list

roelof19:12:03

Im doing the clojure farm course and I cannot solve this problem

roelof19:12:06

(defn my_filter
  "filters a collection on a predicate"
  [collection predicate]
  (let [new_collection (seq collection)] 
     (for [element collection] 
          (if (predicate collection)
            (conj element new_collection)
            new_collection))
     new_collection)
; Syntax error compiling at (chapter4.clj:13:24).
; Unable to resolve symbol: collection in this context

roelof19:12:22

anyone here who can make this work

hiredman19:12:59

for is not a loop

dpsutton19:12:59

You’re also calling the predicate on the entire collection each time rather than the element

roelof19:12:56

oke, but why is collection not known in the let part ?

roelof19:12:26

@hiredman so I can better use recursion ? or another loop ?

hiredman19:12:03

hard to say

hiredman19:12:19

your code is missing a closing paren, so it doesn't run as is

hiredman19:12:35

but if I add a closing paren, I don't get an error

hiredman19:12:47

user=>
(defn my_filter
  "filters a collection on a predicate"
  [collection predicate]
  (let [new_collection (seq collection)]
     (for [element collection]
          (if (predicate collection)
            (conj element new_collection)
            new_collection))
     new_collection)


)
#'user/my_filter
user=>

roelof19:12:52

hmm, I still see a error :

; Syntax error (ClassNotFoundException) compiling at (output.calva-repl:51:22).
; Thread.java:834

hiredman19:12:05

that is not the same error

roelof19:12:26

yep, that is another one

hiredman19:12:27

what class does it say is not found?

roelof19:12:03

nope, I see only this :

; Syntax error (ClassNotFoundException) compiling at (output.calva-repl:51:22).
; Thread.java:834
clojure.lang.Compiler/analyze (Compiler.java:6808)
clojure.lang.Compiler$InvokeExpr/parse (Compiler.java:3820)
clojure.lang.Compiler/analyzeSeq (Compiler.java:7108)
clojure.lang.Compiler/analyze (Compiler.java:6789)
clojure.lang.Compiler$BodyExpr$Parser/parse (Compiler.java:6120)
clojure.lang.Compiler$FnMethod/parse (Compiler.java:5467)
clojure.lang.Compiler$FnExpr/parse (Compiler.java:4029)
clojure.lang.Compiler/analyzeSeq (Compiler.java:7104)
clojure.lang.Compiler/analyze (Compiler.java:6789)
clojure.lang.Compiler/eval (Compiler.java:7173)
clojure.core/eval (core.clj:3214)
clojure.core/eval (core.clj:3210)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:87)
clojure.core/apply (core.clj:665)
clojure.core/with-bindings* (core.clj:1973)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:87)
clojure.main/repl (main.clj:414)
clojure.main/repl (main.clj:435)
clojure.main/repl (main.clj:345)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:84)
nrepl.middleware.interruptible-eval/evaluate (interruptible_eval.clj:56)
nrepl.middleware.interruptible-eval/interruptible-eval (interruptible_eval.clj:152)
nrepl.middleware.session/session-exec (session.clj:202)
nrepl.middleware.session/session-exec (session.clj:201)
java.lang.Thread/run (Thread.java:834)

hiredman19:12:30

it isn't part of the stacktrace, it is part of the exception

roelof19:12:12

?? sorry this is my first step in clojure. What do you mean with look at *e

hiredman19:12:24

are you at a repl?

hiredman19:12:39

type in *e and hit enter

hiredman19:12:18

it will show a data representation of the last exception that bubbled up to the top of the repl loop

roelof19:12:32

then I see this :

clj::chapter4=> *e

#error {
 :cause "Thread.java:834"
 :via
 [{:type clojure.lang.Compiler$CompilerException
   :message "Syntax error compiling at (/home/roelof/clojure/Learning_in_public/ground_up/.calva/output-window/output.calva-repl:51:22)."
   :data #:clojure.error{:phase :compile-syntax-check, :line 51, :column 22, :source "/home/roelof/clojure/Learning_in_public/ground_up/.calva/output-window/output.calva-repl"}
   :at [clojure.lang.Compiler analyze "Compiler.java" 6808]}
  {:type java.lang.ClassNotFoundException
   :message "Thread.java:834"
   :at [java.net.URLClassLoader findClass "URLClassLoader.java" 471]}]
 :trace
 [[java.net.URLClassLoader findClass "URLClassLoader.java" 471]
  [clojure.lang.DynamicClassLoader findClass "DynamicClassLoader.java" 69]
  [java.lang.ClassLoader loadClass "ClassLoader.java" 589]
  [clojure.lang.DynamicClassLoader loadClass "DynamicClassLoader.java" 77]
  [java.lang.ClassLoader loadClass "ClassLoader.java" 522]
  [java.lang.Class forName0 "Class.java" -2]
  [java.lang.Class forName "Class.java" 398]
  [clojure.lang.RT classForName "RT.java" 2207]
  [clojure.lang.RT classForName "RT.java" 2216]
  [clojure.lang.Compiler resolveIn "Compiler.java" 7394]
  [clojure.lang.Compiler resolve "Compiler.java" 7357]
  [clojure.lang.Compiler analyzeSymbol "Compiler.java" 7318]
  [clojure.lang.Compiler analyze "Compiler.java" 6768]
  [clojure.lang.Compiler analyze "Compiler.java" 6745]
  [clojure.lang.Compiler$InvokeExpr parse "Compiler.java" 3820]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7108]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler analyze "Compiler.java" 6745]
  [clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6120]
  [clojure.lang.Compiler$FnMethod parse "Compiler.java" 5467]
  [clojure.lang.Compiler$FnExpr parse "Compiler.java" 4029]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7104]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler eval "Compiler.java" 7173]
  [clojure.lang.Compiler eval "Compiler.java" 7131]
  [clojure.core$eval invokeStatic "core.clj" 3214]
  [clojure.core$eval invoke "core.clj" 3210]
  [nrepl.middleware.interruptible_eval$evaluate$fn__964$fn__965 invoke "interruptible_eval.clj" 87]
  [clojure.lang.AFn applyToHelper "AFn.java" 152]
  [clojure.lang.AFn applyTo "AFn.java" 144]
  [clojure.core$apply invokeStatic "core.clj" 665]
  [clojure.core$with_bindings_STAR_ invokeStatic "core.clj" 1973]
  [clojure.core$with_bindings_STAR_ doInvoke "core.clj" 1973]
  [clojure.lang.RestFn invoke "RestFn.java" 425]
  [nrepl.middleware.interruptible_eval$evaluate$fn__964 invoke "interruptible_eval.clj" 87]
  [clojure.main$repl$read_eval_print__9068$fn__9071 invoke "main.clj" 414]
  [clojure.main$repl$read_eval_print__9068 invoke "main.clj" 414]
  [clojure.main$repl$fn__9077 invoke "main.clj" 435]
  [clojure.main$repl invokeStatic "main.clj" 435]
  [clojure.main$repl doInvoke "main.clj" 345]
  [clojure.lang.RestFn invoke "RestFn.java" 1523]
  [nrepl.middleware.interruptible_eval$evaluate invokeStatic "interruptible_eval.clj" 84]
  [nrepl.middleware.interruptible_eval$evaluate invoke "interruptible_eval.clj" 56]
  [nrepl.middleware.interruptible_eval$interruptible_eval$fn__995$fn__999 invoke "interruptible_eval.clj" 152]
  [clojure.lang.AFn run "AFn.java" 22]
  [nrepl.middleware.session$session_exec$main_loop__1062$fn__1066 invoke "session.clj" 202]
  [nrepl.middleware.session$session_exec$main_loop__1062 invoke "session.clj" 201]
  [clojure.lang.AFn run "AFn.java" 22]
  [java.lang.Thread run "Thread.java" 834]]}

hiredman19:12:38

which depending, may or may not be the same ClassNotFoundException

hiredman19:12:59

you have a random Thread.java:834 somewhere in the code you are trying to evaluate

hiredman19:12:30

which was part of earlier stacktrace, which is why I didn't recognize it as part of the error message

roelof19:12:56

he, I never uses Random anywhere as far as I know

roelof19:12:18

this is my code in the namespace

roelof19:12:24

(ns chapter4)

; Write a function to find out if a string is a palindrome–that is, if it looks
;  the same forwards and backwards.
(defn palindrome? 
  "checks if a string is a palingdrome"
  [word]
  (= (seq word) (reverse word) ))

(defn my_filter
  "filters a collection on a predicate"
  [collection predicate]
  (let [new_collection (seq collection)] 
     (for [element collection] 
          (if (predicate element)
            (conj element new_collection)
            new_collection))
     new_collection))
  

hiredman19:12:44

you are trying to run something else

hiredman19:12:58

maybe without realizing it you copied and pasted too much or something

roelof19:12:06

that can be

roelof19:12:43

I think so, because now I see the code compiling

hiredman19:12:49

because that error says the expression Thread.java:834 literal appears in your program, and for whatever reason clojure is trying to resolve it as a class, which it isn't, which is why you get the error

roelof19:12:07

now time to fin d out how I can make the predicate part in a call

roelof19:12:57

I give up

(my_filter [(1 2 3 4) (fn [x] (even? x))  ])
error :
; Execution error (ClassCastException) at chapter4/eval17683 (form-init1042520059576704410.clj:20).
; class java.lang.Long cannot be cast to class clojure.lang.IFn (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')

dpsutton19:12:49

(1 2 3 4) is calling 1 as a function on the arguments 2 3 4. The error message is saying that 1 a "java.lang.Long" can't be invoked (cast to clojure.lang.IFn)

roelof19:12:26

pff, that one needs to be a collection

dpsutton19:12:50

sure. but you're invoking it, not making a collection

dpsutton19:12:20

(+ 1 1) means invoke +. (1 2 3 4) similarly means invoke 1

roelof20:12:03

pff, how do I then make it a collection ?

noisesmith20:12:21

use [] instead

dpsutton20:12:34

maybe the easiest way is [1 2 3 4] making it a vector

noisesmith20:12:00

that's the normal way in clojure also

noisesmith20:12:18

there's also '(1 2 3 4) but that's a more limited approach

roelof20:12:54

oke, I give up on clojure . on the code that worked I see now suddenly

; Syntax error compiling at (chapter4.clj:10:1).
; Unable to resolve symbol: defn in this context

dpsutton20:12:38

often see this happen when you do (in-ns chapter4) before requiring it

roelof20:12:25

I only do crtl-alt-c crlt-alt-j

roelof20:12:16

thanks for the help butI do not like to fight the whole day against a compiler with error messages that makes no sense

Lars Nilsson20:12:19

For whatever it's worth, you are defining my_filter to take two arguments, collection and predicate, but you only try to pass one argument when you call it, a vector containing the collection and predicate. After fixing the syntax issue with [1 2 3 4] either use deconstruction in in my_filter, (defn my_filter [ [ collection predicate ] ] (...)) or pass the two parts separately as two different arguments.

noisesmith20:12:32

@roelof in-ns is only for debugging, in code it creates broken namespaces

noisesmith20:12:56

they are fixable, but the easier fix is to just not use in-ns

pez21:12:45

@roelof You need to load the file before things start to work. (`ctrl+alt enter` if using Calva).

pez21:12:26

I feel ya about the error messages. But otherwise I kinda like how I am in control of what is defined where, using Clojure.

fappy22:12:02

hi 🙂 I checked https://github.com/bbatsov/clojure-style-guide but didn’t find the following … what do you think about this as a suggestion? > Only return a literal true or false from the body of an if when you actually need a literal as a result and the if’s condition doesn’t already evaluate to a literal. > > Bad — if a truthy non-literal result works in your context: > (if (some pred coll) true false)

dpsutton22:12:42

i'm not sure i'm following. but that repo is open to issues with suggestions for new guidelines and will most likely get some feedback

seancorfield22:12:26

@fappy Better to say (boolean (some pred coll)) instead of if

🎯 6
Michaël Salihi22:12:51

Hi I wonder what's the best candidate in Clojure to ceate a loop like in this Java snippet:

public static Socket getListeningSocket() {
    for ( int port = MIN_PORT ; port <= MAX_PORT ; port++ )
    {
        try {
            ServerSocket s = new ServerSocket( port );
            return s;      // no exception means port was available
        } catch (IOException e) {
            // try the next port
        }
    }
    return null;   // port not found, perhaps throw exception?
}
for? loop?

Michaël Salihi22:12:19

How can I break on first success (first free port assigned)?

dpsutton22:12:49

loop requires a manual recur. recur in your catch and you'll stop on the first successful port

dpsutton22:12:49

ah sorry, can't recur from the catch. so just catch and return a sigil and check that against the sigil

Michaël Salihi22:12:52

Thx @dpsutton What is a "sigil"?

dpsutton22:12:36

some recognizable value that can't come from starting a server. can do (Object.) or ::bad

dpsutton22:12:43

here's an example that just uses nil as the sigil

Michaël Salihi09:12:20

Thanks @dpsutton, it's exactly what I needed! And TIL sigil too. 😉

Scott Starkey23:12:25

Hi community. I am trying to make a https://docs.oracle.com/javase/7/docs/api/javax/swing/filechooser/FileNameExtensionFilter.html with Java interop. This is what I’m doing:

(ns filter.core
(:import (javax.swing.filechooser FileNameExtensionFilter))
....
(def fnef (FileNameExtensionFilter. "CSV files", "csv"))
However, I’m getting the following error message:
Cannot cast java.lang.String to [Ljava.lang.String;
Can someone please tell me what I’m doing wrong? I’m a bit flummoxed! 😩

dpsutton23:12:42

https://clojure.org/reference/java_interop#_vararg_methods that constructor uses varargs: FileNameExtensionFilter(String description, String... extensions)

dpsutton23:12:43

you need to make the array that is used

dpsutton23:12:10

(javax.swing.filechooser.FileNameExtensionFilter. "CSV files" (into-array String ["csv"]))

seancorfield23:12:16

Ah, I see you cross-posted this in #interop as well. We prefer folks not cross-post questions since it can waste people's time replying in one channel, not realizing someone else has already helped you in another channel.

Scott Starkey23:12:05

I’ll delete there.

3
Scott Starkey23:12:12

Thanks for your help!

seancorfield23:12:04

(saved you the trouble -- I deleted your Q and my responses from there @UH0FTE610)

Scott Starkey23:12:31

Great, thanks. Sorry for the faux pas, @U04V70XH6

seancorfield23:12:45

The variadic interop catches folks out all the time. No worries!

st3fan23:12:53

Given [1 2 3 4 5] how do I generate [1 2] [2 3] [3 4] [4 5] ? - Is there a convenience function for this?

nate23:12:25

(partition 2 1 [1 2 3 4 5])

👍 12
st3fan23:12:22

(I think I finally have all the pieces for Day 7 of Advent of Code)