Fork me on GitHub
Roz Townsend07:09:39

Hello - I hope this is the right place to be posting this. I have been having a problem with Calva in VS Code - when I try to start a REPL in my project or connect to a running REPL, I get this error in the output: Error while connecting cljs REPL: TypeError: Cannot read properties of undefined (reading 'search') The problem has only cropped up recently, but switching versions doesn't seem to help me. I've also tried deleting the .calva folder and it helped once or twice, but the problem keeps coming back. Can anybody help me out?


This is a bug we should fix in Calva. Is it intermittent? What else do you do to get things going? I'm pretty sure deleting the .calva folder doesn't do anything at all for this.


So i am doing some java interop. I want to get a list from a java object, add a new element to the list and add that list to the java object. I am unsure how i do the last part though. I have this:

(doto assertion
  (.add attributeStatement))


doto will call the listed methods on the object it's passed. If you're calling a mutable operation that modifies the object it is passed and you want to return that object, I think I would just put a sequence of side effects and return the object. Maybe something like

(defn add-statement! [assertion attribute-statement]
  (.add (.getAttributeStatements assertion) attribute-statement)


Ah i see


I think i might have been confused to the immutability of java objects, which of course are mutable


So it would be just like a "regular" java add


Java objects are generally not immutable. Often I think people like to work with Clojure's data structures as much as possible in Clojure, and then keep the mutable/side-effecty parts of the code as small as possible. So I've seen patterns in code bases where the "thinking" part of the code uses things like a Clojure vector, and then because Clojure's data structures implement a lot of the Java collection interfaces you can pass in the immutable data into a set method for interop to build a java object. But it very much depends on your use case, I think.


Yea i try to limit it, but my usecase is Opensaml for authentication with SAML 2.0. There is not really anything better to use




But thank you very much ๐Ÿ™‚ I got myself confused

๐Ÿ‘ 1

I use it to implement a SAML Service Provider. It's a pretty decent wrapper.


Ah yes, i had seen that one, but I'm using the latest opensaml 4.0


But maybe it should be more like this? :

(doto assertion
  (-> (.getAttributeStatements)
  (.add attributeStatement)))

Eugene Mosh18:09:42

Hello dear friends! :smiling_face_with_3_hearts: Why forms FN, LET and LOOP are mentioned as special forms? They are build atop of other forms. For example: Thnx!


That they're implemented as macros on top of internal compiler forms should be thought of as just an implementation detail -- they are "special forms", for all intents and purposes.


in most clojure documentation "special form" tends to mean something like "lowest level language features programmers are expected to care about" instead of "forms the compiler has built in support for"


from a user perspective the big difference between those being macros or special forms is special forms cannot be shadowed

user=> (let [if identity] (if 1))
Syntax error compiling if at (REPL:1:20).
Too few arguments to if
user=> (let [let identity] (let 1))


Also, clojure.core does some pretty strange stuff that you'd never see elsewhere because it has to bootstrap a lot of core language support -- so it's very unidiomatic in some places and violates all sorts of "best practices" in terms of code that you might write yourself. That said, it can be very instructive reading, to see how many core functions are implemented.


the other one is macros are namespaced, and special forms are not


if was briefly a macro in clojure (that might have been before 1.0) when there were some changes to sequences that effected nil punning, the more complicated if macro would warn you if it thought you where trying to nil pun in a way that didn't work anymore

Eugene Mosh18:09:20

Thnx! ๐Ÿ™‚

Eugene Mosh18:09:43

Guys you are so smart and skillful!


Nah, we've just been using Clojure for a very long time ๐Ÿ™‚


> the other one is macros are namespaced, and special forms are not cough clojure.core/import* ๐Ÿ™‚


In a pedantic sense. it is fn*, and company that are the special forms, but in a practical sense, it is their wrapping macro that form the fundamental units you expect to use to build all other functions and macros with.


The documentation often take the more practical angle. If you were to implement another language and call it a Clojure dialect, and all you had was FN* and the other special forms, it would surprise people a little, they'd expect the normal if, let, fn, def and company to be the minimal set of things to provide.


Yes, in my research, most Common Lisp and scheme and other lisps don't really distinguish special forms from macros, it's just any form that is special in regards with the semantics are not like the others is called a special form. But there's this idea of minimal set of things that have to be bootstrapped for the user to then be able to build all the other forms with. And it seems sometimes special forms refers to those.


Oh, and it doesn't seem that it's from the point of like, the truly minimal set, more like, the set that the language considers fundamental. Maybe this is where you're prevented to shadow/monkeypatch those. I think even it is Common Lisp or one of the Lisps explicitly prevents that, because the special forms form like the base assumptions, the solid foundation, what users should always expect to be there and behave as they know from the language.


And, to your question as well, the wrapping macros for those I think simply adds Destructuring support in the binding. As far as I remember, that's the difference between the wrapping macro and the underlying special form.