Fork me on GitHub
#clojure
<
2016-12-20
>
mingp01:12:33

Is there something like take-while that can stop when an infinite lazy sequence reaches a fixed point? For context, I'm using iterate to generate the result of applying f to x as many times as needed, and I expect this sequence to eventually reach a fixed point, and I'd like to return that.

mingp01:12:48

Like, say the sequence will produce x, y, and z, but then (= (f z) z), so the sequence keeps producing zs forever, and I'd like to return that z value.

mingp02:12:22

In particular, while take-while examines only a single element at a time, it seems like the answer to a fixed point question requires a sliding window of history. This seems like it should be possible with some amount of partition trickery, but I was hoping there was some built-in solution for "iterate f on x until fixed point" or similar.

johnnyillinois02:12:06

Can you reduce your sequence after take-while finishes?

johnnyillinois02:12:50

Also there is reduce to reduce a sequence to a single value.

mingp02:12:41

Yea, that's definitely possible, but the function passed to reduce would have a certain amount of complexity in tracking the trailing window of history etc.

johnnyillinois02:12:18

maybe partition first, for the sliding window?

mingp02:12:13

That's probably my next best option, if there isn't some sort of built-in sequence function relevant here.

mingp02:12:39

It seems like take-while / drop-while are almost but not quite what I want, but the difference is not one I can easily work around.

mingp02:12:10

@johnnyillinois Thank you for the suggestions.

fabrao02:12:42

Hello all, the expression (doall (pmap #(some %) collection)) wait for all some results but only starts 6 threads in my cpu if I have more than 6 elements in collection. I´ve tried to use (doall (map #(future (some %)) collection)), that starts all threads but the results is async. Is there any way to start one thread per collection element and wait for all response like in pmap?

johnnyillinois02:12:56

how many cores does your CPU have?

fabrao02:12:54

I saw in pmap source that is core + 2 threads

mingp02:12:05

What about creating all the futures and then deref-ing them all?

mingp02:12:15

Sorry that I don't have the exact syntax for this.

fabrao02:12:51

🙂 that´s I don´t know how

fabrao02:12:36

the results is important to wait all together because I´ll analyse the results after

mingp02:12:49

I don't know the exact details but I think http://www.braveclojure.com/concurrency/ this page has some good starting points.

mingp02:12:25

In particular, I suspect you can do something with doall, map, and force.

mingp02:12:34

But, again, I'm uncertain of the specifics.

fabrao02:12:15

thanks @mingp I´ll read it to see if it will help me

mingp02:12:23

You're welcome.

mingp02:12:29

BTW, in case anyone was curious as to my earlier question, I came up with this:

mingp02:12:30

(defn fixed-point-of-seq
  [input]
  (if (= (first input) (first (rest input)))
      (first input)
      (recur (rest input))))

mingp02:12:57

Could probably use some better error handling, but I think the general idea is there.

johnnyillinois02:12:05

FYI, @fabrao if you only have 4 cores, you may not get much (if any) more throughput from more threads

fabrao03:12:11

@johnnyillinois so, using simple pmap will be the use for this.

johnnyillinois03:12:57

Yeah, I mean unless each of the functions need to do something to show a user there is forward progress, I would just use pmap

johnnyillinois03:12:14

Also, if you really wanted executing all in a separate thread.

(let [fs (future (my-f))]
   (reduce (fn [state f] (my-r-f state @f)) [] fs))

fabrao04:12:14

interesting johnny, so reduce will sync all to wait for results?

joshjones04:12:58

If the function to map over the collection is just some? then pmap will certainly be slower than map @fabrao

johnnyillinois04:12:58

@fabrao no reduce is a normal function

johnnyillinois04:12:15

@f ; will block until thread finishes 
Like @joshjones is implying "Are you sure you need all these threads?"

tbaldridge04:12:55

But the #1 rule of pmap is....it's just a single letter. map vs pmap, throw in pmap test and see if it's faster. 80% of the time it works every time.

joshjones04:12:44

Two things to consider for pmap. One is computational intensity. If the CPU cost is higher than that of thread creation overhead plus computation (and you might be surprised at how hard it is to perform a non-contrived, useful CPU-intensive operation using a few core clojure functions), it's a good candidate for pmap. The other is frequency of the call to pmap. Paralleling a computation in isolation is one thing, but if you have to repeat this parallelization frequently, then there will be trade-offs. If you're running a server that receives several hundred or thousand requests per second (or even tens maybe), for example, pmap will speed up one response, but the computation will tie up cores that could be used serving other requests. So you can serve some requests very quickly, but at the expense of others, which will be slower than had you not parallelized the operation. In other words, there is no free lunch.

val_waeselynck09:12:26

In order to make some algorithms faster, I'm considering using runtime compilation via eval. Are there known downsides / caveats to this approach ?

bfabry09:12:10

@val_waeselynck I'm not aware of any downsides other than more difficult to understand code, but I'm no export. I would be interested in seeing how you could make something faster using eval though

val_waeselynck09:12:42

@bfabry I wouldn't be the first to do this. For instance: * Plumatic/plumbing uses this technique for eager graph compilation (https://github.com/plumatic/plumbing/blob/31e835f59c330d6ba643859c3f743c487a63718c/src/plumbing/graph/positional.clj#L78). * Specter uses this for dynamic path compilation (https://github.com/nathanmarz/specter/blob/fdd74ea2243bc089eecd984edd8953e4321adcd4/src/clj/com/rpl/specter/impl.cljc#L810) * I think I heard in a talk Rich Hickey hint that Datomic's Datalog query engine uses eval for compiling queries.

val_waeselynck09:12:08

The fact that it's faster boils down to being able to leverage the JVM's JIT I believe

val_waeselynck09:12:34

The kind of issues I'm looking to be warned against are things like memory leaks, race conditions, interferences w/ direct linking, etc.

bfabry09:12:22

totally, there are definitely situations where explicitly creating a code tree and eval'ing it will end up faster than an algorithm that works with a data structure, I was just curious as they're usually really interesting cases. specter and plumatic are great examples

roelofw14:12:40

I have to make a url like this : http://localhost:3000/detail/&lt;id&gt; . Must I do it like this url = (str /detail id) <a href = url > in selmer

mf15:12:33

Hi, I'm using the defun macro to define a function with pattern matching. As you can see the function accepts an options map:

(defun foo
  ([{:a a :b b}]
   (str a b))

  ([{:a a}]
   a))


(foo {:a "foo" :b "bar"}) ;; => "foobar"
Is it possible to use destructuring to bind the whole options map to some-symbol within the parameters definition?

Alex Miller (Clojure team)15:12:35

Quick reminder that the Clojure community survey closes Friday - would love to have your input! https://www.surveymonkey.com/r/clojure2016

limist15:12:32

Maybe I missed the memo, but I'm seeing lots of 404s on the clojure documentation pages, e.g. http://clojuredocs.org/clojure.core/cond-&gt; or https://clojuredocs.org/clojure.core/cond-&gt;&gt;

limist15:12:57

Did someone change the regex on the allowed/recognized URLs? 🙂

stubillwhite15:12:13

Hello, all. Does anyone have any good recommendations for test assertion matchers, something like the Clojure equivalent of Hamcrest et al? I'm using vanilla clojure.test, and had been playing with matcha (https://github.com/yeller/matcha) but it felt a little incomplete. It looks easy to extend and I'm quite happy to start writing other matchers, but I wondered if there was some other library that I've missed. Googling around hasn't thrown up too much, so any advice would be great.

tbaldridge15:12:58

@stubillwhite not completely sure what that library does ^^

tbaldridge15:12:23

Cursive has some nice clojure.test integration that ties into the IDE's text differ

tbaldridge15:12:19

clojure.test + cursive gets you this: https://cursive-ide.com/userguide/testing.html which handles about everything I need.

tbaldridge15:12:02

I'm sure similar stuff probably exists in Cider as well.

stubillwhite16:12:22

Ah, I see. Haven't played with Cursive -- I'm currently Emacs/Cider -- but I keep meaning to as it's what coworkers will probably use. Looks nice. I'm actually looking for a library that does fuzzy matching for tests, so I can assert that (say) the result of a function is a list containing item1, item2, item3, but I don't care about the order, or that a number is approximately equal to an expected value plus or minus some delta. Hamcrest (https://code.google.com/archive/p/hamcrest/) does something similar in other languages and there are a few similar libraries in Java. I could easily write my own, I'm sure, just checking whether that's what people are usually doing, or whether there is a neat library with some prewritten matchers like that. Matcha does that, but seems to be missing a few common ones I'd expect to see. Maybe I'll go with that and see if I can extend it.

tbaldridge16:12:38

So for the first, I normally use sets for that: (is (= (set test-data) #{1 2 3}))

tbaldridge16:12:51

For the other, I may use <= or >= but honestly I haven't hit that problem, even when building systems for rather large retailers and financial institutions. Most of the time you can either query for the answer from an existing dataset, or hard code the test to some value.

tbaldridge16:12:51

I know it's possible to have problems where perhaps the code gets tripped up on precision of Doubles but I haven't seen that in practice. Perhaps mostly because the JVM is consistent across OSes?

stubillwhite16:12:36

Oh, that's not the problem at all, just an example of where I don't care about the exact precision of a calculation. I'm looking to make loose assertions about code in some cases, and not impose a particular implementation on the thing under test because I want the tests to be a little more flexible.

stubillwhite16:12:44

Using a set for that particular example is easy enough; I can quite easily write my own common functions for doing this kind of thing. It's just that libraries in other languages for this are quite common, and Clojure seems to have a few. Midje (https://github.com/marick/Midje/wiki/Checking-sequential-collections) has some of what I'm talking about, but I don't really want to use the rest of Midje as I'm preferring vanilla clojure.test.

stubillwhite16:12:28

I was wondering if maybe there were libraries out there I was missing but maybe not. Clojure is powerful enough that writing this kind of thing is cheap and easy, so maybe that's what people are generally doing.

stubillwhite16:12:37

Thanks, though. And I like the Cursive stuff -- I will check that out to make the sales pitch to colleagues a little easier 🙂

dpsutton16:12:19

you could make a multimethod close-enough that dispatches on its type of first argument and ensures that for whatever type it's "close enough" for that type

dpsutton16:12:38

ie, for long its equal, for double within some epsilon, sets they are subsets of each other, etc

stubillwhite16:12:04

I'll have a play and see.

tbaldridge16:12:58

Okay, so honest question, why don't you care about exact precision? I ask because I see this feature in a lot of test frameworks, but I've never found a case where I didn't care about a number being exact?

tbaldridge16:12:07

Is the use case for non-financial uses or something? Admittedly about 99% of my uses of floating point numbers are for currency, where precision always matters.

dpsutton16:12:27

does java not have an equivalent type of decimal like on .NET?

dpsutton16:12:47

and that's guaranteed precise to some digits?

dpsutton16:12:56

decimal doesn't have problems representing .1 + .2, etc

dominicm16:12:06

That's correct.

dpsutton16:12:22

i'm from .NET land at work so I am pretty lost in the jvm ecosystem

tbaldridge16:12:13

@dpsutton I hear you there, I came from .NET. I had may moments of "Why is it DataOutputStream instead of BinaryWriter?!?!?"

dpsutton16:12:36

yeah. I need a good overview of common utility classes in .NET

dpsutton16:12:02

I've got safari and pluralsight through work so i should really look into an overview for java targeted for people not new to coding

dpsutton16:12:17

nothing worse than trying to get up to speed with a language and it holds your hand about what variables and for loops are

pesterhazy16:12:57

@dpsutton, clojure has a literal syntax for bigdecs: 1.23M

dpsutton16:12:14

thanks for the info!

joshjones16:12:52

@dpsutton in clojure, (rem 2.3 1) yields 0.29999…, whereas (rem (bigdec 2.3) 1) yields the correct 0.3M, as an example. annoying, yes

lyndsysimon17:12:29

Is there a better way to convert from a map to a vector than this? (flatten (apply vector {:foo :bar :baz :qiz}))

tbaldridge17:12:11

(mapcat identity {:a :stuck_out_tongue: :c :d})

bronsa17:12:11

(mapcat identity the-map)

tbaldridge17:12:54

rofl, I fail at life.

jr17:12:07

user=> (apply concat {:foo :bar :baz :qiz})
(:foo :bar :baz :qiz)

lyndsysimon17:12:46

awesome, thanks 🙂

reborg17:12:39

or the faster (reduce-kv conj [] m)

joshjones17:12:48

Not by a long shot @reborg, at least with large maps. quick-bench from criterium shows, on a 50K k-v map defined as (def m (apply hash-map (range 100000))), that your reduce-kv takes 10ms, which is about 30000x slower than (apply concat m) (347ns) and 15000x slower than (mapcat identity m) (748ns)

tbaldridge17:12:47

now try it with transients 😉

reborg17:12:37

@joshjones you’re correct, only for small maps

tbaldridge17:12:57

although we have to realize what "faster" is here

tbaldridge17:12:06

most of these solutions are lazy and aren't even doing anything

sveri17:12:03

Sounds like me in the evening 😄

mungojelly17:12:45

my data is maps of uuids to maps, which contain uuids as values, so a graph of uuids, do you think it's better to use strings for the uuids or symbols

joshjones17:12:39

That is a great point @tbaldridge — depending on the subsequent operation on the result, it may be a big time saver, or not at all. Fully realizing the lazy sequence shows the reduce-kv case to be slightly faster for a large data set, however, whether you would fully realize the result or not is a case-by-case scenario. :thumbsup::skin-tone-2:

joshjones17:12:19

Personally, I’d take the chance, if I did not know, to have the lazy seq so I can at least have the option to save some time

sveri17:12:54

I would choose readability and developer simplicity over "performance" as long as I do not know at all where my performance bottlenecks are. Everytime I think, oh, I could write this function faster I stop and rethink about it if I loose something else for it and usually just let it be.

tbaldridge17:12:55

tried transients?

mungojelly18:12:27

i have more processes than i can reasonably decide resource usage for, do we have any abstractions written over usage of resources like memory and processing so i could give my processes chits they can exchange for cycles instead of deciding directly what resources to use on them

hiredman18:12:35

that is a queue, so core.async channels or java.util.concurrent queues

hiredman18:12:11

what you are describing is a scheduler, which tend to be written around a run list or run queue

mungojelly18:12:20

my sketch in my mind goes like, auction resources for chits (with one of the resources auctioned being more chits (else my processes will spam my resource allocator to death)), so if you have 3 chits you can say "bid 2 chits for a processing block" and if you won you'd be returned info about when you're scheduled to process and deducted the chits

tbaldridge18:12:41

that's way more complex than you need

hiredman18:12:55

that is a priority queue

tbaldridge18:12:09

queues with fixed sizes will give you most of what you need

mungojelly18:12:19

need for what? i want to dump an unlimited number of processes on it from various producers and resolve all the contention? my use case is evolving processes, they mutate and divide, so there's always necessarily more of them than any resource provided to them

tbaldridge18:12:00

That's the problem, don't dump processes, dump messages or data at a fixed number of processes, extra messages are queued in memory or disk

hiredman18:12:10

you are describing a work queue

tbaldridge18:12:19

or preferably on a distributed queue where they can be load balanced across machines.

mungojelly18:12:42

i tried reading stuff from academia and it always just assumes i can let the producers send messages to the allocator, if i let my producers freely send messages they'd grow until clogging that pipe was their bottleneck, so i have to hand out a fixed number of opportunities to bid for resources, do you know any papers about that

mungojelly18:12:43

anyway i'm assuming i have to write up the chit system myself, but what abstractions are there i can feed into it? like what's an abstraction of "some processing" that i could take bids for?

hiredman18:12:08

mapping N processes to M cores where N > M is basically all scheduling is about

tbaldridge18:12:48

@mungojelly I would assert that your premise is incorrect. This "clogging the pipe" you mention is a feature, it's known as backpressure, and it's a tool that can be used to tell producers "hey slow down a bit!". You'll still have to deal with this clogging anyways, since a scheduler has a finite set of resources. If it decides that a consumer doesn't get resources, then that consumer is going to not process its inputs and the producers will "clog" anyways.

mungojelly18:12:07

in my case N is always increasing unreasonably, which breaks assumptions in most of the models i've read, but i can solve that easily enough i think by just handing out a fixed number of opportunities to bid on scheduling

hiredman18:12:22

that doesn't break the model

hiredman18:12:33

that is literally what people model

mungojelly18:12:02

my producers can't be told to slow down a bit, there are necessarily more of them than can fit and they all desperately need processing to survive, they have genuinely contending needs

tbaldridge18:12:29

But they will anyways, if they bid and fail...what are they going to do/

mungojelly18:12:43

then they'll die

joshjones18:12:50

sounds like you need more consumers then to deal with the load

joshjones18:12:50

or a real-time kernel, and most certainly not the JVM

mungojelly18:12:50

no, the whole basic idea is to have more producers than can survive, they're supposed to have unresolveable contention

tbaldridge18:12:42

So now I'm wondering, what sort of system is this?

mungojelly18:12:59

i call them evolving processes

hiredman18:12:07

a priority queue where entries expire

mungojelly18:12:29

the distinction from genetic algorithms is mostly that they're not inherently random, the "mutation" step is intentional change

mungojelly18:12:46

i think i'm ok on what type of queue to use, really, what i'm going to do is hand out a specific finite number of resource chits, and then go back to those finite number of places and find out how they wanted to bid their chits, which can include asking for more chits as one of the resources, and i'll just sell as many chits as i can throughput, my question was what abstractions i can put up for them to buy

mungojelly18:12:50

are memory and processing not abstracted into first class values somehow somewhere? can't i take processing a thing for a while as a thing and work with it??

mungojelly18:12:11

i could make my own abstraction, like, um, what i thought of was just sell processing slices, they run for X milliseconds, make various sizes of them, and you can rent memory for them to work with

mungojelly18:12:37

but that feels like i don't really know what i'm doing, trying to throw together an abstraction of some processing like that, so i was wondering if there are any such abstractions already that would be good for me to sell

joshjones18:12:30

sounds like aws lol

joshjones18:12:13

you can most definitely abstract out anything you want, including a hardware resource — but it’s not a first class “thing” in any programming language — most definitely a “roll your own” (if i’m even in the same universe of what you’re talking about)

mungojelly18:12:49

yeah it's a similar concept to cloud computing but on a micro scale i guess, i want my processes to requisition little cloud computers from me but they're very VERY small computers that have like, a few k of memory and they only last three seconds or whatever

mungojelly18:12:54

for abstracting a fixed amount of memory is the best thing a java ByteBuffer? there's no higher abstractions about memory usage on the clojure side?

pawandubey18:12:30

Has anybody here read The Joy of Clojure? Would you recommend it?

manderson18:12:54

Yep, Joy of Clojure is great. I recommend it after you've gotten your feet wet, though, as it's a pretty aggressive from the get go. I usually tell people to start with Clojure for the Brave and True and then after you've gotten some experience go through Joy of Clojure.

manderson18:12:04

Just my $0.02

tankthinks18:12:31

Yes: I really liked Joy of Clojure … I agree with @manderson

pawandubey18:12:40

I went through Living Clojure by Carin Meier. I think I understand the basics (though the lazy nature sometimes bites me). I am looking to get into the idioms of the language now.

manderson18:12:39

Joy of Clojure should be good for that.

pawandubey18:12:07

Thank you 😄

charafau19:12:51

hello clojurians, are clojurec ( https://github.com/schani/clojurec ) and clojure android dropped ? looking for some language to support both ios and android also functional but it seems like clojure tools are dropped

tbaldridge19:12:13

Clojurescript works great on both

charafau19:12:03

yes I know about clojurescript, was thinking about closer implementation to native

charafau19:12:50

downloading javascript runtime and running app on top of it seems.. strange 😉

tbaldridge19:12:09

iOS and android come with really good is runtines

charafau19:12:08

dont know about iOS, since I work with android everyday. not sure if we’re on the same page, are you talking about react native with clojurescript?

johnnyillinois19:12:01

@charafau I am actually working on exactly what you describe. Unfortunately, those other projects look abandoned. I can let you know if i have something you can use

charafau19:12:24

I’m currently tinkering with react native which is not as good as they describe

johnnyillinois19:12:56

Hey, plus the javascript bindings when working with WebViews are error prone and hard to debug

charafau19:12:58

maybe clojure with xamarin ?

johnnyillinois19:12:23

Does xamarin build with normal webpages?

johnnyillinois19:12:36

Cause yeah that might be your best bet

charafau19:12:49

xamarin doesnt use webpages

charafau19:12:00

I was thinking about CLR version of clojure

lwhorton19:12:50

can someone point me to a good resource on list-like collections? for example: what’s the idiomatic way to check “if vector or list?” — sequential?? are there any data structs other than those two that implement Iseq, etc.?

johnnyillinois19:12:31

(defn vec? [o] (= (class o) clojure.lang.PersistentVector))) ; for example a vector
You can checkout: https://clojuredocs.org/clojure.core and search for the data structures

tbaldridge19:12:35

No, use sequential? To check for a vector or a list

tbaldridge19:12:04

Sequential? Also catches all the iseq impls

hueyp19:12:52

is there a way to parse multiple xml documents from a single file using data.xml? when I pass it a reader it seems to consume past the first document

ag19:12:09

it’s possible to refer specific symbols using aliases? e.g (require ‘[clojure.string :refer [replace :as replace*]])?

ag19:12:15

oh, I guess I’m gonna have to use :rename?

jr19:12:26

yeah use rename

mungojelly19:12:07

when i have some data that's semantically triplets, like none of the things are the primary thing they're just all related, there's no way to say a triplet directly is there, so how should i decide whether to say {:a [:b :c]} or {[:a :b] :c} or what

tbaldridge19:12:15

Use a hash set?

dpsutton19:12:39

if you're using them a bunch it may be worth it to define your own type and define an equality

dpsutton19:12:57

maybe implement ILookup or whatever the "get key value" interface is

mungojelly20:12:13

hmm, yeah, maybe what i mean to say is more like #{ {:op :a :0 😛 :1 :c} {:op :d :0 :e :1 :f}}, i'll try that, thanks, i've seen several videos of you btw @tbaldridge and they were really useful to me thank you

noisesmith20:12:46

@mungojelly ther's a config to turn off emoticon conversion, btw

noisesmith20:12:05

also :0 and :1 are terrible keywords, I hope you aren't really using such things

robert-stuttaford20:12:54

not only terrible, but invalid, i believe

mungojelly20:12:57

well no but i did use :a and 😛 for something similar recently and that didn't seem good either-- what would you recommend there? for like there's an operation and two operands, what should the keys for the operands be

noisesmith20:12:26

@robert-stuttaford the repl accepts them, trying to look up the ctual legality

noisesmith20:12:35

:a and 😛 are fine

robert-stuttaford20:12:07

i think i had issues with starts-with-a-number keywords before

noisesmith20:12:10

:b - much better

noisesmith20:12:16

(the config is per slack)

noisesmith20:12:53

;; A keyword string, like a symbol, begins with a non-numeric
;; character and can contain alphanumeric characters and *, +, !, -,
;; _, and ?.  (see  for details).

noisesmith20:12:03

so not legal per the docs at least

mungojelly20:12:04

it worked fine for me using :a and :b for the operands but then when i wanted to add an arity three operation and put :c i started to feel like, surely there's something more elegant i could be doing here

noisesmith20:12:16

my biggest shame in my own production app is that someone decided unconditionally turning all keys into keywords in incoming json was mandatory, so now we have keywords like :11112223322 floating around the app

bfabry20:12:37

@noisesmith if that's a public API that's a DoS vector

noisesmith20:12:15

@bfabfry among other issues, but no we don't decode from incoming requests that way gladly

noisesmith20:12:23

it's in converting responses

noisesmith20:12:18

I heartily disrecommend the "it's a key in a hash-map so it needs to be a keyword" thing though - terrible idea with terrible consequences

mungojelly20:12:19

btw sorry for complaining but as a lojban speaker the )))))))))) around here really doesn't seem reasonable, everyone in the world is saying that's silly and i really think it is, in lojban we sometimes practice with beginners by putting all the terminators on tuesdays, we call it Terminator Tuesdays, and here i feel like it's Terminator Tuesday every day, why not something like <<def something [stuff] (blah (blah blah stuff) blah (blah blah blah>> at least :/

noisesmith20:12:15

))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))

sveri20:12:31

@mungojelly Not sure if you are joking, but are you suggesting to replace paranthesis by different mathematical symbols? 😄

mungojelly20:12:39

no i'm not joking at all, ))))))))))) is clearly silly, a simple fix would be to have an optional parenthesis that terminates up to that parenthesis when you close it closing all internal parentheses, like if it were << >> then <<open (something (stuff stuff (done>>

mungojelly20:12:46

i know it's not going to change any time soon but i just feel so silly saying )))))) all the time and it seems like i should say something about how ridiculous it is, if my editor didn't help it would hurt my brain every time i ended a sentence

noisesmith20:12:58

have fun implementing your terrible idea, but I promise you aren't going to get clojure people to use it

joshjones20:12:01

Not only will it not change any time soon, it will not change :thumbsup::skin-tone-2:

tbaldridge20:12:27

Amazing reply by a man named @noisesmith

tbaldridge20:12:46

Sine we're talking about noise

joshjones20:12:09

Lisp has survived for 58 years partly by being syntactically simple. Let’s not even suggest something which would be completely orthogonal to its purpose

mungojelly20:12:53

i feel like it's more a collective denial, i mean everyone in the universe tells you all the time that )))))))) is silly, and there's little evidence that it isn't a blocking concern given that hardly anyone speaks lisp. even the original plan for lisp wasn't to say )))))))) that was just a hack that happened to work so they went with it for a few years until now. time to move on really.

noisesmith20:12:23

have fun moving on, don't wait up

seancorfield20:12:08

If you use an editor that manages parentheses automatically for you — and color codes them to pastel shades — then you don’t even see the closing ))))...

seancorfield20:12:55

And, frankly, if you look at non-Lisp languages, you have as much punctuation, you just tend to have styles that put all the closing punctuation on separate lines...

bfabry20:12:23

@mungojelly coming into a lisp chat room and saying lisp is silly seems a little counter productive. as sean says, most editors essentially do what you're saying at the ui layer, by making the closing parentheses unobtrusive

mungojelly20:12:30

sure well that's the terminator you're using instead of actually saying ))))))))) is newlines or indentation changes, and then parinfer or whoever turns it into the unspeakable format, which works ok for typing but there's no way to speak it and you still have lots of visual noise

joshjones20:12:20

i guess we won’t be able to use voice recognition for programming like most developers do then...

mungojelly20:12:56

the spoken form seems to mostly use pauses to show the grouping, but it doesn't work very well and you mostly can't say anything without a projector

sveri20:12:27

Uhm, when did you actually read code aloud? Usually I talk about namespaces, functions and logic...

mungojelly20:12:33

"open parenthesis" is completely unspeakable, you could easily enough change it to "open" or just "op" but then you couldn't really say "clo clo clo clo" at the end of sentences

mpenet20:12:56

https://clojurians.slack.com/archives/clojure/p1482264457004927 good point. Wouldnt any ring app using wrap-kw-param be vulnerable to this

noisesmith20:12:46

I think the fact that we don't use a deterministic hash that restarts with each request mitigates this, at least

mungojelly20:12:33

what i hear a lot in podcasts and such is people just saying "of course we can't say code since this is just audio" which is just sad, that's just complete surrender, and there's no need for it, clojure could easily be speakable with just another pair of parentheses or two that close things off for you

samcf20:12:13

people usually talk about code in terms of patterns, ideas, algorithms ... i don't think people would speak code line by line even if it were feasible to do so

tbaldridge20:12:33

There's two points I'll make on that 1) as Sean mentioned Clojure has very few parens, and the ones it has are just in different positions from C#/Java/JS.

chris20:12:59

I can’t honestly think of a situation where I’ve ever wanted to speak code aloud

samcf20:12:18

clojure as a declarative language is actually far more "speakable" than most imperative ones

dpsutton20:12:24

i've heard people say that php is unspeakable despite being a c style language

tbaldridge20:12:25

But 2) the biggest thing for me is that lisps let me program via ASTs. When I write Clojure code I am writing data that the compiler interprets. Raw data that can be tweaked just like any other data. I've needed that feature way more often than I've needed the ability to speak.

sveri20:12:27

Yep, thats what I mean, I just imagine a podcast where people speak java code aloud: class FooBar curly braces private static int someVariable = 3 semicolon linebreak public FooBar paranthese open... 😄

dpsutton20:12:32

so maybe the parentheses don't make it unspeakable

mungojelly20:12:49

well it's a feedback loop, of course you don't speak code if you'd have to say "close parenthesis, close parenthesis, close parenthesis!" and there's no need felt to improve the spoken form if people don't speak it

chris20:12:00

pseudocode maybe

dpsutton20:12:14

i thought chicken scheme had a way to say terminate all parens

dpsutton20:12:27

honestly i just haven't typed a close parens in months

chris20:12:47

I write more close parens in java and python than I ever do in clojure

mungojelly20:12:55

and i seem to recall chicken scheme being written by a lojbanist, so that would make sense :D

dpsutton20:12:03

what is a lojbanist

mungojelly20:12:30

someone who speaks lojban, a constructed language, in lojban we speak "code" as in unambiguous statements all day long, and it's very easy-- except if we try to say all the terminators, like ))))))), then it's hard to finish sentences

dpsutton20:12:51

i don't care then, i guess

seancorfield20:12:20

Anyone got a link to that talk where someone programmed Clojure in Emacs purely by voice?

tbaldridge20:12:28

Sounds like someone invented a spoken language that's incapable of expressing code.

seancorfield20:12:40

It was a few years back… don’t know whether it was Strange Loop or Conj?

chris20:12:42

the only reason I know of lojban https://xkcd.com/191/

dpsutton20:12:03

> I use most of the time a text editor (which is emacs and an extension called emacspeak, which makes emacs talk), and a browser to look some internal pages of Google with documentation and stuff.

sveri20:12:17

Hm, looking at example lojban I see this: "End of function" I believe I can say the same for clojure functions instead of clo clo clo clo?

dpsutton20:12:41

i wonder what callback hell looks like in that

sveri20:12:59

Oh, forget it, I looked at the english translation 😄

dpsutton20:12:03

close block, new line, parens, close block, new line, parens, comma,

dpsutton20:12:15

some js callbacks

dpsutton20:12:54

> Lojban translation (to be improved)

tbaldridge20:12:01

@seancorfield it was StrangeLoop...2013?

mungojelly20:12:05

that's some friends of mine trying to translate from c, not very elegant or anything but they thought they'd give it a try

dpsutton20:12:37

i mean, its cool you're trying to create a completely unambiguous language

dpsutton20:12:54

or become proficient in it or whatever

tbaldridge20:12:22

@sveri oh that's awesome, I think I've seen some BF code that was cleaner.

sveri20:12:29

I mean, no offense and I dont mean to laugh about it. Its always interesting what people come up with, but, saying clojures parantheses are evil because they cannot be spoken in lojban and then looking at this I think it is way easier to learn clojure and use all the )))))

sveri20:12:51

@tbaldridge that was my second thought after WTF too 😄

seancorfield20:12:59

With my Admin hat on, I suspect that this discussion would do better in #other-languages since it’s starting to get a little close to ad hominem at this point?

dpsutton20:12:01

it looks like binary in base five with only vowels used as the numerals

seancorfield20:12:28

(and this channel is meant to be for technical discussion of Clojure)

mungojelly20:12:48

lojban's grammar is pretty ornate and messy in places, i wouldn't recommend copying it in general, but just in terms of whether it's actually necessary to say ))))))))))) from lojban' perspective clojure is so blub, there's various options for how to not have that problem and clojure chooses none of them

chris20:12:23

but there are plenty of reasons clojure is syntacticly structured the way it is

chris20:12:28

ditto lisp in general

seancorfield20:12:57

Folks, seriously, take this to #other-languages — I won’t ask again. (with my Slack Admin hat on)

mungojelly20:12:27

but of course it's not changing today, or any time soon, i'm going to keep typing )))))) or having parinfer type it for me or whatever, but just it seems right to complain at all rather than simply accept it, it really is silly, we ought to fix it sooner or later

honzabrecka22:12:00

Does anyone know a nice way how to kill hanging clojure.java.shell/sh after some timeout?

noisesmith22:12:31

@honzabrecka - probably easier to use java.lang.ProcessBuilder to create a java.lang.Process and use the destroy method on that

noisesmith22:12:56

afaik sh hangs until the process it invoked returns

honzabrecka22:12:31

@noisesmith I’ll give it a try, thanks

noisesmith22:12:06

@honzabrecka trivial example

=> (let [builder (ProcessBuilder. (into-array ["sleep" "100000"])) proc (.start builder)] (.destroy proc))
nil

noisesmith22:12:16

nothing to import, since ProcessBuilder is in java.lang

noisesmith22:12:39

another bonus, with ProcessBuilder you can interact with it via I/O in real time

johnnyillinois23:12:17

@nwjsmith How are you able to read values from the transaction without committing?

Pishty23:12:17

Hello guys, am just getting into clojure and was wondering if proto repl is a good replacement for emacs, has anyone switched from emacs to proto-repl ?

Pishty23:12:06

if so, why ? apart from the data visualisation reason that proto repl provides

seancorfield23:12:25

@pishty There’s a #protorepl channel that will better be able to answer that (but, yes, I recently switched from Emacs to Proto REPL, after years of Emacs and I’m pretty happy).

Pishty23:12:47

oh very interesting @seancorfield thank u for that info and sharing your preference

arthur23:12:59

In the state of Clojure survey, question 17 uses numeric priority. Are higher numbers higher priority, or are lower numbers closer to the "first priority"

noisesmith23:12:31

@arthur you can drag them, higher on page is lower numbers is more priority