Fork me on GitHub
#clojure
<
2022-02-10
>
Richie00:02:28

Are there any programs that can convert python source to clojure source? It’s fine if I have to fix up the clojure source manually; I’m just trying to save time over doing it all manually.

Richie00:02:01

I didn’t find anything after searching online.

Richie00:02:53

No, I may try to write a source to source compiler myself and run tests with libpython-clj.

Richie00:02:16

I’ll need the python source even if I have to do it manually.

Richie00:02:19

Thank you though.

Richie00:02:22

I mean *cljure source

Richie00:02:28

I’ll need the clojure source…

phronmophobic00:02:04

There was a js -> cljs transpiler released recently, https://gitlab.com/mauricioszabo/js2cljs/-/blob/master/src/js_cljs/core.cljs. You may be able to reuse some of the structure in conjunction with a python parser.

phronmophobic00:02:56

What's the reason behind the clj source requirement?

Richie00:02:16

I joined a clojure company that inherited a python project and new requirements are going to triple the size of the thing. We don’t have experience with python but we have many clojure services.

👍 1
Akshay C. Gollapalli03:02:34

Probably easier than building doing a full transpile.

Richie13:02:04

Thanks! I agree it would be easier.

Drew Verlee03:02:48

Given a tree structure, what would be the best way to remove parent nodes if there are no children nodes after a given filter? I guess there has to be a secondary filter to remove the parent nodes no matter how i do this. It would be nice to just keep the parent info on the child, filter out invalid ones, then re-build the tree using group-by, but then i lose the sort order (that i need to keep) of the parent and the child elements. hmm will group-by maintain the order of values conjed together? yes. it says that in the doc string

hiredman04:02:02

If you do a post order traversal you will visit the parent after the children

mx200007:02:59

I just found out about this: https://clojure.org/guides/dev_startup_time How do I use this with leiningen ? Can I just compile clojure.core or is it already pre-compiled?

seancorfield07:02:20

@mx2000 Clojure itself is precompiled.

seancorfield07:02:51

That suggestion is intended to apply to your own application code (and other libraries it depends on).

seancorfield07:02:49

What you need: 1) create a classes folder in your project, 2) add it to Leiningen's classpath (as a source path I guess), 3) start a REPL and call compile on your main namespace. That will generate .class files into the classes folder which will get used the next time you start a REPL (newer files will be recompiled when they are required).

Martynas Maciulevičius08:02:50

Hey. I have a strange issue where I want to throw an exception inside of a nested map. And I want to test that the exception comes out. But for some reason it gets wrapped into ExceptionInfo. What should I do to throw the original exception? What if I don't want to use a try block? My data looks like this: [ [ item ] [ item item ] ... ] And I do this (map (map...))

dpsutton08:02:16

how are you throwing the exception?

Martynas Maciulevičius08:02:51

(throw (new IllegalArgumentException ...) I also tried (throw (ex-info ...) but it still wraps it into another ex-info. What I want to do is to catch it this way: (is (thrown? ExceptionInfo ...)

Martynas Maciulevičius08:02:12

It could be any type of exception. But for some reason the test runner doesn't catch the exception

Martynas Maciulevičius08:02:25

I think it has something to do with the map nesting. Because if I simply throw it from top-level form then it catches just fine.

Martynas Maciulevičius08:02:51

Found the "bug". The nested map produces a lazy sequence. So it throws only when I evaluate for printing.

dpsutton08:02:21

any time 🙂

Martynas Maciulevičius08:02:24

No, I messed up my testing. It still fails. I'll try more. Edit: Yes, it's lazy sequences.

bortexz09:02:21

What would be an example of API error that would translate to ::anomalies/interrupted? Do rejection due to rate-limits fall into this category?

p-himik09:02:02

My first thought is a request being aborted, something like this: https://stackoverflow.com/a/35133182/564509

achikin09:02:06

Can I print the let block somehow?

achikin09:02:21

Maybe some custom let?

p-himik10:02:50

What do you mean exactly? Print the values, print the bindings with their values, print the evaluated body, print the code,...?

achikin10:02:46

print the bindings names with their vaules

achikin10:02:34

(print-let [a 1 b 2] (...)) => "a 1 b 2"

p-himik10:02:45

A print-let macro can be written, yes. It will rely on a regular let. Is it something you want to write yourself or do you need help with that?

borkdude10:02:13

user=> (defmacro locals [] (let [ks (keys &env) quoted-keys (map #(list 'quote %) ks)] `(zipmap [~@quoted-keys] [~@ks])))
#'user/locals
user=> (let [x 1 y 2] (locals))
{x 1, y 2}

👍 1
p-himik10:02:33

But that'll show all locals, from other outer lets as well. Which might of course not be important.

borkdude10:02:00

(let [x 1
  (let [outer-locals (locals)]
    (let [y 2 inner-locals (remove-outer-locals (locals) outer-locals)]
;)

👍 1
borkdude10:02:02

this could be then wrapped in a custom let macro which always removes the locals from the outer let

p-himik11:02:14

Alright, how about (let [a 1, a (inc a)] ...) then? :) Or (let [a 1] ... (let [a 2] ...)).

borkdude11:02:15

that's local shadowing, when you shadow a local, the previous local is out of scope, so it should not be shown

p-himik11:02:25

Right, so print-let would be good here, even if you already have locals.

borkdude11:02:10

I don't know why it's important to have locals grouped by inner lets, since lets have no name or so. also function arguments are locals.

borkdude11:02:22

seems like a made up requirement ;)

borkdude11:02:51

user=> ((fn [x] (locals)) 1)
{x 1}

p-himik11:02:41

It might be useful for tracing, or debugging.

p-himik11:02:55

But that's up to OP to answer.

Akiz12:02:38

Hi, do you know if there is a JSON library which use ordered-map when decoding? I need to keep ordering of decoded json but data.json doesn’t support this. I am not sure about others like jsonista etc…

lispyclouds12:02:36

I think clj-yaml uses ordered maps and since JSON is valid YAML, should work?

🧑‍🎓 1
nbardiuk12:02:59

https://www.json.org/json-en.html An object is an unordered set of name/value pairs if some library preserves order today it might break order tomorrow. As a suggestion you can hardcore order in the code that reads values from map

p-himik12:02:54

If you have the control over the data and you need the order, then an array should be used. Either to store the k-v pairs to to store the order of the keys. But if you don't control the data and still need to preserve the order, then, assuming you can't find anything better, com.googlecode.json-simple/json-simple (a Java library) supports providing a custom factory for objects.

Akiz13:02:16

@U076FM90B I have got json newline delimited file. It is Bigquery export. The ordering of keys is same like table’s original column ordering and i dont want to lose this information once i decode it. @U2FRKM4TW Thanks, this looks handy!

👍 2
pinkfrog13:02:31

Hi. Where is the place to add some docs for a defmethod

p-himik13:02:48

Comments. defmethod doesn't introduce a new var, so there's nothing to attach the :doc metadata to. But defmulti can have a docstring - just like with regular functions, right after the name.

👍 2
vemv13:02:21

Hack idea:

(defmulti foo ,,,)

(defmethod foo :bar ,,,)

;; Append a docstring to the defmulti:
(alter-meta #'foo update :doc (fn [s]
                                (str s
                                     "\n"
                                     "The behavior for the :bar dispatch value is [...]")))
Different defmethods could append their own bits to the defmulti in a decentralized manner. Tooling that isn't static will be able to use the computed string.

p-himik14:02:47

Reloading namespaces and overriding methods will become more fun. :)

1
Eugen13:02:35

hi, does anyone know if clojure.test changed (and how). I'm working to upgrade clj-commons/claypool from 1.8 -> 1.10. Tests pass with 1.9 but when I switch to 1.10, 6 tests fail because of clojure.test changes with thrown-withmsg? , I believe .

(defn check-input-exception
  "Check that a pmap function correctly passes exceptions caused by lazy
  inputs."
  [pmap-like]
  (let [n 10
        pool (cp/threadpool n)
        inputs (map #(if (< % 100)
                       %
                       (throw (Exception.
                               "deliberate exception")))
                    (range 200))]
    (is (thrown-with-msg?
         Exception #"deliberate"
         (dorun (pmap-like pool inc inputs))))
    (.shutdown pool)))

Eugen13:02:47

lein test :only com.climate.claypoole-test/test-upvalues

FAIL in (test-upvalues) (claypoole_test.clj:489)
upvalues handles input exceptions correctly
expected: (thrown-with-msg? Exception #"deliberate" (dorun (pmap-like pool inc inputs)))
  actual: #error {
 :cause "deliberate exception"
 :via
 [{:type clojure.lang.Compiler$CompilerException
   :message "Syntax error compiling at (/tmp/form-init4146916011584432383.clj:1:6367)."
   :data #:clojure.error{:phase :compile-syntax-check, :line 1, :column 6367, :source "/tmp/form-init4146916011584432383.clj"}
   :at [clojure.lang.Compiler analyze "Compiler.java" 6808]}
  {:type java.lang.Exception
   :message "deliberate exception"
   :at [com.climate.claypoole_test$check_input_exception$fn__1300 invoke "claypoole_test.clj" 484]}]
 :trace
 [[com.climate.claypoole_test$check_input_exception$fn__1300 invoke "claypoole_test.clj" 484]
  [clojure.core$map$fn__5851 invoke "core.clj" 2753]
  [clojure.lang.LazySeq sval "LazySeq.java" 42]
  [clojure.lang.LazySeq seq "LazySeq.java" 51]
  [clojure.lang.RT seq "RT.java" 531]
  [clojure.core$seq__5387 invokeStatic "core.clj" 137]
  [clojure.core$seq__5387 invoke "core.clj" 137]
  [com.climate.claypoole_test$fn__1822$pmap_like__1840$iter__1841__1845$fn__1846 invoke "claypoole_test.clj" 903]
  [clojure.lang.LazySeq sval "LazySeq.java" 42]
  [clojure.lang.LazySeq seq "LazySeq.java" 51]
  [clojure.lang.RT seq "RT.java" 531]
  [clojure.core$seq__5387 invokeStatic "core.clj" 137]
  [clojure.core$concat$cat__5480$fn__5481 invoke "core.clj" 734]
  [clojure.lang.LazySeq sval "LazySeq.java" 42]
  [clojure.lang.LazySeq seq "LazySeq.java" 51]
  [clojure.lang.ChunkedCons chunkedNext "ChunkedCons.java" 59]
  [clojure.lang.ChunkedCons next "ChunkedCons.java" 43]
  [clojure.lang.RT countFrom "RT.java" 649]
  [clojure.lang.RT count "RT.java" 639]
  [clojure.lang.Cons count "Cons.java" 49]
  [clojure.lang.Compiler analyze "Compiler.java" 6780]
  [clojure.lang.Compiler analyze "Compiler.java" 6745]
  [clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6120]
  [clojure.lang.Compiler$FnMethod parse "Compiler.java" 5467]
  [clojure.lang.Compiler$FnExpr parse "Compiler.java" 4029]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7104]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler analyze "Compiler.java" 6745]
  [clojure.lang.Compiler$BodyExpr$Parser parse "Compiler.java" 6120]
  [clojure.lang.Compiler$FnMethod parse "Compiler.java" 5467]
  [clojure.lang.Compiler$FnExpr parse "Compiler.java" 4029]
  [clojure.lang.Compiler analyzeSeq "Compiler.java" 7104]
  [clojure.lang.Compiler analyze "Compiler.java" 6789]
  [clojure.lang.Compiler eval "Compiler.java" 7173]
  [clojure.lang.Compiler eval "Compiler.java" 7131]
  [clojure.core$eval invokeStatic "core.clj" 3214]
  [clojure.core$eval invoke "core.clj" 3210]
  [com.climate.claypoole_test$fn__1822$pmap_like__1840 invoke "claypoole_test.clj" 899]
  [com.climate.claypoole_test$check_input_exception$fn__1302 invoke "claypoole_test.clj" 491]
  [com.climate.claypoole_test$check_input_exception invokeStatic "claypoole_test.clj" 489]
  [com.climate.claypoole_test$check_input_exception invoke "claypoole_test.clj" 478]
  [com.climate.claypoole_test$check_all$fn__1474 invoke "claypoole_test.clj" 711]
  [com.climate.claypoole_test$check_all invokeStatic "claypoole_test.clj" 710]
  [com.climate.claypoole_test$check_all invoke "claypoole_test.clj" 691]
  [com.climate.claypoole_test$fn__1822 invokeStatic "claypoole_test.clj" 906]
  [com.climate.claypoole_test$fn__1822 invoke "claypoole_test.clj" 892]
  [clojure.test$test_var$fn__9707 invoke "test.clj" 717]
  [clojure.test$test_var invokeStatic "test.clj" 717]
  [clojure.test$test_var invoke "test.clj" 708]
  [clojure.test$test_vars$fn__9733$fn__9738 invoke "test.clj" 735]
  [clojure.test$default_fixture invokeStatic "test.clj" 687]
  [clojure.test$default_fixture invoke "test.clj" 683]
  [clojure.test$test_vars$fn__9733 invoke "test.clj" 735]
  [clojure.test$default_fixture invokeStatic "test.clj" 687]
  [clojure.test$default_fixture invoke "test.clj" 683]
  [clojure.test$test_vars invokeStatic "test.clj" 731]
  [clojure.test$test_all_vars invokeStatic "test.clj" 737]
  [clojure.test$test_ns invokeStatic "test.clj" 758]
  [clojure.test$test_ns invoke "test.clj" 743]

Ran 1 tests containing 29 assertions.
1 failures, 0 errors.
Tests failed.

vemv13:02:52

Is the exception in question an Exception? perhaps it's an Error now

Eugen13:02:51

so I did not change any line in the code, besides the upgrade. The check-input-exception used to test functionality has this:

(throw (Exception.
                               "deliberate exception")))

Eugen14:02:30

to my understanding, it should check if input with lazy evaluation throws exception

Alex Miller (Clojure team)14:02:32

I don't think anything has changed with thrown-with-msg?

👍 1
Eugen14:02:34

now I noticed sometjing interesting:

:message "Syntax error compiling at (/tmp/form-init4146916011584432383.clj:1:6367)."
   :data #:clojure.error{:phase :compile-syntax-check, :line 1, :column 6367, :source "/tmp/form-init4146916011584432383.clj"}

Eugen14:02:43

syntax error compiling.

Eugen14:02:48

the code uses eval

Alex Miller (Clojure team)14:02:22

you may be seeing 1.10 changes in what exception types are thrown out of compile/eval

Eugen14:02:45

yes, I think so too now.

Alex Miller (Clojure team)14:02:51

and there is another change in this area in 1.11.0-beta1

Eugen14:02:52

I missed the message

Eugen14:02:32

any pointers on how to move forward ?

(deftest test-upvalues
  (testing "basic upvalues test"
    (cp/with-shutdown! [pool 3]
      (is (= [1 2 3 4]
             (sort (cp/upvalues pool (inc 0) (inc 1) (inc 2) (inc 3)))))))
  (letfn [(pmap-like [pool work input]
            (let [worksym (gensym "work")]
              ((eval
                `(fn [pool# ~worksym]
                   (cp/upvalues
                    pool#
                    ~@(for [i input]
                        (list worksym i)))))
               pool work)))]
    (check-all "upvalues" pmap-like false false false)))

Alex Miller (Clojure team)14:02:11

you probably want to check the message of the root exception, not the top level exception?

Alex Miller (Clojure team)14:02:33

thrown-with-msg? is an assertion handler - you can make your own

Eugen14:02:35

I checked with (is (thrown-with-msg? Exception #"Syntax" and test passes

Eugen14:02:50

ok, thanks

Eugen14:02:58

I'm also thining if this is the right way to fix the test. I mean it does pass but not sure yet if it still holds to its purpose.

Alex Miller (Clojure team)14:02:49

I think I would make sure the thing underneath the top exception is not actually some other problem :)

Eugen14:02:02

thanks ❤️ I will ask for a review later. I will try to fix it like it is (and understand what happens).

kenny17:02:49

What prints as ZWNBSP (see screenshot)? Zero width no break space? It comes from (-> f (slurp) (csv/read-csv))'ing a csv file from a Miscrosoft docs site. Any idea why that char would be present in a csv?

kenny18:02:11

Seems like it

(= \uFEFF (first (first (first csv))))
=> true
How do folks handle this optional case?

noisesmith18:02:28

yeah, it's the byte order mark, if it's placed correctly (directly at the beginning of the file) then (subs (ffirst csv) 1) discards it *edit - fixed missing arg to subs

kenny18:02:56

Right, but why is the default behavior to include it in the output?

noisesmith18:02:31

because microsoft is weird and they use byte order marks

kenny18:02:52

Haha, true. Curious though, why doesn't the underlying jvm reader discard it?

noisesmith18:02:23

that's a good question - it might be because clojure sets a utf8 default

noisesmith18:02:39

you can try (slurp file :encoding "whater-microsoft-uses")

kenny18:02:09

Not sure I follow. It seems like a configuration knob that should be used as necessary when reading from the file. Or are you saying it's a non-standard knob to begin with?

noisesmith18:02:26

there's no magic number on most text files, and that's how you'd programmatically find encoding info

kenny18:02:53

This file is utf-8 encoded. > The Unicode Standard permits the BOM in https://en.wikipedia.org/wiki/UTF-8,https://en.wikipedia.org/wiki/Byte_order_mark#cite_note-3 but does not require or recommend its use. > https://en.wikipedia.org/wiki/Byte_order_mark#UTF-8 Perhaps the jvm doesn't quite follow the standard?

kenny18:02:34

Welp, I should actually read the doc... > The standard also does not recommend removing a BOM when it is there, so that round-tripping between encodings does not lose information, and so that code that relies on it continues to work.

Jimmy Miller18:02:43

The utf-8 bom is EFBBBF not FEFF. That's the utf-16 BOM

kenny18:02:24

That's even more confusing then @U5K8NTHEZ. Decoding as utf-16 does not produce the expected output.

noisesmith18:02:35

I bet someone has a FilterInputStream that removes BOM from a stream

Jimmy Miller18:02:45

Welcome to the world of dealing with csvs :)

😅 1
Jimmy Miller18:02:02

clj-bom has logic for dealing with this stuff.

kenny18:02:47

Fun fun fun...

kenny18:02:12

I'll take a look. My best bet for now is probably just to drop the first char if it's a bom.

Jimmy Miller18:02:48

When it comes to csvs, try to make your output follow a standard. But expect to have to deal with soooo many weird edge cases.

noisesmith18:02:53

sounds like an easy regex :D

kenny18:02:33

Funny, the "Why" section in clj-bom describes exactly what happened to me 😆

kenny18:02:35

Also funny, clj-bom assumes the encoding specified by the bom is correct.

Alex Miller (Clojure team)18:02:42

wars have been fought about this issue in the Java community for decades

🙈 1
Michael Gardner18:02:40

Apache Commons IO BOMInputStream will skip the BOM for you

kenny18:02:17

Oddly, clj-bom works for this file -- the BOM is correctly identified as UTF-8 and read without the BOM.

xceno20:02:37

I'm attempting to develop a feature that is something like the "https://filebrowser.clouddirect.net/Uploads/images/knowledge%20base/Office%20365/365%20owa%20inbox%20and%20sweep%20rules%202.png" of MS Outlook. Where the user has a UI to click together rules like *When* entity name *starts with* 'bla' *then _some action_* . The possible predicate functions (when, if, if-not, ...) are pre-defined and available via dropdowns, the actions however might be either pre-defined or could be "clicked together" in the same way. The goal is to take those rules, generate some datomic queries, filters, reducers, you name it and then applying the actions to the results. The actions might have side-effects as well. I'm currently thinking about simply writing what I need from scratch with limited scope, but I can't be the first one to need something like this. I also thought about using a rules engine or statecharts, but it seems these aren't solutions to this specific problem. Any thoughts on this?

xceno20:02:00

😂 well, fair enough. Now I'm scared

hiredman20:02:06

Oh no, compilers are the best, it's just, you have a dsl defined by your ui, and you are compiling to some queries and function calls

hiredman20:02:34

When you look at from the lense of plt, you can start treating the dsl as an ast that you enrich and transform through compiler passes until you get what you want

xceno20:02:17

yeah, that actually makes a lot of sense. So my DSL could just be a simple map like

{:fn 'when
 :predicate '(str/starts-with "bla")
 ;; ...and so on
and then I transform it to whatever I need. I wonder if it'd make sense to just use the symbols of actual functions and then construct a call chain that I eval. Or maybe I actually generate a list in good old lisp style and go from there... Thinking about it as a compiler actually opens up a lot of possibilities

Colin P. Hill22:02:31

Given a named function produced by a fn expression, e.g., (fn foo [] :bar), is there any way to extract its name?

Akshay C. Gollapalli01:02:21

You could use metadata:

(defn give-fn
  [give-me]
  ^{:brought-to-you-by 'give-fn}
  (fn []
    (str "Give " " to the world!")))
(let [given (give-fn "joy")]
  (meta given))
EDIT: I think I may have misunderstood your question. Sorry.

hiredman22:02:42

there are sort of ways that it could be done, because the name ends up being part of the class that is generated for the function

hiredman22:02:32

but the way to think about it is: if you have 5 bound to a name (def foo 5) or (let [foo 5] ...) would you expect to be able to get "foo" somehow from 5? why or why not? then do those arguments apply to other values like functions

hiredman22:02:37

(where the name in (fn foo [..] ...) is essentially a let binding that gives you access to the this that is the fn object when invoking the method that is the fn body)

Colin P. Hill22:02:50

Yeah, kinda suspected. Thanks. Nbd in my case, just something informational it would have been nice to capture, but I can do without.

hiredman23:02:19

because it is part of the generated class name, it will be part of things like stacktraces

Michael W23:02:19

That works for me for named functions of the (fn somename [..] ...) form

Michael W23:02:07

I can't seem to link to the answer I mean

Michael W23:02:47

The 3rd answer