Fork me on GitHub
#clojure-europe
<
2023-07-08
>
ray08:07:16

A JS dev this week informed me that in JS they can put symbols in an object and have the keys default to the name of the symbol. Has anyone seen or written a macro / tag literal to do this for CLJ/S?

pez08:07:20

I haven’t seen any. Also haven’t been on the lookout. Not particularly fond of that syntax. My brain refuses to help me restore the balance, and I get unpleasant surprises from refactor-rename at times. The latter depends a bit on how things in general are factored, so might not bite everyone.

ray12:07:40

I came up with this

ray12:07:03

(defmacro s->m
  [& syms]
  (if-not (and (seq syms)
             (every? symbol? syms))
    (println "All arguments must be symbols")
    `(do (into {} (map ~(fn [k v]
                          [(keyword k) v])
                       '~syms [~@syms])))))

ray12:07:08

(let [sym1 1
      sym2 2]
  (s->m sym1 sym2))
=> {:sym1 1, :sym2 2}

ray12:07:25

actually I think this slightly tweaked version works better

ray12:07:29

(defmacro syms->m
  [syms]
  `(do (into {} (map ~(fn [k v]
                        [(keyword k) v])
                     '~syms [~@syms]))))
=> #'user/syms->m
(let [{:keys [sym1 sym2]} {:sym1 42 :sym2 420}]
  (syms->m [sym1 sym2]))
=> {:sym1 42, :sym2 420}

pez12:07:18

Very cool! I think the latter approach will be necessary to support the mixing between lone symbols and key->value pairs that you have in JS. That gets less verbose with comma playing a role of separating the entries.

ray19:07:49

The :female_mage: :female_mage: have this one

ray19:07:55

I like this version

(defmacro locals [& xs]
  (zipmap (map keyword xs) xs))
(let [x 1 y 2]
  (locals x y))

ray19:07:18

@UK0810AQ2 gave it to me

pithyless08:07:31

Unsolicited opinion: I’ve worked in a code base that made heavy use of this kind of macro (can’t remember what it was called) and I felt that the savings (less typing?) was not worth the hassle. Mainly, grepping for keywords was more difficult, linters and dev tooling had more issues with understanding the code (this was before clj-kondo and macro expansions), it discouraged use of qualified keywords, and was just one more thing that was unfamiliar to clojure developers walking up to codebase.

pithyless08:07:45

If the need is primarily for tap debugging, one can also consider macros that just tap all local variables in a map (without needing the specify). I would consider also an editor macro that “converts” the shorthand to an actual map in the source code.

pithyless08:07:30

But maybe I just have some untreated PTSD from that project and I’m overreacting. Feel free to ignore ;)

pez09:07:33

I think the idea here is rather that if some language has a useful syntax, a lisp can most often be made to mimic it. Without attaching “should” there. 😀

ray13:07:41

I hear you @U05476190. A lot of this is just to demonstrate that Clojure can have something fairly similar but yeah, code generation always has some issues.

pez09:07:53

In TypeScript if I don’t export a thing from a module, I can’t easily access it anyway, like I can with Clojure. Sometimes I have a private function that I want to unit test, and then it gets to be a tradeoff between having something in the API that is not meant for direct consumption and skipping testing the function directly. I guess this is similar in Java. Anyone has ideas/strategies for how to deal with it?

pez09:07:56

What I tend to do is one of these two: 1. Find a way to test it from the exported objects 2. Prefix the function name with _ Sometime 3: Refactor, because the need to test the function points at something being a bit weird. (However, I tend to not be this smart most often, so 1 and 2 are my gotos.)

borkdude11:07:23

prefix it with _internal_

borkdude11:07:54

in my experience, even _impl isn't clear enough that you should not rely on it as a public interface, this is why I've switched to the word "internal" in newer libs

pez11:07:28

Ah, makes sense. Just tell what it is.

potetm12:07:11

Use defn-?

potetm12:07:05

And use (#'myvar args) in the test

potetm12:07:16

Oh wait. You're asking about typescript. facepalm

ray10:07:37

Morning

lread15:07:06

moooooorniiiiiiing!

mccraigmccraig16:07:59

anyone using tree-sitter in emacs@29+doom and have any pointers ? i've gotten it installed with the standard doom mechanism, which seems to have installed a whole bunch of grammars, and i can enable highlighting with tree-sitter-hl-mode ... is there anything else available atm - e.g. structural editing support ?

otfrom16:07:08

combobulate should give you some structural support for things

mccraigmccraig14:07:44

hmm. not sure what's going on with combobulate, but after following it's install instrux i end up with errors activating tree-sitter because it can't find a grammar .so ... even though i'm on macos and the grammars are in .dylibs

reefersleep22:07:17

I saw this thread on Hacker News: "What programming language has the most beautiful syntax?" https://news.ycombinator.com/item?id=36584346 And maybe it's because I've been drinking the Kool Aid (and nothing else) for so long that I was like, "Why are you even mentioning these languages that are not lisps, I don't get it". I certainly could benefit from learning more languages, and perhaps my opinion would change, had I infinite time for such indulgences. But I want to propose a toast for what I perceive to be two beautiful aspects of the syntax of lisps (as I know it through Clojure): the regularity (the first item in a set of parens is the function you're calling, the rest are the args) and the easily understandable scopes (from ( to the corresponding )). This works so well compared to other languages, and enables the exceptional exceptions that you get in macros and such. Cheers! 🍻

🎉 8
😆 2
🍻 4
Ben Sless04:07:37

It's like more than half of the dragon book is about lexing and parsing! Who tf cares?! I don't want pretty syntax, I want no syntax

6
4
pithyless09:07:09

I have a theory that with the advent of LLMs for generating code, we will see a revival of lisp-like syntax. It took 20(?) years for people to move away from CISC cpu architectures back to RISC. I think something similar will happen with code generators over time: Google / Microsoft / Someone will introduce a brand new AI-focused language and will look like lisp/scheme. Not having too deal with syntax errors and working with simpler AST parsers and paredit-style modifications will make chatgpt-style prompts "smarter" and more likely to generate valid code. And all the languages will have transpilers from their respective syntaxes to this "ai-lisp-language", hence automatically increasing the overall training dataset (of logic/algorithms/etc) without actually having to scrape more code.

pithyless09:07:30

Of course, it won't actually be called "lisp". The marketing VPs would never allow that ;)

simongray06:07:27

> Of course, it won’t actually be called “lisp”. The marketing VPs would never allow that 😉 The same way RDF, triplestores or the semantic web must not be mentioned when discussing Datomic. 😉

reefersleep09:07:47

@U4P4NREBY have you moved all your config/data stuff into triple stores at this point? 😄 You seem very fond of them and their flexibility.

simongray11:07:19

Yeah, I basically only use them now. 😅

reefersleep11:07:29

That's very interesting. Do you tend to have a lot of custom transforming functions for creating more "easy" data structures to pull subsets of info from, or do you use some generalised transformation fn/library?

simongray12:07:50

I am usually either pulling out a list of rows (like in a SQL result) or everything related to a specific resource/entity. In the latter case it’s simply a matter of collecting key-value pairs into a map, in the former you typically consume them as-is (just like with the results of a complex SQL query).

🤓 2