Fork me on GitHub
#clojure
<
2018-03-06
>
emccue01:03:00

When I try importing a class definined in the same project I get "class not found" errors

emccue01:03:34

I am fairly certain all my compiling happens at runtime when I load in the clj files

emccue01:03:46

so I am a bit confused

noisesmith01:03:18

is the class created by a namespace?

noisesmith01:03:52

if so, you must require the ns, or otherwise cause it to be loaded, before using a class it defines

emccue01:03:08

no, its a namespace loading in the class

emccue01:03:17

the namespace is throwing the error

noisesmith01:03:33

where does the class come from?

emccue01:03:47

the same project

emccue01:03:52

in a differnt package

noisesmith01:03:49

what I mean is, how is the class generated? from clojure? from java? who compiles it? when?

noisesmith01:03:53

so the workflow is that you compiled the java, then started the repl, and it couldn't find the class?

emccue01:03:17

I compiled the java, the repl can find the class

emccue01:03:40

the java code that calls the clojure.java api cannot find the class

noisesmith01:03:43

maybe an issue with the classpath in the process running java and using clojure.java?

emccue01:03:02

Makes sense

emccue01:03:15

but Im not sure how to resolve it

noisesmith01:03:18

@emccue a start would be to see if the target-path lein / lein-javac are compiling to is on the classpath of the java process

noisesmith01:03:31

unless the java process is using your jar

emccue01:03:51

I just ran maven compile a few times and it started working randomly

emccue02:03:13

I don't know what was causing the problem but I guess it's solved

noisesmith02:03:51

if a clojure class is generated twice (via reload for example) the two classes have the same name but aren't the same class

noisesmith02:03:57

similar issue with methods/protocols

noisesmith02:03:09

this can cause similar but not identical bug behaviors

emccue02:03:05

Im not sure that was this issue but that is definitely useful information

emccue02:03:49

okay the issue came back but at least now I think I know why

emccue02:03:08

Its something with my namespaces being AOT compiled, which I dont want anymore

emccue02:03:30

but after I turn that on my clj files are no longer on the classpath

hiredman02:03:42

you need to add you clojure src as a resource in the pom I think

hiredman02:03:56

(you may not need the clojure maven plugin at all without aot)

emccue03:03:56

@hiredman That fixes every problem, thank you

emccue03:03:13

This started as a AOT compile project and im pretty glad that the requirements were bendable to the point where I could make it all dynamic

schmee09:03:34

it’s not merged yet but you can check out this branch locally and try it yourself 🙂

schmee09:03:51

I use it all the time, it works great

Bravi11:03:15

phew it was a good practice, learned a few good things

mbjarland11:03:27

I'm probably still not grokking clojure symbols properly...in clojure.reflect, how would I go from the symbol returned for the parameter-types to the actual class, i.e.:

(let [type (first
             (:parameter-types
               (first
                 (filter #(= (str (:name %)) "matches")
                         (:members (reflect/type-reflect String))))))]
  (prn :type type :class (class type)))
=> 
:type java.lang.String :class clojure.lang.Symbol
where I want class java.lang.String?

mbjarland11:03:56

ah (resolve symbol) seems to do it...ok I retract my question and advance to the rear

jmckitrick13:03:11

Does anyone here recall a demo of Pedestal showing a sales funnel, with dots migrating between pulsating circles that showed customers in various stages of their shopping experience? It was shown at a ClojureConj a few years ago…..

alexmiller14:03:26

if you have questions about that demo, I can probably point you to someone useful

Bravi14:03:35

is there a shorthand of doing something like this?

(defn generate-players
  [user computer]
  {:user user
   :computer computer})

Bravi14:03:51

basically generating a keyword based on argument name

Prakash15:03:29

I dont think there is a built in, I think I have seen this done with a macro though

Bravi15:03:46

👍 thanks

reborg15:03:03

records are pretty close:

(defrecord Player [user computer])
(into {} (Player. "foo" "bar"))
{:user "foo", :computer "bar"}

achikin17:03:50

What is the state-of-the-art library to extract mime types from files?

achikin17:03:33

Not something that maps file extensions to mime types, but something that really looks into the file searching for headers/blocks?

achikin17:03:20

Does any one use either of them?

joelsanchez17:03:54

I use pantomime, it's cool

seancorfield17:03:30

@qqq There's a #vim-fireplace channel -- maybe that should have its focus expanded to other vim stuff?

qqq17:03:19

@seancorfield moving over; thanks!

ajs19:03:17

I am having a bizarre experience where the falling returns false at my repl: (= "Date" (first ["Date" "Apple" "Orange"])) I suspect it is because the vector is read in from a CSV so perhaps there is some kind of encoding that makes the letters of the word actually different than they appear? Is there a way to convert the imported text into a "standard" encoding?

ajs19:03:14

it would appear that if you copy/paste my code snippet exactly, you will also get false at any repl, but if you type it out yourself, then you will get the expected true

noisesmith19:03:23

@ajs to debug you could look at (seq (.getBytes s)) and compare for each string

ddellacosta19:03:26

@ajs I see this in my repl:

ajs19:03:27

i get bytes of (-17 -69 -65 68 97 116 101) what does that mean?

ajs19:03:38

oh weird

ajs19:03:52

so there is an underscore there, that is not appearing anywhere in my repl? why would yours show that?

ddellacosta19:03:03

sorry, not sure that worked, slack gave me some complaint about storage space

zylox19:03:04

my repl shows a space

noisesmith19:03:40

I bet it's a non-printing unicode

ajs19:03:41

strange, so you copy/paste my code snippet but it appears differently after pasting?

ajs19:03:56

how can I "clean" these strings?

ddellacosta19:03:01

@noisesmith was trying to figure out what that’s called, one of those gave me no end of trouble a little while ago

ddellacosta19:03:24

@ajs one approach is to use a regex to strip that garbage out

ajs19:03:29

and why do everyone's repls display it differently?

ddellacosta19:03:59

I’m in cider, could be an emacs vs. terminal repl thing

ajs19:03:06

i'm in cider also, in emacs

noisesmith19:03:53

(String. (byte-array [-17 -69 -65]) "UTF-8") => ""

zylox19:03:05

im in cursive for reference

ajs19:03:31

what would the regex look like to just extract the letters?

ajs19:03:58

looks like something along the lines of (re-find #"[a-zA-Z]+" (first ["Date" "Apple" "Orange"]))

noisesmith19:03:10

(.replaceAll "Date" "\\p{C}" "?" ) => "?Date"

noisesmith19:03:29

so you could use "" instead of "?", maybe there's something more elegant

zylox19:03:33

(Character/codePointAt "" 0)
=> 65279
(Character/getName 65279)
=> "ZERO WIDTH NO-BREAK SPACE"

lxsameer19:03:48

hey folks, what kafka client do you use with clojure ?

tbaldridge20:03:29

@lxsameer my first recommendation is to always use the Java libs, unless they don't do what you want. There's just not enough eyes on Clojure wrapper libs.

tbaldridge20:03:17

Java libs are often produced by the vendor themselves, that helps a lot when trying to find tutorials, and troubleshooting, and even when talking to the vendor themselves.

tbaldridge20:03:50

3rd party wrappers will often be blamed by the vendor when there's some bug that appears. When you use the vendor's libs, they can't blame that layer anymore 😄

lxsameer20:03:53

@tbaldridge Yeah good points. I'll go with the java client then. Thanks

kenrestivo20:03:01

tricky bastards: vmware won't let you run vmware console from within a vm

senorflor21:03:19

^ emoji game on point, @kenrestivo @zylox!

datran21:03:37

I'm trying to reset a private atom for testing. I'm using alter-meta! and it seems to work just fine at the repl but it blows up when compiling

datran21:03:01

I suspect that the compiler sees the private atom and freaks out, but it should work at runtime

datran21:03:13

what's the best way to tell the compiler to back off?

noisesmith21:03:21

so you are trying to update the metadata on a private atom, which works in a repl, but this doesn't work when running your tests?

datran21:03:30

yes, exactly

noisesmith21:03:14

FYI the compiler used in the repl is the same one that is used when running tests, and clojure doesn't have an interpreted mode

senorflor21:03:39

Best thoughts on/resources for making Clojure’s flavor of simple also beginner-friendly (not easy, mind you 😄)? I fell in love with the language and its primitives/view on development because I had the great luck to land on a team of awesome senior devs using it effectively. I want to have a goto set of resources to help people experience that banana without also having to bring the monkey (pushing through tooling setup), the tree (pre-existing team), and the jungle (sorry I stretched this metaphor too far). Will ask this differently phrased in #beginners as well.

sundarj22:03:07

what do you mean by 'Clojure's flavor of simple'? 'simple' in the context of Clojure is merely one of the lesser-used meanings of the word: 'Composed of a single element; not compound.' (i.e. 'simplex')

senorflor22:03:30

Yes, that one. It’s maybe obvious that one of the side effects of making things simplex is that you also make them separate, but I’ve been thinking about the consequences of that kind of simplification a lot recently. For someone starting out one consequence is that it makes for many entry points at each level of simplification, e.g. I read the Rationale at https://clojure.org/about/rationale and at the end it takes me at the end to Features (https://clojure.org/about/features). I think it’s possible because of this branching factor for people to spend inordinate time down minor branches of the path, and have observed this when introducing people to the language/libs/tools: I’m looking for something that teaches how to learn Clojure, i.e. gives a strong heuristic for searching the frontier.

senorflor22:03:00

More concisely: resources/unifying values to help people see the forest (a bunch of possible DAGs of learning to go follow) for the tree (the reasons the language’s DNA caused it to branch out into these separate paths here) at each juncture.

senorflor22:03:52

Something like a digest of Clojure’s instantiations of SICP’s 3 language mechanisms: - primitive expressions, which represent the simplest entities the language is concerned with, - means of combination, by which compound elements are built from simpler ones, and - means of abstraction, by which compound elements can be named and manipulated as units.

gtrak22:03:49

I don't think it's the 'simple' that makes it hard to learn, it's the garbage-in-garbage out, and also the host leaking through. But lots of people want to paint by numbers and plenty of other languages do a good job at that. The thing that 'simple' itself is responsible for is delaying gratification.

sundarj22:03:21

Simplicity doesn't necessitate something having many 'entry points'. The reason Clojure has all those features is that Clojure isn't merely an academic exercise: it's a practical language designed to be used to solve real-world problems, robustly and effectively, and those features are what Rich Hickey considers important in achieving that goal. They are a separate concern to its underlying philosophy of simplicity (in syntax or in semantics). Dynamic development doesn't follow from simplicity; nor does concurrent programming; or being a hosted language. They're orthogonal decisions.

gtrak22:03:38

Scheme might be a better choice for learning, since even though it doesn't do any better at 'simple', there's just less stuff, and it's introduced gradually in a well-considered order by people who thought a lot about teaching. ML might be a better choice because interacting with a complex compiler is probably going to help a lot for the earliest and most trivial kinds of mistakes.

sundarj22:03:10

In addition, the SICP mechanisms are just about the core language (e.g. def, let, fn) are they not? Are you asking about Clojure's core, or about Clojure's features beyond that?

sundarj22:03:09

Or about how the http://clojure.org website is structured (Rationale leading through to Features etc.)?

sundarj23:03:52

Clojure has a tiny amount of operators built into the compiler (https://clojure.org/reference/special_forms), but that's barely scratching the surface of Clojure as a whole

sundarj23:03:08

I think the way https://aphyr.com/tags/Clojure-from-the-ground-up approaches explaining Clojure is quite good

senorflor23:03:10

@U61HA86AG thanks for your notes and questions! I think “features” is indeed what I mean by entry points: each simplex feature is an entry point for a learner (e.g. vars vs refs vs agents vs atoms) at each point of considered language simplification (although note that in this case https://clojure.org/about/state is an ideal guide/motivation!). It’s in this sense that I mean there are many entry points at different language junctures due to simplification (which yet again is a good thing: it lays bare the false dilemma between Python’s one obvious Pythonic way and Ruby’s AllTheThingsAndSyntaxes design choices at important points in language design). Understand that I am entirely in agreement with: > The reason Clojure has all those features is that Clojure isn’t merely an academic exercise: it’s a practical language designed to be used to solve real-world problems, robustly and effectively, and those features are what Rich Hickey considers important in achieving that goal. but I am also a teacher by trade and disposition: I want to show and motivate and enable people as efficiently as possible, and with as high a conversion rate as possible, to see what’s so beautiful and useful about this sort of simplification cum pragmatism. So I’m just trying to find high leverage tools and paths and principles so that people can join in the fn. Re: SICP’s mechanisms, yes absolutely, it’s about def, let, and fn (actually values, lists, and def/`let`/`fn`/application to be precise pointwise) but (recursively) much more too: it’s about the basic things you introduce at any level of abstraction, the ways you can put them together to express/do useful things, and how you can then name/manipulate/generalize/export that usefulness to other realms.

senorflor23:03:38

I had forgotten about aphyr’s project: thanks so much for the reminder! Will post back here with the completed list/introductory structure I get out of this exercise.

sundarj23:03:22

I dabble in teaching myself, and I completely get where you're coming from! Please know I'm merely trying to get to the core of your question, so that I can better answer it 🙂

senorflor23:03:37

Awesome, I sensed as much, but neither text conversations nor S-expressions is very often sufficient to imply shared goals, so figured I would try to make them explicit 😄 really grateful for your questions and thoughts here.

sundarj23:03:51

One thing I feel is that the full scope of Clojure isn't really relevant to a learner. The only bits of Clojure they need to learn are those they're going to use; they can learn about the rest on an as-needed basis. It doesn't matter that Clojure has refs, agents, and atoms until you're in a position where you need to know about all of them. I have a vague sense of the differences between them, but since I've only ever needed to use atoms and vars so far, I don't actually need to

sundarj23:03:05

you can get very far only knowing about the language fundamentals, and perhaps a small but mighty subset of the standard library - the rest you can learn as you go

sundarj23:03:24

it's important not to delve overly deep into Clojure when there's no need for it

sundarj23:03:31

Whereas trying to isolate a minimal subset of, say, Ruby might be more difficult, since everything is built into the language, so you need to know about them, with Clojure, being a lisp, you can get by just fine without knowing most (or even all) of clojure.core, since you can write it all yourself once you've grasped how to write macros

sundarj23:03:58

the only time you need to know about clojure.core functions is when reading other people's code really, but that's rather far into the learning process

senorflor23:03:27

That’s a great point. Core of my question: what language features, ancillary tools/materials, ideas, and experiences have you found unusually effective in teaching newcomers to Clojure to () for themselves, and complementarily: is there anywhere you have observed people disproportionately getting stuck and dropping out? Any of three audiences: people coming from Javascript/web development; people coming from programming servers, especially in OO/OO+scripting languages; and beginners to programming. I’m not yet ready to believe that JS or Python is better to begin in 🙂

sundarj23:03:19

I actually think JS/Python are worse to begin in, due to their inherent complexity/largeness

sundarj23:03:47

especially JS has so many weird rules and quirks you need to be aware of

sundarj23:03:04

Python's no stranger to gotchas either though

sundarj23:03:26

funny you should mention those two, since they were my first two languages 😛

senorflor23:03:34

Likewise, but I think more people successfully begin there, at least by observation, thus driving me to this question.

senorflor23:03:51

🙂 that’s funny!

sundarj23:03:36

Well, one thing i've observed is that beginners don't necessarily need simplicity. What they need is small, easy, chunks to get their head around (which sure, it's helpful if the language itself adheres to those chunks, but it's far from a necessity). That's where their teachers come in - how you're being taught a language is vastly more important than the language itself

sundarj23:03:24

JavaScript is a very large language, but as long as you can start with console.log("hello world") and then move on to functions, it's not really an issue

sundarj23:03:24

teaching is a UX problem - doesn't matter that Wikipedia is vast, since its interface lets you explore it bit by bit, starting with the specific article you need at that given moment

sundarj23:03:20

a teacher is the interface between the student and what they're learning, and so the same sorts of approaches apply

senorflor23:03:14

@gtrak important point about the host leaking through. Re garbage-in-garbage-out, do you mean malformed/mistaken expressions -> yucky errors? If so thanks for the reminder that I have highly tuned stacktrace filters by now: really easy to forget as a blocker to interactive learning.

sundarj23:03:06

the biggest reason Python and JavaScript see so much success among beginners is that they're popular, so there's a lot of people teaching it and wanting to learn it (rather than any inherent learnability)

senorflor00:03:04

Yes, and good teachers also deftly redirect requests to get themselves out of the picture and to get students to the right resources/habits of resource finding at the right time. This is both to scale teaching as well as to self-obsolesce as a teacher! Want to keep growing my bag of tricks 🙂 301 Knowledge Moved Permanently

sundarj00:03:51

right! 🙂

senorflor00:03:59

Great points about small firewalled chunks and interactivity.

sundarj00:03:07

Some insightful things to read: http://worrydream.com/LearnableProgramming/ https://www.maa.org/external_archive/devlin/LockhartsLament.pdf Don Norman's The Design of Everyday Things (designing a user interface to be intuitive, approachable and delightful is isomorphic to teaching a given subject to be intuitive, approachable, and delightful: they're both about learning)

sundarj00:03:18

Eric Normand's https://www.youtube.com/watch?v=jJIUoaIvD20 is also quite good (in particular, the part about using physical metaphors to drive intuition)

sundarj00:03:05

An excellent example of using real-world metaphors is in Eric Normand's course on Category Theory: https://purelyfunctional.tv/courses/category-theory/

sundarj00:03:27

(you should ask him about teaching Clojure, he has lots of experience doing it!)

senorflor00:03:03

Nice, thanks, I think I was at the conj talk above; thanks @U050P0ACR!

sundarj00:03:21

very good point about self-obsolescence by the way. it's vital to teach learners how to become more adept and more self-sufficient learners; to become their own teachers. give a man a fish and whatnot 🙂

sundarj00:03:15

though there's somewhat of an art to balancing student agency and teacher aid: too much of one and the students don't learn enough about the subject to be self-sufficient, too much of the other and the students never learn to be self-sufficient

sundarj00:03:04

i recently had a teacher who left too much to the students, and needless to say my knowledge of and confidence in the subject suffered greatly

sundarj00:03:01

re: 'what language features, ancillary tools/materials, ideas, and experiences have you found unusually effective in teaching newcomers to Clojure to () for themselves, and complementarily' i think the repl is really important for this. it's one thing to talk at someone, but when that person is trying things for themselves and seeing the specific results of their own exploration, it really helps them to piece it all together. especially with things like https://www.maria.cloud/ and https://github.com/google/clojure-turtle, since they turn Clojure code into something more tangible

sundarj00:03:01

and that's also a major reason behind JavaScript and Python's success with beginners I feel. JavaScript has the browser, and Python has a REPL (albeit less interactive than Clojure's, though IDLE makes it somewhat better)

sundarj00:03:06

another thing Python has, which is quite cool to use interactively, is Tkinter

datran21:03:49

but the compiler freaks out while compiling, and it definitely works in the repl

datran21:03:58

let me hunt up an example

zylox21:03:22

it would probably be helpful to provide an example of what you mean by "freaking out"

datran21:03:41

(defonce ^{:private true} testatom (atom "hey"))

datran21:03:56

^that's in one namespace. then in another namespace:

datran21:03:31

(do (alter-meta! #'ns1/testatom assoc :private false) (reset! cirrus.domains.database/testatom "yo"))

datran21:03:45

That works fine in the repl, but when compiling I get this:

noisesmith21:03:37

oh, so you aren't altering meta on the atom, you are altering meta on the var holding the atom

datran21:03:48

Exception in thread "main" java.lang.IllegalStateException: var: ns1/testatom is not public, compiling:(proj/test.clj:134:15)

datran21:03:00

oh, yeah, good point

noisesmith21:03:29

is the do at the top level of the ns? I know there are special case rules for top-level do

zylox21:03:32

additionally...you can get around private with @#'

zylox21:03:31

try just calling (reset! @#'cirrus.domains.database/testatom "yo")

noisesmith21:03:41

@datran that is, (do ...) at the repl, or at the top level of an ns, doesn't act exactly like (do ...) inside a defn

datran21:03:20

hmm, let me play with that for a sec

zylox21:03:50

additionally, its not crazy to have a fn in that ns that sets the value for you

datran22:03:21

alright, that seems to be working!

zylox22:03:24

though that depends on what you are trying to present

datran22:03:43

so what in the world is @#' - does that read as deref the var-quote?

zylox22:03:01

its dark magic and you should use it sparingly

datran22:03:01

and why does that ignore private?

zylox22:03:13

private is....more of a suggestion than you might think it is

noisesmith22:03:19

because deref of a var ignores the metadata on the var

datran22:03:14

but it returns the value of the var?

noisesmith22:03:46

right, deref of a var gets its contents - a var is just another mutable container

datran22:03:58

okay, it all makes sense now.

datran22:03:15

thanks very much @noisesmith @zylox! 😄

zylox22:03:26

use this power wisely

greglook22:03:58

good for white-box unit tests, generally best avoided though

noisesmith22:03:21

arguably needing to do something like that exposes a design flaw in the original code - a mutable singleton that determines the correctness of your code is usually a bad idea - many prefer to pass such a thing as an argument rather than hard-code the global availability

noisesmith22:03:26

that makes testing much easier

gtrak22:03:51

senorflor: try the cheat sheet

gtrak22:03:06

a java guy i introduced clojure to thought it was a godsend

senorflor22:03:54

thanks @gtrak, I forgot about that!

gtrak22:03:07

for 'I want to program bottom-up, but learn top-down!' :-)

senorflor22:03:45

Re: the top down part, I’m doing some sort of CBT self-talk therapy on a thread at https://clojurians.slack.com/archives/C03S1KBA2/p1520375632000516?thread_ts=1520373219.000385&amp;cid=C03S1KBA2; let me know if you have any insight there too 🙂

roklenarcic23:03:30

here's a construct that comes up all the time, and I'm wondering if there's some kind of shorthand for it: (if (pred x) (f x) x)