Fork me on GitHub
#beginners
<
2021-08-11
>
Edward Ciafardini02:08:46

I want to iterate over this map and run a function on each phone number... I have been trying it with doseq, but I keep running into errors. Any advice? (pretty new to clojure here). (Phone numbers belong to friends, blurred out in example code)

(defonce people (atom {"dane"        
{:name "dane" :phone "+1######"}
                       "me"          
{:name "me" :phone "+1#########"}
                       "john"        
{:name "john" :phone "+1########"}
                       "steve"       
{:name "steve" :phone "+1########"}
                       "anoushe"       
{:name "anoushe" :phone "+1########"}
                       "dominique"   
{:name "dominique" :phone "+1#######"}
                       "flynn"       
{:name "flynn" :phone "+15555555555"}
                       "ted"         
{:name "ted" :phone "+1########"}}))

dpsutton02:08:51

get rid of the complication. make a function that does what you want on a single phone number and then figure out how to do it multiple times

dpsutton02:08:39

(defn text [phone-number] (twilio/send ...)) and then (run! text (map :phone @people))

dpsutton02:08:41

or (reduce (fn [text-results person] (conj text-results (text (:phone person)))) [] @people) or whatever you need

dorab02:08:21

@dpsutton You might have a slight typo (it's hard to read the example). Perhaps it should be (run! text (map :phone (vals @people))) ?

dpsutton02:08:07

probably. i didn't pay attention to the shape very much and assumed it was a vector of maps. but yeah whatever the shape calls for

girish02:08:23

I am building a cli app, I can build a uberjar ok. But when trying to use lein-bin https://github.com/Raynes/lein-bin I get following error

> lein --version
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Leiningen 2.9.6 on Java 17 OpenJDK 64-Bit Server VM

> lein bin
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
'bin' is not a task. See 'lein help'.
Here is my project.clj
(defproject gen-types "0.1.0-SNAPSHOT"
  :description "xyz"
  :dependencies [[org.clojure/clojure "1.10.1"],
                 [clj-http "3.12.3"]
                 [org.clojure/core.match "1.0.0"]
                 [lein-bin "0.3.4"]
                 [tupelo "21.07.08"]]
  :main gen_types.core/-main
  :paths ["src"]
  :repl-options {:init-ns gen_types.core}
  :profiles {:uberjar {:aot [gen_types.core]
                       :main gen_types.core}}
  :aot [gen_types.core]
  :bin {:name "gen-types"
        :bin-path "./bin"
        :bootclasspath true})
Googling didn’t help. Any hints?

dpsutton02:08:26

i think you need it as a plugin not as a regular dependency?

girish03:08:01

wow.. it worked. Thanks @dpsutton!

popeye10:08:43

y it returns true if we use every?

pyry10:08:58

Because there is no element in the empty list that doesn't satisfy the predicate. 🙂

seancorfield15:08:09

@U01J3DB39R6 Essentially for the same reason these 0-argument calls work and return the values they do:

dev=> (and)
true
dev=> (+)
0
dev=> (*)
1

Dmitrii Pisarenko16:08:47

Hello! Imagine I need to traverse a long sequence x (e. g. all integer numbers) until I find a pair of elements with indices n and (n+1) such that there is a particular relation between x[n] and x[n+1]. What is the preferred Clojurian tool for traversing such sequence with having access to both current and previous (or next) element? I feel that I could do this with transducers, but maybe there are other constructs.

Russell Mull16:08:04

If I understand correctly, this can be implemented using the partition function's step argument. (https://clojuredocs.org/clojure.core/partition)

dpsutton16:08:14

i would do

(let [xs (range)]
  (loop [[x_n x_n1] xs
         idx 0]
    (if (f x_n x_n1)
      idx
      (recur (rest xs) (inc idx)))))

Russell Mull16:08:47

(->> (range) (partition 3 1) (take 5))
((0 1 2) (1 2 3) (2 3 4) (3 4 5) (4 5 6))

David Caudill20:08:59

can anybody confirm whether Cursive is even supported/documented for Windows?

David Caudill20:08:30

i am on about my 3rd day of trying to make Clojure work in windows with SOME kind of modern-ish workflow and I can't find anything usable

seancorfield20:08:26

@davidkcaudill Have you asked in the #cursive channel where the author/maintainer @cfleming is and can respond?

David Caudill20:08:49

nope, will do!

seancorfield20:08:15

@davidkcaudill I pointed you at the #cursive channel on Monday 🙂

David Caudill20:08:46

i probably just moved on to try one of the seven other semi-working things i've monkeyed with this week facepalm

David Caudill20:08:11

my HOPE is that i can have roughly the same workflow on Mac and windows

seancorfield20:08:02

The only way I've gotten "the same" workflow on Mac and Windows is to use WSL2 on Windows but YMMV.

David Caudill20:08:28

emacs i guess?

seancorfield20:08:05

(I have no idea how Cursive works on Windows with WSL2 -- VS Code has a really slick integration: it effectively runs nearly everything on WSL2 as a headless server and you have the usual slick UI on the Windows side that talks to it)

seancorfield20:08:58

Emacs is... its own hill to climb... I used it on and off for twenty years but just got tired of dealing with its quirks (and switched to Atom in 2015, then VS Code a year or so ago).

David Caudill20:08:04

yeah i am just trying to get to the place where i can spend the time learning the language

seancorfield20:08:48

I like the VS Code syncs all of its settings and extensions across all your machines. So if I install something on the Mac, it appears on my Windows laptop shortly after, and vice versa.

David Caudill20:08:28

is this Calva or something else?

seancorfield20:08:48

VS Code handles all the sync on its own. I have Calva installed for all the code assist/static analysis. But we don't use nREPL at work so I have that disabled (and use Clover instead with a Socket REPL). For the vast majority of VS Code Clojurians, Calva is going to be all you need.

seancorfield20:08:13

I didn't realize VS Code sync'd everything so well when I set it all up on my Mac so I'd taken careful notes about what extensions I installed and what settings I'd tweaked... then I installed it on Windows, signed into GitHub for the sync and... bingo! Everything just magically appeared on Windows, from my Mac!

🙌 2
David Caudill20:08:29

ok, trying Calva now I guess.

seancorfield20:08:08

There's a #calva channel (of course) -- and the Getting Started experience in Calva is really good! @pez has spent a lot of time and effort on that.

David Caudill20:08:39

yeah these docs are tremendous

seancorfield20:08:54

(just bear in mind timezones -- the maintainer of Cursive is in NZ and pez is in Sweden)

David Caudill20:08:36

solo projects in both cases?

pez20:08:36

Calva is a team effort. In the #calva channel users and maintainers help each other.

David Caudill21:08:42

It's very polished, great work!

❤️ 4
David Caudill21:08:05

ok so one glaring thing missing in my onboarding to this language is expectations. I have worked a lot in REPL oriented languages(R, Python, PowerShell), but I don't know what to expect in terms of dev experience. Can I connect a REPL with a running process? how should i expect this process to be different than working on a compiled language?

hiredman21:08:29

I would expect clojure's repl to feel most like a shell. Other languages are usually built around notions of programs existing in files, so things like parsing, analysis, compilation/interpretation are often built around operations on files

hiredman21:08:44

but shells, as command line interfaces have semantics around interpetting/running a command at a time, and usually process script files as just one command after another

hiredman21:08:20

and while clojure is compiled, the unit of compilation is top level form (what you type into a repl) so it has more in common with that shell style execution

hiredman21:08:07

something to keep in mind is the jvm is multithreaded, so it is very easy to have multiple repls connected to the same clojure process, or to fire off other threads to do things in the repl (again more similar sort of to shells then a lot of languages with repls that don't have good multithreading support)

David Caudill21:08:59

For instance, in a lot of powershell and R development, your commands are fed to an interpreter and it's easy to inspect a given object and determine what's in it...but also sometimes messy because of runspace surprises

David Caudill21:08:21

Similarly, sometimes i have had to connect a Scala REPL to stuff like spark and poke around as part of debugging

alexmiller21:08:14

Loading a Clojure source file == reading (string -> Clojure data) and evaluating each top level form, so identical to you typing it into a REPL

alexmiller21:08:54

there is no interpreter (small lie, there kind of is for very simple cases but above is still true)

alexmiller21:08:28

loading a compiled Clojure file is a bit different but designed to mimic the above in most respects

alexmiller21:08:49

you cannot generally connect a REPL to a running process, unless that process was started with that intent (which is pretty easy to do). if you do connect, you are doing the same thing as above. vars can be redefined at the repl, allowing you to change the running program.

David Caudill21:08:38

thank you! What's the most common way that people use the REPL to debug?

alexmiller21:08:57

this is a large and highly varied topic :)

alexmiller21:08:52

https://clojure.org/guides/repl/enhancing_your_repl_workflow#debugging-tools-and-techniques is a start (the greater guide that's in may lead you to other tools too)

🙌 2
alexmiller22:08:10

In Clojure "debugging" and "programming" at the REPL are to a large degree the same thing rather than two topics

David Caudill22:08:37

ok so what's the best way to inspect/reflect an object in the REPL? like in Python one would use dir(object)

David Caudill22:08:18

I am seeing inspect() recommended a lot but it doesn't work in REPL...which lead me down the rathole of how to add libraries to the REPL

seancorfield22:08:55

What sort of "object" @davidkcaudill?

seancorfield22:08:09

Clojure's data structures just print "as-is".

David Caudill22:08:31

ok so this is likely a lingering OOP thing that i just can't translate

✔️ 2
David Caudill22:08:57

but essentially one would do this in other languages to learn the methods and properties of an object

seancorfield22:08:07

I mean, we interop with Java objects from time to time, but Clojure doesn't really have objects -- just data.

ghadi22:08:12

No objects, just data

David Caudill22:08:19

and data has no methods or properties

seancorfield22:08:35

Data is just data.

alexmiller22:08:45

just use prn

2
seancorfield22:08:25

Or clojure.pprint/pprint if you want the data laid out nicely.

David Caudill22:08:38

type() is helpful too

alexmiller22:08:53

less than you'd think :)

seancorfield22:08:06

(keys some-map) might be helpful for you.

David Caudill22:08:24

oh i like that one

David Caudill22:08:44

yeah i generally need ways to poke/learn as i work, this is all helpful, thanks folks!

David Caudill22:08:15

i am ok "trusting the process" with learning a language but i don't think i've ever felt like i suspended disbelief this long in order to learn one

David Caudill22:08:53

it's gonna take me all week to get over this weird implementation of and

David Caudill22:08:38

Clojure uses the Boolean operators or and and. or returns either the first truthy value or the last value. and returns the first falsey value or, if no values are falsey, the last truthy value. 

alexmiller22:08:08

logical false = nil | false logical true = everything else

David Caudill22:08:45

ok but:

user=> (= false nil)
false

David Caudill22:08:41

so nil is not equal to false, but both would evaluate to false in a conditional?

David Caudill22:08:49

ok makes sense!

alexmiller22:08:58

you can use the boolean function to coerce logical boolean to actual boolean

alexmiller22:08:13

other predicates of use: true? false? nil?

alexmiller22:08:29

and this is probably a good time to point to https://clojure.org/api/cheatsheet

🙌 2
David Caudill22:08:25

excellent thank you!

alpox22:08:32

That is actually the case in many languages. Javascript does the same and if im not mistaken python too.

alexmiller22:08:46

that is NOT the same in either of those afaik :)

2
David Caudill22:08:04

i can't vouch for JS but i can confirm that Python doesn't do this

alpox22:08:17

Ok fair enough, i was talking only about the evaluation order

hiredman22:08:42

>>> if "foo":
...   print("x")
... else:
...   print("y")
...
x
>>>

David Caudill22:08:00

(looking for the and)

hiredman22:08:02

>>> if None:
...   print("x")
... else:
...   print("y")
...
y

hiredman22:08:26

>>> if "foo" and True:
...  print("x")
...
x
>>>

David Caudill22:08:37

ok so "first truthy" is a what i'd consider a common language pattern

David Caudill22:08:55

but returning the LAST thing if it's not? that's peculiar to me.

David Caudill22:08:34

and i guess the SRE half of me is mortified

hiredman22:08:41

>>> print(False or None)
None
>>>

dgb2322:08:57

@davidkcaudill I just had a long-ass discussion about nil in here just one or two days ago. And I think I finally understand what it means and why it is valuable to have it be falsy, what nil-punning is, why it is is there, why we use seq to check if a sequence still has stuff in it, why there is a difference between rest and next . How certain functions flow nicely into each other like get , nth , if-let , when-let and so on. nil is a value that signals “not there” or “end of line” and similar things in a given context. If that meaning has to break out of a context we have these wonderful things in keywords to communicate more.