Skip to content

Instantly share code, notes, and snippets.

@levand
levand / cider-opinions.md
Last active November 20, 2023 07:50
Why I don't use cider

Why I don't use cider.

This is all personal opinion and a matter of taste. I'm putting it here because people have asked - I'm glad Cider exists and that a lot of people are obviously using it to great effect. This is not an attack on Cider or a an attempt to negate the experience of those who like it, just my own experience.

Also some of the critiques are more properly aimed at nRepl than Cider - I don't use nRepl either, in Emacs. For some reason I have fewer issues with it in Cursive (though I still do have some).

  1. With Cider, there's too much "going on" between Emacs and Clojure. When something glitches, hangs, doesn't return a value, throws an excption, etc (as it does, multiple times a day), I don't know whether the problem is in Emacs, in the Cider client, the nRepl server, one of any of the default middlewares or in my actual program. I run Emacs in inferior lisp using lein trampoline -m clojure.main - if something goes wrong, it's either in Emacs (which is usually obvious) or my program. Mi
@levand
levand / data-modeling.md
Last active May 19, 2023 16:38
Advice about data modeling in Clojure

Since it has come up a few times, I thought I’d write up some of the basic ideas around domain modeling in Clojure, and how they relate to keyword names and Specs. Firmly grasping these concepts will help us all write code that is simpler, cleaner, and easier to understand.

Clojure is a data-oriented language: we’re all familiar with maps, vectors, sets, keywords, etc. However, while data is good, not all data is equally good. It’s still possible to write “bad” data in Clojure.

“Good” data is well defined and easy to read; there is never any ambiguity about what a given data structure represents. Messy data has inconsistent structure, and overloaded keys that can mean different things in different contexts. Good data represents domain entities and a logical model; bad data represents whatever was convenient for the programmer at a given moment. Good data stands on its own, and can be reasoned about without any other knowledge of the codebase; bad data is deeply and tightly coupled to specific generating and

@levand
levand / keywords.csv
Last active April 4, 2022 05:18
List of software programs used by a particular company
We can make this file beautiful and searchable if this error is corrected: No commas found in this CSV file in line 0.
Windows
Linux
iOS
Jira
Excel
WordPress
@levand
levand / util.js
Created January 25, 2019 19:51
PulumiContext utility
const pulumi = require("@pulumi/pulumi");
const deepmerge = require('deepmerge');
const isPlainObject = require('is-plain-object');
const merge = function(x, y) {
return deepmerge(x || {} ,y || {}, { isMergeableObject: isPlainObject });
};
class PulumiContext {
("[ -> tableAll() ]"
"[ -> (rdf:type rdfs:range rdfs:Class) ]"
"[ -> (rdfs:Resource rdf:type rdfs:Class) ]"
"[ -> (rdfs:Literal rdf:type rdfs:Class) ]"
"[ -> (rdf:Statement rdf:type rdfs:Class) ]"
"[ -> (rdf:nil rdf:type rdf:List) ]"
"[ -> (rdf:subject rdf:type rdf:Property) ]"
"[ -> (rdf:object rdf:type rdf:Property) ]"
"[ -> (rdf:predicate rdf:type rdf:Property) ]"
"[ -> (rdf:first rdf:type rdf:Property) ]"
;; Say we are writing a model of a zoo, and most of our code depends on
;; values like this:
(s/def :zoo/animal (s/keys :req [:zoo.animal/name
:zoo.animal/num-legs]))
(s/def :zoo.animal/name string?)
(s/def :zoo.animal/num-legs (s/and integer? (complement neg?)))
;; In some of our code, we know we're dealing with a more specific type of
;; Sample of what the new DSL could look like
(config
(:require
[arachne.core.dsl :as a]
[arachne.http.dsl :as http]
[arachne.pedestal.dsl :as pedestal]
[arachne.assets.dsl :as asset]
[arachne.pedestal-assets.dsl :as pedestal-asset]
[arachne.cljs.dsl :as cljs]
[arachne.figwheel.dsl :as fig]))
;; Currently, Arachne follows a particular idiom for creating named entities:
;; Every DSL form that creates an entity takes an optional first argument, which is its Arachne ID,
;; and also returns an entity ID
;; This permits two forms of defining and using components
;; Method A
(a/component :my.app/a 'whatever)
(a/component :my.app/b 'whatever {:a :my.app/a})
@levand
levand / explicit-flow-dsl.clj
Last active January 10, 2017 19:36
Arachne asset DSL with the flow wired up as a separate form
(def opts {:output-to "main.js"
:asset-path "js"
:output-dir "js"
:optimizations :none
:main 'arachne.cljs.example})
(a/input-dir :test/input {:dir "src/cljs" :watch? false})
(cljs/build :test/build {:compiler-options opts})
(a/output-dir :test/output {:dir "out"})
@levand
levand / asset-dsl.clj
Last active January 10, 2017 15:48
What style of asset/cljs DSL do you find more natural?
;; Both of these code samples do exactly the same thing: define an asset pipeline
;; with a ClojureScript build that reads from "src/cljs/*" and compiles to "out/*".
;;The question is, which style of DSL is more readable/natural?
(require '[arachne.assets.dsl :as a])
(require '[arachne.cljs.dsl :as cljs])
(def opts {:output-to "js/main.js"
:output-dir "js"
:asset-path "js"