clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
pez 2020-12-31T00:19:58.123600Z

I know this is a big ask, @didibus, but I get a bit dizzy by trying to sort all this out into a coherent suggestion on what Calva could do in this space. Knowing how you can structure thoughts… If you do find some time, I’d appreciate a feature request (or several) on the Calva repo. I also of course understand if you do not have the time.

pez 2020-12-31T00:22:25.123800Z

(The load current namespace command is already in the works, https://github.com/BetterThanTomorrow/calva/pull/904 It is the rest of this that I find myself thinking in circles with.)

2020-12-31T08:31:28.125800Z

@seancorfield I am using your clj-new, which is great. One thing I don’t understand is, I see a clj_new.clj file in the jar archive. But that file does not exist in the github repo, https://github.com/seancorfield/clj-new. Which magic makes that file into the jar?

2021-01-03T03:43:37.278500Z

Thanks. I see that now.

2020-12-31T09:39:14.126200Z

https://github.com/seancorfield/clj-new/blob/develop/src/clj_new.clj the file is there

sveri 2020-12-31T10:29:10.127400Z

Hi, so we have that nice if-let binding. However, when I check on strings, if-let works on an empty string, which makes sense. Is there a similar macro for strings that only creates a let binding if a string is not null or empty?

p-himik 2020-12-31T10:40:52.127500Z

You can wrap something that returns a string (or any other collection) in a call to not-empty. Just in case - also note that if-some exists.

2020-12-31T10:42:31.127700Z

(defn not-empty-str [s]
  (when-not (string/blank? s) s))

(if-let [x (not-empty-str "")]
  x
  "FAIL")

p-himik 2020-12-31T11:30:50.128100Z

string/blank? is different from "an empty string": "True is s is nil, empty, or contains only whitespace."

p-himik 2020-12-31T11:31:27.128300Z

If you know for sure that something is a string, there's absolutely no reason to not use not-empty in the described scenario.

vemv 2020-12-31T12:01:52.128600Z

> there's absolutely no reason {...} there is: as you hinted, string/blank? is a stronger predicate, and the one that one would likely want to use in a custom macro. (Whether a custom macro is worth it for such a specific use case is a different topic)

dharrigan 2020-12-31T12:03:30.128800Z

I also use seq which works with strings, collections and so on.

dharrigan 2020-12-31T12:04:01.129Z

which, not-empty uses under the covers

Timofey Sitnikov 2020-12-31T12:08:55.130700Z

Good Morning Clojurians. How come the https://maven.apache.org/guides/mini/guide-mirror-settings.html lists the official maven repo as <https://repo.maven.apache.org/maven2> and my clj seems to think that (https://repo1.maven.org/maven2/) is the central repo?

borkdude 2020-12-31T12:12:44.131800Z

I'm using a transit library from 2016 (by @russ767, the golang one) I see this warning on the transit-java page: NOTE: Transit is intended primarily as a wire protocol for transferring data between applications. If storing Transit data durably, readers and writers are expected to use the same version of Transit and you are responsible for migrating/transforming/re-storing that data when and if the transit format changes. Does this mean a go transit lib from 2016 might not be compatible with a clj/java transit lib from 2020?

borkdude 2020-12-31T12:13:01.132300Z

I mean, what kind of standard is transit, if you cannot rely on this?

borkdude 2020-12-31T12:13:22.132600Z

Is the spec versioned?

borkdude 2020-12-31T12:13:55.132800Z

It seems so? Version: 0.8

borkdude 2020-12-31T12:14:45.133200Z

Are changes to transit versions documented?

p-himik 2020-12-31T12:18:24.133300Z

I think it's the same repo but available at different URLs. Check out the top &lt;url&gt; tag here: https://repo.maven.apache.org/maven2/.meta/repository-metadata.xml

dharrigan 2020-12-31T12:18:28.133500Z

Both ultimately resolve to a caching provider (fastly) with the same subnet, so I wouldn't be surprised if they are simply the same service.

1
p-himik 2020-12-31T12:20:07.133700Z

Some details: https://maximilianmichels.com/2017/who-is-behind-maven-central/

1
😀 1
p-himik 2020-12-31T12:22:17.134Z

@vemv str/blank? is not stronger, it's completely different:

(str/blank? "   ")
=&gt; true
(not-empty "   ")
=&gt; "   "

vemv 2020-12-31T12:24:39.134300Z

This is the original q: > only creates a let binding if a string is not null or empty? str/blank? satisfies that. It's stronger than not-empty because it rejects more invalid strings. A custom let that considered "" blank but " " not blank would seem fairly contradictory.

sveri 2020-12-31T12:25:43.134700Z

Actually in my context I indeed look for str/blank. I ended up copying the if-let macro and adding an additional predicate on the test: (if (and temp# (not (str/blank? temp#))) instead of (if temp#)

p-himik 2020-12-31T12:27:09.134900Z

Sorry but I don't follow you at all @vemv . The original question does not use the word "blank" but uses the word "empty". Maybe we have differences in our understanding of the word "empty". I treat it as empty?, but maybe you treat it as "not visible if rendered with no context" or something like that? But given the elaboration from sveri, this is now but a discussion of semantics. :)

sveri 2020-12-31T12:29:49.135100Z

Sorry for being unclear in my original question. For me > if a string is not null or empty? refers to str/blank?, but thats just my interpretation.

👍 1
roklenarcic 2020-12-31T13:35:44.136400Z

If I want to represent a pair in clojure, which representation has the least memory used: vector, list or something else?

roklenarcic 2021-01-01T19:07:08.245500Z

thanks people, I wanted equality semantics so I didn’t go with array, but rather with (List/of (object-array [val1 val2]))

2021-01-01T23:50:10.260400Z

Does that really take less memory?

2021-01-01T23:55:54.262300Z

Also, forgot to mention before, if you're storing primitives, you can try vector-of it is a space efficient version of vector, the purpose of it is space efficiency.

2021-01-01T23:56:31.262500Z

It's basically a vector interface implemented over a typed homogeneous array of primitives

p-himik 2020-12-31T13:52:33.136500Z

defrecord, according to a small experiment with https://github.com/clojure-goes-fast/clj-memory-meter

p-himik 2020-12-31T13:53:17.136800Z

If you don't care about immutability then regular Object[] will be even smaller.

2020-12-31T14:11:05.137500Z

also worth a look: https://github.com/ztellman/vertigo

vemv 2020-12-31T14:14:00.139500Z

I encountered this exact thing (for IPV6 specifically) https://support.cloudbees.com/hc/en-us/articles/360035734031-Stuck-thread-looking-up-IPv6-hostname in a clj program of mine Is -<http://Djava.net|Djava.net>.preferIPv4Stack=true a good idea then? Or at least a not-terrible one I hope? (I've seen it in various clojure projects, I never happened to know what was being fixed there)

Timofey Sitnikov 2020-12-31T14:22:54.141700Z

I am trying to run test for https://github.com/fulcrologic/fulcro-rad-sql but getting No matching ctor found for class org.flywaydb.core.Flyway error. like so:

[I] /home/sporty/clojure/fulcro/fulcro-rad-sql~&gt; clj -M:test
Clojure 1.10.1
user=&gt; (require 'com.fulcrologic.rad.database-adapters.sql.query-test)
Syntax error (IllegalArgumentException) compiling new at (com/fulcrologic/rad/database_adapters/sql/migration.clj:170:28).
No matching ctor found for class org.flywaydb.core.Flyway
I am I missing something in the setup?

vemv 2020-12-31T14:23:43.141900Z

Sounds like a dependency resolution issue. Are you on Lein or deps.edn?

Timofey Sitnikov 2020-12-31T14:24:02.142100Z

deps.edn

vemv 2020-12-31T14:25:17.142300Z

ok, I lack expertise there but the underlying issue, I think, is that Fulcro expects one specific version of the Flyway .jar, but deps.edn is fetching another Different jars can have different versions of the java code, which would explain the not-found constructor

1
Timofey Sitnikov 2020-12-31T14:30:51.142500Z

Thats crazy, but but yes, that was the problem. I make all the deps to use the same older version and now it works. Thank you.

🙌 1
Timofey Sitnikov 2020-12-31T14:31:35.143Z

Phew, I have so much to learn with this huge Clujre stack.

Askri Ghassen 2020-12-31T14:37:52.144600Z

Hello every one i am here for searching a good documents that's helps me build a web api using pedestal integrant and vase

vemv 2020-12-31T14:40:22.144700Z

10 years on the JVM and still learning (as you can see in the question I posted above yours)... 😃 at least us clojurians tend to not break APIs so much. I don't remember an issue like yours (which is relatively common in Java) with clojure .jars

simongray 2020-12-31T15:41:03.145800Z

There’s no way to add support for with-metadata to instances of a Java class, is there?

simongray 2021-01-01T16:32:31.230800Z

Thank you for that example. I’m not sure I understand what the delegate part is in the example and how it differs from java proxies, since the the example seems to use proxy? Anyway, if my understanding is correct, I will need the proxied class to have constructor that can take an existing instance of the class and create a new instance from it, right? It is a great hack, but unfortunately it’s not general enough to wrap e.g. random Java objects from a Java library, which is really what I’m looking for… :/

rutledgepaulv 2021-01-05T03:55:05.367300Z

my apologies for not being very clear. proxy the clojure function isn't the same as a java.lang.reflect.Proxy instance although they're similar in purpose. You can use Proxy instances to support classes that don't necessarily have a "delegate" constructor by adding a layer of indirection between the object consumers see and the real object instance underneath (this is what a java.lang.reflect.Proxy does). To use java.lang.reflect.Proxy you'll need to have interfaces that you can rely on for each type of object (one of which would be IObj), otherwise I believe you'd need to dip even deeper into things like javaassist / cglib to pull it off if your objects don't have interfaces and instead are using abstract classes or things like that

rutledgepaulv 2021-01-05T04:00:48.367900Z

would be interested in hearing more about what you're trying to solve by adding metadata to java classes though - there may be another way to approach the problem that is almost certainly worth pursuing over doing funny things with javaassist / cglib

simongray 2021-01-05T07:36:14.379Z

Sure. The issue is the following: In Stanford CoreNLP you define a pipeline based on a list of annotators. Then when you annotate a piece of text, you get back an instance of an Annotation class. This is basically just a glorified map containing other annotations. As an aggregate, they form a tree of different kinds of annotations. You can navigate down the tree using a set of functions picking different kinds of annotations. One issue is that there is nothing in particular marking what type of annotation the instance is - you only know this from the key that you got it from. You also don’t know what kind of pipeline setup it was constructed from or what it was a child of, so I can’t navigate back up the tree like you would do with something like clojure.zip. One way of solving this lack of information is to wrap the Annotation in a Clojure map when you get it, but that would introduce new complexity when interfacing with the Java API, since it’s now an instance of a different class. Another way of solving it would be to mutate the Annotation object by setting my own key using its setter function, but that would 1) add mutation and 2) pollute the domain with implementation code that doesn’t really belong there. So I thought that maybe I could use metadata to solve this issue with a lack of, well, metadata.

Schpaa 2020-12-31T16:06:49.146100Z

(core/defmacro or
  "Evaluates exprs one at a time, from left to right. If a form
  returns a logical true value, or returns that value and doesn't
  evaluate any of the other expressions, otherwise it returns the
  value of the last expression. (or) returns nil."
This sentence does not compute

dpsutton 2020-12-31T16:10:36.147100Z

read the or on the second line not as a logical construct but as the macro under discussion. "If a form returns a logical true value, this form returns that value and doesn't evaluate any of the other expressions..."

Schpaa 2020-12-31T16:14:35.147600Z

this is the fragment that is particularly confusing ”

, or returns that value and doesn't
  evaluate any of the other expressions,

Schpaa 2020-12-31T16:16:53.148800Z

But what do I know - I am not a native speaker, this could be James Joyce quality for what I know

bronsa 2020-12-31T16:17:59.149700Z

"if a form returns a logical true value, or returns that value (the logical true one) and doesn't evaluate any of the other expressions"

alexmiller 2020-12-31T16:19:43.150200Z

Yes, but there have been no changes since it's initial release in 2014

dpsutton 2020-12-31T16:20:48.152Z

yeah. substitute that "or" with "this macro". It is certainly confusing because we need a way to specify if we're talking about the conjunction "or" or the macro or

Schpaa 2020-12-31T16:20:50.152100Z

funny how the description of boolean stuff sounds so unboolean in english

dpsutton 2020-12-31T16:22:19.153700Z

also, there's an "and" after it which probably primes our brain to interpret the preceding or as the conjunctive part of speech rather than the macro this docstring is describing

alexmiller 2020-12-31T16:22:32.153800Z

This refers to the transit format spec, which has not changed.

borkdude 2020-12-31T16:22:38.154Z

Btw, I'm using the russolsen go transit lib for real now.

Schpaa 2020-12-31T16:22:54.154400Z

I agree, it need more parens

😁 1
borkdude 2020-12-31T16:23:03.154500Z

OK, I feel lucky

dpsutton 2020-12-31T16:28:39.155100Z

I dont see how parens would help. I think bronsa put the best solution which is to put backticks around the confusing or

2020-12-31T16:50:28.155200Z

haha, James Joyce was famous for prose that made no clear sense :D

seancorfield 2020-12-31T17:48:06.155800Z

@i Glad you find it useful! There's a #clj-new channel if you get stuck or want to deep dive on anything.

lilactown 2020-12-31T18:34:40.156200Z

anyone have experience drawing ASCII art in a REPL?

lilactown 2020-12-31T18:35:14.156900Z

I'm guessing that there's going to be issues dealing across various displays (e.g. TTY, Cursive, Emacs buffers)

2020-12-31T18:36:01.157800Z

if all you do is print line by line, and you use a standard character set, it should just plain work (though emacs bugs out with wide lines)

2020-12-31T18:36:59.158900Z

if you are trying to do cursor control, you need a cursor control lib, and those don't target cursive or emacs (though at least emacs does have buffers that are vt100 compatible...)

lilactown 2020-12-31T18:37:23.159100Z

yeah I just need to be read only for now

lilactown 2020-12-31T18:37:32.159400Z

and print line by line

phronmophobic 2020-12-31T18:37:56.160Z

I've been using https://github.com/mabe02/lanterna for terminal graphics

2020-12-31T18:38:03.160300Z

I think any output that displays fixed width properly would just work

2020-12-31T18:38:17.160700Z

yeah, it looks like lanterna is great if you need cursor control

phronmophobic 2020-12-31T18:38:31.161Z

or mouse support!

phronmophobic 2020-12-31T18:38:52.161600Z

it's also graalvm compatible if you want to have fast start up

lilactown 2020-12-31T18:40:27.162900Z

I think that printing to a REPL buffer is as much as I want to do to keep it simple enough to: • View remotely (e.g. across a socket REPL/nREPL connection) • Use in CLJS / browser

👍 1
lilactown 2020-12-31T18:41:13.164200Z

if I was only interested in Clojure and doing local dev then lanterna would probably be better

2020-12-31T18:41:17.164400Z

yeah, I've had good luck viewing ascii formatted text in a browser, just make sure to use &lt;pre&gt; or otherwise ensure fixed width

2020-12-31T18:41:36.164700Z

(I used this for tabulating cljs test output)

2020-12-31T18:41:58.165100Z

(who wants to mess with browser rendering in your test suite...)

2020-12-31T19:05:53.169300Z

Hey all I'm trying to wrap a defn in a macro. Can anyone explain to me why this doesn't work? A little new to macros. (defmacro m [x] (defn f [x] (x)))`

2020-12-31T19:08:10.171Z

@buterajay this might be better for #beginners but to start, macros return lists and the list gets compiled, in your list the function argument is nonsensical

2020-12-31T19:08:48.171800Z

this one is small enough to work out by hand: (m 5) would become (defn f [5] (5))

2020-12-31T19:10:16.172700Z

(well it would work as (m conj) for example, except it would create a function that takes an argument named conj and then calls its arg with no args...)

2020-12-31T19:10:49.173200Z

@buterajay do you understand this syntax error?

(ins)user=&gt; (defmacro m [x] `(defn f [~x] (~x)))
#'user/m
(ins)user=&gt; (m conj)
Syntax error macroexpanding clojure.core/defn at (REPL:1:1).
user/f - failed: simple-symbol? at: [:fn-name] spec: :clojure.core.specs.alpha/defn-args

2020-12-31T19:13:14.174500Z

Hm ok that makes sense, but what if my input is a simple symbol like (m 'v)

2020-12-31T19:13:38.175300Z

it would break, as 'v is (quote v) which is not a valid argument name

2020-12-31T19:14:43.176100Z

also, your macro gets one step closer to working as follows (but probably isn't doing what you want)

(cmd)user=&gt; (defmacro m [x] `(defn ~'f [~x] (~x)))
#'user/m
(cmd)user=&gt; (m foo)
#'user/f
(cmd)user=&gt; (f conj)
[]
(ins)user=&gt; (f +)
0

2020-12-31T19:15:08.176700Z

the arg name to m doesn't matter at all, as it is just a placeholder inside f

2020-12-31T19:15:57.177600Z

(what I did to fix the previous error is unquote then quote f, so that ` wouldn't namespace it and break the defn)

2020-12-31T19:16:34.177900Z

Ooh gotcha

2020-12-31T19:16:47.178200Z

have you used macroexpand ?

2020-12-31T19:17:15.178800Z

Ya but my macros often are too broken for it to work lol

2020-12-31T19:17:57.180200Z

yeah, that's frustrating, here's a small workaround for debugging:

(ins)user=&gt; (defmacro m [x] `(_defn f [~x] (~x)))
#'user/m
(cmd)user=&gt; (macroexpand '(m foo))
(user/_defn user/f [foo] (foo))

2020-12-31T19:18:17.180700Z

I thought with a macro, the inputs are not evaluated, so passing in a symbol would just be the symbol and not (quote v)

2020-12-31T19:18:23.180900Z

it's interesting that the schema check runs by just expanding the macro, kind of agressive...

2020-12-31T19:18:40.181200Z

'v prevents evaluation outside macros

2020-12-31T19:19:03.181700Z

it expands to (quote v) which is a reader syntax for not evaluating

2020-12-31T19:19:22.182100Z

but if you already aren't evaluating, you just get (quote v) when you use ' too

2020-12-31T19:19:37.182400Z

user=&gt; ''''''''foo
(quote (quote (quote (quote (quote (quote (quote foo)))))))

2020-12-31T19:20:36.183200Z

because quote doesn't mean "make a symbol when reading" it means "don't evaluate this form", so when you nest it, you get the inner quote as is

2020-12-31T19:22:46.184900Z

Ok that makes sense. So then how would you define a variable name like x? Should I evaluate a string into a list?

2020-12-31T19:23:03.185100Z

what should this macro do?

2020-12-31T19:24:15.187200Z

Basically (m v) should return (defn f [v] (v))

2020-12-31T19:24:47.187700Z

I asked that because I don't understand the question "how would you define a variable name" - usually in macros the variable names are auto-generated and what matters is that they match the binding

2020-12-31T19:25:07.188Z

the binding block on f there means that v is meaningless

2020-12-31T19:25:12.188400Z

it's just a throwaway name

2020-12-31T19:25:21.188700Z

(for an arg, that gets called with no args)

2020-12-31T19:25:51.189600Z

I see what you mean, maybe I need to rethink exactly what it is that I need..

2020-12-31T19:26:03.189900Z

so as you specify, (m asdfljasdfk) and (m foo) and (m conj) all do the same thing

2020-12-31T19:32:31.196500Z

Essentially I'm looking for a way to compress an expression into a single macro with free variables as inputs. If you have a free moment, I have a video of visual clojure editor I'm working on. Basically this macro would help me to compress larger expressions into single reusable blocks. https://photos.app.goo.gl/Yh2emBVrgsEcDxhF9

2020-12-31T19:39:04.200300Z

@buterajay if I understand what you are trying to do, I think your best bet is to set aside ` entirely, and look at what a macro does your own program is doing some of the work that ` does, while missing the variable capture safety both your program and `, are tools for constructing lists from templates, you can just return the list you want compiled from a macro

2020-12-31T19:40:18.200600Z

(ins)user=&gt; (defmacro silly [] (list 'defn 'f ['x 'y] (list '+ 'x 'y)))
#'user/silly
(ins)user=&gt; (silly)
#'user/f
(ins)user=&gt; (f 1 2)
3
• edited in an attempt to make it clearer what I'm demonstrating

2020-12-31T19:40:52.201400Z

for a non "silly" example, you would be doing something other than just returning that defn list - you'd be doing some sort of list interpolation / splicing / substitution

2020-12-31T19:41:24.202Z

I don't think ` will help you much here - you are making an alternate way of doing that - which is valid, it's just a series of tree transforms

2020-12-31T19:42:05.202500Z

you might want to skip defmacro entirely, and just construct lists to pass to eval

2020-12-31T19:43:33.203700Z

perhaps the domain of your program is that a user interacts with the GUI to construct a namespace, this means the goal would be to translate the GUI state into a series of forms that clojure could load to create a namespace

2020-12-31T19:49:16.206500Z

Wow ok I think I'm seeing what you mean. I knew it would just take someone with a clojure mindset haha. I need to process this a bit more. Thank you very much

alexmiller 2020-12-31T20:05:13.207900Z

the check happens at macro expansion time so I don’t actually think it’s aggressive at all

cfleming 2020-12-31T20:16:36.208200Z

Cursive does implement some ASCII escape codes, but it’s very far from implementing a full terminal. I can get a list of the supported codes if that’s useful.

emccue 2020-12-31T20:28:21.208400Z

If you want, you could define "truthyness" differently

emccue 2020-12-31T20:29:05.208600Z

(defn truthy? [v]
   (not (or (nil? v)
            (false? v)
            (empty? v))))

emccue 2020-12-31T20:29:13.208800Z

and then build something around that

2020-12-31T20:59:56.209Z

The answer is no. If-let checks for truthy values, and truthy values are all values except for nil and false. So a String, no matter what characters it contains or doesn't is always truthy. So like others said, you need to wrap the string in some other function that returns the string or falsy.

2020-12-31T21:03:31.209300Z

A wire protocol? It just says that new version of transit could be incompatible with the old versions. And since wire is the focus, my guess is if for any reason an incompatible change improves performance a lot of addresses some other major issue they'd do it.

2020-12-31T21:04:46.209600Z

An array most likely

borkdude 2020-12-31T21:08:37.209800Z

@didibus sure, but this means that a web service in language A talking transit 0.8 (of company Y) and a web service in language B (of company Z) upgrades to 0.9 suddenly can't talk to each other anymore?

borkdude 2020-12-31T21:09:18.210Z

that seems like a very brittle way of doing things. what if JSON makes a breaking change?

2020-12-31T21:12:07.210200Z

I get it, but I don't believe this is the use case for transit.

2020-12-31T21:13:05.210400Z

The use case is fast communication between services. I think it's meant for micro-service and client/server communication. Where if you upgraded, you'd upgrade everything together.

2020-12-31T21:14:39.210600Z

I also think what it would mean, is that the two services when communicating would need to agree on the version of transit to use. So maybe transit 0.9 can still communicate in transit 0.8 to a 0.8 client.

2020-12-31T21:15:09.210800Z

But I don't know if that's the case, or maybe since the protocol never actually changed yet, this problem and it's solutions haven't come up

borkdude 2020-12-31T21:30:32.211Z

One problem I'm specifically having: babashka can communicate with pods (standalone programs) via transit. If babashka would upgrade its transit lib but the sqlite pod (written in Go) doesn't, there may be a problem

borkdude 2020-12-31T21:30:43.211200Z

and this go lib doesn't even mention a transit version

borkdude 2020-12-31T21:31:49.211400Z

In this case I would prefer stability over performance, so maybe transit isn't the right pick then

borkdude 2020-12-31T21:32:06.211600Z

I picked transit because it has support for byte arrays which JSON hasn't

borkdude 2020-12-31T21:32:34.211800Z

sending a byte array from clojure to a pod works seemlessly without having to think about base64, or whatever

2020-12-31T22:13:44.212Z

I guess my surprise is that I'm used to thinking of macro expansion as manipulating symbols of lists, and defmacro wasn't expanding a defn but rather constructing one - it' s a minor thing to be sure

2020-12-31T22:15:15.212200Z

my mental model was that (macroexpand '(defn ...)) would go through defn's validators as it expands defn itself, but I didn't expect the result list to also get validated based on the first symbol

2020-12-31T22:43:38.212500Z

Hum... Well I think it is up to you to negotiate a version of transit to use maybe? But this "negotiation" mechanism isn't in the Spec. And so Transit libraries for various languages don't have to support it or anything. I don't know, are there a lot of data encodings out there that took a stand on cross version compatibility?

borkdude 2020-12-31T22:47:08.212800Z

> This implementation's major.minor version number corresponds to the version of the Transit specification it supports. I have trouble finding out which major and minor version this lib has: https://github.com/russolsen/transit

borkdude 2020-12-31T22:47:56.213200Z

I think it would be appropriate to have different namespace names in transit libraries if there are breaking changes, so you can support multiple at the same time

borkdude 2020-12-31T22:48:10.213400Z

transit08.clj, transit09.clj

borkdude 2020-12-31T22:52:41.213600Z

but as Alex has said, the format hasn't changed since 2014 so maybe it's a non-issue

👍 1
2020-12-31T22:53:29.213800Z

Ya, the thing is the libs don't really matter

2020-12-31T22:53:34.214Z

This is the spec: https://github.com/cognitect/transit-format

2020-12-31T22:53:42.214300Z

Current version is 0.8

2020-12-31T22:55:44.214600Z

That said, the spec does say: "Each library's major.minor version number corresponds to the version of this specification it implements."

2020-12-31T22:56:08.214800Z

So I think a well designed lib for transit should have versions mapping to the spec it implements

2020-12-31T22:56:37.215Z

But ya, I guess namespaces would be nice, since then you could support multiple versions

borkdude 2020-12-31T22:57:04.215300Z

> Ya, the thing is the libs don't really matter What do you mean?

borkdude 2020-12-31T22:57:50.215500Z

So they way they propose to use transit is in controlled environments where you have control over each component - not as something you expose to the outside world, I guess?

2020-12-31T22:58:48.215700Z

I mean that the library can easily be designed badly, or behind, in some given language. The transit version I believe is part of the payload, since transit is self-describing. So in theory, a good lib can decode transit of any versions, or throw if it knows it can't.

2020-12-31T22:59:08.215900Z

But two systems exchanging messages, should also make sure they use the same protocol

borkdude 2020-12-31T23:00:21.216200Z

I don't think the transit version is part of the payload

2020-12-31T23:01:00.216400Z

I mean, you can expose it to the outside world. But say I had an API, and I took and returned Transit 0.8, I'd tell my clients. And if I'm about to upgrade to 0.9 and no longer support 0.8, that be for me to communicate it to them, and help them migrate, or I can provide another API that takes 0.9, etc.

2020-12-31T23:01:12.216600Z

> I don't think the transit version is part of the payload Hum...

2020-12-31T23:01:45.216800Z

If that assumption I'm making is wrong, then I guess ya, Transit might be meant for closed systems that you control end to end

2020-12-31T23:02:16.217Z

Because that means there'd be no way to handle a 0.9 that is incompatible with 0.8 if it ever happens

2020-12-31T23:02:58.217200Z

Maybe that's still a non-issue. Like Alex said, who knows if we will ever need a 0.9, and if we do, maybe it will be made backward compatible anyways.

vemv 2020-12-31T23:03:00.217400Z

using this flag didn't seem exactly harmless as it triggered this kind of error: > I get the above exception when I set bind_host to :: but specify -<http://Djava.net|Djava.net>.preferIPv4Stack=true -<http://Djava.net|Djava.net>.preferIPv4Addresses. https://github.com/elastic/elasticsearch/issues/15143#issuecomment-160945522

borkdude 2020-12-31T23:03:05.217800Z

Interesting: https://groups.google.com/g/transit-format/c/jSo-nE4JoHU

borkdude 2020-12-31T23:03:16.218Z

> Transit was released as version 0.8 July 2014 and has not been changed since

2020-12-31T23:04:57.218300Z

Ya, but if the encoding isn't describing of its protocol version, that does mean it can't gracefully handle breaking changes.

2020-12-31T23:05:40.218500Z

So we have to rely on the rationale that most likely at this point, they'd never break compatibility since so many people use it.

2020-12-31T23:06:43.218700Z

Maybe they'd do a Transit2 instead of a 0.9 if they needed a breaking change. I wouldn't be surprised. Clojure core devs and Rich hates breaking people's code, so I think its fine not to worry about this scenario

2020-12-31T23:15:50.219Z

My conclusion is not to worry about it. I really suspect this is a similar case to Clojure libs being stuck in 0.x forever. And I'm like 99.9% convinced they'd never introduce a breaking 0.9 transit version.

2020-12-31T23:19:40.219200Z

Also, I see the spec specifies MIME types. So maybe the payload doesn't tell you the protocol, but it seems to be intended to use a MIME type with it. So I think it be easy to add a new MIME type if Transit changed in incompatible ways.

borkdude 2020-12-31T23:21:24.219400Z

right. right now I use transit+json as the "mime" type in babashka pods

borkdude 2020-12-31T23:21:44.219600Z

this could also be transit0.9+json in the future

2020-12-31T23:23:28.219800Z

Ya exactly

2020-12-31T23:25:47.220Z

I think its safe to use for pods.