Fork me on GitHub
#beginners
<
2020-03-07
>
Tzafrir Ben Ami05:03:01

speaking of next.jdbc, in case of a “simple” select statement (`select from where`) would it be more “appropriate” to use sql/find-by-keys? should also be more secure?

seancorfield05:03:06

@tzafrirben I would recommend you stick to the main API in next.jdbc and avoid next.jdbc.sql -- that's really only meant as a migration step from clojure.java.jdbc

seancorfield05:03:22

(that said now it's there, it will be supported forever)

👍 4
Tzafrir Ben Ami05:03:59

@seancorfield thanks for clearifiing - I’ve actually never used clojure.java.jdbc before and jumped straight to next.jdbc , and found this function in the https://github.com/seancorfield/next-jdbc/blob/master/doc/friendly-sql-functions.md. Make sense to me to stick to main API though

seancorfield05:03:04

Yeah, the SQL functions are very helpful sometimes, for very simple get/find/insert/update/delete operations. Feel free to use them. They are not going away. But remember that the core API is the only way to do anything more powerful.

jaihindhreddy08:03:17

I believe this is the third time I've seen you say this:

Feel free to use them. They are not going away. But remember that the core API is the only way to do anything more powerful.
Does putting this (with different phrasing possibly) in the docstring of next.jdbc.sql make sense? FYI this is what the docstring says today:
"Some utility functions that make common operations easier by
  providing some syntactic sugar over `execute!`/`execute-one!`.

  This is intended to provide a minimal level of parity with
  `clojure.java.jdbc` (`insert!`, `insert-multi!`, `query`, `find-by-keys`,
  `get-by-id`, `update!`, and `delete!`).

  For anything more complex, use a library like HoneySQL
   to generate SQL + parameters.

  The following options are supported:
  * `:table-fn` -- specify a function used to convert table names (strings)
      to SQL entity names -- see the `next.jdbc.quoted` namespace for the
      most common quoting strategy functions,
  * `:column-fn` -- specify a function used to convert column names (strings)
      to SQL entity names -- see the `next.jdbc.quoted` namespace for the
      most common quoting strategy functions.

  In addition, `find-by-keys` supports `:order-by` to add an `ORDER BY`
  clause to the generated SQL."

seancorfield18:03:51

@U883WCP5Z Not sure exactly what change you're suggesting? Feel free to submit a PR.

jaihindhreddy14:03:45

I just re-read all the docs, and found this section. Just wanted to confirm such a section existed.

In addition, convenience functions -- "syntactic sugar" -- are provided to insert rows, run queries, update rows, and delete rows, using the same names as in clojure.java.jdbc. These are in next.jdbc.sql since they involve SQL creation -- they are not considered part of the core API.
And sure enough, it already exists. No PR necessary. The docs are a delight to read. Thanks for all your hard work ❤️! The new Readme lib works great as well.

4
dil-h-jawan08:03:26

Hi all, I have started learning Clojure today : ) , to start with i wanted to loop over a sequence & print the index of an item if it matches a given value, I am doing two thing worng, 1. thinking in terms of imperative programming way 2. wrong syntax (lots of confusinon becuase of parens) How would this be done in a more functional way?

Alex Turok08:03:55

Hi! A couple things that I could suggest: 1. Make use of the map-indexed function. If you combine it with doseq you could achieve the desired result quite concisely 2. Take a look at the -> and ->>. 3. In your first let you have excessive vectors - you could skip wrapping each binding into its own vector and writing just (let [a 1 b 1] But to get a more detailed view at the problem, take a look at this SO question: https://stackoverflow.com/questions/4830900/how-do-i-find-the-index-of-an-item-in-a-vector (the top two answers + their comments for extra insights) And have a nice time diving into Clojure - you’d love it!

dil-h-jawan08:03:29

(let [[u -1] [idx -1]]                                      ; u,idx = (-1,-1) 
    (doseq [x [1 2 3 4 5 6]]                                ; for x in [1,2,3,4,5,6]
        ((inc idx) (if (= x 5) (let [u idx])))              ;       idx +=1; if x==5 : u=idx
    (println u)                                             ; print (u)
)

jaihindhreddy08:03:52

This returns a seq of indices at which 5 is present

(keep-indexed #(when (= %2 5) %1)
              [1 5 3 4 5 5 10])
Check out keep-indexed.

👍 4
dil-h-jawan09:03:25

thanks a ton 🙂

dil-h-jawan10:03:05

does % here represents a modulo operation?

hindol11:03:52

% is the function argument to an anonymous function #(...). If there are more than one, the arguments are named %1, %2 and so on.

hindol11:03:41

The modulo operation in Clojure is covered by rem and mod.

jaihindhreddy15:03:08

@UV136PREU Here are the relevant docs: https://clojure.org/guides/learn/functions#_anonymous_function_syntax In any case, I recommend reading that entire page.

Alex Turok08:03:55

Hi! A couple things that I could suggest: 1. Make use of the map-indexed function. If you combine it with doseq you could achieve the desired result quite concisely 2. Take a look at the -> and ->>. 3. In your first let you have excessive vectors - you could skip wrapping each binding into its own vector and writing just (let [a 1 b 1] But to get a more detailed view at the problem, take a look at this SO question: https://stackoverflow.com/questions/4830900/how-do-i-find-the-index-of-an-item-in-a-vector (the top two answers + their comments for extra insights) And have a nice time diving into Clojure - you’d love it!

dil-h-jawan09:03:52

@chaot8 thanks a ton for responding back, I was trying to get it solved myself, I have come something like this, i am going to look into the link you posted 🙂 :

(loop [i 0 arr '(1 2 3 4 5)]
    (if (< i 5)
        ; (if (= arr[i] 3)        
        ;     (println "yes"))
    (recur (inc i) arr))
    )

Alex Turok09:03:30

You’re welcome! But also definitely take a look at the answer by @U883WCP5Z - it’s more concise than what I suggested.

Alex Turok09:03:55

And one more: do explore the loop+recur, but keep in mind that it’s a very low level construct and normally you would avoid it unless there is no other option

dil-h-jawan09:03:19

I can't find an answer from @U883WCP5Z

Alex Turok09:03:48

It’s under your original question shown as reply

dil-h-jawan09:03:55

got it thanks 🙂

👍 4
Old account12:03:14

is there any function that tells shape of data. like [#{} [] {} ] or something

hindol12:03:29

I am not aware of any. But why do you need it? If you want to validate an input against an expected shape, there is clojure.spec

Old account12:03:38

during the development I am having some nested data strcture - I would like to see it's shape instantly

hindol12:03:25

For basic validation, there is also :pre and :post supported by fn and defn directly.

Old account12:03:52

it is for development only - for REPL

hindol12:03:26

Maybe just print to the REPL?

hindol12:03:53

There is pr, prn, pr-str, print, println and pprint.

Alex Turok12:03:03

You could use print (any flavor that suits you best) or you could go with ‘type’, which would tell you the exact underlying data type (although it may be too precise for your task). There are also collection kind testing functions like ‘map?’

pinkfrog13:03:26

for syntax quote, let =y= be a plain symbol

pinkfrog13:03:30

`y gives user/y,

pinkfrog13:03:53

why y give (quote user/y) . while `user/y is still user/y ?

4
jsn17:03:45

syntax quote resolves all symbols, so for qualified symbols like user/y nothing changes, and for unqualified symbols the current namespace (`user` , in your case) is added

pinkfrog13:03:39

\`\`\`y . three `here becomes (clojure.core/seq (clojure.core/concat (clojure.core/list (quote quote)) (clojure.core/list (quote user/y))))

Michał 'Chlebik' Piotrowski14:03:36

Hello. Is there Clojure-roadmap somewhere? Eg. something similar to this one: https://github.com/Alikhll/golang-developer-roadmap

Michał 'Chlebik' Piotrowski20:03:04

I meant 'learning' roadmap like I've put in the example. No the language development roadmap.

seancorfield21:03:14

Ah, gotcha. I didn't look at the link because the only context I've ever heard for "roadmap" around languages is how they evolve. Never heard of a "roadmap" for learning.

Chase18:03:39

I'm still not comfortable with taking in user input. Is there a guide somewhere on read-line and read and various IO/input things? Is everything read as a string? I find myself assigning the input to a name using let and then going from there. Is that idiomatic? The docstring for read-line is "Reads the next line from stream that is the current value of in ." I am not familiar with streams and what exactly is meant by in. read 's docstring brings in a lot more unfamiliar, java-ish terms.

seancorfield18:03:41

The core team are planning the 1.11 release at the moment. But changes to Clojure are very conservative because the team values backward compatibility.

andy.fingerhut18:03:20

read-line reads everything as a string. read attempts to parse text input as Clojure data/code.

andy.fingerhut18:03:57

*in* is roughly equivalent to standard input on Unix/Linux. *out* is like standard output.

Chase18:03:23

And when is it necessary to use this flush thing?

Chase18:03:30

If I'm taking a 2nd input?

andy.fingerhut18:03:25

There is a Clojure cheat sheet with an IO section that groups IO-related Clojure functions there, also with some links to Java Reader, Writer, InputStream, and OutputStream classes, that would be good to at least be aware of, even if you don't dive into the details: https://clojure.org/api/cheatsheet

andy.fingerhut18:03:37

It also groups most other Clojure functions into related groups, too, not just IO

andy.fingerhut18:03:55

Many kinds of IO use 'buffered' readers and writers for efficiency. If you do some printing to a buffered output stream, and want to make sure the in-memory buffer contents are forced out, i.e. flushed, you may call flush . There is usually a similarly-named function provided in most programming languages for the same purpose.

andy.fingerhut18:03:59

Useful for forcing debug output to appear in files, logging-destinations, etc. near times where you expect the program to crash, or if you need to make sure that everything you have printed to some destination is actually there, before proceeding to some next step that expects all file contents to be there.

jumar06:03:04

Note that flush usually means only “flush to OS managed buffers” not actual storage- that’s what fsync is for

Chase18:03:11

Thank you! Sadly I do know of those docs but reading it isn't clearing things up. All those Java things you mentioned are unfamiliar. It's a big fear in my Clojure development that my lack of any experience, but especially Java experience, is really going to hold me back despite others saying they don't use much Java and I can't find the learning materials within the Clojure ecosystem to fill in those gaps.

andy.fingerhut18:03:26

Depending upon what you are doing, you can often get by without knowing the Java things. e.g. with-open to open a file for reading, using a file name given in a string, and then using calls to read-line and similar functions inside of there, is commonly done.

Chase18:03:54

When folks say they use Spec "at the boundaries" are they referring to taking in user input like this? Since these kinds of things are super side effect-y and non-pure right?

Chase18:03:43

That does make sense. I'm probably being overdramatic. I just really like Clojure but always have this feeling I don't understand anything going on under the surface/nice abstractions that it provides.

andy.fingerhut18:03:14

It is useful to know the name of the Java class Reader since you will come across that term when looking at docs. It is simply a "file handle" returned when opening a text file using one of several functions, one being http://clojure.java.io/reader, that you can then use to read that file as text. The Reader class handles various kinds of text encoding for you.

andy.fingerhut18:03:18

I understand how disorienting it can feel when getting into a new programming language, or any kind of technology/art/science where most things are unfamiliar. This beginners channel can be a pretty useful place to ask basic questions when getting started.

Chase18:03:03

Definitely. I love this slack. I miss it when exploring other languages. I've been dabbling with programming/Clojure for a while now though but don't seem to progress much. So mostly looking for scapegoats when I keep struggling. Hahaha. Thanks for the chat and advice!

andy.fingerhut18:03:34

If you are interested enough in Clojure to spring for the cost of a book, there are several good ones available. I'm not the best resource to pick the 'optimal' book for you, but ones like "Programming Clojure, 3rd ed", and "Getting Clojure" I have heard good things about, and would be worth checking reviews / samples on-line

Chase18:03:07

I have those books and more! I've read through them. My real problem I think is I don't build my own projects. I keep flitting about tutorials. I'm basically everything Rich disagrees with here: https://gist.github.com/stijlist/bb932fb93e22fe6260b2

Bobbi Towers04:03:40

Ha! I just read this and feel totally called-out! Fellow "perpetual beginner" here. I do feel that my excessive "flitting about" is somewhat justified by my admittedly dense skull - I feel that I need to experience concepts from as many different angles as possible before I truly grok them.

Chase18:03:14

I'm trying to get away from that.

Chase18:03:54

I keep switching languages and trying out their beginner tutorials

Chase18:03:03

Perpetual 1st year programmer kind of thing I think

andy.fingerhut18:03:04

Makes sense. Any application areas you are especially interested in when it comes to programming?

andy.fingerhut18:03:34

"Makes sense" meaning "understood", not "I recommend continuing with that approach" 🙂

Chase18:03:54

I do want to build full stack web apps which seems right in the CLJ/CLJS wheelhouse but I convince myself I don't understand the underlying fundamentals of web development/java/js.

andy.fingerhut18:03:36

If you don't need JavaScript/cljs right away for the interactivity they provide in a web page, you can probably save yourself a lot of time by focusing on the 'back end' part first, since that is needed in pretty much any web dev. (Unless you really prefer JavaScript/front-end design/interactivity aspects of web dev).

Chase19:03:16

I agree and that's what I'm going to explore now. I was told here a while back to just start with Ring, Compojure, and maybe hiccup or selmer and build a little app and I've been seeing now why.

andy.fingerhut19:03:29

It certainly sounds like good advice to me. Start with a small set of libraries that people have found are enough to get a lot of things done, and practice making something with those, asking for help on things if you get stuck. Save the "taking over the world new web site" for next year 🙂

Chase19:03:33

Yup, that is who was giving me that great advice earlier. I need to start listening! Lol. Thank you.

Chase19:03:59

... And despite what I just said, I'm currently recreating little temperature and weight converter command line tools for myself as I'm currently living down in South America. Hence the question on user input because I was struggling with it.

Chase19:03:07

Thanks again for the chat and encouragement!

andy.fingerhut19:03:29

FYI, reading from *in* can be a little strange (or impossible?) in some Clojure REPL environments, because Clojure and the REPL env 'fight' over who gets to read the input. Not all have problems, but some do. Reading from *in* interactively is probably best done in a Clojure program that you start from the terminal, rather than in a REPL situation.

andy.fingerhut19:03:12

In a REPL situation, simply passing 'Fahrenheit temp to convert' as a parameter to a function is more reliable than reading from *in*

Chase19:03:42

I've encountered that already. Yup! By "starting from a terminal" do you mean like using lein run ?

Chase19:03:16

Gotcha. Yup, that's the little things I am finally learning from real world experience.

andy.fingerhut19:03:45

If you write a Clojure function that reads from a named file on the file system, then calling that from a REPL should not encounter that problem.

hindol19:03:09

When writing programs that read from stdin, I create a file named stdin and bind *in* to it. Typing the input everytime is a hassle anyways.

Gulli22:03:02

Anyone here use Calva? I'm using Repl and it's like the clojure.repl namespace is not available, I can't doc functions

hiredman22:03:31

You need to require(causing the code to be loaded) a namespace before that kind of thing works

Gulli22:03:42

Never mind, the repl was messed up. It's good now 🙂

Gulli22:03:36

Yeah I had required it. I was starting to think I was going mad. Turns out the Repl was in some limbo state, just needed a good restart 🙂

Guillermo Ithier22:03:26

Hello everyone. I'm getting this error I can't figure out while installing lein

Guillermo Ithier22:03:38

Leiningen on my Mac: sudo mv lein /usr/local/bin/lein                           Password: mv: lein: No such file or directory sudo chmod a+x /usr/local/bin/lein lein version Downloading Leiningen to /Users/guillermoithier/.lein/self-installs/leiningen-2.9.2-standalone.jar now...  % Total  % Received % Xferd Average Speed  Time  Time   Time Current                  Dload Upload  Total  Spent  Left Speed 100  618 100  618  0   0  2414   0 --:--:-- --:--:-- --:--:-- 2414 100 13.9M 100 13.9M  0   0 6470k   0 0:00:02 0:00:02 --:--:-- 8713k shasum: /Users/guillermoithier/.lein/self-installs/leiningen-2.9.2-standalone.jar.pending.shasum: no properly formatted SHA1 checksum lines found Failed to properly download https://github.com/technomancy/leiningen/releases/download/2.9.2/leiningen-2.9.2-standalone.zip The checksum was mismatched. and we could not verify the downloaded file. We expected a sha256 of 09805bd809656794cfe7d9155fd4b8bea2646092318690bf68e3c379574a2d3c and actually had 13174ff1bd353dbe2bdc5f20093d6b2d4139fd35da10131c17bbe83f0328dd1c. I'm not sure where to go from here.

Guillermo Ithier22:03:43

I did run this script before the other scripts:

curl  > lein