Fork me on GitHub
#clojure
<
2021-04-30
>
Jim Newton08:04:03

Does anyone recall if there’s been a discussion of added a goto primitive to Clojure? Apparently there is such an instruction in the JVM. Obviously you don’t need goto for high level user code. But sometimes it is good to have in macro expansions, if you want the macro to create extremely efficient code. Also when transcribing Knuth algorithms verbatim.

Jim Newton08:04:30

One example is when serializing a finite state machine into clojure code, it is extremely efficient to translate it into labels and goto, especially in light of the fact that tail call optimization is not an option.

Jim Newton08:04:34

Another example is discrimination nets where the code represents a binary tree of if/then/else nodes. it might be the case that you want some of the nodes to be identical, copying the code causes an exponential explosion of code size, a goto would divide the code size by 2 every time it is used.

Jim Newton08:04:16

again, that would be for machine (macro) generated code.

delaguardo08:04:33

with jvm clojure you always have an option to write low-level java code (with GOTO instructions if you like) and use it in clojure code.

✔️ 4
Jim Newton08:04:06

can I have a clojure macro expand to low level java code? or better, expand to JVM instructions?

delaguardo08:04:36

you can (to some degree) use https://clojure.github.io/tools.emitter.jvm/ but I don’t think it will have any significant improvements forget that, it is for introspection, not for comsuming

✔️ 4
Jim Newton08:04:54

Anyway, having some primitive operations directory in clojure would be useful. Humans aren’t the only ones who write code.

Jim Newton08:04:37

I’ll create a thread in clojureverse.

delaguardo08:04:46

right, not only, but I don’t think clojure team prioritize towards machines instead of humans.

borkdude08:04:29

@jimka.issy One relevant issue is some work done around recur-to which is a mechanism in loop which allows different recur targets

borkdude09:04:00

loop translates into fairly low level bytecode which could fulfil your needs

Jim Newton09:04:07

very interesting. Thanks for the link. Would you mind also commenting on the askclojure thread?

Jim Newton09:04:28

I’ll take a look at the presentation, but I can’t imagine how a DFA could be implemented with concentric loops. I’ll keep an open mind when I watch the video.

borkdude09:04:42

I don't know if you can, I don't know what a DFA is. Just for what it's worth.

4
Elliot Stern19:04:23

Deterministic Finite Automata, usually

Elliot Stern19:04:00

As opposed to nondeterministic ones, or NFA

Jim Newton09:04:20

Can someone help me with human-speak terminology. I want to describe to an audience who is not clojure-savvy what kind of call-site argument lists are compatible with a function such as: (fn [a [b c] d e) ...) . How should I describe what type the 2nd argument is expected to be. Should I say tuple ?

delaguardo09:04:42

tuple is not the best way to describe because you can pass any sequential object longer (or even shorter) than destructuring form

borkdude09:04:47

yes, tuple is common in Clojure

borkdude09:04:10

although technically you can pass any vector in there

p-himik09:04:30

Anything that supports nth.

Jim Newton09:04:42

it can take a list, or cons, or vector, or lazy sequence, or or or or

borkdude09:04:50

a tuple is constrained on size, while destructuring just accepts anything really, what p-himik says

Jim Newton09:04:19

so is there a word which describes all objects supported by nth ?

Jim Newton09:04:54

perhaps sequentials ?

borkdude09:04:55

Returns the value at the index. get returns nil if index out of
  bounds, nth throws an exception unless not-found is supplied.  nth
  also works for strings, Java arrays, regex Matchers and Lists, and,
  in O(n) time, for sequences.

borkdude09:04:36

perhaps seqable is better here since sequential? doesn't return true for strings

borkdude09:04:06

but that also doesn't quite cover it since sets are seqable but not compatible with nth

borkdude09:04:18

so yes, informally, sequential things

p-himik09:04:22

Any ordered collection, I would say.

Jim Newton09:04:31

(defn seqable?
  "Return true if the seq function is supported for x"
  {:added "1.9"}
  [x] (clojure.lang.RT/canSeq x))

borkdude09:04:03

I think what p-himik says is best: ordered things, like sequential collections, strings and arrays

borkdude09:04:17

In Clojure it is most common to (sequentially) destructure on a vector or seq

borkdude09:04:57

In wide-audience-speak you could even say "array-like things" or "list-like things"

4
Jim Newton09:04:42

yes everyone will vaguely understand sequence-like or array-like

Jim Newton09:04:10

Is that a typo in the docstring of nth ? or is that really intended “get returns nil if index out of bounds” ?

(defn nth
  "Returns the value at the index. get returns nil if index out of
  bounds, nth throws an exception unless not-found is supplied.  nth
  also works for strings, Java arrays, regex Matchers and Lists, and,
  in O(n) time, for sequences."
  {:inline (fn  [c i & nf] `(. clojure.lang.RT (nth ~c ~i ~@nf)))
   :inline-arities #{2 3}
   :added "1.0"}
  ([coll index] (. clojure.lang.RT (nth coll index)))
  ([coll index not-found] (. clojure.lang.RT (nth coll index not-found))))

borkdude09:04:41

The function get returns nil, as opposed to nth

Jim Newton09:04:29

ahh, the meaning is *Whereas get returns nil …, nth throws an exception.” is that the meaning?

delaguardo09:04:51

the only thing you can say for sure about that form (fn [a [b c] d e] ...) that this is a function of 4 arguments.

borkdude09:04:15

and that it will crash on an argument which does not work with nth in the second position

Jim Newton09:04:22

@delaguardo, exactly the kind of subtleties in trying to describe what is happening. especially to a non-clojure-savvy programmer

delaguardo09:04:22

other constrains probably should sit on top of the function via spec for instance

Jim Newton09:04:46

in my opinion, since there are soooooo many useful type-like predicates in clojure core, int? number? sequential?, and since destructuring is so fundamental to how clojure works, there should be a predicate destructurable? which captures this nth-compatibility question.

delaguardo09:04:30

you could sketch out it’s interface and propose in http://ask.clojure.org

delaguardo09:04:06

“destructuring” is a process of extracting and binding information from structured data described by entity called desctructuring form which should follow some rules described in https://clojure.org/guides/destructuring

4
delaguardo09:04:27

that’s my attempt to describe what is going on 🙂

ivana09:04:39

Hello! I created some lib for using on developing my work projects, but I don't want to add it as a dependency in project.clj or deps.edn. Althow I want to be it allowed at every namespace in repl. I found a way:

lein repl
  (load-file "my_lib.clj")
once on repl start and then in any repl ns eval
(do
    (use '[my-lib :as ml])
    (ml/my-fn ....))
Is there any other convinient way of doing it? Or just altering standart classpaths? Maybe starting lein repl with some classpath parameters?

emilaasa10:04:49

You could create a user.clj

ivana10:04:23

Thanks, good way. But it's already created and added to git, and I dont want to alter it - if I'l require my lib there, then I'l have to send my lib to all my colegues, but they dont need it

emilaasa10:04:27

Maybe add in a developer source path in the project configthat's gitignored?

emilaasa10:04:46

(defproject hello "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url ""
  :license {:name "Eclipse Public License"
            :url ""}
  :dependencies [[org.clojure/clojure "1.5.1"]]
  :source-paths ["dev"])

ivana10:04:07

We have common project.clj and it's not git ignored. Can I create another one? I'm not sure what do you suggest, sorry

emilaasa10:04:32

I mean you could git ignore the folder, call it local-dev or something

emilaasa10:04:00

But an even easier way is to just add it in your lein config probably, jsut as

emilaasa10:04:03

just a sec..

ivana10:04:09

yep, and all my local lib lives here.

emilaasa10:04:45

Does it work to put it in your ~/.lein/profiles.clj ?

ivana10:04:59

Hm, didn't try it, thanks. Maybe it will work, I'l try in a time.

emilaasa10:04:08

"If you want to access dependencies or plugins during development time for any project place them in your :user profile. Your ~/.lein/profiles.clj file could look something like this:"

emilaasa10:04:24

I think that's what you want if you don't need to share this between devs.

ivana10:04:11

Seems like that, yep. Thanks alot! Will try this way after work.

borkdude09:04:06

@jimka.issy There is also a destructure function which is used when destructuring, maybe helpful in some way

borkdude09:04:25

But since you are speaking to a wide audience, maybe it's better to not get into too much detail

✔️ 4
Jim Newton09:04:36

@borkdude, I took a look at the code for destructure … it is shocking

delaguardo09:04:09

a bit aggressive ) maybe worth to add more details?

delaguardo09:04:28

what particular you found shocking?

Jim Newton09:04:58

sorry, don’t mean to be agressive. just when I look at the function, it appears to be an internal function having no docstring or comment explaining what it does. it’s not easy to understand what the function does.

Jim Newton09:04:20

I suppose the function is not really intended for public consumption.

Jim Newton09:04:04

nothing essentially wrong with hard to understand code, especially when not intended for general consumption.

Jim Newton09:04:04

Sorry if my words come across like I’m an ass. I’m really a sweat guy. just sometimes not skilled in serializing my thoughts.

delaguardo09:04:18

no hard feelings ) and yes, destructure function is for advanced usage which usually assume you are writing a complex macro

borkdude09:04:27

destructure is used by clojure itself primarily

Alex Miller (Clojure team)13:04:46

it's public in case other implementors need to leverage it, but not generally intended for public use

Alex Miller (Clojure team)13:04:18

the absence of docstring is to prevent it from showing up in the api docs

borkdude13:04:28

It's pretty useful to have this, so thanks for including it anyway

2
Alex Miller (Clojure team)13:04:10

having spent many hours in that function, I agree that it is far more painful to read/understand that it should be

Alex Miller (Clojure team)13:04:18

and I apologize for the additional trauma I have inflicted upon the code and future readers :)

😉 2
💥 2
borkdude13:04:45

I have ripped off this function in sci, and merged it with the CLJS version to make it a .cljc version

zackteo15:04:38

just for mild curiosity's sake, when might one want to use destructure :thinking_face:

borkdude15:04:29

Usually you don't need it, but it can be handy for debugging as well, to see how clojure destructures things

zackteo15:04:14

I see I see!

Alex Miller (Clojure team)15:04:08

potentially if you were writing a macro or something you could explicitly call it, but really most macros just expand to a let or something else that will call it for you, so it is pretty rare to need to call it directly

bherrmann16:05:16

You (concerned developer with commit rights) might want to add a comment to the destructure source to mention "destructure() is public in case other implementors need to leverage it, but not generally intended for public use. The the absence of docstring is to prevent it from showing up in the api docs" .... at or near https://github.com/clojure/clojure/blob/clojure-1.10.1/src/clj/clojure/core.clj#L4389

zackteo15:04:24

Hi Everyone :) I am trying to see how feasible it is to try creating a thin wrapper around optaplanner https://quarkus.io/version/1.7/guides/optaplanner . However, based on the example it seems like the set up for it can be very heavy on class creation - some of which have several annotations. Is there any similar project that I can take reference from? / Any advice for such interop? I understand that I might need gen-class and I do understand that so far, this undertaking seem a bit out of reach at my current proficiency levels ><

emccue04:05:06

Can you document all the pain points you have working with this library?

emccue04:05:09

this seems like a pretty good example of the kind of lib clojure tends to have trouble with

emccue04:05:34

and I am personally interested in what libraries can be written to ease some pains

zackteo04:05:40

Alright! Hope I can get a minimal example working ... ><

zackteo04:05:43

Any suggestions on how I should document it though? @U3JH98J4R

zackteo04:05:59

As of now I've been trying to do a one to one translation of the code from java to clojure

emccue19:05:30

None - also sorry for the late reply

emccue19:05:41

just whatever doodles you feel are appropriate

zackteo16:04:08

Right! Let me look into that first then :)

vncz16:04:05

I like this rule a lot https://guide.clojure.style/#function-length even though I admit I sometimes fail to follow it

Jim Newton16:04:19

Here is a link to the draft of a https://drive.google.com/file/d/1jcBy0Hu59wDVWHIyvl6g4CWPR-9GMbbc/view?usp=sharing which will accompany my upcoming ELS (european lisp symposium) talk. If anyone sees anything horribly wrong, there’s still time for me to fix it.

borkdude17:04:48

First feedback: you call multi-arity functions "variable arity". I think this is confusing since we call (fn [& xs]) a varargs function and "variable arity" might be confused with that. Instead, I would use "single arity" and "multiple arity" or "multi-arity"

borkdude17:04:43

What is the trick you are using to go to the next page? Just layout the code so it works when you navigate page down, or is this an elisp package?

borkdude17:04:15

The rest was pretty clear to me, kudos

Ed19:04:58

@borkdude not sure what he's using to navigate pages, but Emacs does understand the form feed character ... So maybe that? http://ergoemacs.org/emacs/modernization_formfeed.html

raspasov21:04:05

@jimka.issy pretty clear; One note: you have something called (satisfies …) . For a moment I got confused that this is (clojure.core/satisfies? …) https://clojuredocs.org/clojure.core/satisfies_q