Fork me on GitHub
#beginners
<
2019-09-06
>
JoshLemer01:09:36

I wonder why clojure's relational algebra functions (in clojure.set) are based off of "tables" being sets of maps, when relations aren't usually sets (they can contain duplicate rows)

Alex Miller (Clojure team)01:09:55

relations are usually sets

Alex Miller (Clojure team)01:09:31

your sql databases have ruined you by giving you bags :)

âž• 4
JoshLemer01:09:13

hehe ok I stand corrected

Alex Miller (Clojure team)02:09:42

if you read Codd's original database stuff (like https://www.seas.upenn.edu/~zives/03f/cis550/codd.pdf), it's sets. later was extended to bags and that became the norm in sql.

JoshLemer02:09:45

Cheers! 🍺

tjb02:09:01

hey team im still a little confused by the quote macro https://clojure.org/reference/reader#_quote would someone be able to give me another example of the usage outside of the one provide? or some additional context around it?

tjb02:09:54

i came across this which led me to ask why use the quote macro

tjb02:09:56

(require '[honeysql.core :as sql]
         '[honeysql.helpers :refer :all :as helpers])

Alex Miller (Clojure team)02:09:37

the Clojure evaluation model is to read (turn characters into Clojure data), then evaluate that Clojure data

Alex Miller (Clojure team)02:09:46

most things in Clojure evaluate to themselves

Alex Miller (Clojure team)02:09:21

the two main special cases are symbols (which evaluate to what they refer to) and lists (which invoke the first element of the list with the other elements as args)

Alex Miller (Clojure team)02:09:33

quote means: read but DON'T evaluate

❤️ 4
Alex Miller (Clojure team)02:09:58

so the places where quote is useful are mostly where you want to suspend evaluation - symbols and lists

Alex Miller (Clojure team)02:09:27

in the case above the quote is being used to avoid evaluation of symbols

Alex Miller (Clojure team)02:09:19

as a shortcut it's being used on the vector, but really it's like

(require ['honeysql.core :as 'sql]
         ['honeysql.helpers :refer :all :as 'helpers])

Alex Miller (Clojure team)02:09:46

that's obviously tedious so quoting the outer vector is kind of a short cut

Alex Miller (Clojure team)02:09:57

another place you'd want to avoid eval is with lists

Alex Miller (Clojure team)02:09:04

(1 2 3) will try to invoke 1

Alex Miller (Clojure team)02:09:21

but '(1 2 3) is the read list holding elements 1 2 3

tjb02:09:12

ah so the read list != (1 2 3), correct?

Alex Miller (Clojure team)02:09:36

(1 2 3) will be read as the list but THEN evaluated

Alex Miller (Clojure team)02:09:43

quoting it says read but DON'T evaluate

tjb02:09:48

OHHHHH ok

tjb02:09:18

would you be able to give a "real world" example of when you would want to use a read list?

Alex Miller (Clojure team)02:09:35

doesn't come up quite as often

Alex Miller (Clojure team)02:09:59

but a lot of the power of Clojure/Lisp/homoiconicity is that your code IS data and you can manipulate it as such

Alex Miller (Clojure team)02:09:12

and that means you can make a dsl that uses literal lists and choose to interpret it

Alex Miller (Clojure team)02:09:35

the ns macro is such a dsl

Alex Miller (Clojure team)02:09:59

you used vectors above in require but it can take lists too

Alex Miller (Clojure team)02:09:15

spec is another example - in (s/def ::foo (s/and int? pos?)) - the (s/and int? pos?) is a symbolic form interpreted by a spec macro

tjb02:09:43

ok ok cool, ima do more reading / playing around but that makes sense (sorta because i am still new) i have starred your responses to refer back to them. thanks for taking time to explain that to me @alexmiller i truly appreciate it

Alex Miller (Clojure team)02:09:39

well they will fall off the archive within a day or two fyi

jumar05:09:28

btw. the limit doesn't apply to Starred messages in the usual way - at least I can still see my starred messages from 2018

seancorfield06:09:08

True, you can see any messages you've Starred -- but you can't jump to them (and see the conversation in context) for older ones.

tjb02:09:59

ah! ill screenshot then 🙂

tjb02:09:02

thanks for the heads up!

seancorfield02:09:09

They are archived in Zulip...

Alex Miller (Clojure team)02:09:10

if you want more, go buy Programming Clojure and Clojure Applied :)

đź‘Ť 8
seancorfield02:09:58

Most channels here are archived in Zulip (and searchable) going back to near the start of 2019.

tjb02:09:09

!! awesome thanks Sean

seancorfield02:09:23

They're also logged here https://clojurians-log.clojureverse.org/ but that service has been a bit in flux as the maintainer has had a number of problems with the pipeline of data processing and keeping the server processes stable. It should become stable and up-to-date in due course.

seancorfield02:09:14

(right now I think the clojureverse log archives are only processed to the end of August)

seancorfield02:09:29

Zulip is a nice way to catch up on conversations here because the client is all keyboard driven -- and you can read almost any Slack channel there, even if you're not a member of the channel here!

seancorfield02:09:48

@tjb How's your Clojure learning going so far?

tjb02:09:27

honestly a little slow but i am learning! having some end goal def helps a lot more than "do these practice problems"

tjb02:09:48

in my example, i have the logic already done for what i want in node now i just need to port it over which def helps me a ton

tjb02:09:12

i can think less of "how should i do this" and more of "how would i do this in clojure"

đź‘Ť 4
seancorfield02:09:10

Yeah, I hear ya! At work we're rewriting one of our legacy apps, switching it to Clojure, and while it's mostly "grunt work" it's often an opportunity to enhance the functionality in ways that would have been harder in the old code because so much of it turns into data manipulation in Clojure and that makes it easier to do more with it, without adding a lot of code...

tjb02:09:02

totally! i would also be open, once im done migrating things over, to have people take a look at the code and critique it since i dont really have anyone doing code reviews for me

seancorfield02:09:26

There's a #code-reviews channel for when that time comes.

seancorfield02:09:23

One of the things about our app rewrite is that it's a JVM app already and we're calling into Clojure code from the legacy code as we rewrite pieces. So I provide a JVM option at start up for Clojure's runtime to start a Socket REPL, and then I can connect my editor into the running legacy app and do live RDD into the app without needing to restart and reload etc. I love that about Clojure.

‼️ 4
seancorfield02:09:35

(we have Socket REPLs running in several production apps -- including the production version of this legacy app -- which allows us to apply live patches if something critical comes up, so we don't need to have a full deployment/downtime for some stuff)

tjb03:09:25

that is super cool

tjb03:09:39

perhaps one day if the need comes i can convince my team to use clojure

borkdude09:09:07

@seancorfield I find that super useful too (REPL in production)

borkdude09:09:18

even if only for inspection of weird problems

lech4311:09:55

Hello. I've been learning clojure.spec recently. I'm curious that the error message is not detailed in instrumentation.

seancorfield18:09:36

@lech9343 FWIW, here's what I see in the default REPL:

(! 544)-> clj -A:test
Clojure 1.10.1
(ns myspace.test
 (:require [clojure.spec.alpha :as s]
           [clojure.spec.test.alpha :as st]))
nil
(defn square [x]
 (* x x))
#'myspace.test/square
(s/fdef
 square
 :args (s/cat :num number?)
 :ret number?)
myspace.test/square
myspace.test=> (st/instrument `square)
[myspace.test/square]
myspace.test=> (square "3")
Execution error - invalid arguments to myspace.test/square at (REPL:1).
"3" - failed: number? at: [:num]
myspace.test=> 
You do get the extra information you want. I also tested lein repl (for Leiningen 2.9.1) and it also prints that extra information. So this seems to be a Cursive problem (maybe ask about error reporting in the #cursive channel).

lech4311:09:12

(ns myspace.test
 (:require [clojure.spec.alpha :as s]
           [clojure.spec.test.alpha :as st]))

(defn square [x]
 (* x x))

(s/fdef
 square
 :args (s/cat :num number?)
 :ret number?)

(st/instrument `square)
(square "3")
this is my code

lech4311:09:24

Syntax error (ExceptionInfo) compiling at (test.clj:14:1).
Call to #'myspace.test/square did not conform to spec.
this is the printed error message.

lech4311:09:34

Call to #'myspace.test/square did not conform to spec: 
val: "3" fails at [:args] predicate: number?
I want to see this error message. Is there a way?

lech4311:09:49

My dev environment is Win10 + intellij + cursive. And dependencies of project.clj is,

:dependencies [[org.clojure/clojure "1.10.0"]
              [org.clojure/test.check "0.10.0"]]

Leon11:09:55

For readable spec errors I'd recommend checking out expound

lech4311:09:02

Oh thank you. ill check it right now

oliver11:09:17

Hi everyone! I have a question on how to best begin studying ClojureScript. Here's my current situation: I'm new to ClojureScript, but have been a Lisper for a couple of years already (CL, Emacs Lisp and Clojure). Only recently though have I decided to take my programming to the web… so far I have taken udemy classes on PHP, HTML, CSS and Javascript. I have now ordered “Learning ClojureScript” and “Reactive with ClojureScript Recipes” in order to take a swing at ClojureScript in the near future. Since I'd like to use the Reagent library I thought I'd first get a basic grip on the React framework. Most resources on React (including the top classes on udemy) start by introducing JSX and build everything from there. According to my superficial understanding, however, ClojureScript doesn't use JSX but Hiccup… so maybe given my ultimate goal I shouldn't even invest time and effort into yet another set of syntactic rules I'm not going to actually use… What do you think? Do you know any good resources that teach React in plain JS, rather than JSX? Should I just dive into Clojurescript+Reagent right away with the books I ordered? Happy to read your thoughts on this!

danielneal11:09:56

Current react and reagent have diverged a bit. If you’d like to learn reagent, it’s probably best of just jumping in with reagent. The way state is handled - with r/atoms - and how renders are scheduled - is different from basic react, and hiccup is different from jsx so it’s easier to just jump in imo. Current react in a functional style tends to favour use of hooks, which are not really used in reagent, you’d need to look at a different lib like hx

danielneal11:09:50

Reagent is pretty fun and straightforward to pick up - in some ways, less to think about than react itself

manutter5111:09:18

I use reagent/re-frame a lot, and honestly there’s very little React-specific stuff I actually use. It’s a good idea to know at least how the basic React component lifecycle in case you need to write any advanced components, but the Reagent stuff is largely “independent” of React, in terms of how the developer experiences it.

sheepy 4
manutter5111:09:05

Reagent lets you use React props and so on, but I almost never even think in terms of props, except in the case of advanced components, or interacting with React libs that use them (which I personally rarely do).

manutter5111:09:28

So I’d say yeah, just go for Reagent, and pick up the React details as you need them.

oliver11:09:39

@manutter51 @danieleneal Many thanks to both of you… that's actually good news for me!

zav15:09:40

Anyone know of a good library (Clojure or Java) for converting PDF files to some kind of Clojure-like data structure? I have a group of about 300 PDFs that my company receives monthly. Each month, it takes an individual about a week to read all of the data on it and move it to an Excel spreadsheet for our Ops team. That's an enormous amount of time for us and we're looking to automate it. My task is to build a PDF parser, nothing crazy advanced, to read in a PDF file and pull specific blocks of data from it (typically in table form). My plan right now is: 1. Read PDF file 2. Convert to HTML 3. Parse HTML to map via hiccup/hickory/etc... 4. Extract wanted data table via a get-in 5. Convert data table to a structure I can efficiently work with based on my reqs from the next step 6. Write to a file our Ops team likes (Not sure what this is going to be yet, probably CSV to import to Excel) Where I'm hung up is the PDF -> Data step. I've found dotemacs/pdfbox on GitHub which allows for PDF->String but the string parsing is wildly complex and not a simple thing to expand on in the future. Does anyone know of a Clojure or Java library that I can use to convert from PDF to HTML or have an approach to convert from PDF to data?

madstap15:09:56

Not exactly what you're asking for, as it's a paid service, but @U09A6U6GJ's https://www.pdfdata.io/ does this. PDFs are fundamentally terrible at transmitting data, so I'm not sure you're gonna get something better that a wildly complex string that'll be fun* to parse. *not fun

JoshLemer16:09:49

Hey I saw that quite some time ago, the clojure developers created an implementation of rrb-vector here https://github.com/clojure/core.rrb-vector, was wondering why that never replaced the standard vector implementation, my understanding after reading the paper (and looking at scala implementation benchmarks) is that it strictly dominates the traditional vector

andy.fingerhut17:09:03

@joshlemer I have been doing some bug fixing on that library recently -- I do not think it has reached the quality/reliability level that one would wish before considering including it in Clojure core.

andy.fingerhut17:09:06

Even if it ever gets to that point, the Clojure core team is very cautious and selective about what they choose to include in core, and having it as a separate library available via a single require and a single dependency added to your project is not a big hurdle.

andy.fingerhut17:09:16

The current core.rrb-vector implementation in that library is also slower than the built-in Clojure vectors, when you restrict yourself to operations that are supported by both.

andy.fingerhut17:09:00

not in the big oh notation run times for operations, but in the constant factors, which are also important.

JoshLemer17:09:50

>The current core.rrb-vector implementation in that library is also slower than the built-in Clojure vectors, when you restrict yourself to operations that are supported by both. Ah, that’s not ideal, and makes sense that it isn’t the default vector until/unless that changes

seancorfield18:09:36

@lech9343 FWIW, here's what I see in the default REPL:

(! 544)-> clj -A:test
Clojure 1.10.1
(ns myspace.test
 (:require [clojure.spec.alpha :as s]
           [clojure.spec.test.alpha :as st]))
nil
(defn square [x]
 (* x x))
#'myspace.test/square
(s/fdef
 square
 :args (s/cat :num number?)
 :ret number?)
myspace.test/square
myspace.test=> (st/instrument `square)
[myspace.test/square]
myspace.test=> (square "3")
Execution error - invalid arguments to myspace.test/square at (REPL:1).
"3" - failed: number? at: [:num]
myspace.test=> 
You do get the extra information you want. I also tested lein repl (for Leiningen 2.9.1) and it also prints that extra information. So this seems to be a Cursive problem (maybe ask about error reporting in the #cursive channel).

lech4323:09:45

@seancorfield ah it's related in cursive's repl. Yesterday I checked printing entire error message in clojure 1.9.0, so I decided to use it. But from that, I should change the repl setting to lein. thx