Fork me on GitHub
#clojure
<
2021-04-25
>
zimablue07:04:04

is it idiomatic to create a record with no fields as the equivalent of what I'd use a python (implicitly static) class for - a quasi-namespace grouping related functionality?

borkdude07:04:37

@zimablue can you give an example of how you use it?

borkdude07:04:52

If you need a marker interface you can also use definterface

zimablue07:04:32

in interactive development, often around manipulating data like data munging, in python my workflow is like (mess with in repl) => (end up with lots of functions) => (throw those functions into static python classes grouped by area) => (refactor into some static classes, some normal classes, some loose functions)

zimablue07:04:14

so right now I'm messing with a git diff and I'd probably throw the functions I've some up with into a couple of static classes if I was in python, split by "upstream" and "downstream" processing

borkdude07:04:48

In clojure you usually use a namespace. why not use one?

zimablue07:04:54

being a clojure noob I don't get the idiomatic equivalent, from the linked stackoverflow it seems that what I'd normally do is funky since it would require creating protocols for no reason, and I need to use like a raw map

Matti Uusitalo07:04:01

No need for extra wrapping, just defn them in the namespace

zimablue07:04:35

because the unit of grouping and formality is lower, each namespace should be in it's own file? I could do that but it's a bit more ceremony and slightly more complication than static classes would be

zimablue07:04:48

not a big deal, sorry I'm new-ish to clojure so overthinking stuff probably

borkdude07:04:00

If you want to subdivide functions within a namespace, some people use conventions like

(defn foo:bar1 [])
(defn foo:bar2 [])

zimablue07:04:07

interesting

zimablue07:04:17

thanks, that's an example of solving the same sort of problem I think

zimablue07:04:21

just rough organization

zimablue07:04:36

I could just split the files, it's not a big deal maybe, just feels like overkill

zimablue07:04:06

ok sounds like my three options: just use ordering/naming conventions, do something clever with maps/macros, just use namespaces

zimablue07:04:16

I'm not missing some perfect abstraction for my use-case hopefully

Alex Miller (Clojure team)14:04:15

The feature in Clojure for grouping and naming functions is namespaces

andy.fingerhut14:04:27

I guess one question to ask about the practice you have developed in Python is: for what reason do you want to collect multiple Python functions in a Python 'static class'? Why did you do that, vs. put those Python functions at the top level in your source file? Clojure functions at the top level in a namespace seem to correspond closely with Python functions defined at the top level, certainly. There isn't a direct analog in Clojure of creating a static class that is there for nothing but containing methods, but it naturally leads to the question of "why bother creating such a class?"

emccue17:04:50

@zimablue one thing that can be useful is to design functions such that they are meant to be used with a namespace alias

emccue17:04:02

so like instead of

emccue17:04:40

(ns your-project.stack)

(defn stack-create []
  '())

(defn stack-pop [stack]
  [(first stack) (rest stack)])

(defn stack-push [stack item]
  (cons item q))

(ns other-ns
  (:require [your-project.stack :refer [stack-create stack-pop stack-push]]))

(let [stack1 (-> (stack-create)
                 (stack-push 1)
                 (stack-push 2))
      [head stack2] (stack-pop stack1)]
  ...)

emccue17:04:37

(ns your-project.stack)

(defn create []
  '())

(defn pop [stack]
  [(first stack) (rest stack)])

(defn push [stack item]
  (cons item q))

(ns other-ns
  (:require [your-project.stack :as stack]))

(let [stack1 (-> (stack/create)
                 (stack/push 1)
                 (stack/push 2))
      [head stack2] (stack/pop stack1)]
  ...)

emccue17:04:52

if you want object-ey things, this is a decent way - a protocol and a defrecord isn't strictly needed unless you want the dispatch bits of it