clojure

New to Clojure? Try the #beginners channel. Official docs: https://clojure.org/ Searchable message archives: https://clojurians-log.clojureverse.org/
2020-10-28T00:22:05.330500Z

I see similar evidence of structural sharing when I switch it to vector

(ins)user=> (def big-load (into [] (range 1000)))
#'user/big-load
(cmd)user=> (count (to-bytes big-load))
14934
(ins)user=> (count (to-bytes (into [] (repeat 100 big-load))))
15555

jmckitrick 2020-10-28T00:24:06.330700Z

@seancorfield Neat! I’ll have to check out β€˜Reveal’ since I’m back on the Clojure scene.

jmckitrick 2020-10-28T00:24:49.331Z

@noisesmith thanks for that breakdown

alexmiller 2020-10-28T00:27:41.331200Z

from glancing at the code, that is what I'd expect - it's just relying on normal Java serialization of object graphs, without any specialized read/write mods

emccue 2020-10-28T01:28:05.331400Z

I have this macro

emccue 2020-10-28T01:28:22.331600Z

(let [x 1 y 3]
  (m x y))

emccue 2020-10-28T01:28:32.331800Z

that will evaluate to {:x 1 :y 3}

emccue 2020-10-28T01:28:39.332Z

and also this one

emccue 2020-10-28T01:28:57.332200Z

(let [x 1 y 2]
  (m+ x y | :z (+ x y)))

emccue 2020-10-28T01:29:07.332400Z

that will evaluate to {:x 1 :y 2 :z 3}

wilkerlucio 2020-10-28T03:07:02.332900Z

that's pretty cool πŸ™‚

vlaaad 2020-10-28T06:29:39.333500Z

@jmckitrick https://vlaaad.github.io/reveal/

Matias Francisco Hernandez Arellano 2020-10-28T14:51:14.339500Z

Hey Folks.. I have a talk about Clojure 101 for Javascript devs.. I have some sintax comparison code samples and now i'm struggling to come out with some good idea to show some code .. real thing. I'm thinking in some httpserver with http-kit vs expressJS... sounds like a good example for clojure begginers?

samoleary 2020-10-28T15:02:49.339600Z

Not a direct answer to your question about comparing code samples but I guess it's syntax related at least! Building up to a lisp-y syntax from a Javascript perspective, there's a clojure snippet at the end https://clojurians.slack.com/archives/C8NUSGWG6/p1603700061197400

πŸ’ͺ 1
euccastro 2020-10-28T16:25:39.341400Z

the only way to extend a java interface in clojure is through gen-interface, right? in particular, definterface doesn't seem to allow that

dpsutton 2020-10-28T16:27:47.341700Z

what do you mean by extend?

euccastro 2020-10-28T16:29:51.342200Z

declare a new interface that extends an existing one

euccastro 2020-10-28T16:31:09.343400Z

for background, I'm trying to create a custom redis command spec using a java library, as explained here: https://lettuce.io/core/release/reference/index.html#redis-command-interfaces

euccastro 2020-10-28T16:46:14.343900Z

related question: how would I declare a varargs method in gen-interface?

uosl 2020-10-28T16:49:24.344Z

When I once did a similar talk, I showed how Clojure's core library gave much more succinct and readable code than JS. Would that be of interest?

robertfw 2020-10-28T17:13:42.346Z

Hi all - I recently came across a Clojure library for representing regexes as data structures, and now I can't remember what it was called nor have had any luck finding it using google. Any ideas what it might have been?

Jakub HolΓ½ 2020-10-29T08:07:25.362100Z

FYI #find-my-lib

alexmiller 2020-10-28T17:14:11.346100Z

I think that's correct

1
dpsutton 2020-10-28T17:16:16.346400Z

i bet its https://github.com/lambdaisland/regal

robertfw 2020-10-28T17:16:42.346700Z

that's the one! thanks!

πŸ‘ 1
robertfw 2020-10-28T17:17:08.347Z

A colleague is having regex problems of the "now you have two problems" variety, and I wanted to dangle this in front of them

alexmiller 2020-10-28T17:27:26.347200Z

you can use a Java array type string, like "[Ljava.lang.String;"

alexmiller 2020-10-28T17:27:46.347400Z

where you'll replace java.lang.String with your type

alexmiller 2020-10-28T17:28:55.347600Z

so something like this I think would make a String foo(String...) for example:

(gen-interface 
  :name my.Foo 
  :methods [[foo ["[Ljava.lang.String;"] java.lang.String]])

Matias Francisco Hernandez Arellano 2020-10-28T17:59:57.347900Z

That sounds really good

2020-10-28T19:59:44.353Z

Is there a limit to the number of multimethods available in a namespace? I am assuming no. I have this really weird issue in which I have several mms in a ns. Everything is working fine and then I just added a new one and when I invoke it it throws an NPE. As a test, I literally duplicated one that works and renamed it. When I invoke it I get a NPE. Does this sound at all familiar to any existing issues?

unbalanced 2020-10-30T19:32:06.427300Z

I wear that cone all the time πŸŒ€ @markbastian

p-himik 2020-10-28T20:00:33.353100Z

How many mms do you have in that ns? What's the stacktrace of the NPE?

2020-10-28T20:01:51.353300Z

And maybe this is not relevant, but are you starting a new JVM from scratch after modifying the Clojure code, or trying to add the new multimethod to a running JVM with other Clojure code previously loaded?

2020-10-28T20:02:20.353500Z

9 previous. This is number 10.

Execution error (NullPointerException) at my.api/eval37134 (api.clj:63).
null
nrepl.middleware.interruptible-eval/evaluate/fn  interruptible_eval.clj:   82
...
clojure.core/with-bindings*                core.clj: 1973 (repeats 2 times)
clojure.core/apply                core.clj:  665
...
nrepl.middleware.interruptible-eval/evaluate/fn/fn  interruptible_eval.clj:   82
clojure.core/eval                core.clj: 3214
...
my.api/eval37134                 api.clj:   63
...
java.lang.NullPointerException: 

2020-10-28T20:04:07.353700Z

@andy.fingerhut - tried both. It was in a longer running session, but i restarted to ensure there wasn't any old state hanging around, like an older definition or something.

p-himik 2020-10-28T20:04:35.353900Z

And what's at api.clj:63?

2020-10-28T20:04:44.354100Z

(froob {} {})

2020-10-28T20:04:53.354300Z

^the mm that blows up.

p-himik 2020-10-28T20:05:38.354500Z

Can you create and share a minimal reproducible example?

2020-10-28T20:05:38.354700Z

(defmulti froob)
^the definition
(defmethod froob :default [this & _] (log-no-dispatch "froob" this))
^default implementation
(defn log-no-dispatch [fn-name dispatch-key]
  (timbre/errorf
    "No dispatch function for multimethod '%s' with dispatch key:\n%s."
    fn-name
    (with-out-str (pp/pprint dispatch-key))))
That's the whole thing.

2020-10-28T20:06:31.354900Z

And as I said, this is just a copy+paste+rename of an existing mm that works fine.

p-himik 2020-10-28T20:06:33.355100Z

Hold on. (defmulti froom) is not valid.

p-himik 2020-10-28T20:06:44.355300Z

There has to be a dispatch-fn.

2020-10-28T20:06:52.355500Z

dumb me

2020-10-28T20:07:00.355700Z

of course

2020-10-28T20:07:08.355900Z

didn't copy that line

dpsutton 2020-10-28T20:07:08.356100Z

simple repro:

p-himik 2020-10-28T20:07:11.356300Z

So not really a copy-paste then. :)

dpsutton 2020-10-28T20:07:12.356500Z

user=> (defmulti thing)
#'user/thing
user=> (defmethod thing :default [x] :hi)
#object[clojure.lang.MultiFn 0x7b60c3e "clojure.lang.MultiFn@7b60c3e"]
user=> (thing :hello)
Execution error (NullPointerException) at user/eval144 (REPL:1).
null
user=>

2020-10-28T20:08:05.356700Z

This is one of those dumb user error things. Thanks guys!

2020-10-28T20:08:18.356900Z

The one above it (defmulti put-file afs-api-dispatch-fn). <- yep

2020-10-28T20:11:10.357500Z

I need to wear the cone of shame on this one.

uosl 2020-10-28T20:35:09.357700Z

Alright, I'll dump the code examples I used. My talk was more about teaching FP, so I used Clojure functions in C-style syntax, but you can easily translate them back.

uosl 2020-10-28T20:35:41.357900Z

{ teamA: { ..., commits: [ { ..., date: "2017-12-17T03:24:00" }, ... ] },
  teamB: { ..., commits: [ { ..., date: "2018-12-17T03:24:00" }, ... ] } }

=&gt; [ { ..., date: "2018-12-17T03:24:00" },
     { ..., date: "2017-12-17T03:24:00" } ]

// Functional example
function teamToCommits(team) {
  return threadLast(team,
    vals(),
    mapcat(:commits),
    sortBy(:date,
      comp(-, compare)),
    take(25)
  );
}

// Procedural example
function teamToCommits(team) {
  var commits = [];

  for (var key in team) {
    var repoCommits = team[key].commits;
    for (var i = 0; i &lt; repoCommits.length; i++) {
      commits.push(repoCommits[i]);
    }
  }

  commits.sort(function(a, b) {
    return b.date - a.date;
  });

  return commits.slice(0, 25);
}

dpsutton 2020-10-28T20:36:16.358200Z

i put in that http://ask.clojure.org question that there's some feedback already so wondering if this might also get a consideration. and honestly it's an easy to overlook problem either way

uosl 2020-10-28T20:36:58.358400Z

Conway's Look-and-say sequence
1, 11, 21, 1211, 111221, 312211, 13112221, 1113213211, ...

// Functional example
function lookAndSay(seq) {
  return mapcat(
    juxt(count, first),
    partitionBy(identity, seq)
  );
}

// We have extra space; let's
// turn it into a lazy sequence!
var lookAndSaySeq =
  iterate(lookAndSay, [1]);

// The 100th member
lookAndSaySeq[99];


// Procedural example
function lookAndSay(seq) {
  var result = [];
  var lastChar = seq[0];
  var times = 0;

  for (var i = 0; i &lt; seq.length+1; i++) {
    var nextChar = seq[i];

    if (nextChar === lastChar) {
      times++;
    } else {
      result.push(times, lastChar);
      lastChar = nextChar;
      times = 1;
    }
  }

  return result;
}

2020-10-28T20:37:32.358600Z

Yeah, I was so convinced I was following the pattern of my bank of defmultis and totally missed the missing dispatch fn.

dpsutton 2020-10-28T20:39:05.358800Z

https://clojure.atlassian.net/browse/CLJ-2584 alex promoted it to jira. so good on you for asking the question.

πŸ‘ 1
euccastro 2020-10-28T21:52:48.359200Z

thank you!

Ed 2020-10-28T22:01:52.360300Z

Oh @borkdude ... https://github.com/borkdude/grasp ... You're a genius ;)

borkdude 2020-10-31T21:28:26.496300Z

@l0st3d There is a binary available now: There's also a binary available now: https://github.com/borkdude/grasp#binary I experimented with a simpler DSL, but it didn't ago anywhere. I decided to expose spec as it is on the command line as well. For longer specs you can use the -f option

Ed 2020-11-01T17:03:44.001300Z

πŸ‘ ... it looks great .... many thanks. I think it's difficult to define a simpler dsl without losing too much functionality ... grasp looks really useful πŸ™‚

borkdude 2020-11-01T17:13:35.001500Z

@l0st3d speaking of which, I just added some convenience macros: https://github.com/borkdude/grasp#convenience-macros

Ed 2020-11-01T17:47:36.002Z

πŸ‘

Ed 2020-10-28T22:03:57.360500Z

Do you have plans to compile this for graalvm?

borkdude 2020-10-28T22:06:06.360700Z

Thanks. Probably at some point. Not sure what the command line API should look like

Ed 2020-10-28T22:24:37.360900Z

No ... Me either ... Look forward to finding out ;)

borkdude 2020-10-28T22:35:42.361100Z

@l0st3d Initially I was inspired by grape which has a less sophisticated pattern matching language and I came up with this:

"($cat reify ($+ ($symbol ($* $list))"

borkdude 2020-10-28T22:36:38.361300Z

but not sure if it's worth doing this. one could also post their spec in a file which can then be fed as an argument