This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-07-03
Channels
- # aleph (3)
- # announcements (2)
- # babashka (24)
- # beginners (71)
- # biff (5)
- # calva (19)
- # cider (7)
- # clj-kondo (15)
- # cljdoc (3)
- # clojure (76)
- # clojure-australia (1)
- # clojure-china (1)
- # clojure-denver (24)
- # clojure-europe (56)
- # clojure-filipino (1)
- # clojure-hk (1)
- # clojure-indonesia (1)
- # clojure-japan (1)
- # clojure-korea (1)
- # clojure-my (1)
- # clojure-nl (1)
- # clojure-norway (37)
- # clojure-sg (1)
- # clojure-taiwan (1)
- # clojure-uk (6)
- # clojurescript (2)
- # cursive (2)
- # datalevin (71)
- # datomic (9)
- # dev-tooling (5)
- # emacs (19)
- # events (1)
- # gratitude (1)
- # hoplon (6)
- # introduce-yourself (5)
- # jobs (1)
- # juxt (2)
- # lsp (23)
- # nbb (26)
- # off-topic (12)
- # other-languages (97)
- # practicalli (2)
- # releases (2)
- # remote-jobs (1)
- # shadow-cljs (24)
- # tools-deps (17)
- # vim (2)
I have a few basic questions again. I have a vector of string integers which I want to convert into integers.
(map Integer. ("4" "8" "9")) ; This doesn't work
(map (fn [x] (Integer. x)) ("4" "8" "9")) ; This works
I am curious about what is "Integer." doing semantically and how does it work.
Also, what is the best way to convert string to integer in clojure?https://clojuredocs.org/clojure.core/int
;; Use Java interop instead
(Integer/parseInt "1")
;;=> 1
This didn't work for me btw. Also curious whyYou can't pass static methods as arguments to clojure functions (for now) But parse-long does what you need
Integer.
is a call to a Java method. Java methods are not first class, they cannot be passed as arguments or returned. Map takes a function as argument, and a Java method won't work, so you need to provide a function.
You can create a function that calls a Java method internally, this is your second approach, and that will work. But the Java method directly won't.
With Clojure interop, you can call Java methods, but that's all you can do with them, like I said, you cannot pass them as arguments or return them.
This is possibly going to change soon, as Clojure 1.12 is looking into a feature that will allow Java methods to become first class, and that would make your first example work as well, but until that feature makes it, for now, you cannot.
To parse integers in Clojure, in 1.11, some standard parsing methods were added: https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/parse-long and https://clojure.github.io/clojure/clojure.core-api.html#clojure.core/parse-double You should also know, in Clojure, all numbers are represented as longs by default, not as ints, similarly, all decimals are represented as double, not as floats. That's why it is parse-long, and there is no parse-int.
> I am curious about what is "Integer." doing semantically and how does it work.
Specifically, to that question. In Java, you have Objects, and you create an instance of an Object using a Constructor method.
The syntax to call a Java object constructor method in Clojure is: (ConstructorMethod. <params>)
, basically the name of the constructor method followed by a dot .
This is a shorthand syntax, the long form is: (new ConstructorMethod <params>)
You can learn more about interop with Java here: https://clojure.org/reference/java_interop
@U0K064KQV Thank you. This was very informative. However, I could not use parse-long.
(parse-long "5")
Syntax error compiling at (foreverclojure:localhost:36483(clj)*:816:22).
Unable to resolve symbol: parse-long in this context
Does on need to import something or am I doing something wrong?How can I bind an exception to *e? I have a try catch and I want to do it on catch block
You could use binding
to scope it, or set!
. I'm not sure if I'd recommend doing it, but it works in my limited experiments.
The binding for *e is setup in the outer repl code, and then inside the repl any exceptions on the repl thread that bubble up to the repl loop are handled by set! *e to the exception
The question is why would you want to set *e? It is just the mechanism by which the repl tracks the last exception it saw
Do if you have code that sets *e that code will throw an error when run without a binding setup for *e (which is the case outside of the repl) unless you explicitly setup your own binding for *e, which will get popped before control is returned to the repl loop if you are using it in the repl
I want to set *e so I can debug from repl an exception that was caught, I am currently creating an _e symbol to debug from repl every time I need it
Thought that using *e would make more sense since I want to debug from repl, that is where I run my whole application
if that is the case, and the exception is happens on a thread where *e is bound you can just set! it
if you find yourself constantly looking at some exception in the repl, maybe whatever that is shouldn't be an exception, it isn't exceptional
Maybe it's kinda out of scope but you can also rely on calling :ex using ClojureStorm.
Whenever I define records in cljs, the constructor functions(map->Name, Name.) stop being recognized on hot reload, other files can't seem to use their methods consistently, and I have to add type hints when I can. This is using vscode + shadow-cljs + calva. Any ideas as to what's causing this and how I can fix it?
most likely you are calling those functions from another namespace. consider adding a fibrin like new-name
or create-name
into the same namespace where you define a record. and call that function instead of generated.
This happens because during reload new objects represent a record got defined but other namespaces still using methods of the old one.
I'm not sure I follow, I need to create a function for each method of a record so they can be accessed in other namespaces? not sure if "fibrin" is a misspelling or something I'm not familiar with.
Also, sometimes before hot reload, after clear cache refresh, other namespaces won't recognize record methods even though I've required the record. So I feel like there may be something, or multiple things wrong here.
(ns example.primitives (:require [example.tools :refer [distance]])) (defrecord Sphere [position radius] (get-distance [this point] (- (distance this.position point) this.radius))) ;these all work in the namespace the record is declared ;and sometimes(before hot reload) in other files (def test-sphere (Sphere. [0 0 0] 1)) (def test-sphere-two (->Sphere [0 0 0] 1)) (def test-sphere-three (map->Sphere {:position [0 0 0] :radius 1})) (ns example.core (:require [example.shapes :refer [Sphere]])) (def spheres (mapv (fn [_] ;this works before hot reload, but doesn't after (Sphere. (vec (repeatedly 3 rand)) (rand))) (range 8))) (def sphere-distances (apply min (map (fn [sphere] ;but this often doesn't work before or after hot reload ;unless it's in the same file the record is declared ;".get-distance is not a function" (.get-distance ^Sphere sphere)) spheres)))
yeah, sorry, was typing from my phone. "fibrin" is misspelled "function" 🙂
(ns foo
(:require [bar :as b]))
(def common-name (b/map->Name {:val "John"}))
and another namespace where Name is defined
(ns bar)
(defrecord Name [value])
in that case when you change namespace bar
you will get a new Object representing Name with different map->Name
and ->Name
functions pointing to this new object.
Because namespace foo
isn't reloaded it is still uses old definition of the record Name
to fix that you can define common function new-name
in namespace bar:
(ns bar)
(defrecord Name [value])
(defn new-name [value]
(->Name value))
and use this function everywhere you need to define an instance of Name
from your snippet: I think most of the problems will go away if you will define functions with defn
instead of making global objects with def
the code doesn't seem right, you're missing an interface name before (get-distance ...
in your defrecord declaration. And you're applying get-distance to a sphere, when it takes a sphere and a point. Do you have compilation errors ?
I think this should work fine if you fix the bugs, but you can have problem with stale records/protocols if you're storing them in a state (defonce myatom (->Sphere [0 0 0] 1))
Hi all, I am using Java interop for the first time and I'm not fully sure what is going wrong in this test I am writing. I am using a library called Sudachi (see here: https://javadoc.io/doc/com.worksap.nlp/sudachi/latest/index.html). In it, there is an interface called Morpheme (https://javadoc.io/doc/com.worksap.nlp/sudachi/latest/com/worksap/nlp/sudachi/Morpheme.html) which has a method called surface() (here: https://javadoc.io/doc/com.worksap.nlp/sudachi/latest/com/worksap/nlp/sudachi/Morpheme.html).
I am writing a test for a function we wrote that takes in a string foo
and returns a lazy sequence of Morphemes with only the words in the string. I tried calling Morpheme/surface (.surface didn't work) on the list but I get the following error: "No matching method surface found taking 1 args for interface com.worksap.nlp.sudachi.Morpheme." I am also not sure the (import ...) here is necessary but I'm a bit confused. Any help appreciated!
Here is the part of the code that's relevant:
(Morpheme/surface %)
is calling a static method named surface from the class MorphemeHi thanks, I tried using .surface but I also get an error.
This time I get: Reference to field surface can't be resolved.
Yes I thought so too and I also tried using .surface, maybe I messed up syntax?
(is (= '["漢字" "いい"] (vector (map #(.surface %) (get-words words)))))) this is what I had for that part of the code
are you sure the version of the code you are using matches the version of the docs you are looking at
Let me check
Or rather: how can I check?
0.7.3 I believe?
I mean I pulled this from a git repo but I also installed 0.7.3 on my own system locally
So I assume it is correct, we just wrote this code
Just to check, I ran (type (get-words words)) and I get LazySeq
Reflection warning, /home/mayumin/Documents/Programming/Bunseki/test/bunseki/analyzer/word_test.clj:11:42 - reference to field surface can't be resolved.
Try (Morpheme/surface) In Javadoc it doesn't take an argument
...sudachi.MorphemeImpl
I just ran (type (first (get-words words)))
So if I do like lein test you mean?
Let me try
the above is not an error, it is a reflection warning, an optional thing you have to turn on to get reported to you, it is the compiler warning you that it doesn't know the types involved in the method call, so it is emitting reflective code which isn't the most efficient
AH, okay I think it is working properly then, thank you
I get a test failure but I think this may be due to me
Thank you so much, I was going crazy
Hey one more zip question here: how do you add a node at the end of a tree? For example
(-> (zip/vector-zip '[1 [2]])
(zip/next)
(zip/next)
(zip/next)
(zip/next)
(zip/prev)
(zip/insert-child 3) ;;#object[TypeError TypeError: Cannot read properties of null (reading 'cljs$core$IFn$_invoke$arity$1')]
)
I can't walk back either, because running zip/prev returns niliirc, what I've done in the past is if next
is end?
then do the insertion, otherwise go next
I managed to brute force the issue, although I don't think I should have had to:
(defn replace-node
"Catches the error you get when trying to replace the last node"
[loc node]
(-> (if (zip/end? loc)
(-> (zip/root loc)
(conj node)
(zip))
(zip/replace loc node))
(zip/root)))
@U013JFLRFS8 my codebase separates out the navigation to and operations on locs in different functions, I'd hate to bundle them together. But that makes sense. I just like the api of
( -> (go-to tree n)
(operate args)
(zip/root)
)
ofc the issue here is that it doesn't do what I'd expect for conj to do on seq, but that's how you learn I guess
you can break it up - the initial ask had them compounded, but going to the last node could be a separate thing - I think a discrepancy here is that if end?
is true, if I'm remembering things correctly, then the walk has proceeded past the last place to insert a node, and an insert will fail at that point, so for insert to succeed, I think zip/end?
has to be false
yea that makes sense and what I have above doesn't at all - it adds a child to the root instead of the last node. Here it is:
(defn crossover [t1 t2 n1 n2]
(let [p1a (go-to t1 n1)
p2a (go-to t2 n2)
p1 (if (zip/end? p1a) (go-to t1 (dec n1)))
p2 (if (zip/end? p2a) (go-to t2 (dec n2)))
replace #(-> (zip/replace %1 (zip/node %2)) (zip/root))]
[(replace p1 p2) (replace p2 p1)]))
> Nil
signifies an empty location, and there is no reference to the previous step in it. The zip/up
, zip/right
and other functions also return nil
for an empty location. If you iterate in a cycle and do not take this into account, you’ll just end up spinning your wheels.
>
(-> [1 2 3]
> zip/vector-zip
> zip/down
> zip/left
> zip/left
> zip/left
> zip/left)