Fork me on GitHub
#clojure
<
2018-04-02
>
seancorfield00:04:23

Bing suggests it's part of CounterClockWise...

qqq00:04:37

Looking at RT.var, I think I can just replaced it with "clojure.core" (i.e. it wants a string that encodes a namespace)

seancorfield00:04:09

Yes, it's just Java code calling Clojure's old API (via clojure.lang.RT).

seancorfield00:04:53

So it's (clojure.core/require ...) and whatever the INITIALISE_NS_SYMBOL stuff is

seancorfield00:04:50

Hmm, not CCW. It's ClojureUtils namespace doesn't have that constant.

qqq01:04:36

1. I am trying to learn how to add a Clojure nrepl to an existing java application. 2. I created a blank Java app in IntelliJ. I added the Clojure 1.9.0 jar dependency from https://repo1.maven.org/maven2/org/clojure/clojure/1.9.0/ (by the way auto completion works, jar added successfully) 3. I have an application of the form:

package com.example;

import clojure.java.api.Clojure;
import clojure.lang.IFn;

public class MyRepl {
    public static void main(String[] args) {
        System.out.println("Hello World");

        IFn require = Clojure.var("clojure.core", "require");
    }
}
4. The above application, before the "IFN require" line, runs fine -- i.e. I got the "Hello World" 5. Now, when I try to run it with the "IFn require" line, I get an error concerning
Caused by: java.io.FileNotFoundException: Could not locate clojure/spec/alpha__init.class or clojure/spec/alpha.clj on classpath.
	at clojure.lang.RT.load(RT.java:463)
	at clojure.lang.RT.load(RT.java:426)
	at clojure.core$load$fn__6548.invoke(core.clj:6046)
	at clojure.core$load.invokeStatic(core.clj:6045)
What is going on here? I'm not using clojure spec. Is spec not part of the jar? Do I need to add another jar?

zentrope01:04:01

Normally if you have a build system (like Gradle), it’ll pull in those transitive dependencies.

qqq02:04:04

@zentrope: good suggestion; I am now switching from "Jva Project" to "Gradle Project"

seancorfield02:04:46

(hopefully Gradle will pull that in too automatically)

mv05:04:59

Is anyone seeing an issue like this: java.lang.ClassNotFoundException: clojure.spec

mv05:04:25

Didn’t realize spec wasn’t included in the core language. I’m on 1.9.0 in project.clj

seancorfield05:04:55

@mv How are you starting Clojure?

seancorfield05:04:20

Oh, wait, it's clojure.spec.alpha

seancorfield05:04:57

(it was clojure.spec very briefly when it was first introduced, but it's been clojure.spec.alpha for a long time)

mv05:04:07

That’s odd. All I have changed is the deps from vase 0.9.1 to 0.9.3

mv05:04:13

I’m running lein run

seancorfield05:04:02

Well, 0.9.2 (and earlier) were based on prerelease builds of Clojure 1.9.0 so I expect that's where the clojure.spec reference came from.

seancorfield05:04:00

I suspect you need to do lein clean @mv to clean up old dependencies

mv05:04:51

@seancorfield anything beyond lein clean?

mv05:04:05

My deps:

[org.clojure/clojure "1.9.0"]
                 [io.pedestal/pedestal.service "0.5.3"]
                 [com.cognitect/pedestal.vase "0.9.3"]

mv05:04:36

No change after running clean

seancorfield05:04:19

Does anything in your code base require clojure.spec?

mv06:04:36

Ah, looks like there was something in the vase example

mv06:04:32

Thanks!

4
danielo51508:04:11

Hello, one question: how can I create a variable accesible on the whole file that is not computed at compile time ? Something like a http client that I provide credentials to instantiate an instance ?

robert-stuttaford08:04:30

@rdanielo write a function and call it when you need it? 🙂

danielo51508:04:01

That is what I do for most of the things, but I want the function to retain some defaults. Something like an instance on java or a closure on javascript

robert-stuttaford08:04:06

unless i’m misunderstanding you .. (defn make-thing [] (let [default 1] (Ctor. default)))

dominicm08:04:15

@rdanielo clojure provides delay for this, alternatively.

danielo51508:04:18

Works on clojurescript too ?

danielo51508:04:08

I'll check it out

danielo51508:04:24

So, can I use this for creating some namespace-global defs that I can use across the entire file ?

dominicm08:04:25

It would work for that, yep.

danielo51508:04:05

Any examples ? The documentation is a bit... succinct

robert-stuttaford08:04:52

(def lazy-const (delay (expensive-work)))(do-something-with @lazy-const) expensive-work will only happen once, when lazy-const is first deref’ed; @ is shorthand for (deref …).

danielo51509:04:47

Thank you. Is this the preferred way of doing this kind of stuff ?

danielo51509:04:13

For example, if you want to load some configs from a file, would you declare the fetched variables as delayed ?

danielo51510:04:29

is normal on clojure-land to return a map containing functions to be used ?

schmee11:04:27

Clojure functions are first-class constructs. it's no stranger to return a map of functions than a map of strings or integers 🙂

hmaurer10:04:41

Hello! Do any of you have advice on when it is best to use metadata over “explicit” data in a system? I find metadata a very tempting approach to track some things about how expressions flow through my system, but I am not sure whether it’s sensible

hmaurer10:04:09

(I do realise my question is very project-specific, so you could interpret it as “have you used metadata to track X in your system, and how was your experience?“)

schmee11:04:54

one thing to keep in mind is that metadata does not affect equality

schmee11:04:24

so if the data you track should affect equality, you can't use metadata

schmee11:04:34

IMO, metadata should be used for "information about the program", ie. line and column numbers, which source file... IIRC tools.namespace uses it to track what has been reloaded

schmee11:04:52

so (again IMO) don't put program logic in metadata

qqq14:04:50

I get this error:

null
java.lang.ExceptionInInitializerError
	at clojure.lang.Namespace.<init>(Namespace.java:34)
	at clojure.lang.Namespace.findOrCreate(Namespace.java:176)
	at clojure.lang.Var.intern(Var.java:148)
	at clojure.java.api.Clojure.var(Clojure.java:82)
	at clojure.java.api.Clojure.<clinit>(Clojure.java:96)
	at MyRepl.actionPerformed(MyRepl.java:13)
	at com.intellij.openapi.actionSystem.ex.ActionUtil$1.run(ActionUtil.java:220)
	at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAware(ActionUtil.java:237)
	at com.intellij.openapi.actionSystem.impl.ActionMenuItem$ActionTransmitter.lambda$actionPerformed$0(ActionMenuItem.java:301)
	at com.intellij.openapi.wm.impl.FocusManagerImpl.runOnOwnContext(FocusManagerImpl.java:307)
	at com.intellij.openapi.wm.impl.IdeFocusManagerImpl.runOnOwnContext(IdeFocusManagerImpl.java:104)
	at com.intellij.openapi.actionSystem.impl.ActionMenuItem$ActionTransmitter.actionPerformed(ActionMenuItem.java:291)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
	at com.intellij.openapi.actionSystem.impl.ActionMenuItem.lambda$fireActionPerformed$0(ActionMenuItem.java:111)
	at com.intellij.openapi.application.TransactionGuardImpl.runSyncTransaction(TransactionGuardImpl.java:88)
	at com.intellij.openapi.application.TransactionGuardImpl.lambda$submitTransaction$1(TransactionGuardImpl.java:111)
	at com.intellij.openapi.application.TransactionGuardImpl.submitTransaction(TransactionGuardImpl.java:120)
when I try to load a clojure nrepl in an IntelliJ plugin action via:
import clojure.java.api.Clojure;
import clojure.lang.IFn;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;

public class MyRepl extends AnAction {
    public MyRepl() {
        super ("Hello");
    }

    public void actionPerformed(AnActionEvent event) {

        IFn require = Clojure.var("clojure.core", "require");
        require.invoke(Clojure.read("clojure.tools.nrepl.server"));

        IFn server = Clojure.var("clojure.tools.nrepl.server", "start-server");
        server.invoke(Clojure.read(":port"), Clojure.read("5555"));
    }
}
This appears to be an issue with the way I'm trying to call Clojure from Java. Any idea what I am doing wrong?

val_waeselynck14:04:07

I'm writing a guide to teach new Clojurians how to deal with objects from Java-land, and am looking for accessible, dependency-free examples. Do you have examples of Java objects that have a completely obscure printed representation in the Clojure REPL? Preferably Java classes which purpose is easy to understand, and which are available in the JDK by default (no additional deps)

val_waeselynck14:04:46

Best one have come up with so far is InputStream.

qqq14:04:26

Graphics2D ?

👍 4
qqq14:04:45

you can have the reader draw stuff in Graphics2D to show the interactions, and I'm pretty sure it comes with all JDK installations

Alex Miller (Clojure team)14:04:48

java.awt.Point is always a useful example

👍 4
val_waeselynck14:04:10

@alexmiller the problem with all of those is that their .toString() is still somewhat informative (e.g "java.awt.Point[x=12,y=23]" - I'm really looking for a situation where the user gets nothing but the class name).

Alex Miller (Clojure team)14:04:55

most “data” classes in Java will print some subset of their fields in the toString()

Alex Miller (Clojure team)14:04:20

user=> (def pb (ProcessBuilder. ["ls"]))
#'user/pb
user=> (def p (.start pb))
#'user/p
user=> p
#object[java.lang.UNIXProcess 0x2eee3069 "java.lang.UNIXProcess@2eee3069"]

👍 4
gklijs14:04:54

Any java collection will also have this problem right?

Alex Miller (Clojure team)14:04:02

many of the Java colls have print writers installed in Clojure so they will print like Clojure collections

lemontea14:04:20

if you don't mind non-objects, how about primitive int array? (it uses something like type descriptor which is pretty cryptic to the uninitiated)

Alex Miller (Clojure team)14:04:40

that’s a good idea re printing, but probably bad if you subsequently want to show invoking methods / fields on it

ecolui14:04:52

Greetings - I have a relatively simple question. Any advice will be appreciated.

ecolui14:04:55

(def person {:name "Tom" :weight 120.1}) (def same-person {:name "Tom" :weight 120.1M}) (= person same-person) ;;yields false, because 120.1M is BigDecimal and 120.1 is a Double Does a macro, function, or special form already exist that compares maps and ignore value type for individual keys that are numeric?

Alex Miller (Clojure team)15:04:26

although I guess that’s not deep

ecolui15:04:48

Ya, I was looking for a deep comparison

ecolui15:04:57

Its all good, thank you for your response sir!

Alex Miller (Clojure team)15:04:22

generally, I find any time you are trying to redefine deep equality, your path will end in sadness :)

Alex Miller (Clojure team)15:04:38

better to avoid needing that in the first place

ecolui15:04:40

hehe - cool Mr. Miller, thanks for the advice. Take it easy.

achikin15:04:06

(reduce and (map = [1 2] [1 2 3 4]))
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/and

achikin15:04:53

The code looks reasonable to me, but still shows an error.

achikin15:04:17

Ah, maybe apply would work...

tbaldridge15:04:21

@achikin try (every? identity (map ...))

tbaldridge15:04:42

No and is a macro, and so it can't be used as a function

tbaldridge15:04:56

replacing and with (fn [a b] (and a b)) would also work

qqq15:04:37

is there a way to get clojure.tools.reader to run in "tokenization" mode instead of reading? so for example, suppose the string is (+ :a :b :c) if we run the reader, we get back (+ :a :b :c) as one sexp what I want instead, is to get back, six different calls, of: ( + :a :b :c )

qqq15:04:12

I don't want to read the sexp and then call flatten; I want something that reads one token at a time

Alex Miller (Clojure team)15:04:57

I know there are some out there in antlr or javacc

qqq16:04:33

@alexmiller: I might try to repurpose ./tools.reader/src/main/clojure/clojure/tools/reader.clj:(defn- ^String read-token

tbaldridge16:04:12

@qqq there are parts of Clojure's syntax that are context sensitive. You're going to run into problems with that trying to write a tokenizer. It could be done, but you'd probably have to rewrite the entire parser from scratch.

tbaldridge16:04:20

But what's the point in doing this?

mindenaaron16:04:08

Hi everyone! I have a simple question: Are there any built-in solution to generate only the required keys of a map based on its spec or i always have to use custom generators with s/keys for this purpose?

Alex Miller (Clojure team)16:04:40

you could separate the req and opt parts of your spec though and use the full spec as the s/merge of those two sub specs with the generator from just the req spec

kennytilton17:04:00

Does Clojure need the equivalent of CL packages? NS require clause juggling during new development is making me old. Just sayin.

mindenaaron17:04:01

Thank you Mr. Miller!

tbaldridge17:04:58

@hiskennyness how so? Some editors like Cursive do a lot of management for you. I can type str/starts-with? and the IDE adds in the require for clojure.string to my ns macro.

👀 8
tbaldridge17:04:42

That's not hardcoded either, it works for user namespaces as well, sometimes with an additional tooltip prompt to make sure it pulls in the ns you want.

justinlee17:04:27

@tbaldridge how does it know that str is short for clojure.string?

tbaldridge17:04:16

For the clojure stuff I think it's hardcoded, at least it seems to be. For user namespaces it learns by looking at the rest of your code. So if you did [myapp.foo :as foo] it will assume that naming in other parts of the app

tbaldridge17:04:01

Another good reason to not use core as a namespace name 😄

justinlee17:04:27

cool that does work. what a neat feature. i’d love something that maintains my :refer lists. i don’t think it does that.

tbaldridge17:04:57

Yeah, I wouldn't mind a go-lang-esque linter that sorts the :requires in a namespace

justinlee17:04:45

namespacing is a necessary feature but in some sense it’s a waste of life because 99.9% of the time there are no conflicts

mtnygard17:04:47

@tbaldridge @lee.justin.m With cider + clj-refactor, I can do a cljr-sort-namespace

mtnygard17:04:13

I forget the function, but it can also remove unused namespaces

juhoteperi17:04:42

I think cursive will look at which namespaces provide e.g. starts-with? function and then propose those and adds the require with the alias you used in code, (sdfsdfsdf/starts-with? ...) should add [clojure.string :as sdfsdfsdf] (but I didn't test this)

tbaldridge17:04:21

@lee.justin.m less namespaces perhaps? I think people split stuff up too much. I don't mind a files with > 2000 loc

tbaldridge17:04:39

< 200 loc in a file and it becomes a pain to manage

tbaldridge17:04:00

but a lot of that also depends on how modular the code is

justinlee17:04:06

yes @juhoteperi that’s interesting (and would be a good idea even if that’s not what it’s doing). the fact that cursive can just kind of figure it out is only possible because namespacing isn’t really necessary most of the time, and at most there are just a couple of choices

justinlee17:04:46

@tbaldridge yea agreed. i love having all my related react components in one file. i used to have a billion small files in javascript

justinlee17:04:00

of course, the conciseness helps

tbaldridge17:04:38

@lee.justin.m no, I'd say it's because we very rarely rename namespaces differently across files, or have conflicts in short names. We'll more often do [my.app.core :as mac] instead of [my.app.core :as core]

tbaldridge17:04:14

So if you index all the :as X symbols there's only ever one or two back-refs.

justinlee17:04:39

that’s true, but I think it is likely also true that there’s only one starts-with? in your code base

tbaldridge17:04:15

maybe? but that approach would be more error prone.

tbaldridge17:04:02

A lot of this also works with keywords, so if I do :my.app.foo/bar and later refer to that namespace as :foo it will suggest ::foo/bar in other parts of the app.

tbaldridge17:04:41

That's something I don't think is possible at all with dynamic introspection repls, perhaps if you hooked into Clojure's KW registry?

myguidingstar18:04:28

hi all, I'm happy to announce Walkable, a new SQL library for Clojure: queries with Datomic pull syntax and pure Clojure filtering, configuration driven

myguidingstar18:04:32

please check it out, the README covers quite a few examples https://github.com/walkable-server/walkable

myguidingstar18:04:52

for those who've known about walkable: version 1.0.0-beta2 has just been deployed to clojars with the ability to use pseudo columns in filters

dominicm18:04:38

is there any way to perform a classpath-seq, much like file-seq? The only examples I'm finding seem to be assuming classpath locations are always on the fs, which isn't true.

hlship18:04:57

It's always been a pain / haphazard to do this even in Java land ... the JDK doesn't provide this functionality, so you have to cobble it together from guesses and assumptions.

dominicm18:04:42

I see, makes sense that some classloaders couldn't do it (e.g. remote urls)

kennytilton19:04:08

@tbaldridge Well, in a multi-file situation I am effectively redefining a package in every source. If we could bundle all that up as a package in one place I would be all set. Then in CLJS, I do not have :refer :all, so I really have to work. Minor gripe, mind you. Just doing a lot of new code the past week. Btw, yes, Cursive is nice when I need a new require altogether.

gabriele19:04:29

awesome, starred and i'm going to play with it this week, thanks for the library.

myguidingstar02:04:34

I'm glad you like it 🙂

cfleming20:04:09

@lee.justin.m @tbaldridge @hiskennyness Right, Cursive does that by looking at existing aliases in the code. There are no built-in defaults for core nses, but the examples also come from library code so someone always has clojure.string :as str in there somewhere.

4
cfleming20:04:31

No :refer list management yet but I want to add that soon.

cfleming20:04:04

Also general ns rewriting, although I’d like it to be general and cljc makes it hard.

qqq23:04:52

@alexmiller @tbaldridge: so I'm implementing a new paredit-like editor. Now, suppose || = cursor, and we have ... ) || some-other-stuff and we do a "word left" -- then I want the cursor to move left "by one tokeh" (i.e. a string, a number, a symbol, a regex, or a keyword) for this and other things, if possible, I'd prefer to use tools.reader as a tokenizer instead of rolling my own regex

qqq23:04:57

this looks like a function which does what I need (read off one token)

bfabry23:04:02

#_#_#_#_ foo foo ka chew

bfabry23:04:10

well, that's how the reader is context sensitive (one way). probably not actually that function sorry

tbaldridge23:04:24

@qqq sure, that gives you tokens, but you don't know what those tokens mean. foo# means something different inside a syntax quote.

tbaldridge23:04:44

It's a fairly well known issue, regexes are for "regular" languages (hence the name), Lisp is not a "regular" language

tbaldridge23:04:17

Same issue with XML, search for "parsing XML with regex" and you'll see a whole ton of articles talking about it (and how it's not possible)

qqq23:04:55

@bfabry @tbaldridge: I think your argument is "this is not perfect" whereas my issue is "to implement apredit-like, I need some type of string -> ast, and using tools.reader seems better than regex"

tbaldridge23:04:21

no, my point is it won't work at all

bfabry23:04:49

tbh I was just saying "this is how the reader is context sensitive". I didn't read the context

tbaldridge23:04:33

esp if you want anything beyond highly mechanical formatting, and that's a problem since Clojure's indent rules are not even close to machine understandable, lol

tbaldridge23:04:40

and you're saying "ast", and that implies a context aware parser

qqq23:04:06

@tbaldridge: in your definition of "won't work at all?", does emacs/paredit fall under "won't work at all" ? if yes ==> many people use it in practice if not ==> what do they do right?

tbaldridge23:04:54

looks like clojure mode builds context aware code on top of a text buffer

tbaldridge23:04:17

So I go back to my original statement, a token stream will get you tokens, but you'll have to rewrite most of the reader to do any sort of processing on that token stream

tbaldridge23:04:46

so it's probably much better to just write the whole thing from scratch. The Clojure reader isn't that bad, although it got 10x worse with reader conditionals, lol

qqq23:04:21

or just run tools.reader on the entire file instead of one token at a time, but then there's issues of "what to do if the file is (due to editing) temporarily invalid clj"

tbaldridge23:04:50

yep, and that sort of parser is completely different

tbaldridge23:04:49

I can't find it now, but the Roslyn devs did a talk about that around 8 years ago, how a compiler parser and an editor parser are completely different and can't really be the same thing.