Fork me on GitHub
#beginners
<
2022-05-05
>
kennytilton01:05:26

This simple deftype beginner, aspiring to using set!, starts with this:

(deftype Universe [^:unsynchronized-mutable answer])

(let [mr (Universe. 42)]
    (.-answer mr))
He does not get very far:
Execution error (IllegalArgumentException) at words.core/eval2046 (core.clj:2).
No matching field found: answer for class words.core.Universe
Same with (. mr -answer). That type hint seems like what The Google shows in various examples. The code works without the type hint, fwiw. Confused. 😕

ghadi01:05:14

when you make a field mutable, it's made private automatically @hiskennyness

ghadi01:05:46

can only access from within the deftype

kennytilton01:05:36

Oh, cool, I did see an example like that, but this example worked for me so I did not think it essential:

(let [object (java.awt.Point. 1 2)]
        (set! (. object  -y) 8)
        (bean object))
And now I see "...at which point (set! afield aval) will be supported in method bodies.", which does imply "exclusively". Missed that. 😊 Thx! 🙏

didibus02:05:05

It's different for Java objects, those could have public mutable properties that you can set

kennytilton02:05:26

Thx, @U0K064KQV! 🙏 These fault lines on The Interop Divide...if I was not working I would blog about this.

seancorfield03:05:45

Since that came from michalmarczyk I imagine this was done to make it easier for people to build alternative implementations of vectors. I wonder if it's used in core.rrb-vector?

🙌 1
seancorfield04:05:43

So you can ignore it unless you're implementing a new kind of vector type 🙂

NickName06:05:01

How do I provide void return type hint for a class method generated with :gen-class? I tried (defn InitDatabase ^void [] (load-initial-data)) but it gives me:

Syntax error (IllegalArgumentException) compiling fn* at (src/task02/Database.clj:13:1).
Only long and double primitives are supported

Ferdinand Beyer10:05:55

I might be missing something, but it seems to me you can’t, as in Clojure you will always return something, even it if is nil?

jkxyz11:05:07

You don't need to type hint the defn, you put the void return type in the method definition within the :gen-class at the top of the namespace: https://clojuredocs.org/clojure.core/ns#example-542692cac026201cdc326b76

NickName15:05:05

Oh, I thought directly typing methods was interchangeable with typing inside (ns … (:gen-class …)) . Anyway, compiler does not complain now so I guess it works 🙂 Thanks! I actually don't know whether it is even possible to have void signature for Clojure functions. Maybe it employs some tricks under the hood based on the presence of type hints.

James Amberger14:05:13

is there \a notation for the empty string?

1
delaguardo14:05:54

no, \a is a character literal. empty string is a string with zero characters

delaguardo14:05:30

(type \a) ;; => java.lang.Character

(type "") ;; => java.lang.String

1
James Amberger15:05:08

What’s the word on keywords like :1057229

James Amberger15:05:17

(why) should these be avoided?

1
danielneal15:05:49

heya, I think I”m making a silly mistake writing a transducer - getting a null pointer when I use (into [] xf coll) but (sequence xf coll) works ok. Any ideas what I’m getting wrong?

(defn take-between
  "A transducer that starts taking at start, and stops taking at end, inclusive"
  [& [opts]]
  (let [{:keys [start end]} opts]
    (fn [rf]
      (let [state (volatile! (if start nil :started))]
        (fn
          ([] (rf))
          ([result] (rf result))
          ([result input]
           (cond
             (and (nil? @state)
                  (= input start)) (do
                                     (vreset! state :started)
                                     (rf result input)) 
             (and (= @state :started)
                  (not= input end)) (rf result input)

             (and (= @state :started)
                  (= input end)) (do
                                   (rf result input)
                                   (reduced result)))))))))q

(sequence (take-between {:start :1-hours
                         :end :1-months}) [:1-minutes :1-hours :1-months :1-years])
'(:1-hours :1-months)

(into [] (take-between {:start :1-hours
                        :end :1-months}) [:1-minutes :1-hours :1-months :1-years])
;; Unhandled java.lang.NullPointerException conj! (result is nil)

Serafeim Papastefanos15:05:09

Let's suppose I've got a thing called foo. I'd like to use that to print the form preceding it.

danielneal15:05:11

oh do I maybe need to call (rf result) as the default case

oly15:05:15

Is there a way to work out what to import when using an existing java library ? I want to use com.microsoft.bingads/microsoft.bingads {:mvn/version "13.0.13"} importing it like so (:import com.microsoft.bingads.v13.campaignmanagement) I can see I have the library just not sure what the import should look like, probably a lack ok knowledge on the java maven ecosystem

ghadi16:05:47

you'll want to look up the java docs for that library

ghadi16:05:06

the important thing: com.microsoft.bingads/microsoft.bingads has nothing to do with the classes that you will import

ghadi16:05:36

you'll need to look up the docs to know the specific class names

ghadi16:05:44

they may or may not start with com.microsfot

oly07:05:52

Cheers figured it out in the end I was trying to import at a higher level as an alias which perhaps you cant do, importing via a full namespace path worked though

Serafeim Papastefanos15:05:53

Fe (+ x foo y) would print x and eval the expression

flowthing10:05:29

I guess it sort of depends on what you're trying to do. You do something along those lines, but I'm not sure whether it's possible to do in a way that meets your specific requirements. For example:

(def code '(+ x y foo z))
;;=> #'my.ns/code
(def x 1)
;;=> #'my.ns/x
(def y 2)
;;=> #'my.ns/y
(def ret (take-while #(not= % 'foo) code))
;;=> (+ x y)
(map eval (rest ret))
;;=> (1 2)
(eval ret)
;;=> 3
But I'm making a lot of guesses there. 🙂

🙌 1
Serafeim Papastefanos15:05:28

Is this somehow possible?

maverick16:05:17

While running mvn clean install on Clojurscript project getting error as Could not transfer artifact lein-cljsbuild:lein-cljsbuild:jar:1.1.7 from/to Internal nexus PKIX path building failed

James Amberger16:05:44

a little confused about general use of sets. If I try to use sets where order doesn’t matter in my domain logic, it seems there are lots things that give me back vectors. e.g.

(group-by count #{"dog" "cat" "lion" "bird"})
which of course gives
{3 ["dog" "cat"], 4 ["bird" "lion"]}
I don’t have a clear case where this screws me up, and I could of course map this back to sets, but…

delaguardo16:05:23

result usually explained in the docstrings https://clojuredocs.org/clojure.core/group-by for example:

The value at each key will be a vector of the
corresponding elements, in the order they appeared in coll.

hiredman16:05:06

very few collection functions (maybe just conj?) in clojure.core have the contract of give me an A and return an A

hiredman16:05:52

filter, map, mapcat, etc for example are all give me a seqable and return a seq

kennytilton16:05:41

Yep. Clojure code generally includes (a) processing wrapped in (b) a bit of code to get the result into the type desired for ongoing processing.

Ben Sless16:05:41

This is a personal opinion regarding group-by but I believe it's missing an arity for specifying the init and accumulator

James Amberger17:05:08

> very few collection functions (maybe just conj?) in clojure.core have the contract of give me an A and return an A True. I thought I understood why that is the way it is and why it is not bad. But now I’m like, ok then why bother with sets when as soon as you map/filter/etc one of them you’ll have a not-set?

hiredman17:05:43

sometimes you just want a set

hiredman17:05:06

I wrote a connection pool for redis at work, and it keeps connections in a set(I actually just changed it to a map, but ended up reverting it back to a set because the map stuff made things more robust but solved a problem we ended up not having), it never maps or filters over it

kennytilton17:05:16

If your application wants a set, for semantic reasons, give it a set. 🙂 One good use for sets, btw, is for use with some.

James Amberger17:05:59

I feel better about this now.

hiredman17:05:19

if you use map/filter/mapcat as transducers you can do A to A