Fork me on GitHub
#clojure
<
2022-03-14
>
Nikolas Pafitis14:03:24

I don't know if this is the correct channel to ask, but does anyone else have the feeling that because Clojure is so simple, they no longer get the satisfaction of building complicated software?

quoll18:03:21

2 weeks ago I was traveling for work. Today, I am looking back at some of the messages I missed. This one warrants feedback! šŸ™‚

quoll18:03:55

I find that Clojure gets out of my way. It lets me focus on the problem at hand. In the past, relatively simple problems required complex software to address it. Complex problems were almost impossible for an individual. They needed a team. I've worked on such problems with large code bases in C, C++, Delphi, VB (IKR?), and Java. With Clojure, relatively simple problems are typically solved with relatively simple solutions! Complex problems take work, but now it's tractable for an individual to work on them. For instance, I have a single project of nearly 9k lines, of which I wrote almost every line. I could never have attempted such a thing in, e.g. Java

potetm14:03:02

More like Iā€™m bewildered at everyone elseā€™s fascination with it (even though I was on the same train myself 10 years ago).

potetm14:03:39

Iā€™m plenty satisfied with solving real complicated problems instead of self-induced ones.

ā˜ļø 10
1
1
potetm14:03:18

Well. ā€œRealā€ meaning: Not due to programming-language-level choices. I suppose ā€œpostgres scalingā€ or ā€œpipeline processingā€ is somewhat self-induced, just at a different level :)

Stuart15:03:54

I wish I was at that point< i'm still at the stage with some stuff where I don't know how to do the thing I want to do, and I'm not even sure what the question is I need to ask.

Stuart15:03:27

Especially with clojurescript stuff

mruzekw15:03:41

Not to mention business / world problems!

šŸ’Æ 1
pavlosmelissinos15:03:20

Apologies if this has been asked before but given that there's an int?/`integer?`, a float? and a double?, how come there isn't a long? core function?

dpsutton15:03:40

int? and integer? donā€™t check for the particular type of integer. Their docstrings are ā€œReturns true if n is an integerā€ and ā€œReturns true if x is a fixed precision integerā€. They are not looking for the integer/Integer java classes

pavlosmelissinos16:03:05

Sorry, I should have been more specific: float? is analogous to int? in the sense that you describe, it checks if the input is a floating point number (either an instance of Double or a Float) Still, there's a double? that checks specifically if n is an instance of Double. So I suppose my question should have been, how come there's a double? but not a long? ?

dpsutton17:03:01

My thinking is that there hasnā€™t really been a need. From the double? function you can see its just an instance check but in my 6+ years of Clojure iā€™ve never needed such a predicate. And outside of interop Iā€™m wondering what need it might serve

āž• 1
dpsutton15:03:47

it means integer in the mathematical sense

Braden Shepherdson16:03:35

I definitely have some colleagues who find it very satisfying to wrestle with our complex beast of a (non-Clojure) codebase and production environment, and win. I've come to view that as a deep, personality-type difference in software development. for me it's all friction making it hard to achieve whatever we're actually trying to do, but not everyone feels that way.

Dave Russell16:03:47

Heya folks! Suppose I have a spec definition for a map whose values are only booleans and sets (i.e. the number of combinations that satisfy the spec is small). Is there a way to exhaustively generate all possible valid maps? I've looked through test.check but unless I'm missing something I couldn't find anything that generates all possible values. Thanks! šŸ™‚

p-himik16:03:38

> booleans Only 2 values. > sets An infinite amount of values..?

respatialized16:03:20

If it's actually that small you can probably just use a for expression over the booleans and sets (though you might need to nest it to generate the set values)

Dave Russell16:03:26

@U2FRKM4TW what I mean is that I have a specced map like:

(s/def ::foo boolean?)
(s/def ::bar boolean?)
(s/def ::baz #{:dog :cat :mouse})
(s/def ::foobar-map (s/keys :req-un [::foo ::bar ::baz]))
and I want to enumerate every possible map satisfying this spec, rather than simply sampling from the space of valid maps.

p-himik16:03:01

Ah, you have specs. You didn't mention that.

p-himik16:03:58

Yeah, for is probably your best bet here. Should be enough here and you can throw in clojure.math.combinatorics if you need more complex values, like all possible subsets of a set.

Dave Russell16:03:33

Thanks! I'll try that, although it would be great if it would be based on the spec for consistency reasons šŸ™‚

Dave Russell16:03:58

I guess I was hoping that there was some generate-all-possible function lurking somewhere

Joshua Suskalo16:03:51

Not really @U01BP1CB37B considering the way spec sees sets is as predicates, and so every possible value in the clojure runtime would need to be tested against it unless special cases were added for sets. Which I can see why it'd look like there is a special case, but there is not.

p-himik16:03:52

There actually is a special case for sets. :)

(defn gen-for-pred
  "Given a predicate, returns a built-in generator if one exists."
  [pred]
  (if (set? pred)
    (elements pred)
    (get @gen-builtins pred)))

Joshua Suskalo17:03:31

Ah, yeah, in the generator it makes sense there's a special case.

Joshua Suskalo17:03:10

I was thinking more about spec itself, not spec's generators

Joshua Suskalo17:03:01

thanks for pointing that out

devn17:03:45

Whatā€™s the simplest way to take a file and get its hex as a string?

p-himik17:03:58

What do you mean by "its hex"? Its binary content encoded in hex or some checksum?

devn17:03:08

the former

ghadi17:03:30

java.util.HexFormat in 17

ghadi17:03:01

Otherwise copypasta on your favorite hex routine

Ferdinand Beyer17:03:14

You could use to read the file into a byte array, then use buddy-coreā€™s bytes->hex: https://funcool.github.io/buddy-core/latest/buddy.core.codecs.html#var-bytes-.3Ehex

Ferdinand Beyer17:03:41

(Donā€™t do that for large files though)

devn17:03:09

nice, didnā€™t know about HexFormat

Ferdinand Beyer17:03:51

Here is a file->bytes function that we have lying around somewhere:

(defn file->bytes [file]
  (with-open [xin (io/input-stream file)
              xout (ByteArrayOutputStream.)]
    (io/copy xin xout)
    (.toByteArray xout)))

devn17:03:15

yeah i have that part, just missing the bit that converts the resulting out to hex

Ferdinand Beyer17:03:38

OK cool. If you donā€™t mind the dep to buddy, it has what you need

Ferdinand Beyer17:03:22

Behind the curtain it just delegates to apache commons, or you could HexFormat as @U050ECB92 suggested if you donā€™t need to support older Java versions

dpsutton17:03:07

org.apache.commons.codec.binary.Hex/encodeHexString is the method being called

borkdude19:03:36

(.toString (BigInteger. 1 (.getBytes "foo")) 16)
"666f6f"

šŸ’Æ 1
devn19:03:22

hey, that ainā€™t bad either

noisesmith19:03:03

@U04V15CAJā€™s approach is the best here IMHO, except for a larger file you probably want to partition the bytes and calculate N at a time (instead of making one BigInteger out of the entire file at once)

Ferdinand Beyer19:03:29

Actually it is not a very good solution because it will skip leading zeros. (.toString (BigInteger. "1") 16) will return "1" instead of "01". And before writing code to encode in chunks using BigInteger, I would go with apache commons codec and write:

(defn file->hex [file]
  (with-open [in  (io/input-stream file)
              b   (ByteArrayOutputStream.)
              out (Base16OutputStream. b true true)]
    (io/copy in out)
    (String. (.toByteArray b))))

noisesmith19:03:58

@U031CHTGX1T thanks, that's a good point, though I still think there's a lot of value to avoiding dependencies if there's a way to avoid commons

Ferdinand Beyer19:03:12

I donā€™t agree at all. If your program needs to encode files to Hex / Base16, depending on commons.codec is totally reasonable. Beware of ā€œNot invented hereā€

noisesmith19:03:37

(cmd)user=> (transduce (map #(format "%02X" %))
                       (fn ([] (StringBuilder.))
                           ([done] (str done))
                           ([sb s] (.append sb s)))
                       (byte-array (range 20)))
"000102030405060708090A0B0C0D0E0F10111213"

šŸ‘ 1
noisesmith19:03:20

for smaller inputs that fn should just be str

noisesmith19:03:39

should have included above, it correctly translates -1 to FF

Ferdinand Beyer20:03:47

That works. But please note that you still need to read the file, itā€™s hard to argue that it is simpler, and it is about 40x slower than just using streams šŸ¤·

West21:03:41

Hey guys, currently trying to compile a project using clojure -T:build . I think my build.clj is alright, but I attached it since I might be doing something wrong. I get this error:

$ clojure -T:build uber
$ java -jar target/bee-solver-0.1.1-standalone.jar
Error: Could not find or load main class wildwestrom.bee_solver.core._main
Caused by: java.lang.ClassNotFoundException: wildwestrom.bee_solver.core._main

hiredman21:03:36

:main is your main namespace

hiredman21:03:12

you look like you have taken the symbol naming your main function

wildwestrom.bee-solver.core/-main
and then turned into the symbol

hiredman21:03:15

wildwestrom.bee-solver.core.-main

hiredman21:03:41

were the correct symbol is likely something like

wildwestrom.bee-solver.core

West21:03:19

Oh man, that was exactly it. I figured I needed the main function. Not only that but I forgot that the functions are denoted by a /. wildwestrom.bee-solver.core works.