Fork me on GitHub

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#)


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


what operations do you want to do on it?


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


@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 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”


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.


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


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


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.


but, I was trying to take advantage of what Overtone already had. Maybe there’s some good rationale for the definition of REVERSE-NOTES 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 ( 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)


@joe.lane super interesting!


thank you so much for this!


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.


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


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


forcing improvisation and ear training


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


“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.


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


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


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


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


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


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.


@joe.lane 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


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


@joe.lane 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


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


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.)


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.


either one works for me


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.


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


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)


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 😛


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


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


why does the lang not make a literal for PersistentQueue?


or put it into the core?

Alex Miller (Clojure team)05: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.

Alex Miller (Clojure team)05: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?

💯 4

@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?

Alex Miller (Clojure team)14: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.

Alex Miller (Clojure team)14: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


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


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


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...


I always just define the printer bit for it


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


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


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.


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.


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


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


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



👍 4

Hum... I guess I always do it recursively


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


breadth first recursively?


vector/list only work if you want a filo


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


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


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


Will Byrd had a student looking into this


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


I’m not a theory wonk by any stretch


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...


cheers to dissonant counterpoint


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


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


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?


From "All references to that symbol within a syntax-quoted expression resolve to the same generated symbol."


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


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


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

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


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


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])


Cool, thanks for the ideas.

👍 4

Calling gensym explicitly worked.


You can replace (gensym "deferred") with



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.


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


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


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
                (catch Throwable ex
                  (l/error ex)))))

(defonce worker-warehouse
  (dotimes [x 3]
    (go-loop []
            (let [job (<! queue-warehouse)]
              (l/debug "run warehouse job" job)
              (when-not (nil? job)
                (<! (thread
                        (catch Throwable ex
                          (l/error ex)))))
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?


Do you have something that consumes data from worker channel?


worker and worker-warehouse


run independent jobs and nothing use worker and worker-warehouse


if I understood your question


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

👍 4

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


you can also run to check if something is blocking or overusing queues


on production?


but probably your first idea is the right one


we are using JMX on production


how to run workers then?


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


hmm not sure how it should be done


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


do you mean

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


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


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


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


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


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


hmm so when should use async? For what pattern?


and what I should use for my current case


I asked on #core-async


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


Thank you for help!


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

Why not remote REPL then?


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


Internal threadpools dedicated for core.async


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?


I say that because you just park on the thread


So each worker is consuming one job at a time


It also looks like you just discard the result of thread


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


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


You should write it as such:


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


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


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

Alex Miller (Clojure team)14: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).

Alex Miller (Clojure team)14:12:29

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

Alex Miller (Clojure team)14:12:26

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

👍 4

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


Any known memory issue with async?


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


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


(reduce + xs) probably.


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


(reduce + xs) will work


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


Like (apply + 10 20 xs)


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


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


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)})


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


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


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.


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


Though they're all quite close in performance


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


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


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

flowthing14:12:57 this seems to be a somewhat updated fork


if that's not sufficient, I have an up to date fork of clojail as well: (


this is used in tests for speculative:


Thank you, I will look into these!


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


Post in #clj-commons to ask

Alex Miller (Clojure team)14: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?


Let me think about that for a moment


Fwiw, you can use this alternative: which can be linted as schema.core/defn


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.


(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))



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


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.


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


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?


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


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.


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.


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?


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


One thing though, the fig task is a trampoline


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


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


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?


@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


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.


Yes. figwheel has api exposed and can be programmatically started


Hi - is this odd?

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


It is not 2020 yet in UTC afaik:

> (ZonedDateTime/now (ZoneId/of "UTC"))
#<java.time.ZonedDateTime@5723da7f 2019-12-30T17:11:17.712Z[UTC]>


try "yyyy"

👍 12

Y is used for week based years


which causes this kind of thing


👀 - today I learned. @chris441 ^


@markmarkmark - thanks, friend.


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

#<java.time.ZonedDateTime@5723da7f 2019-12-30T17:11:17.712Z[UTC]>


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


👌:skin-tone-4: thanks


Sure, is it good or bad in your opinion?


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


the #<... syntax is old-style


that's my CIDER repl output above ^


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


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

💯 4

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


(val is incorrect, I assume a simple typo)


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))


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


is there anything wrong I am doing here

Joe Lane21:12:43

Any reason youre writing a macro?


This is a library I am using, not my code


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


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


is there anything wrong with it


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


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


everyone is out on PTO 🙂


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


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


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


into doesn't accept a string as collection


That's what is causing the error


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


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


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


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


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


"msg" perhaps is not a good ctx 🙂


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


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


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


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


(info "msg") works fine ? 🙂


It seems that cambium works like so:


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


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


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


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 ^^

🙌 4

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!)


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


properties and env vars are separate things


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


(via third party libs)


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

👍 8