Fork me on GitHub
#clojure
<
2017-05-02
>
stardiviner02:05:16

How to use use to load libraries at Leiningen REPL startup?

noisesmith02:05:09

most people define an :init-ns in project.clj

noisesmith02:05:23

but if you want to do it by hand, (use 'my.ns)

stardiviner02:05:52

@noisesmith Thanks, good idea. But I wander why I add (use '(incanter core stats datasets charts io pdf)) will failed lein repl timeout?

noisesmith02:05:05

that's not the syntax

noisesmith02:05:35

you could set the timeout - but really why not make a namespace that uses those and switch to it on bootup?

noisesmith02:05:50

and in the long run, it's better not to utilize use

john02:05:15

using use is usurious

stardiviner03:05:26

@noisesmith If that, should I define my.ns in :repl-options or just in top level in profiles.clj?

noisesmith03:05:40

I'd do it in the way shown in lein help sample (checking now...)

noisesmith03:05:12

yeah, put it in :repl-options

cmal03:05:01

Hi, everyone. May I ask a question of how to improve my clojure skills? I've been working on clojure for one year, and I have read the book Clojure programming brave clojure and also have some cljs experiences. I have not working with java before that. I am now feeling comfort of writing clojure code and want to read some source code of clojure, like the source code of clojure language, or the source code of ptaoussanis. I feel those difficult to start. I feel it easy to write a working clojure program, use some libraries written by others, and do the things I want to finish when doing my job, but I feel it difficult to start to write a clojure lib or design a new program. Should I learn java lang /jvm first, should I read the jdk8's core docs, or should I just write more and more applications? Thanks!

stardiviner03:05:42

@noisesmith I checked out lein help sample now, but have not found where is the :init-ns foo.bar's namespace foo.bar is defined? If I want to define namespace foo.bar in Leiningen profiles.clj, where should I define it?

noisesmith03:05:18

you define it in src/foo/bar.clj

stardiviner03:05:24

I mean profiles.clj not project.clj. Does ~/.lein/ can load src/foo.bar.clj ?

noisesmith03:05:38

if you have a dependency that you want to load regardless of project, you should have an artifact for it and put it in your :dependencies in profiles.clj

noisesmith03:05:10

you can run lein install in a project to make it available from other local projects as a dep

noisesmith03:05:27

(or use a proper library and deployment for serious things of course)

stardiviner03:05:56

No, I want to load some dependencies with :use instead of :require at Leiningen REPL startup.

noisesmith03:05:26

to use code it needs to be on the classpath

noisesmith03:05:55

use rather than require is just a question of how you define your namespace (or which function you use)

noisesmith03:05:06

lein is responsible for classpath and startup

stardiviner03:05:50

I see, thanks.

qqq04:05:49

I know that I can't write: (apply of (map f lst)) however, how what is the best way to say "if there some x in lst" such that (f x) is true ?

qqq04:05:02

(some f lst)

stardiviner04:05:33

How to convert (use '(incanter core stats datasets charts io pdf)) into require which load the incanter.charts/histgram into histgram?

qqq04:05:57

(require [incanter.charts :refer [histgram]])

qqq04:05:17

@stardiviner : I've now cleared my debts and you owe @akjetma an answer

stardiviner04:05:42

Oh, sorry for this. @noisesmith I use (require LIBRARY :refer :all)` solved my problem.

stardiviner04:05:27

@qqq I wish to load all functions under incanter.charts/.

noisesmith04:05:12

@stardiviner FYI that's identical to use

noisesmith04:05:39

why wasn't use working?

stardiviner04:05:41

@noisesmith I don't know. That's what I wander. But require solved my problem, I will pass it off now.

jlmr06:05:16

Hi, I’m pretty new to Clojure struggling to understand something. Why do (fn? inc) and (fn? (first '(inc))) return different values? How can I check whether a Symbol in a list refers to a function?

matan06:05:40

jlmr: I think you can use function? to test that

matan06:05:54

it is part of the clojure.test namespace. so you need to require/use/refer it first

matan06:05:27

I am not sure how it defers from fn? so not really helpful on my part I guess

jlmr06:05:34

function? works so that’s great! Now for the understanding part 🙂

noisesmith16:05:55

‘(inc) is not a list with a function, it’s a list with a symbol

noisesmith16:05:40

symbols happen to be callable, but they don’t do what you want (unless what you wanted was the same behavior as keywords (‘a ‘{a 0}) => 0

noisesmith16:05:18

the problem here is that ' is not a list constructor, it’s a way to prevent evaluation

frederic06:05:26

@jlmr inc is a function ; it is found by first finding the var named inc (skipping over the namespace part here), and then dereferencing that var

frederic06:05:38

But (first '(inc)) is 'inc, not inc. It just a symbol, not a function

jlmr06:05:04

@frederic thanks, and I guess you would have to eval a symbol to find the var?

jlmr06:05:14

@rauh (fn? (resolve 'in)) also returns false…

rauh06:05:04

You'd need to deref the var.

jlmr07:05:23

ok that works, I guess I should read some more to understand what’s actually going on

frederic07:05:11

'inc is a symbol. Pretty much a glorified string.

frederic07:05:46

(resolve 'inc) is the var named inc

frederic07:05:17

a var is a reference, a stable identity

frederic07:05:59

(deref (resolve 'inc)) is the current value of the var

frederic07:05:04

and that happens to be a function

frederic07:05:11

so you’d write (fn? (deref (resolve (first '(inc)))))

frederic07:05:31

although this looks like a perfect opportunity for threading macros

frederic07:05:59

(-> '(inc) first resolve deref fn?)

jlmr07:05:44

@frederic thanks for your explanation?

frederic07:05:22

@jlmr You’re welcome 🙂

frederic07:05:32

Oh, one last thing, I’ve not seen deref used very often in the wild

frederic07:05:35

I guess that one reason is that we don’t need/want to do magic with vars very often (that’s the mutable part of the language, so you wouldn’t want it spread throughout your program)

frederic07:05:03

the other reason is that people tend to use the reader macro @ instead.

frederic07:05:26

@whatever is just a shorthand for (deref whatever)

frederic07:05:59

in practice you meet the @ form more often than the deref form

matan07:05:12

@frederic are (deref (resolve 'inc)) and inc not actually the same thing? or just seamlessly interchangeable? I mean in the first form you just instruct the runtime to do what it would otherwise automatically do with the second one.

bronsa09:05:29

matan: there are some subtle differences actually

bronsa09:05:04

(deref (resolve 'inc)) is executed at runtime, everytime and will pick up any changes to inc

bronsa09:05:29

inc is resolved at class init time and will capture the value of inc

matan17:05:12

@U060FKQPN class init time?

bronsa19:05:36

between compile time and runtime... not easy to explain

frederic07:05:50

@matan ‘in the first form you just instruct the runtime to do what it would otherwise automatically do with the second one’ yes, agreed

cmal08:05:54

Hi, how should clojure programmers learn java and jvm? where to start and what are important things? Thanks very much!

qduval09:05:29

Hi, I wonder if someone could help in regards with the usage of defs inside macros. I asked the detailed question on Reddit here: https://www.reddit.com/r/Clojure/comments/68ru92/newby_question_on_the_correct_usage_of_vars_in/

leonoel09:05:49

@qduval it's very uncommon to need to resolve symbols by hand inside a macro what you're trying to achieve is usually written like this :

(defmacro add [a b]
  `(+ ~a ~b))

leonoel09:05:53

but in this case the macro has no benefit

qduval09:05:22

Hi @leonoel, thank you for the answer. I was quite sure it was not usual. But then the macro that you link just inlines the call to the operator +. It does not perform the computation at compile time.

qduval09:05:17

I was looking for a way to still do things at compile time, but somehow split the code a bit, to make it more readable and reusable (by using constants and such).

rauh09:05:46

Best is to declare your constants as (def ^:const YOUR-CONST 138234.234) and then just write normal code. The JVM will optimize the constant expression

qduval09:05:06

In fact, I was looking to mimic some meta-programming constructs I know from my C++ background: constexpr. constexpr add(int a, int b) { return a + b; } In that setting, add can be given any integer or constexpr: constexpr int x = 1; constexpr int y = 2; add(x, y); //would work fine Any chance I might fullfil this need otherwise?

rauh09:05:08

Though the :const declaration is required for this to work.

qduval09:05:48

@rauh so basically, if I just annotate my def, it should be fine inside the macro call? I will try.

rauh09:05:05

IMO, eval in macros(!) is fine. Not so in normal clojure code.

rauh09:05:30

No it won't be done during macro expansion, but the JVM will just inline the constant expression.

qduval09:05:16

Ok, I just tried this and it fails indeed: (def ^:const x 1) (def ^:const y 2) (defmacro add [a b] (+ a b)) (add x y) What you are telling me is that I should be using const instead, like this: (def ^:const x 1) (def ^:const y 2) (defmacro add [a b] (+ a b)) (add x y)

qduval09:05:31

I meant like this (def ^:const x 1) (def ^:const y 2) (def ^:const sum (+ x y))

rauh09:05:35

No macros necessary.

qduval09:05:06

Ok @rauh, this is pretty clear answer, thank you 🙂 I just wonder, will it really happen at compile time (the computation), or at the load of the namespace, or at first call?

rauh10:05:07

Actually, it'll happen at compile time, just checked.

qduval10:05:45

@rauh, how did you manage to do the check? This looks interesting 🙂

rauh10:05:11

(compile 'compile-inspect), then open the class file in IntelliJ

rauh10:05:15

Comes with a decompiler

qduval10:05:40

Ok great! I just tried this too (scoping the defs): https://gist.github.com/deque-blog/9b0ad33323a1eb232cb801359f402cd2 But is it even a good idea to try this?

rauh10:05:41

No, terrible idea.

qduval10:05:08

What would be the best way to try to do these computations at compile time, and still have a limited scope?

rauh10:05:14

Just make it function with let bindings and hope that the JVM inlines+optimizes it 😄

rauh10:05:33

Potentially make use of ztellman's primitive library

rauh10:05:48

But again, eval in a macro isn't all that evil.

qduval10:05:34

Ok, I will do some experiments with both approaches, and have a look at the library you just mentioned. Thank you so much for the great answers, it helps a lot 🙂

dergutemoritz10:05:24

@qduval Note that the eval appraoch doesn't work local scopes either, e.g. (let [x 1 y 2] (add x y)) will produce wrong results because it will look up x and y on the namespace level rather than in the current lexical scope.

qduval10:05:39

I saw that indeed in my previous tries. I think the global scope is the only way. But this is not too bad for me: after all, my need is for declarative information about the program itself that I would like to somehow compile into some values that I can exploit at runtime. Global is okay there.

rauh10:05:27

You can do this and it'll be straight forward java code:

(defn ^long eval-test []
  (let [x 1
        y 2]
    (+ x y)))

rauh10:05:04

I'd bet the JVM will completely inline this result and make it consant:

public static long invokeStatic() {
        long x = 1L;
        long y = 2L;
        return x + y;
    }

dergutemoritz10:05:56

Yeah, best to rely on the Sufficiently Smart Compiler ™️ 🙂

rauh10:05:02

@qduval Also forgot to mention: All the above is compiled with (set! *unchecked-math* :warn-on-boxed)

rauh10:05:23

Also you could just do the entire computation in the macro which will just emit the constant:

(defmacro my-const-expr
  []
  (let [foo 23.2]
    (Math/sqrt foo)))

andershessellund11:05:43

core.match seems like an awesome library but it also seems inactive, with the last release being a two year old alpha release. I wonder why? Is nobody using it? Are there better alternatives? I consider using it for matching messages received on core.async channels.

octahedrion11:05:44

@andershessellund I've used core.match for exactly that - for dispatching events in an Om app

octahedrion11:05:20

it's very flexible for matching, but one can't change the rules at runtime

octahedrion11:05:46

simpler to use a map

andershessellund11:05:58

@octo221 Thanks. I don't think I need to change the rules at runtime. I think I'll just go ahead and try it.

octahedrion11:05:06

or, for async you can use pubsub

alexelcu11:05:17

Hi folks, I’ve enjoyed the Spec-ulation keynote by Rich Hickey (https://www.youtube.com/watch?v=oyLBGkS5ICk) and was wondering, are there any libraries that place the major, backwards incompatible, version in the package, like … myproject.v2.stuff?

john12:05:58

the latest spec does that. it's all in a namespace alpha

john12:05:51

I'm thinking about releasing my new library under a namespace preview, since breaking changes are such a guarantee at this point.

john12:05:55

And then maybe preview future features in the pre namespace

tjtolton12:05:54

woah woah. woah. what is going on with this destructuring syntax? {[w h] :pixi.renderer/size, transparent? :pixi.renderer/transparent? :as options}

tjtolton12:05:23

ohhhhh wait I see now

tjtolton12:05:28

he destructured the first value

tbaldridge13:05:47

@tjtolton yeah destructuring nests but it gets harder to read with more nesting

tjtolton13:05:27

yeah, its pretty clear once you know what you're looking at, though

tbaldridge13:05:45

In most cases I'd say the [w h] should be in another line of the let, but it's pretty simple in this case.

tjtolton13:05:07

I just thought I was looking at some crazy, yet unknown 3 element sequence, forloop destructuring or something

tbaldridge13:05:26

Nesting map destructuring gets really ugly: {{:keys [w h]} :foo/bar {x :z} :baz/qux}

tbaldridge13:05:33

That's almost unreadable ^^

tjtolton13:05:51

eh, yeah its a little wonky I guess, but I think it's actually a pretty visually consistent way of reading the info, once you know what you're looking at.

tjtolton13:05:47

Id definitely throw a destructure like that behind a helper function

tjtolton13:05:05

but, it would be a pretty readable helper function, is all im saying

tbaldridge13:05:07

perhaps, but it adds to visual noise. For example:

(defn my-func [{:keys [a b] :as mp} {{[w h] :qux} :baz}]
    ...)

tbaldridge13:05:19

How many arguments does that take, and what's its structure ^^

tbaldridge13:05:45

That's the problem I have with it a lot of times, I have to sit way to long and figure out what the function expects before I can use it.

tjtolton13:05:45

Yeah, there are probably other ways you could write said helper function that would be more readable. Too much nesting is probably just language abuse.

tjtolton13:05:06

well, that's kind of an axiom of any language

potetm14:05:27

Hmmm, interesting. I don't often part with @tbaldridge, but I honestly prefer that you tell me what crazy you expect rather than having to piece it together in my head throughout the body of the function.

potetm14:05:17

Best is probably to not do crazy. But if you're gonna do it, make it 1) as localized as possible and 2) look crazy.

potetm14:05:14

I guess, having said that, to your point, destructuring is great at both of those things!

rauh14:05:00

A little "trick" I find helpful: If the destructing map key is a keyword, you continue reading left-to-right. If it's anything else, you read from right-to-left (So first read the value, then the key). That being said, I never nest destructing, I'd rather use a let.

zane14:05:55

I'm pretty partial to core.match for pulling values out of nested maps.

Alex Miller (Clojure team)15:05:34

@rauh the idea is that the local you're binding is always on the left

alex.ter.weele17:05:27

I’ve extended my protocol to SuperClass and provided it an implementation of my-proto-fn, but when I call that on a member of SubClass, no implementation is found

hiredman17:05:32

how do you know SubClass is-a SuperClass?

hiredman17:05:02

how do you know SuperClass is SuperClass? (classes with the same name loaded by difference classloaders are not the same class)

alex.ter.weele17:05:27

All I know is that SubClass extends SuperClass (Java classes). Don’t know about the classloader. I’m just working in the REPL right now, so I assume I’m only dealing with one?

hiredman17:05:02

did you load the code that extends your protocol to the class?

alex.ter.weele17:05:03

(isa? Inet4Address InetAddress) is true, so I’m pretty sure I loaded it (`Inet4Address` and InetAdress are sub and super, respectively)

hiredman17:05:39

the clojure code where you extend the protocol to the class

hiredman17:05:03

have you pasted that in your repl, or required it, or some other means of loading it

alex.ter.weele17:05:09

yeah, trying to get that to work in isa? now and it does not seem to be working

hiredman17:05:19

isa? doesn't do that

hiredman17:05:37

isa? is the java class hierarchy, not protocols

hiredman17:05:51

satisfies? is what you want

alex.ter.weele17:05:16

Inet4Addresses satisfy the protocol: (satisfies? IPAddress (InetAddress/getByName "0.0.0.0")). I can’t seem to create an object that is just an InetAddress though

hiredman17:05:04

InetAddress is an interface (or an abstract class, I forget which), which by definition you cannot make an instance of, you can only make instances of something that implements the interface (for an interface) or extends the class (for an abstract class)

alex.ter.weele17:05:55

the javadoc (https://docs.oracle.com/javase/7/docs/api/java/net/InetAddress.html) says

public class InetAddress
extends Object
implements Serializable
. I think it’s non-abstract

hiredman17:05:57

huh, or I guess they just made the constructor private

hiredman17:05:20

so why are you trying to get an instance of InetAddress?

alex.ter.weele17:05:52

Yeah, it’s weird. It functions much like an abstract class though: getByName returns either an Inet4Address or an Inet6Address. I was trying to make an InetAddress instance to see if it satisfied IPAddress, which is my protocol

alex.ter.weele18:05:05

so I’ve got this:

(defprotocol IPAddress
  (version [this])
  (bytes [this]))

(extend-protocol IPAddress
  InetAddress
  (bytes [this] (.getAddress this))
  Inet4Address
  (version [_] 4)
  Inet6Address
  (version [_] 6))
and bytes is the protocol function that’s not finding an implementation. I could paste the same code under 4 and 6 and get the functionality that way, but I would like to find why this doesn’t work as I expected

hiredman18:05:31

at the repl, if you invoke the protocol fn on an inet4address, what happens?

hiredman18:05:54

yeah, that is not going to work

hiredman18:05:19

you cannot implement a protocol piecemeal for a class and a super class

hiredman18:05:46

so all three of those classes have an incomplete implementation

alex.ter.weele18:05:29

ok. Is this documented? I googled before I asked but couldn’t find anything…

hiredman18:05:41

depends what you mean, I don't know of something that says "this exact thing won't work" but there are no examples that show anything like it as working

alex.ter.weele18:05:54

Thanks for the help!

bsima19:05:38

does anyone know if there is something like Ruby's "pry" tool for Clojure?

bsima19:05:54

i'd like to set a breakpoint inside of a let binding...

taylor19:05:04

speaking of protocols and extending them, is there some “best practice” for where to define protocol extensions in a project? e.g. so they’re only defined in one place but get loaded reliably whether you’re doing REPL or running a JAR?

bsima20:05:18

taylor: a lot of people use a protocols.clj file i've seen

bsima20:05:58

I think this is what I was looking for, in case anyone else finds it useful https://github.com/clojure-emacs/cider/blob/master/doc/debugging.md

matan20:05:01

stopped for a moment to look at project complexity:

matan20:05:29

anything easy and simple you'd recommend beyond line counts? any common tool? 🙂

matan20:05:13

pesterhazy: gut feeling: sort of alright 🙂

tbaldridge20:05:49

complexity is less about line counts and more about structure and design

bsima20:05:52

i second what tbaldridge said

bsima20:05:39

I find the "single responsibility principle" the best design principle to follow when determining complexity

matan20:05:05

@bsima in that regard, I'm 98% clean

bostonaholic20:05:29

here’s a great talk from Sandi Metz talking about code complexity. It mirrors what Tim said. https://www.youtube.com/watch?v=8bZh5LMaSmE

mobileink20:05:39

what's a good metric for measuring code complexity in Clojure? LOC is obviously the minimum but not very helpful.

mobileink21:05:39

oops, just saw @matan 's q. must be a tool out there. but even if not: what properties should be measured?

mobileink21:05:50

e.g. number of dashes in names, number of nested let clauses in fns.

tbaldridge21:05:32

That's the problem, none of that matters. It's mental complexity that matters. Simplicity of design in the face of requirements.

tbaldridge21:05:07

Is a PersistentHashMap more lines of code than a mutable hash map? Yes, does that mean it's more complex? Perhaps for the maintainers, not for the users.

tbaldridge21:05:39

So in my code reviews I value: Readability, which is subjective. Ease of extensibility, also subjective. And Leverage.

tbaldridge21:05:54

Readability - If I know nothing about the structure of your project, can I jump into it and understand what the code is doing? Do you use a lot of macros and clever tricks that are non-standard? Ease of extensibility - You may have three modules, how hard is it to add a fourth. If you currently accept data from two sources how hard is it to add a new source? Leverage - If I do write a new data source, can I leverage existing code, or is everything so tied to a single implementation that I have to rewrite it? Are your business rules spread out in many files, or are the general enough that I can use one set of functions to validate all data.

hagmonk21:05:39

@mobileink see also https://codescene.io which tries (and does a very interesting job, I think) to measure some of the other dimensions in a project that might be considered measures of complexity

hagmonk21:05:45

(it's written in clojure!)

mobileink21:05:56

@tbaldridge: agree. just thinking there oughta be a way to at least approximately measure. for example "mental complexity" is too vague. there are at least 2 kinds of complexity, conceptual and formal (structural?). since names and concepts are closely related name analysis would be a start. fns with names like "glop-x-then-frake-the-whosit-until-done" could be flagged as conceptually complex for two reasons: invented terms and too many dashes.

mobileink21:05:19

@hagmonk looks very interesting, thanks. fwiw i think this issue is also closely related to the whole Literate Programming thing. Full disclosure: imo LP is completely wrong-headed, and lack of measurement is just one reason. What is code anyway, really? https://github.com/mobileink/codegenres/wiki

hagmonk21:05:44

To be literal about it, code is a set of commands written by a person. As such it's not entirely dissimilar to any other thing a human writes down and expects other humans to read. How easy it is to understand is going to be highly variable depending on who is writing and who is reading.

mobileink21:05:14

code is a literary genre. as such, it can be investigated (and maybe measured) in the same way that that literature is studied quantitatively. http://digitalhumanities.org/companion/view?docId=blackwell/9781405148641/9781405148641.xml&amp;chunk.id=ss1-6-9&amp;toc.id=0&amp;brand=9781405148641_brand

hagmonk21:05:55

although exercises like the one you linked are very interesting, I don't see us computing the complexity of shakespeare in any globally useful way

hagmonk21:05:34

there is no "inherent complexity truth" that can be extracted and measured

hagmonk21:05:05

(that is my philosophical position, anyway 🙂 )

mobileink21:05:41

i would not bet on that. it's pretty common these days to measure the complexity of speech - this politician speaks at a 6th-grade level, that at a 12th grade level (guess who wins). i don't see why such techniques could not be adapted to code in order to measure some kind of "complexity".

taylor21:05:38

those are measuring things like vocabulary and sentence structure

hagmonk21:05:40

grade level is a proxy for how many symbols a reader would recognize, it really says nothing at all about the kind of complexity that bedevils software.

taylor21:05:50

code is entirely different symbolically and structurally

mobileink21:05:40

code is not vocab and syntax?

mobileink21:05:08

maybe we should move to #off-topic ? ;)

hagmonk21:05:31

I think we'll have an answer to your original question in about 20-30 years 😄

mobileink21:05:13

there's a business opportunity there for some clojurist. simple_smile

tbaldridge21:05:33

But questions of code complexity are often linked to other factors, like business logic complexity. For example, all tax software is going to be horrifically complex, although it may not be the fault of the software design. I guess I'm talking about incidental complexity there.

hagmonk21:05:43

@tbaldridge check out that http://codescene.io project, it's super interesting to see some of the approaches they're taking. They have showcases of projects they've analyzed: https://codescene.io/projects/167/jobs/736/results

hagmonk21:05:22

they are all proxies or "warning indicators" I would say, rather than strict measures of complexity, but some very interesting ones nonetheless

qqq21:05:30

I wonder if trying to minimize taxes in the US is NP-complete.

noisesmith22:05:49

in systems there’s a concept of requisite variety here - you need at least N moving parts to model a system with N moving parts you care about, might be related

hagmonk22:05:42

I feel like anything with a highly dependent set of variables where you want to discover the global minimum ends up being NP-hard

hagmonk22:05:27

I'm not a mathematician but I'm always surprised how often it comes up

mobileink22:05:28

think bigger. somewhere an English prof, a linguist, an accountant and an AI expert are making a system that understands all the vocabs involved and will be able to score your code for complexity as you write it. or maybe it will just write the code, heh, ouch.

jsa-aerial00:05:21

mobileink: On that last note - there is quite a bit of work being done on this. Some of it more than just interesting. Here is a link giving a simple overview (but it is reasonably accurate): http://highscalability.com/blog/2016/7/6/machine-learning-driven-programming-a-new-programming-for-a.html

mobileink00:05:32

thanks for that link. i'm kinda glad i'm oldish. i think programmers's are ripe for replacement by AI. Let's talk again in 5 years. :)

john22:05:46

It comes down to branches, right? And there are explicit branches and implicit branches. As long as problems in implicit branches don't creep back into your explicit model, they don't count against your design's complexity. But if your explicit design has unnecessary branches, that's overly complex.

mobileink22:05:38

what's an implicit branch?

john22:05:00

But you could be sitting on a mountain of complexity and as long as the formalism being presented from below is consistent / doesn't break.

john22:05:09

any branch you don't have to think about

mobileink22:05:16

i mean formally. how can an analyzer pgm distinguish explict and implicit branches?

john22:05:19

well, I mean, we've got branches down in the machine code that we don't care about. And the analyzer isn't going to be judging that complexity. Then you have libraries with branches we don't care about. But if we bring in a bad library that fails to hide its branch mechanics from downstream users, then those downstream users' code must become more complex, to accommodate the leaky model below.

john22:05:54

I'm not sure if I have a good definition that would allow one to just write a complexity analyzer right quick

john22:05:07

But complexity should not be conflated with chaos and vice versa

mobileink22:05:39

ok. but assume we have a whiz-bang complexity analyzer. it understands the language of your text, so it analyzes that. the fact that your text compiles down to machine microcode is out of scope. ditto for any lib calls you make, e.g. to java code.

mobileink23:05:30

a complexity analyzer can only work on source text.

john23:05:45

I think what you want to get at is the organizational complexity rather than the informational complexity. Ordered complexity vs. disordered complexity. One is purposeful, the other is incidental.

mobileink23:05:44

huh? what does complexity have to do with purpose?

john23:05:07

Hard to explain... let me use cellular automata as an example. Wolfram classifies 4 types of CA. Class 1 pertains to highly ordered CAs. 2 to semi ordered. 3 to highly randomized. 4 to complexly ordered. 4 is more like 2, as it falls between 1 and 3, between order and chaos. Class 4 though has the necessary primitives to create unboundedly complex states of affairs. So does 3, probably, but it's too disordered to control. Basically an RNG.

john23:05:19

what code isn't about purpose? 😉

mobileink23:05:31

i hope we're not talking about Intelligent Design. the amount of complexity associated with something is independent of intention

john23:05:55

So, looking at code like a CA, there are certain code paths that will produce your desired behavior. Most of them will also, necessarily, produce some incidental complexity. The "bad complexity" is that kind. The "good complexity" is the kind that directly solves your problem.

john23:05:05

"the amount of complexity associated with something is independent of intention" I fundamentally disagree

mobileink23:05:15

ok we're talking about different things. the fact that your code runs O(n) has absolutely nothing to do with intention or purpose. it's just a fact.

mobileink23:05:47

whether your code is hard to understand is totally orthogonal to that.

john23:05:03

outside of a subjective interpretation of some logic, all branches are just branches

mobileink23:05:40

in cs compplexity is well studied. pretty sure it has about as much to do with intention as nuclear physics does.

mobileink23:05:18

conceptual complexity is of course a whole 'nother thing.

john23:05:03

In one place, a shift might be an addition, in another it might be a subtraction. In yet another, it might just be a shift. What it happens to be in a specific context depends on the purpose / intention related to that context.

mobileink23:05:11

fwiw i don't understand what "directly solves your problem" means. to me that means "abracadabra" and your problem is nagicalky solved. in reality nothing is ever "directly" solved, afaik.

mobileink23:05:00

oh goodness. no no no. it is what it is. if it really did involve intention, i could write "2+2" intending 5.

john23:05:21

you could! 😉

john23:05:50

Suppose you have to clone an object every time you pass it, due to the mutability of the system. That creates incidental complexity, unrelated to your problem.

mobileink23:05:56

full disclojure: i'm a bit of a filosofy geek.

john23:05:36

So am I and I'm thinking about naming my library I'm working on "filo" 🙂

john23:05:50

means thread in latin, apparently

mobileink23:05:46

sure. using lambda creates "incidental" complexity, since combinatory logic is more fundamental (no vars/substitution). i guess i do not see the usefulness of a distinction between incidental and whatever kind of complexity.

mobileink23:05:41

ps. "filium" sounds more impressive - more latinate, and more syllables!

john23:05:16

filiums pretty cool too

john23:05:56

relative to certain problems (purposes ;)) lambdas will create incidental complexity. Relative to some other problems, they will be the perfect fit.

mobileink23:05:55

fwiw i think "normal form" make a lot more sense than whatever it is clojurists want to call the opposite of "incidental complexity". it's very well understood and it means exactly the it cannot be further simplified, i.e. all "incidental" cruft has been removed.

john23:05:30

intentional complexity

john23:05:39

or necessary complexity

mobileink23:05:08

we have purposes. algorithms do not, therefore their complexity cannot involve purpose.

john23:05:54

There's no such thing as an algorithm independent of some purpose.

mobileink23:05:56

let's move to #off-topic before we drive everyone mad.