Fork me on GitHub
#beginners
<
2020-01-10
>
Greg Jennings00:01:02

Hi everyone, I’m trying to do a very simple tutorial and I’m not sure why this is giving me a compile error. Sorry for the stupid question

(ns tutorial.core
  (:require [clojure.string :as str])
  (:gen-class))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (def str1 "This is a string")  
  (str/blank? str1)
)

Greg Jennings00:01:13

This yields the error: Syntax error compiling at (core.clj:9:3). No such namespace: str

Greg Jennings00:01:02

but this works:

(ns tutorial.core
  (:require [clojure.string :as str]) 
  (:gen-class))

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (def str1 "This is my second string")  
  (clojure.string/blank? str1) 
  )

Greg Jennings00:01:22

sorry for the stupid beginner question

noisesmith00:01:58

an aside: def inside defn doesn't do what you probably think it does - it creates a new global at namespace scope

noisesmith00:01:11

it doesn't create a binding that's local to that function

fappy00:01:25

use a let instead (still as part of the aside)

noisesmith00:01:12

for the error of str namespace not being found, there has to be something else going on, the code is correct aside from the def usage

Greg Jennings00:01:53

so, thanks for that. Interestingly when I tried switching def to let, I got this: (let str1 "This is a string") => Syntax error macroexpanding clojure.core/let as core.clj:7:3).

noisesmith00:01:19

(let [str1 "This is a string"] (str/blank? str1))

noisesmith00:01:31

let has explicit scope based on its parens

Greg Jennings00:01:33

is my clojure setup corrupted or something I wonder. I’m using VSCode and Calva on a mac

noisesmith00:01:22

@greg024 I would assume more likely user error in the IDE, you can verify without any of the tooling by running clj path/to/file.clj in a terminal

Greg Jennings00:01:35

ah sorry - that worked, but the other Unresolved namespace str. Are you missing a require? still persists

noisesmith01:01:11

that sounds like some reset / error clearing is needed via your IDE UI

noisesmith01:01:48

I assume there's a channel for Calva / vscode users here

Greg Jennings01:01:55

yep, this indeed does run fine (I’m using lein so I did lein run on the project):

(ns tutorial.core
  (:require [clojure.string :as str]) 
  (:gen-class))

(defn -main
  [& args]
  (println (str/blank? "str1"))
)

Greg Jennings01:01:14

it must be something with my vscode setup. Thanks!

hiredman02:01:24

You likely are try to evaluate the definition of -main without having evaluated the ns declaration above

hindol05:01:03

Exactly. I get this error all the time if I forget to evaluate the ns expression. In Calva, Ctrl + Alt + Enter evaluates the whole file (Windows/Linux).

johnj05:01:04

How do I load/require an in-memory namespace?

seancorfield06:01:18

@lockdown- Not quite sure what you're asking. If a namespace has been required, it will be in memory. Do you mean "How do I reload a namespace from disk?"

johnj06:01:57

I mean a ns with no file, like after (create-ns 'foo)

seancorfield06:01:36

Hmm, never seen anyone call create-ns to be honest, but you can just refer to its content via its name...

seancorfield06:01:07

...so if you have added any Vars to it, you can just say foo/some-var to refer to some-var in that foo namespace.

seancorfield06:01:27

You can also use alias to add a local alias to an in-memory namespace.

seancorfield06:01:33

Example:

user=> (in-ns 'foo)
#object[clojure.lang.Namespace 0x1bb9aa43 "foo"]
foo=> (clojure.core/refer 'clojure.core)
nil
foo=> (defn bar [n] (* n n ))
#'foo/bar
foo=> (in-ns 'user)
#object[clojure.lang.Namespace 0x2e52fb3e "user"]
user=> (foo/bar 4)
16
user=> (alias 'f 'foo)
nil
user=> (f/bar 5)
25
user=>
(you don't need create-ns since in-ns auto-creates it -- but it's "empty" -- it doesn't even have clojure.core stuff in it, so we need to refer in the core functions to make it easier to define stuff in the ns)

noisesmith18:01:21

there's a special case so that you can always run (refer-clojure) even in a namespace where clojure.core isn't referred oops I need coffee, just tested and this does not actually work in 1.10.1

seancorfield18:01:26

(! 1096)-> clj
Clojure 1.10.1
user=> (in-ns 'foo.bar)
#object[clojure.lang.Namespace 0x17ca8b92 "foo.bar"]
foo.bar=> (clojure.core/refer-clojure)
nil
foo.bar=> (defn quux [n] (* n n))
#'foo.bar/quux
foo.bar=> (in-ns 'user)
#object[clojure.lang.Namespace 0x377008df "user"]
user=> (foo.bar/quux 4)
16
user=> (alias 'f 'foo.bar)
nil
user=> (f/quux 5)
25
user=> 
^ @U051SS2EU?

seancorfield18:01:13

(since clojure.core isn't referred into the ns, you need to qualify that call to refer-clojure as I did above for the call to refer)

noisesmith18:01:21

right, clojure.core/refer-clojure alwasy work, as clojure.core is always loaded

noisesmith18:01:45

but I thought there was a special case for refer-clojure to work

johnj06:01:18

yes, very much thanks, you cleared my confusion

hiredman06:01:40

If you use intern you can add things to your namespace created with create-ns, but have names resolved using whatever the current space is

johnj06:01:14

ah, was looking for that, the idea was to create the ns without switching to it, hence create-ns instead of in-ns

seancorfield06:01:45

Ah, yeah, I forgot about interning into other nses...

seancorfield06:01:32

user=> (create-ns 'foo)
#object[clojure.lang.Namespace 0x1bb9aa43 "foo"]
user=> (intern 'foo 'bar (fn [n] (* n n )))
#'foo/bar
user=> (foo/bar 4)
16
user=> (alias 'f 'foo)
nil
user=> (f/bar 5)
25
user=>
@lockdown- There's a revised REPL session 🙂

Ho0man14:01:00

Hi everyone, Can anyone help me with this? Why do I keep getting :

Reflection warning, stellar/single_runner/components/state/ref/transition.clj:140:3 - call to method submit on java.util.concurrent.ExecutorService can't be resolved (argument types: unknown).
for this piece of code :
(defn resp-handler
  [state db om
   ^java.util.concurrent.ExecutorService pool
   ^java.util.concurrent.ExecutorService db-pool]
  (async/go-loop []
    (try
      (let [cid (otocol/<-client-id om)]
        (when-let [{r-cid :client-id :as resp}
                   (async/<! (otocol/<-resp-ch om))]
          (if (= r-cid cid)
            (.submit
             ^java.util.concurrent.ExecutorService pool
             ^Callable (fn []
                         (handle-resp-on-start
                          state db om resp db-pool)))
            (.submit
             ^java.util.concurrent.ExecutorService db-pool
             ^Callable (fn []
                         (opdb/->response db resp))))))
      (catch Exception e
        (throw
         (ex-info "resp-handler"
                  {:cause e
                   :params {:state state}}))))
    (recur)))
Thanks a lot

Alex Miller (Clojure team)14:01:54

those Callable type hints probably aren't getting applied

Alex Miller (Clojure team)14:01:38

but if you pull them up to let locals and then type-hint the local reference, that will work

Alex Miller (Clojure team)14:01:59

(let [handle-resp (fn [] (handle-resp-on-start ...))]
   ...
   (.submit pool ^Callable handle-resp))

Ho0man19:01:01

Sorry, Alex But even after changing it to

(defn resp-handler
  [state db om
   ^java.util.concurrent.ExecutorService pool
   ^java.util.concurrent.ExecutorService db-pool]
  (async/go-loop []
    (try
      (let [cid (otocol/<-client-id om)]

        (when-let [{r-cid :client-id :as resp}
                   (async/<! (otocol/<-resp-ch om))]
          (let [resp-handler (fn []
                               (handle-resp-on-start
                                state db om resp db-pool))
                stray-resp-handler (fn []
                                     (opdb/->response db resp))]
            (if (= r-cid cid)
              (.submit pool    ^Callable resp-handler)
              (.submit db-pool ^Callable stray-resp-handler)))))
      (catch Exception e
        (throw
         (ex-info "resp-handler"
                  {:cause e
                   :params {:state state}}))))
    (recur)))
I still get the same reflection-warning.

Ho0man19:01:22

call to method submit on java.util.concurrent.ExecutorService can't be resolved (argument types: unknown).

Alex Miller (Clojure team)19:01:36

are you importing Callable?

Ho0man03:01:39

No I’m not But there are other cases of .submit in the same ns that do not cause reflection warning

Alex Miller (Clojure team)04:01:39

you have to import java.util.concurrent.Callable - it might not be needed in the other cases

Ho0man06:01:39

Thanks a lot Alex but that didn't fix it either.

Alex Miller (Clojure team)14:01:22

the hints on pool in the .submit call shouldn't be needed - the hint at the top is sufficient there

Ho0man14:01:43

Thanks a lot @alexmiller Why weren't the ^Callable type hints getting applied before ? Did it had something to do with fn form or is there sth I don't know ?

Alex Miller (Clojure team)14:01:18

function objects in general don't have metadata

Alex Miller (Clojure team)14:01:39

so that metadata doesn't have anywhere to go

alberson15:01:03

Hello! Is there any way to deprecate a single defmethod of a defmulti?

dpsutton15:01:07

supposing there was, what benefit would it have? suppose foo is a defmethod that is deprecated. here x may or may not trigger the method that is deprecated (foo x) do you want some indication in your editor that it is deprecated?

thanks 4
ghadi15:01:53

I agree this sound weird. Callers of a multimethod shouldn't care about which dispatch branch was hit

ghadi15:01:57

if you want feedback in the program, you could tick a metric or emit a log that said "vestigial branch hit, rework the calling code"

4
thanks 4
alberson15:01:05

Yeah, I think this is the goal. I'm forwarding a question that was asked in my organization. It's a multi dispatcher that returns a token, and a single dispatcher will be removed

Alex Miller (Clojure team)15:01:51

or you can literally remove it

alberson15:01:53

Yeah, but I think the point of deprecation is to give visual hint and time to everybody rework their code without a hard break. But what I'm seeing is that there is no way to do that

alberson15:01:13

But thanks!

metehan16:01:48

(if @filtered [records ^{:key "t"} true] [records ^{:key "f"} false]) i can't make refresh the records element when filtered is changed

enforser17:01:19

Looks like this could be Reagent specific, I'd try asking in #reagent

metehan16:01:01

btw my first attemp was [records @filtered]

metehan16:01:36

this works fine but obviously far from ideal

(if @filtered 
            [:<> {:key "t"} [records true]] 
            [:<> {:key "f"} [records false]] )

bfabry16:01:24

@m373h4n I'm unsure what you're trying to achieve here. could you post some expected/desired output from that statement? your first example seems to be trying to add metadata to a boolean which I don't think you can do. your second example is creating a 3 element vector with the first element being the keyword :<> and the second element being a map

metehan17:01:56

(defn showme [tf]
  (r/with-let
    [rfsubs tf] ;<<<<--- This doesn't change
    (if rfsubs [:p "TRUE"] [:p "FALSE"])))

(defn testi []
  (r/with-let [filtered (r/atom false)]
    [:<> 
     [:button {:on-click #(reset! filtered (not @filtered))} "CHANGE"]
     [showme @filtered]]
    ))

metehan17:01:17

I made simple sample of my problem

metehan17:01:13

when you click button it should show text TRUE or FALSE but it doesn't

bfabry17:01:30

right yes this is a reagent question, I don't know reagent sorry.

🍺 4
dpsutton17:01:49

can you try it without the with-let bindings? just (defn showme [filtered?] (if filtered? [:p "True"] [:p "False"]))

metehan17:01:35

then it works. but I need with-let in the real function. this was just demonstration of my problem

Eric Ihli21:01:01

https://reactnavigation.org/docs/en/state-persistence.html

const persistNavigationState = async (navState) => {
  try {
    await AsyncStorage.setItem(persistenceKey, JSON.stringify(navState))
  } catch(err) {
    // handle the error according to your needs
  }
}
const loadNavigationState = async () => {
  const jsonString = await AsyncStorage.getItem(persistenceKey)
  return JSON.parse(jsonString)
}

const App = () => <AppNavigator persistNavigationState={persistNavigationState} loadNavigationState={loadNavigationState} />;
How is an async function created in ClojureScript? I'm having a hard time finding what happens behind the scenes to know how to create a CLJS version of the persistNavigationState function that will work with ReactNavigation as in that example. (edited)

enforser22:01:46

I believe the most common way to handle this would be to use a promise instead of async/await.

(-> (.setItem AsyncStorage persistenceKey (.stringify JSON navState))
    (.then (fn [resolve reject]
             ...)))

🤙 4
fappy22:01:48

When await-for times out, what happens to the actions it was waiting on? Do they get to live out their natural lives?

hiredman22:01:44

await (and await-for) is basically just a ping/pong to an agent. drop an action on their queue of actions to let me know when it is run

4
hiredman22:01:39

not even basically actually, looking at the implementation that is exactly how it is implemented

bocaj23:01:32

Looking for ways to replace in the string

[sql column name]
Characters in
#{"[" "]" " "}
to be used as the {:identifiers fn} function in clojure.java.jdbc/query

andy.fingerhut23:01:56

replace what, with what result?

andy.fingerhut23:01:38

clojure.string/replace and clojure.string/replace-first can do some kinds of replacements in strings, but not sure from your stated request exactly what you are looking for.

bocaj23:01:51

Sorry, trouble formatting in slack. I want to remove a set of characters, this. This will be used as the identifiers cleaning function in clojure.java.jdbc/query opts parameter

andy.fingerhut23:01:56

So given a string "[sql column name]" you want back a result that is the sequence of strings ("sql" "column" "name") ?

andy.fingerhut23:01:37

I'm not familiar with the argument of clojure.java.jdbc/query you mention, so I am perhaps not the ideal person to help, but if you can describe the result you are looking for....

bocaj23:01:14

I think I can take care of that part. But here's input "[sql column name]" and output "sql_column_name"

Pavel Klavík23:01:02

you can just use clojure.string/replace

Pavel Klavík23:01:55

something like

(-> input (str/replace #"[\[\]]" "") (str/replace " " "_"))

bocaj23:01:41

Great! just got through the docs and see replace matchers is a regex

Pavel Klavík23:01:45

ya, it can work with regex, string, characters, quite strong

andy.fingerhut23:01:51

It can be a regex, but it can also be a character or a string -- whatever you need for the situation at hand.

bocaj00:01:55

Thanks! I was hoping use just one call to replace, but couldn't work out the regex. Two is much easier atm.

Pavel Klavík00:01:48

You could even write it like that:

(reduce (fn [input [from to]] (str/replace input from to)) input {"[" "", "]" "", " " "_"})

bocaj00:01:50

(defn sql-column [^String s]
  (-> s
    (str/replace " " "_")
    (str/replace #"\[|\]" "")))

(defn sql-column2 [^String s]
  (reduce (fn [s [from to]] (str/replace s from to)) s {"[" "", "]" "", " " "_"}))

bocaj00:01:19

;;for fun:
 (criterium/quick-bench (sql-column2 ["sql column x y z"]))
Evaluation count : 89472 in 6 samples of 14912 calls.
             Execution time mean : 4.911902 µs
    Execution time std-deviation : 144.066895 ns
   Execution time lower quantile : 4.743076 µs ( 2.5%)
   Execution time upper quantile : 5.114157 µs (97.5%)
                   Overhead used : 1.686448 ns
=> nil
(criterium/quick-bench (sql-column ["sql column x y z"]))
Evaluation count : 129804 in 6 samples of 21634 calls.
             Execution time mean : 4.812074 µs
    Execution time std-deviation : 613.110069 ns
   Execution time lower quantile : 4.287340 µs ( 2.5%)
   Execution time upper quantile : 5.770675 µs (97.5%)
                   Overhead used : 1.686448 ns

Found 1 outliers in 6 samples (16.6667 %)
	low-severe	 1 (16.6667 %)
 Variance from outliers : 31.5509 % Variance is moderately inflated by outliers
=> nil