Fork me on GitHub
#clojure
<
2019-12-30
>
devn01:12:56

any thoughts on the right datastructure to represent a guitar fingerboard? I am building something where any of the 2048 subsets of the chromatic scale are represented as some combination of 1 b2 2 b3 3 4 b5 5 b6 6 b7 7 (always containing 1 (example: [1 b3 5 b6 7]) I want to render these on an ascii fretboard using their proper note name according to the key they’re being played in. Example: [1 b3 5 b6 7] in the key of G major is G Bb D Eb F# (because Gmaj has 1 sharp, F#)

devn01:12:08

my gut is to use a vector of vectors, but im a little iffy on it

Probie01:12:46

what operations do you want to do on it?

didibus01:12:57

It depends, seem like order matters, and you'd be able to use indices to access certain ones. So vector of vectors sounds pretty good to me

devn01:12:06

@ludvikgalois good question. i’m kind of figuring this out as I go. I’m building a practice tool based on Wayne Krantz’ Improviser’s OS 2nd edition.

devn01:12:33

http://azzang.github.io/audible-math/ is an example of something that let’s you browse the combinations by clicking and hearing the tones of any “formula” (1 b3 5, for example is a formula). I’d like to go a little further and generate exercises and diagrams for various “formulas”

devn01:12:28

this may mean being able to do analysis for any representable chords within a “zone” (4 fret section of the fretboard), search for related formulas, etc.

devn02:12:52

it’s kind of an exploratory thing right now. i built something simple which does the basic thing: 1. It generates all combinations of the chromatic scale 2. You can select any combination and play it 3. You can take a combination and find any nameable (common or exotic) scale that matches it

devn02:12:04

However, it does not take into consideration key signatures, so while the resolved note may be enharmoic, it does not represent the context of the key. For example, D# may be printed, but in context it’s actually named as Eb, because it’s in Ab major

devn02:12:13

It’s a bit of a mess. Representations shift between midi note numbers, total number of semitones from the root, scale pattern, and the actual nameable notes (like C#4). It feels dirty to have all of these representations.

devn02:12:11

but, I was trying to take advantage of what Overtone already had. Maybe there’s some good rationale for the definition of REVERSE-NOTES https://github.com/overtone/overtone/blob/master/src/overtone/music/pitch.clj#L90 here, but it seems to ruin any notion of resolving correct note names by key for a midi note number

Joe Lane02:12:55

@devn I'm not sure how far down the rabbit hole you want to go, but I believe you might be interested in "Pitch Class Sets", which is a very interesting approach to modeling music theory. This (http://www.jaytomlin.com/music/settheory/help.html) seems like a decent introduction (without going all the way to a Music Theory textbook). You would have to project the pitch classes back onto a fretboard, but once you wrap your head around music theory as sets, the projection will likely be the easy part. (A fun aside, writing programs for this in University is what made me decide to switch to a Computer Science major)

devn02:12:30

@lanejo01 super interesting!

devn02:12:37

thank you so much for this!

devn02:12:26

scrolling through, i had in my head that there was some connection to a matrix, but was unsure how to proceed

Joe Lane02:12:41

The matrices are just scratching the surface. This is means to leverage the rigor of discrete math + graph theory in the context of music. This will also unlock the gateway to transition between different musical keys in ways that classical tonal theory say shouldn't exist.

devn02:12:47

interested to see multiple iOS apps that have post-tonal calculators of various kinds

devn02:12:00

yes, that’s really what im interested in. part of this book is about finding those things on your own

devn02:12:26

forcing improvisation and ear training

devn02:12:35

im less interested in the composition side, and more interested in the improvisation, but they can’t exist without one another. If I pick a random key and formula, I would love to be able to find good candidates to explore instead of sitting there working through 2048 combinations of the chromatic scale

devn02:12:53

“Computer, tell me all of the most likely tonal planets which orbit 1 b2 b5 7 that could sustain life in Gmaj”

Joe Lane02:12:40

The program I mentioned writing up above was a graph traversal tool. "Given that I'm at chord X in key foo, and I want to get to chord Q in key L, find me all the paths from X to Q with the most parsimonious motion. Play it. Ok, Try some different inversions, expand the path, enhance, ok, perfect. Project that back into sheet music (fret board)"

Joe Lane02:12:18

core.logic is a great tool for that.

devn02:12:36

This is a frequent thing I sit there and work out on my own, though without any serious degree of rigor beyond my own ear

devn02:12:17

I’ll play some phrase that’s “out” and try to make it “in”, and then try to find paths from or to it

devn02:12:36

as a tool for improvisation it would be really cool to generate interesting ways to get home, and then mark paths as interesting as i play

devn02:12:21

have footswitches to expand or contract the paths, the features that the pathfinding uses, etc.

Joe Lane02:12:43

The biggest takeaway I hope to give is to not represent sharps/flats as b2 or a keyword, but to use the pitch sets. Then you can more easily reason about which notes are in multiple keys at the same time, without worrying about representation. I hope you have fun, I lost months of my life to exploring this topic. And you may have just inspired me to dive back in haha

devn02:12:45

my super long term goal has been to build a tool for improvising with my computer

devn02:12:50

so i play some phrase on my guitar, midi pitches hit the computer, it thinks im playing in 7/4 and loosely in F. it comes up with an idea and tries it out. I respond, repeat.

devn02:12:44

@lanejo01 that’s a really valuable suggestion. this book i’m reading gets to the end and starts talking about formulas and their application: … 3. as containers of subsets 4. as superimpositions into tonalities that contain them as subsets 5. as superimpositions into tonalities that don’t contain them as subsets

devn02:12:07

where “formula” defined as any combination of 1 b2 2 etc. in a key

devn02:12:16

@lanejo01 FWIW, if you’re interested in working on something, DM me. Sounds like you know good deal more on this topic and I’d love to collaborate

devn02:12:15

@lanejo01 one question I suppose I have is: as far as improvisation is concerned, would you still be advocating for thinking in pitch sets?

devn02:12:00

is there any valuable reason to prefer a dumber representation when not in front of a computer that can crunch the numbers?

Joe Lane02:12:58

The last few statements had a couple of different questions in them.

Joe Lane02:12:54

I may dm you, as I just pulled out a few dissertations I had in a box in my closet.

Joe Lane02:12:34

You're technically off by 1, but yes, that looks right (thats how I would represent it on a computer anyways 0-11 not 1-12.)

devn03:12:16

if it’s not too much trouble i’d love links to those dissertations or at the very least some titles to peruse

Joe Lane03:12:34

I think it's extremely valuable to understand pitch sets because it will force you to understand the relationship of subsets of notes within your chords as they relate to their positions in other possible chords you could transition to. That being said, I wouldn't "think" in pitch sets, because they are far too low level, but they will inform whatever higher level model you're going to use. Be it the normal "tonal" model, or something like a more "modal" approach which doesn't adhere to the concept of a key with a tonic. In either case (you may come up with a third!) pitch sets are the underlying model.

Joe Lane03:12:23

RE: Dissertations, I can send you a photo of their titles or type them out. whichever you prefer. I got them off of JSTOR so you may need to go to a Library for access.

devn03:12:32

either one works for me

devn03:12:57

finally, on one level i can’t believe my luck in receiving such an interesting set of replies, but on another i was slightly unsurprised to find multiple clojure projects that were focused on this book Improviser’s OS.

devn03:12:37

thanks so much for the reply

Joe Lane03:12:33

No problem, I can't tell you how much joy it brought me to revisit this part of my life.

Joe Lane03:12:05

1. Enharmonic systems: A theory of key signatures, enharmonic equivalence and diatonicism 2. Cross-Type Transformations and the Path Consistency Condition

devn02:12:03

finally, interesting enough, i think i basically wound up at pitch class sets before we started chatting about this:

(map INTERVAL-LOOKUP '(:1 :b3 :b5 :5 :6 :7)) ;;=> (0 3 6 7 9 11)

didibus02:12:24

Well, you guys are discussing two parallel things. One is the correct musical model, and the other is the correct data-structures for that model 😛

didibus03:12:07

Can't help with #1. But, when it comes to data-structure, its mostly about optimizing queries.

didibus03:12:49

And I feel in your case, you'd probably eventually end up with multiple representations. Like instead of having a single data-structure that you navigate for everything, you might want to have a few different one, even if they duplicate the content, it seems like the structure of the content matters a lot, and you might want multiple structures exposed

introom03:12:00

why does the lang not make a literal for PersistentQueue?

introom03:12:04

or put it into the core?

alexmiller05:12:17

The thing is that queues are most useful between threads or cases where identity can be maintained over the stateful data structure. We have a better solution for that - core.async channels (or even Java queues). The only place I use the persistent queue is in a single-threaded algorithm over a graph or a tree. This is way less common than the other persistent structures.

alexmiller05:12:32

My personal opinion is that I do not think queues deserve a literal. I do think it would be worth making the queue constructor and predicate queue?

💯 1
introom09:12:01

@U064X3EF3 “between threads or cases where identity can be maintained over the stateful data structure.” Can you elaborate on this? How is it related with a fifo data structure?

alexmiller14:12:01

Because it is a persistent queue, changes result in a new queue instance. If you have two threads, you need an identity that both threads can hold on to, like an atom that wraps the queue.

alexmiller14:12:16

A shared queue is inherently stateful (identity + value) and the persistent queue is just the value part. Core.async channels are both and much better suited to this than pqueue+atom

didibus03:12:23

Its just not a data structure people use enough I think to motivate the work to bring it in as first class

didibus03:12:53

Though now that CLJS has it, it might be a better argument to just copy what they did, dunno

seancorfield03:12:54

Yeah, I asked about it nearly eight years ago (in the Google Groups thread linked in that ticket). But the reality of those eight years since is that I've hardly ever used the persistent queue data structure and certainly not enough to be bothered by the lack of a literal syntax for it so...

devn03:12:19

I always just define the printer bit for it

devn03:12:47

I don’t use it much in practice, but when tinkering with ideas it’s nice to have it printed readably

didibus03:12:57

Ya, its also, since the proposed syntax anyways is just a default reader literal, anyone who really cares can add it themselves to their own code base

devn03:12:47

I don’t think the general line has changed: PersistentQueue’s lack of polish suggests you should stop and think whether you want what it’s offering. I might be overstating but I think it’s the case that no part of the clojure core codebase uses it, unlike every other data structure defined by the language.

didibus04:12:18

Well, its that everything needs to be vetted by Rich Hickey, and that's a good thing in my opinion. But it also means that priorities go to high impact issues.

didibus04:12:11

And my impression is there's a philosophy of good enough that plays into priorities as well. Persistent Queue feels good enough that when you need a queue, you'll manage with it

didibus04:12:52

Also, I feel, when do you reach for a queue? I can only think of distributed or concurency use cases, and for that, you'd either use SQS/RabbitMQ directly, or you'll want a BlockingQueue or a core.async channel

didibus04:12:13

Might be just having a blank, but can't remember any algo that uses a queue

potetm04:12:06

breadth-first-search?

👍 1
didibus04:12:50

Hum... I guess I always do it recursively

hindol04:12:24

A vector as a queue also works fine. Conj to the end and destructure the head.

potetm04:12:39

breadth first recursively?

potetm04:12:15

vector/list only work if you want a filo

potetm04:12:05

i.e. it would change the weighting of, e.g. A*

didibus04:12:58

Hum, ya you're right. I just mostly never implement bfs actually

ghadi04:12:37

@devn for a tool for improvising, a solver for the 5 species of counterpoint could be useful

ghadi04:12:37

Will Byrd had a student looking into this

devn04:12:01

@ghadi you owe me a DM along with will. ;) Interested in talking about the practical applications.

devn04:12:09

I’m not a theory wonk by any stretch

ghadi04:12:46

if you take the complete opposite approach that AWS took with Deep Composer you'll be golden 🙂

Joe Lane14:12:48

I know the perfect white elephant gift...

devn06:12:37

cheers to dissonant counterpoint

devn06:12:03

> He wrote that “the effect of this discipline” was “one of purification”.

devn06:12:26

a lot of the stuff of counterpoint I’ve heard and worked through was sickeningly sweet and doesn’t even come close to anything approximating improvisation, though it may not claim to

ro607:12:52

I'm working on a macro to wrap functions that accept success and error callbacks and return a Manifold deferred value (like a promise), but having some trouble. When evaluating a defn using this macro, I get:

Unable to resolve symbol: de__31544__auto__ in this context
I tried removing pieces and testing, so I think it's the references to de# inside the callback fns. Is it something about nesting a syntax quote section inside an unquote section?

p-himik09:12:07

From https://clojure.org/reference/reader#syntax-quote: "All references to that symbol within a syntax-quoted expression resolve to the same generated symbol."

ro609:12:15

Right, but does that still apply inside nested syntax-quoted forms?

p-himik09:12:17

Nested syntax-quoted forms are still different forms. You can just run macroexpand-1 on your macro and see for yourself.

p-himik09:12:56

If callback-accepting-fn is a regular function call, you can use something like

(defmacro defer [callback-accepting-fn]
  `(let [de# (m/deferred)]
     ([email protected]
       (fn [~'response] (m/success! de# ~'response))
       (fn [~'error] (m/error! de# ~'error)))
     de#))

p-himik09:12:52

(although, it should work for any iterable, not just a list that represents a function call).

p-himik09:12:11

And your variant with concat could be written as

(defmacro defer [callback-accepting-fn]
  (let [resp-fn `resp-fn#
        err-fn `err-fn#]
    `(let [de# (m/deferred)
           ~resp-fn (fn [~'response] (m/success! de# ~'response))
           ~err-fn (fn [~'error] (m/error! de# ~'error))]
       ~(concat callback-accepting-fn
                [resp-fn err-fn])
       de#)))

ro609:12:17

Cool, thanks for the ideas.

👍 1
ro609:12:48

Calling gensym explicitly worked.

p-himik09:12:17

You can replace (gensym "deferred") with

`deferred#

p-himik09:12:10

And you don't need to use auto gensym for response and error since they cannot affect any scope. Using auto gensym here is actually a bit detrimental as it makes the functions' signatures worse.

p-himik09:12:58

Also, I'd say that using [email protected] is much more idiomatic than using concat. But if you really need concat, please tell me why - maybe I don't know something.

ro612:12:02

I ended up going with yours, just wanted to add what I'd come up with.

kwladyka09:12:38

How do you run workers in async? I have mysterious issue:

(defonce queue (chan 100))
(defonce queue-warehouse (chan 100))

(defonce worker
  (go-loop []
    (let [job (<! queue)]
      (l/debug "run job" job)
      (when-not (nil? job)
        (<! (thread
              (try
                (job)
                (catch Throwable ex
                  (l/error ex)))))
        (recur)))))

(defonce worker-warehouse
  (dotimes [x 3]
    (go-loop []
            (let [job (<! queue-warehouse)]
              (l/debug "run warehouse job" job)
              (when-not (nil? job)
                (<! (thread
                      (try
                        (job)
                        (catch Throwable ex
                          (l/error ex)))))
                (recur))))))
One per 2-4 weeks both workers stop doing jobs at the same time. I have no idea why. Can channels close themself for any reasons?

delaguardo09:12:06

Do you have something that consumes data from worker channel?

kwladyka09:12:55

worker and worker-warehouse

kwladyka09:12:39

run independent jobs and nothing use worker and worker-warehouse

kwladyka09:12:14

if I understood your question

delaguardo09:12:04

(defonce worker (go-loop … returns a channel so it is possible to overflow default capacity if nothing is consuming data from it

👍 1
kwladyka09:12:04

what is the best solution to run workers and not have this issue?

delaguardo09:12:46

you can also run https://visualvm.github.io to check if something is blocking or overusing queues

kwladyka09:12:21

on production?

kwladyka09:12:15

but probably your first idea is the right one

delaguardo09:12:17

we are using JMX on production

kwladyka09:12:30

how to run workers then?

delaguardo09:12:07

> what is the best solution to run workers and not have this issue? run separate and independent worker for each incoming message

kwladyka09:12:55

hmm not sure how it should be done

delaguardo09:12:59

right now your code consuming data to process and start processing in the same thread. it is better to keep those stages separated

kwladyka09:12:48

do you mean

(>!! ch f)
and run
(thread
              (try
                (<! queue)
                (catch Throwable ex
                  (l/error ex))))

kwladyka09:12:40

in the same thread? I use thread to do it not in the same thread

kwladyka09:12:49

I am confused… What is the point of async if I can’t have workers? I could run thread instead of channels then

delaguardo09:12:32

I’m not sure that core.async is the best way to handle queue/workers pattern)

delaguardo09:12:34

it is always better to handle messages synchronously to track all problems and deadlocks.

delaguardo09:12:31

But i’m not pro there, probably worth to ask in #core-async

kwladyka09:12:15

hmm so when should use async? For what pattern?

kwladyka09:12:09

and what I should use for my current case

kwladyka09:12:39

I asked on #core-async

kwladyka09:12:16

Uch I was learning async so long time ago. I don’t remember it deep right now. I have to refresh my memory.

kwladyka09:12:09

Thank you for help!

kwladyka11:12:32

What JMX exactly do? As I can see it lets connect by port to JMX and run some queries like `

:HeapMemoryUsage
Why not remote REPL then?

delaguardo11:12:54

You can not get all information (or at least I don’t know how) from running repl. state of threadpools as an example

delaguardo11:12:09

Internal threadpools dedicated for core.async

didibus11:12:48

I'm also not super knowledgeable in core.async. But, I'm curious, what's the point of using core.async here? Just so you can run warehouse jobs and worker jobs concurrently?

didibus11:12:00

I say that because you just park on the thread

didibus11:12:16

So each worker is consuming one job at a time

didibus11:12:31

It also looks like you just discard the result of thread

didibus11:12:42

So I'm not sure why you do a take on it

didibus11:12:27

It also seems a bit weird, you recur all the time, but as soon as job is nil, it means the channel has closed

didibus11:12:31

You should write it as such:

didibus11:12:34

(go-loop []
  (if-let [job (<! queue)] 
    (do 
      (l/debug "run job" job)
      (thread ...)
      (recur))
    (l/debug "Closing!")))

kwladyka11:12:43

to have a queue and be sure processes never processing at the same time

kwladyka11:12:19

look at #core-async - there is already interesting discussion

alexmiller14:12:45

This code looks pretty good to me btw. I think the key is to first add enough code that you can diagnose why things stop when they do. Is the problem with adding jobs (channel is full), taking jobs (channel is empty), or go blocks not running (usually b/c they are doing io and blocked).

alexmiller14:12:29

The last one is pretty easy to spot from a thread dump

alexmiller14:12:26

And by the way (when-not (nil? job) ...) is same as (when-some job ...)

👍 1
kwladyka14:12:39

I added more logs and we will see after a few weeks. At least I will close a few hypothesis.

kwladyka09:12:08

Any known memory issue with async?

yuhan12:12:50

Which is a more idiomatic way to express "sum", (apply + xs) or (reduce + 0 xs)

yuhan12:12:17

I used to always go with apply but recently ran into a case where reduce was many times faster, I think because it avoided having to allocate the entire sequence

p-himik12:12:38

(reduce + xs) probably.

didibus12:12:58

Reduce will be faster for larger sequences. You don't need the 0 btw

didibus12:12:49

(reduce + xs) will work

didibus12:12:47

There are cases where I use apply over reduce, its when I want to tack on some extra numbers to add

didibus12:12:01

Like (apply + 10 20 xs)

didibus12:12:12

That's mostly when I'll use apply over reduce

yuhan12:12:06

It's nice that (+) = 0 , so there's no need to worry about edge cases

yuhan12:12:59

Another somewhat stylistic question - are there semantic differences between the following forms?

(assoc data
  :foo (something)
  :bar (something-else))

(into data
  {:foo (something)
   :bar (something-else)})

(merge data
  {:foo (something)
   :bar (something-else)})

yuhan12:12:29

eg. overwriting a value vs adding a new key to the map

yuhan12:12:03

I almost always use assoc and assume it's faster (haven't done benchmarks), but noticed others using into quite frequently

p-himik12:12:11

into should be the fastest because it utilizes transient collections when they're available. But arguably, it has a more vague semantics because with assoc and merge you're pretty sure that you're working with associative collections. I don't think you should care about the fastest option unless it's a bottleneck in your application. I almost always use assoc when the set of keys and values is known since it has the clearest display of intent IMO.

3
didibus06:12:51

I did a very quick benchmarking and it seems assoc might be fastest

didibus06:12:11

Though they're all quite close in performance

didibus06:12:56

I think into and merge suffer from the overhead of creating the input map

didibus06:12:26

So I'd say assoc is a safe bet for both performance and readability

zilti13:12:29

What is there out there for sandboxing Clojure using whitelists? Clojail hasn't seen an update in 9 years

flowthing14:12:57

https://github.com/huahaiy/clojail this seems to be a somewhat updated fork

borkdude15:12:15

if that's not sufficient, I have an up to date fork of clojail as well: https://github.com/borkdude/clojail (

borkdude15:12:25

this is used in tests for speculative: https://github.com/borkdude/speculative

zilti16:12:55

Thank you, I will look into these!

didibus06:12:19

Could it be a good candidate to move that fork to clj-commons?

borkdude08:12:42

Post in #clj-commons to ask

alexmiller14:12:21

The author passed away. It might have been forked and picked up by clj-commons or someone else though.

Duck Nebuchadnezzar14:12:08

I'm trying to get clj-kondo set up, but it doesn't seem to like Orchestra's defn-spec. Anyone know what function lints quite like that, or how to go about writing one if none exists?

borkdude15:12:51

Let me think about that for a moment

borkdude15:12:02

Fwiw, you can use this alternative: https://github.com/danielcompton/defn-spec which can be linted as schema.core/defn

borkdude15:12:16

what you can also do is put a (declare my-fn) before the call to defn-spec and ignore the call to defn-spec via the config. this way clj-kondo will know that there is a var with the name my-fn

Duck Nebuchadnezzar15:12:06

Yeah, that would be a lot of clutter/maintenance. I might actually look into the other one

Duck Nebuchadnezzar15:12:03

If only I didn't already have a ds as a standard prefix in my code.

borkdude15:12:08

(ns foo {:clj-kondo/config '{:linters {:unresolved-symbol {:exclude [(orchestra.core/defn-spec)]}}}})

(require '[orchestra.core :refer [defn-spec]]
         '[clojure.spec.alpha :as s])

(declare get-meow)
(defn-spec get-meow any?
  [meow-map (s/map-of keyword? any?)]
  (:meow meow-map))

(get-meow)
`

borkdude15:12:25

not optimal, but it's the only thing I can think of right now

borkdude15:12:16

maybe you could ask the author to support the schema.core notation as well

Duck Nebuchadnezzar15:12:20

Thanks for the help. I think I'm going to explore this other one.

borkdude15:12:42

The complete picture with the other one:

(ns my.ns
  {:clj-kondo/config '{:lint-as {net.danielcompton.defn-spec-alpha/defn schema.core/defn} }}
  (:require [net.danielcompton.defn-spec-alpha :as ds]
            [clojure.spec.alpha :as s])
  (:import [java.time ZonedDateTime]))

;; Predicate definitions elided for brevity
(s/def ::instant any?)
(s/def ::zone-id any?)
(s/def ::zoned-date-time any?)

(ds/defn to-zoned-dt :- ::zoned-date-time
  [instant :- ::instant
   zone-id :- ::zone-id]
  (ZonedDateTime/ofInstant instant zone-id))

Duck Nebuchadnezzar16:12:41

Unfortunately, it looks like that one doesn't work with clojurescript

borkdude16:12:01

Hmm, too bad. Maybe post an issue about this at clj-kondo and I'll give it some thought

Luke Schubert14:12:24

Using logback for logging in clojure is there a clear way to write to the Mapped Diagnostic Context?

craftybones14:12:28

I need some help with launching a custom server and figwheel together via lein.

craftybones14:12:17

I’m following the instructions outlined on the figwheel main docs site. While it illustrates how to run a custom server with the Clojure CLI, I’ve been unsuccessful at getting it to work with lein.

craftybones14:12:12

I’ve a scripts/server.clj and I am running it as lein do exec -p scripts/server.clj, fig where fig is an alias that starts figwheel.

craftybones14:12:46

What happens is that the scripts/server.clj launches, but somehow, figwheel doesn’t. join? in run-jetty is set to false

Duck Nebuchadnezzar14:12:20

does it work if you do them as two separate commands?

craftybones14:12:24

And so cool too, but no idea why the lein do exec doesn’t

craftybones14:12:50

One thing though, the fig task is a trampoline

craftybones15:12:24

This is really confusing. The standalone server starts just fine, and independently figwheel.main when launched via leiningen also launches fine

craftybones15:12:37

But put them in a lein do, and it doesn’t

craftybones15:12:27

Which makes sense since the script is a server and putting it in a do will not yield at all, but how does clojure -i achieve the same?

craftybones15:12:13

@duck I don’t think this can be done via lein alone. You will have to do it programmatically. Think about it, lein will launch a server and that process won’t stop till the server exits, so lein can’t do a thing to launch figwheel

craftybones15:12:34

Another way to do it is to have lein launch a target other than figwheel main which calls figwheel main and requires the server somehow

Duck Nebuchadnezzar15:12:17

Is it possible to launch figwheel as a mounted component? (in certain environments)

Duck Nebuchadnezzar15:12:59

That's something I might want to look into myself so that figwheel starts even before I connect.

craftybones15:12:51

Yes. figwheel has api exposed and can be programmatically started

Harold17:12:32

Hi - is this odd?

> (.format (ZonedDateTime/now (ZoneId/of "UTC"))
           (DateTimeFormatter/ofPattern "YYYY"))
"2020"
My software is breaking, anyone else experiencing this?

Harold17:12:39

It is not 2020 yet in UTC afaik:

> (ZonedDateTime/now (ZoneId/of "UTC"))
#<[email protected] 2019-12-30T17:11:17.712Z[UTC]>

markmarkmark17:12:55

try "yyyy"

👍 3
2
markmarkmark17:12:04

Y is used for week based years

markmarkmark17:12:09

which causes this kind of thing

Harold17:12:12

👀 - today I learned. @chris441 ^

Harold17:12:51

@markmarkmark - thanks, friend.

ghadi17:12:43

@hhausman what environment are you using that prints using the style:

#<[email protected] 2019-12-30T17:11:17.712Z[UTC]>

Harold17:12:57

@ghadi - that was copy/pasted from my CIDER repl. Not sure if that's the default output style - I use puget for pretty printing.

ghadi17:12:10

👌:skin-tone-4: thanks

Harold17:12:22

Sure, is it good or bad in your opinion?

ghadi17:12:37

(java.time.ZonedDateTime/now)
#object[java.time.ZonedDateTime 0x832285c "2019-12-30T12:53:28.767326-05:00[America/New_York]"]

ghadi17:12:55

the #<... syntax is old-style

ghadi17:12:11

that's my CIDER repl output above ^

Harold17:12:38

oic, I may be a few versions behind on things :^)

Eduardo Mata20:12:03

howdy! I am reading a csv file that a header contains comas (i.e. :this,is,a,key ) I tried to do a rename-keys but I get a unable to use symbol when the keyword contains a comma. I though about making the keyword in to a string replacing the comma with "' to remove it. How can I correct the keywords by removing the comas and keeping the values as they are?

Eduardo Mata20:12:44

I thought about using [(keys col) (val coll)] but I am positive I can get the keywords and the values in a complete different order

noisesmith20:12:16

the best solution is to not turn the header into a keyword

💯 1
noisesmith20:12:56

keys and vals are guaranteed to return the items in the same order

noisesmith20:12:06

(val is incorrect, I assume a simple typo)

huthayfa21:12:52

Hello, I get the following exception java.lang.IllegalArgumentException "Don't know how to create ISeq from: java.lang.Character" when I try to call this function

(defmacro info
  "Log at the info level"
  [& args] (apply info-impl args))

huthayfa21:12:50

The function call looks like this (info "msg" "msg")

huthayfa21:12:25

is there anything wrong I am doing here

Joe Lane21:12:43

Any reason youre writing a macro?

huthayfa21:12:09

This is a library I am using, not my code

huthayfa21:12:26

i am just making the call (info "msg" "msg")

huthayfa21:12:22

it's internal library written by a team in my company

huthayfa21:12:38

is there anything wrong with it

seancorfield21:12:59

You'd better ask them how you're supposed to use it then...

seancorfield21:12:18

without knowing the definition of info-impl it's hard to say what's wrong...

huthayfa21:12:37

everyone is out on PTO 🙂

seancorfield21:12:47

Having a macro that doesn't use a syntax quote for the form it expands to looks a bit suspicious.

seancorfield21:12:04

Can you show us the info-impl function (or, more likely, macro)?

huthayfa21:12:24

(defn ^:no-doc info-impl
  ([msg] (info-impl {} msg))
  ([ctx & args] `(cambium/info (into default-context ~ctx) (str [email protected])) ) )

didibus06:12:16

into doesn't accept a string as collection

didibus06:12:27

That's what is causing the error

didibus06:12:57

ctx can't be a string, from the code it seems it is supposed to be a map

didibus06:12:06

`(into {} "msg") IllegalArgumentException, don't know how to create ISeq from clojure.lang.Character`

didibus06:12:31

I'm guessing you need to call it as such: (info {} "msg")

didibus06:12:52

Where I'm guessing you can optionally add key/values to that map and it'll show in the logs

p-himik08:12:22

A small pedantic correction - into does accept strings (`(into [] "abc")`). The issue is that a character cannot be turned into a MapEntry.

kulminaator21:12:14

"msg" perhaps is not a good ctx 🙂

erik21:12:26

how to (import org.jpl7.Float) without the Float already refers to: ... error?

seancorfield22:12:00

@UECLGBLES Don't import it. Just use the fully-qualified name where you need it.

2
kulminaator22:12:51

you would confuse the hell out of people who would not expect Float to be java lang Float 😄

erik22:12:23

agreed, I was hoping for a way to alias, but didn't realize fully qualified works

kulminaator21:12:57

(info "msg") works fine ? 🙂

dharrigan22:12:18

It seems that cambium works like so:

kulminaator22:12:44

i suppose (info {} "msg" "msg") also would ...

seancorfield22:12:41

Tell that team to start writing docstrings so folks know how to use the library! 🙂

kulminaator22:12:17

nobody needs docs .... until you need them 😛

seancorfield22:12:20

It looks like (info "msg") and (info {} "msg" "msg") both ought to work tho', per @kulminaator @huthayfa.ainqawi

Lennart Buit22:12:51

And, preferably to not have multiple arities with different meanings for a particular argument on the same spot ^^

🙌 1
seancorfield22:12:02

I agree with @lennart.buit -- that's not good design so maybe open an internal issue about that too @huthayfa.ainqawi (in addition to asking for docstrings to be added!)

alidlorenzo23:12:30

how can I set an environment variable? tried using System/setProperty but when I try accessing it via System/getenv it's nil

noisesmith23:12:08

properties and env vars are separate things

noisesmith23:12:27

there's no portable way to set an env var in the vm - there's code that's unix-only that does this via jni

noisesmith23:12:34

(via third party libs)

noisesmith23:12:13

there are two pairs; System/setProperty System/getProperty / x - System/getEnv

👍 2