Fork me on GitHub

I would love to see triple quoted string literals, or anything that's multiline and removes the leading spaces.


@hlolli Just be aware that """foo""" is already legal Clojure. It's just three consecutive strings:

user=> """foo"""


it could be '''foo''' as well? triple qutations a common thing?


but yeh, hard to fit it in


If you read the design archive page above, one of the big concerns about this is that it ripples across all the Clojure tools in the ecosystem that parse code (as @vdmit11 found our with REPL-y / nREPL).


And I am fairly certain that the Clojure/core team have rejected this repeatedly...?


So it has to be something beyond triple quotes, something that is not legal syntax today, that cannot break any existing Clojure programs and will be easy for tooling to catch up with (or can already be handled by existing tooling).


#string/multiline " Foo Bar "


@lilactown That won't address the primary issue which is the ability to embed quotes etc without needing escapes.


You can already spread a string across multiple lines.


user=> "


This is a much harder problem than most people seem to think..


clojure 2.0, just a breaking change language, where all the "nice to have" stuff that was put aside have a chance to be tested out.


I don't have so many examples of nice stuff missing in clojure 🙂 but strings is for sure on my top nice to have list


To be honest, this is not realistic. Python 3 was released more than 10 years ago, but a lot of projects still didn't switch. And all IDEs, syntax highlighters and all sorts of tools will break, and their maintainers will have to support both versions of the language for a long time. I don't think that Clojure community is powerful enough to afford that.


I went to PyCon in 2013. They talked about the 2.7 / 3.0 split and said it would be another five years before they expected 3.0 to be the standard. Six years on, it's not even close. Python 3.x truly split the Python ecosystem and it's still split. This is why Clojure's approach is better.


I've been doing Clojure in production for about eight and a half years. We've been able to run Alpha/Beta builds in production throughout that time because the Clojure/core team take backward compatibility very seriously. That has incredible value, compared to a lot of other languages.


Find a guaranteed, non-breaking way to add a feature you want, sure, I'll be interested. If it breaks my 90,000 lines of code, nope, dead set against.


There are dire warnings from Python's pip that bug fix support will end for Python 2 in 2020, starting early 2019. There are also a bunch of major library maintainers who will stop support Python 2 soon, the list I found is here: That said, I won't be surprised if someone picks up supporting some of those things for at least a while longer for Python 2.


Nothing will change until Python 3.x is the default install on every platform that currently ships with Python 2.7 tho'.


I've been a Fellow of the Python Software Foundation for a decade and man, even if it's the default now, a lot of capital was burned with a lot of core Python people


(I mean I do Clojure now mostly because of the complete mess that transition was)


I was very excited after PyCon 2013 -- Python 3 is a lovely language and the talks about it got me very buzzed! I went back to work, determined to replace all of our random bash scripts with nice, maintainable .py files... and then found that everything was still 2.7 and it was kind of a PITA to not only get Python3 installed but to navigate the world of packages to find what actually ran on Python 3 😞


Speaking of which, if you really want to do triple quoted strings and use python strings interpolation, you can always use libpython-clj 😈


Really @U3BALC2HH? Could you share a working example showing that?


I'm still waiting @U3BALC2HH -- where's that example?


Lol it's 11:29 on a Friday night Sean


but here, just for you:

(require '[libpython-clj.python :as py])
(-> (py/run-simple-string "x=\\
      (get "x"))
;; =>    "tripple\nquoted\nstring\n"


Wow, that's a pretty miserable way to write a docstring :rolling_on_the_floor_laughing:


And it's using ''' inside " so it's a complete "cheat" as far as the original discussion was concerned.


(and don't complain about the time if you're trying to "pick a fight" over language or semantics 🙂 )


Hey man, there’s a talk on it at clojure/conj, I thought it was neat? ¯\(ツ)


Sure, it's neat that you can "dip into Python" inside a function call from Clojure -- and it was Clojure/South I think, not Clojure/conj? -- but that's a far cry from what was being discused.


Which arcs back to the "discussion" you tried to have yesterday.


You are being controversial/argumentative for no useful reason. It's really not appreciated.


Dial it back if you want to continue to be a member of this community, OK/


(this reflects pretty much every interaction I've seen with you here)


10am, Friday


So, not a talk that you have seen.


Not a talk you've seen that you "thought was neat".


Random walk through libpython-clj. I'm excited about it. Sorry it's coming across the wrong way to you. I'm really not trying to start anything. Would be happy to discuss it at the conj if you're there :)


I don't know why you like to provoke weird arguments over stuff -- the whole lazy/eager/unevaluated stuff the other day was just really unpleasant.


I will be at Conj. Happy to discuss over a beer. I'll buy. But you are pretty disruptive here, even if you don't mean to be.


Sorry, I get a little overly passionate about language semantics. Would you say I'm a little overly "eager" myself? ;). Perhaps even greedily... 😂


I know "text" doesn't always convey emotion. Something to consider, given how badly everyone reacted to that...


Yeah, maybe. Just... I dunno... try to dial it back a bit?


Looking forward to beers 🍻


Perhaps keep that stuff in #off-topic ?


No offense meant


I'm always looking forward to beers. I arrive Wednesday morning (because of a red-eye).


We'll be there Monday :)


We? Ah, multiple J.J.'s? 🙂


East Coast? (I'm West Coast)


Rust has a technique I had not seen before for this. You can use as many # marks before a " as you want, and the terminating " must have that many # after it, or it is not the string end.


I'm using test.chuck to parse regexes and I want to write a generative test that requires generating regexes; is there a way for a lazy person to use instaparse to turn parse trees back into strings?


test.chuck has a regex generator -- isn't that suffiicent?


test.chuck has a thing that takes a regex and produces strings matching it, I'm looking to generate new regexes


(context: I'm writing and trying to come up with cool pathological examples)


Oh... gotcha... wow... regexes all the way down.


I mean it's fine, I'll just write a spec and get a generator for free


(I'm writing a blog post to go with it to demo core.logic and Clojure in general so I care extra about quality and exposition)

Ivan Koz01:11:37

can one say that rust lang is ideologically opposite to clojure?


One can say many things!


I'm not sure what it means to be ideologically opposite to Clojure


Does Rust dislike immutability? Certainly not

Ivan Koz01:11:36

i'm not sure myself


Does Rust dislike being hosted? Eh, it's not the default, but it's not like they hate WASM


Does Rust hate functional programming? I don't think so


Also mostly the people I've met in the Rust community are nice and the same is true for Clojure


(Perhaps you do not believe being a jerk can be an ideological language position but that has not been my experience)


Anyway I hope we can all be friends -- sincerely, the person who spends way too much time figuring out how to call C ABI libraries properly from Clojure

Ivan Koz01:11:18

thanks for sharing your thoughts


I wouldn't say so no


I think its actually much closer to Clojure in ideology than C, C++ or Java are


I like Rust and the community is great. I think as a language approach, yes, it is very different to Clojure but I don't think it's fair to call it "ideologically opposite to Clojure".


It definitely shares goal. Create a modern language free of data races, designed for the multi-core, multi-processor era, with concurrency and parallelism in mind


It kinda embraces an industry standard by being built on top of LLVM same way Clojure is built on JVM


It's not a Lisp, but it does make heavy use of macros


Bindings are immutable by default. And it guides you towards safe idioms, but still gives you escape hatch when you need more raw performance.


The polymorphism is open just as Clojure's is


And its pretty functional and not so much OO, in that it favours interfaces the same way Clojure does, and open implementation of them over classes and inheritance.


And it supports function closures, higher order functions and immutable references.


The biggest difference is that it's not a Lisp, and it heavily relies on static compile time types to achieve those goals, while Clojure relies more on dynamic runtime constructs to do so.


Because of its linear types, it can afford to provide more mutability, but I think the guarantees of the borrow checker make it so it is still following the spirit of Clojure. Clojure makes similar choices in a few places, when mutability doesn't leak or exposes people to data races, Clojure allows it.

Ivan Koz13:11:29

@didibus 🙏:i_love_you_hand_sign:

Ivan Koz13:11:40

thank you guys


somewhat related, i remember a quote somewhere that went something like "functional programming is a clever demonstration that you can write code without mutation that woks, rust is an even more clever demonstration that you can do the same with mutation"


Given a seq of ints [2r11 2r1101], I want to add them such that (add-them [2r11 2r1101]) -> 2r0000001100001101 which is 781 in base10. Basically I want to add 0's to LSB of each int to make in an octet, and then string them up. I can do this through string manipulation, but I suppose there should be a more elegant approach using bitwise operators, any suggestions ?


@murtaza52 haven't thought a whole lot about your specific case, but there's bit-and and bit-or:


you need to bit shift the first operand and then or them together


@dpsutton thanks that worked like a charm (bit-or (bit-shift-left 0x03 8) 0x0D) I was always thinking in terms of the second operand, but the trick was bit shifting the first one.

👍 4

I'm trying to reduce in reverse so to iterate from the last index and on through until the 0 index? Can you please help me:

Søren Sjørup18:11:09

I know evaluation order of set literals is undefined. But what is the reasoning behind this?

(def a (atom 0))
  (defn inca [] (swap! a inc))
  #{(inca) (inca)} ;; Duplicate key: (inca)


The set literal requires distinct forms at read time.

Søren Sjørup19:11:38

Thanks. Do you know why that is?


because its a literal


its for use with literal values


same thing with map literals. {:a 3} uses literals. {(foo) 1 (foo) 2} aren't literals


another way to put it: the constraint is not a runtime constraint, it is a reader constraint, the reader doesn't care what (foo) means and treats two instances of (foo) as two of the same value

Søren Sjørup19:11:53

Thanks, I’m working on a self-interpreter but found this hard to replicate. But now that I see it’s the reader not the evaluator that reports this it makes sense again.


the executor has another layer of check {(+ 1 1) :x (- 3 1) :y} also errors, but at a different stage


cool - wanted to make sure my answer here was complete (Execution error vs. Syntax error)

👍 4
Søren Sjørup12:11:58

That was very nice of you, thank you.


There is rseq that is like seq, only works for 'reversible' collections, and returns a seq in the reverse order that seq does. Vectors are reversible collections, as are sorted sets and maps. Not sure if anything else is.


anyone know anything about the origins of the wording of the new tap> functions? Is "tap" synonymous with "send this value to a queue without blocking and handlers can be added to process the queue"? Is there a more precise definition?


I think it means, turn 90 degrees right until the start of the next turn


But, maybe it is visualized like a water tap (another output area)?


The same verb is used in core.async for mults, which multiply data flowing over a channel, you put data in to the source channel, and the mult copies the data to each channel that has tapped (been tapped? tapped into?) the mult


Oh yeah, I hadn't considered that about core.async/tap. I'm reconsidering the naming of some functions I use. Essentially side-effecting functions can be added to a set of functions (in an atom) which are all run in turn on each new incoming value of a stream. Essentially the same as the tap> feature. Currently using the terms handlers/`add-handler` but i'm not sure if that has a connotation that the return value should be meaningful when it's not for these functions, and the word tap is starting to grow on me for some reason


In my experience handler is a common term for the kind of function you describe, and does not imply that the return value is meaningful. FWIW.

👍 4

Another common term is subscriber.


i think in brewing whiskey and wine you tap a large vat to sample without disturbing the main process. to me tap sounds like siphon a bit for sampling


Also in plumbing, a tap can be created in an existing water pipe, even when water is still flowing through it:


tap meaning a branch off of the main water flow


Also there's the phrase "to tap into"

tap or tap into [TRANSITIVE] if you tap something such as someone’s ability or a supply of information, you use it or get some benefit from it : Are you tapping your staff’s full potential?
    Several other companies were already tapping this market.
(found this here:


so much nicer to think these things than "wiretap" 🙂


I am pretty sure that tap in wire tap was inspired by the earlier meanings


that makes sense 🙂


> Meaning "to designate for some duty or for membership" is recorded from 1952, from notion of a tap on the shoulder. so "choosing" might be another sense?