Fork me on GitHub
#beginners
<
2020-06-11
>
seancorfield03:06:00

@somedude314 dissoc will remove a key from a map.

coetry04:06:23

One thing that i find kind of tedious is specifying the latest version of a dependency. Coming from a js background where we can do something like npm i react and it will automatically create a package.json with the latest version of react in it ... is there something similar for clj/cljs?

seancorfield04:06:34

@coetry It's not recommended -- because of reproducibility concerns -- but you can use "RELEASE" as the version and you'll get the latest stable release of a library.

๐Ÿ‘ 1
valerauko04:06:44

also there is lein-ancient which lets you check if anything is outdated

valerauko04:06:54

just like npm outdated

seancorfield04:06:18

Depot is an equivalent for the Clojure CLI / deps.edn

amirali05:06:55

hi folks. how can i compile a block of code that i get as user input?

mruzekw05:06:55

(eval (read-string "(+ 1 1)"))

valerauko09:06:29

what's the clojurescript equivalent of import Foo from 'bar' ? i can't seem to get it working

fabrao09:06:55

["bar" :default Foo]

fabrao09:06:11

you have this reference in shadow-cljs docs

valerauko09:06:57

that is exactly what i've been looking for, thank you

sove13:06:12

Morning All ๐Ÿ˜ƒ

morning 1
gon14:06:39

try with (into [1 2 3] [4 5])``

๐Ÿ’ฏ 1
alexmiller15:06:25

what is that?

sove15:06:22

is that like a latex file

noisesmith15:06:56

it's a file used to make latex bibliographies http://www.bibtex.org/

alexmiller15:06:27

source for the paper is latex so I can ask Rich if it's somtehing he might already have

Jim Newton15:06:05

Often a site which lets you download a paper, also lets you download the bibtex.

noisesmith16:06:08

Used to set thread-local-bound vars, Java object instance
fields, and Java class static fields.
set! is specifically for thread local (`^:dynamic`) vars, and java interop

noisesmith16:06:28

to create a var, you can use def or intern

ghadi16:06:46

I would be cautious of registering global resources in general

๐Ÿ’ฏ 1
Jim Newton16:06:53

cautious in what sense?

ghadi16:06:07

like don't do it

ghadi16:06:10

๐Ÿ™‚

ghadi16:06:15

e.g. if it's a database connection

ghadi16:06:19

you can use alter-var-root to alter non-dynamic vars. Again I caution against it

Jim Newton16:06:40

no, its a global definition whose value needs to change as the program loads. In the same sense that defmulti defines a global resource and defmethod updates it. Or defn defines a global function. These are not generally seen as something to avoid.

ghadi16:06:04

an example of a common pattern is the spec registry. that's an atom that gets swapped: (swap! registry assoc key some-spec)

ghadi16:06:20

(defonce registry (atom {}))

ghadi16:06:42

the defonce is there so that a namespace reload doesn't blow it away

ghadi16:06:08

rather than swapping the var itself, swap an atom that the var points to

Jim Newton16:06:14

I was trying to use atom and swap. but couldn't make it work.

ghadi16:06:50

it would be helpful if you pasted what you tried

noisesmith16:06:56

that was a macro error, described in the thread under that code

noisesmith16:06:09

but there are multiple problems before hitting the macro error

ghadi16:06:16

ok I see it

ghadi16:06:23

yeah that doesn't have to be a macro at all

ghadi16:06:58

(swap! supported-nontrivial-types conj new-thing)

noisesmith16:06:03

it doesn't need to be a macro, doesn't need an anon fn even if it was a macro, and shouldn't be derefing inside swap!

Jim Newton16:06:56

@ghadi, would you rather write a call to swap! or a (defmethod ...) ? of course defmethod doesn't have to be a macro, but it is friendlier.

ghadi16:06:19

hate to tell you but it depends

ghadi16:06:44

you need to clarify the higher level goal to choose between a simple set containing values or open dispatch (a multimethod)

ghadi16:06:31

are you associating different behavior with the different registered things? then multimethod

ghadi16:06:02

if you must declare something before using it, but all things are handled the same way, then a set is sufficient

Jim Newton16:06:24

Yes, depends on the situation. But in general the correct way to manage global resources in clojure has been unclear to me.

valerauko16:06:56

what would be such a global resource?

ghadi16:06:11

there's not a single correct way, there's only situational considerations

valerauko16:06:01

i think you might need something like mount https://github.com/tolitius/mount

โ˜๏ธ 1
โŒ 1
alexmiller16:06:13

the best answer is to not have a global resource, but instead to instantiate your resource when the program starts and give it to the code that needs it

alexmiller16:06:33

if it's stateful, wrap it in an atom

noisesmith16:06:49

based on the example code, I think "resource" is being used loosely here. in clojure itself, there are multiple examples of a central registry that gets appended as you develop - defmethod, defprotocol, ns, spec

noisesmith16:06:35

where the registry itself is an implementation detail, but the behavior offered is the same variety as @jimka.issy is trying to implement

noisesmith16:06:22

so a first hint might be not making the registry part of the public api, if you do need one

Jim Newton16:06:24

Yes this is what I'm calling a global resource. i.e., the global set of multi methods, or the global set of name spaces.

Jim Newton16:06:19

and yes, one reason for the macro is to hide the implementation using atom and swap!

noisesmith17:06:10

after various experiments and designs, my current heuristic is to avoid things that are not referentially transparent, whether implemented by myself or clojure, and if I can prove I need something that's spooky (eg. driven by a hidden mutable registry), I stick to the thing that's already in clojure itself unless I can prove I need a new one whose behavior clojure can't do properly

noisesmith17:06:01

I need a small amount of spookiness in order to do normal repl dev, of course. But beyond that I can keep it pretty minimal.

Jim Newton17:06:15

Does that mean you make your implementation details apparent to the user of the API? Isn't that limiting if you want to change the implementation later?

noisesmith17:06:57

if my implementation is value focused and referentially transparent, there are no details to leak

noisesmith17:06:13

but for a case like yours - you could use a multimethod and then dispatch on a symbol, where a simple false is the default method output, and true is set for anything you extend

Jim Newton17:06:21

I'm not sure what referentially transparent means in this context. normally it means you can replace a reference with the implementation. right?

noisesmith17:06:55

right - so you aren't using mutation of some other location in application logic

Jim Newton17:06:44

isn't defining a method a mutating operation?

noisesmith17:06:23

so a defmulti version of what you had above:

(defmulti registered? dispatch)
(defmethod registered? :default [_] false)
(defmethod registered? '= [_] true)

noisesmith17:06:46

right - as I said, I avoid those things, but when I need them, I prefer something already in the language

Jim Newton17:06:16

And how do I get the set of registered symbols, to iterate over them, or to print them in a diagnostic message?

noisesmith17:06:16

I picked defmulti because it looked like the set of registered things would be extended arbitrarily by client code

Jim Newton17:06:08

I guess it would use the method reflection api?

Jim Newton17:06:23

explicitly throwing away :default?

noisesmith17:06:34

anyway, you don't need a "reflection api"

(ins)user=> (doc methods)
-------------------------
clojure.core/methods
([multifn])
  Given a multimethod, returns a map of dispatch values -> dispatch f
ns
nil

sove18:06:12

Is there a reason I keep seeing

java.lang.IllegalAccessException: class clojure.lang.Reflector cannot access class jdk.internal.loader.BuiltinClassLoader (in module java.base) because module java.base does not export jdk.internal.loader to unnamed module @5aa6da2

sove18:06:42

Which JDK ought I be using?

alexmiller18:06:44

Any jdk will work

alexmiller18:06:37

Many reflective calls will be reported this way now unfortunately, even though a type hint is really needed in the Clojure code

sove19:06:06

does it make any sense to ask the upstream java people to put it back? lol

sove19:06:26

complecting at a distance

sove19:06:47

quantum enplectlement

๐Ÿ’ฏ 1
sove19:06:09

Missing a typehint... hmm

alexmiller19:06:12

if you use the debug flag it's usually pretty clear where the issue is

alexmiller19:06:31

--illegal-access=debug

sove20:06:46

I don't know where to add that flag. Is it a jvm-opts? I'm using lein to run a project

alexmiller21:06:38

nothing special, just an example of a meta keyword

noisesmith21:06:51

(ins)user=> (meta ^:journal {})
{:journal true}

noisesmith21:06:14

various tools / libs use metadata, it's kind of a grab bag

noisesmith21:06:38

oh ๐Ÿ˜† that example is incorrect

(ins)user=> (meta ^:journal 'foo)
nil
(ins)user=> (meta '^:journal foo)
{:journal true}

noisesmith21:06:42

someone should edit that page

alexmiller21:06:16

well the example showing it doesn't work still doesn't work so that part's not wrong :)

noisesmith21:06:43

but the example claiming it works - while irrelevant to the thing being documented - is still incorrect

alexmiller21:06:02

could just use a []

Daniel ร–stling22:06:06

What's the common way to break long string literals to keep line width reasonable? Do people just use something like (str "long string 1" <line break here> "long string 2")?

noisesmith22:06:10

either str or format yeah - depending on what's clearer in your context

๐Ÿ‘ 1
noisesmith22:06:38

also you can put it in a file and load it with io/resource of course

iyerland22:06:38

Are there any new books out? What resources do you use to learn Clojure?

seancorfield22:06:49

Living Clojure and Getting Clojure are good books for that. Can't remember when they came out but they're relatively recent.

seancorfield22:06:57

Online, there's a version of Clojure for the Brave and True -- some people find it too quirky, and it starts out assuming you're going to learn Emacs which some people think is a bit much if you're trying to learn both Clojure and Emacs at the same time.

seancorfield22:06:29

And there's the official Getting Started material https://clojure.org/guides/getting_started

seancorfield22:06:59

That has a lot of links to books, tutorials, and so on.

iyerland22:06:18

Thanks @seancorfield ... guess I am on the right track, just got started with Living Clojure ๐Ÿ‘

noisesmith22:06:45

be sure not to miss this (linked from the page @seancorfield shared) https://clojure.org/guides/learn/syntax

noisesmith22:06:11

it's a really good "learn how to fish" intro that relies on built in documentation and discoverability in the language itself

iyerland22:06:22

@noisesmith Thanks, will take a look at that too ๐Ÿ‘