Fork me on GitHub
#clojure
<
2017-12-09
>
qqq00:12:52

@noprompt: afaik, forth doesn't support var-arity functions, so f-> won't either

qqq00:12:06

all functions passed to f-> take a single arg (the stack) as input and produces a stack as output

noprompt00:12:23

@qqq right but you could imagine something like [a b c ^{:argc 2} str] as way to tell the compiler to take 2 args from the stack when applying str to it.

qqq00:12:13

(f-> a b c (mod 2 str)), where mod :: int -> func -> func , specifies how many args to take and use

noprompt00:12:40

oh nice. i like that.

qqq00:12:40

except instead of calling it mod, we should call it m! or something

noprompt00:12:23

heh, i sometimes wish clojure had that in core. when mapping over a list of lists (for example) i often want something that takes a number n and function f and pulls n many arguments from each list and applies them to the f rather than writing the function that unpacks the arguments by hand. it’s easy to write but i sometimes i wish i didn’t have to. 🙂

noprompt00:12:20

@qqq ap might be a nice shorthand there. [a b c str 2 ap]

qqq00:12:32

@noprompt: how does 'str know to delay evaluation?

bronsa00:12:16

i'm assuming nothing but ap applies anything

qqq00:12:50

the model I had in mind was: if you get a constant, you push it, if you get a function, you eval it

qqq00:12:01

but in this model, it appears to be "push until you hit ap" ?

bronsa00:12:09

how would you do HOF then?

qqq00:12:29

can you give me a concrete example you have in mind ?

bronsa00:12:41

write (map inc [1 2 3])

qqq00:12:59

is [1 2 3] a single arg on the stack, or is it a stack of 3 items ?

bronsa00:12:09

that's clojure

bronsa00:12:15

write that in your stack based dialect

bronsa00:12:49

if your semantics are "if the top element in my stack is a function, apply it", then you have no way of using a function as a value

qqq00:12:44

I was going to do all function combinators in clojure

qqq00:12:09

the model I had in mind for f-> is: 1. f-> gets a list of args 2. eval each arg 3. if arg is a constant, change it to a push 4. if it's a function, apply it

bronsa00:12:47

well good luck, keywords symbols vectors maps sets are functions too

noprompt00:12:30

@qqq let me get back to you. 😉 I've gotta play with my kids right now. I will be back to meditate on this some more. 😄

fmind06:12:50

Hi, I just saw the changelog of Clojure 1.9. Do you know why the deps and cli tools were added to the language ? https://clojure.org/guides/deps_and_cli

fmind06:12:26

as far as I understand, this is a new improvement on resolving dependencies, but what about building clojure apps ?

noisesmith06:12:32

because clojure.core can't run without the clojure.spec.alpha library that is packaged separately

fmind06:12:41

will it replace or complement lein/boot ?

noisesmith06:12:44

it's not a build tool, it just helps use deps

noisesmith06:12:21

the goal was that people should be able to run clojure directly using a simple tool from the clojure team - clj is designed for that, and just that

fmind06:12:14

so do you think there will be a need to create a new build tool ?

fmind06:12:32

in other language, you usually have a compiler/interpreter and a build tool

noisesmith06:12:44

clj isn't mandatory and isn't a build tool

noisesmith06:12:57

leiningen and boot are still build tools

noisesmith06:12:18

it doesn't replace leiningen or boot but there are plans to use it from boot at least

fmind06:12:23

I when I begin using clojure, I was confuse about boot and lein. I didn't know if these tool where the interpreter/compiler

noisesmith06:12:32

that's a common problem

fmind06:12:00

ok, i see the picture

fmind06:12:31

the goal is to have: 1) clj as the main interpreter, 2) deps.edn as a format to specify dependencies 3) boot/lein as build tool

fmind06:12:44

but at the moment, boot and lein does everything

noisesmith06:12:13

even if you run boot or lein clojure is still the compiler and runs the repl itself

fmind06:12:26

so they might just "wrap" (1) and (2) from boot/lein instead of providing them as they do now

noisesmith06:12:47

they might - but you can run clojure 1.9 from lein or boot without clj

fmind06:12:59

I see, but I'm curious how the boot/lein team will address the overlap

noisesmith06:12:55

they might find it useful, but they don't have to address it - everything still works the old way

dpsutton06:12:12

what's the best way to get the distinct by value of a collection. (?? [[:a 1] [:b 1] [:c 2] [:d 1]]) => [:c 2]

dpsutton06:12:47

i've got some really gross partition by, filter, first, second, first threading going on

noisesmith06:12:46

maybe group-by, then test which values are 1 element long?

dpsutton06:12:21

yeah but it ain't pretty

partitions             (->> edges
                                      (map (fn [kid] [(node-weight adjacency kid) kid]))
                                      (group-by first))
          [size distinct-edge]   (->> partitions
                                      (filter (fn [[p-size nodes]] (= 1 (count nodes))))
                                      first
                                      second
                                      first)

dpsutton06:12:53

was hoping there was a better way

dpsutton06:12:51

maybe some instead of filter but it's not much prettier

noisesmith06:12:41

(->> [[:a 1] [:b 1] [:c 2] [:d 1]] (group-by second) (filter (comp #{1} count val)) (first) (val) (first))

dpsutton06:12:21

that's certainly better

dpsutton06:12:44

i always forget about the #{1} style checking

noisesmith06:12:41

it's more fun to write, but there's also #(= 1 (count (val %))) which performs better

kauko12:12:51

I'm having a strange problem. I'm working on a problem from the advent of code, and I need to copy an input string from the webpage, and transform it into a data structure. A basic (#{:a :b} :a) comparison was returning nil, which prompted me to take a closer look at the result of the transformation. If I call (transform raw-input-string), the printed result looks fine (and in fact, works fine!), but if I compare the printed result to the value returned by the function call (= (transform raw-input-string) <previous result>) I get false!

kauko12:12:14

I'm guessing there's some hidden special characters in there, that get dropped when the output is printed into the repl

kauko12:12:43

Is there a way to remove them..? I'm already removing non-breaking spaces, and using trim (which doesn't really do much I guess)

kauko12:12:08

I've tested this in cursive's repl inside Idea, lein's repl, and planck

kauko12:12:26

Eh, I spit the data structure into a file, and then (-> file slurp read-string)

kauko12:12:34

And apparently the special characters are gone

New To Clojure12:12:36

@kauko (clojure.string/replace "your string" #"[^\p{Print}]" "")

New To Clojure12:12:37

or (clojure.string/replace "your string" #"[^\x00-\x00]" "") with range of characters (replace 00 with proper values)

kauko12:12:22

I tried the first one, I don't think it did anything. I'm probably not going to bother with the second one for now, since I got it working with that hacky file workaround. Appreciate the help though 🙂

octahedrion12:12:21

I've never "installed Clojure" before (always used lein) but I was curious - is there an update for MacPorts rather than Brew ?

New To Clojure12:12:10

version             1.8.0
maintainers         nomaintainer

octahedrion12:12:57

@ghsgd2 yeh I was thinking of Clojure 1.9 the latest

Alex Miller (Clojure team)13:12:28

I’m not sure what that is in MacPorts, but it’s not published by the Clojure core team

ajpierce15:12:51

Hi, Clojurians! I have a question about Java Interop. I'm trying to translate some of the examples from [web3j](https://docs.web3j.io/getting_started.html#start-sending-requests) into Clojure. The synchronous requests work fine:

// Java
Web3j web3 = Web3j.build(new HttpService());
Web3ClientVersion web3ClientVersion = web3.web3ClientVersion().send();
String clientVersion = web3ClientVersion.getWeb3ClientVersion();
; Clojure
(def http (new HttpService))
(def web3j (Web3j/build http))
(-> web3j
    (.web3ClientVersion)
    (.send)
    (.getWeb3ClientVersion))

; "Geth/v1.7.3-stable-4bb3c89d/linux-amd64/go1.7.3"
But my asychronous requests aren't working, and I think it has something to do with the Java 8 lambdas:
// Java
Web3j web3 = Web3j.build(new HttpService());
web3.web3ClientVersion().observable().subscribe(x -> {
    String clientVersion = x.getWeb3ClientVersion();
    ...
});
; Clojure
(def http (new HttpService))
(def web3j (Web3j/build http))

(defn callback [x]
  (println "received value:" x))

(-> web3j
    (.web3ClientVersion)
    (.observable)
    (.subscribe callback))

; CompilerException java.lang.IllegalArgumentException: No matching method found: subscribe for class rx.Observable
The [rx.Observable docs](http://reactivex.io/RxJava/javadoc/index.html?rx/Observable.html) say the subscribe method takes an argument of type Action1, which extends the Action interface, which extends the Function interface. Any ideas as to what I should be passing to a Java function that expects to receive a lambda? Thanks!

New To Clojure15:12:37

You need to use reify but I'm not sure which interface it's needed to implement here

leonoel15:12:51

java lambdas are just syntactic sugar, at the bytecode level they're equivalent to anonymous classes there's no way to infer a conversion between clojure functions and Rx functions so you have to explicitly pass an instance of Rx expected type Action1

leonoel16:12:51

thanks, I was unaware of that

leonoel15:12:40

(def callback
  (reify Action1
    (call [_ x] (println "received value:" x))))

ajpierce15:12:31

@leonoel @ghsgd2 Thanks! I will try this out and report back :thumbsup:

ajpierce15:12:01

@leonoel After figuring out which class to import (it was rx.functions Action1), it worked flawlessly! Going to write up a blog post with my adventures when I have something a bit more substantial, and I will give you the credit for helping me out with this one. Thanks for the lesson!

leonoel16:12:49

@ajpierce np but have look at @ghsgd2’s link in the thread, my comment is inaccurate

ajpierce17:12:51

Thanks again for the help! 🙂

scknkkrer16:12:37

I have a question;

clojure
(list? (cons 'do '((identity x) bla-bla)))
=> false | In Clojure
=> true  | In Clojurescript

scknkkrer16:12:11

What makes the difference ?

scknkkrer16:12:42

I am sorry if it’s a newbie question or it’s obvious. But I really wondering, why…

mikerod16:12:45

I always found it sneaky that a cons returns something that isn’t a list? in clj. It can trick you in situations like macros. Especially involving syntax quote because you don’t always know when it might return a cons. So really I end up just avoiding using list? for these sorts of things (so mostly just never use it)

mikerod16:12:08

It’s odd that cljs would be different though. I didn’t know that

scknkkrer16:12:56

So what are you using as a pred ?

noisesmith16:12:16

@mikerod often when you think you want list? the right predicate is sequential?

noisesmith16:12:32

though that is true for vectors

mikerod16:12:37

Typically sequential?

mikerod16:12:14

Yeah if you don’t want vectors perhaps just not vector?

scknkkrer16:12:15

Oh, I did it right. 😇

tbaldridge16:12:36

Yeah, I think that's a holdover from lisp? @mikerod

tbaldridge16:12:55

Seems like the real predicate is seq?, and sometimes sequential?

tbaldridge16:12:17

Often, outside of lisps, list? implies something that has O(1) counting.

mikerod16:12:22

@tbaldridge interesting. I’d have to check out something like Common Lisp to compare on that one.

scknkkrer16:12:43

As a sub-routine, doesn’t it bother anyone ?

Thom18:12:49

does anybody know of any nice documentation around creating a custom implementation of Spec/Specize from clojure.spec.alpha? I can find one gist in all the web of someone that's attempted it.

Alex Miller (Clojure team)19:12:19

it’s not documented because we don’t want to encourage you to do that

Alex Miller (Clojure team)19:12:03

in general, you should either be plugging predicates into the specs (use any predicate you like) or combining the things that are provided, which cover the possible data structures appropriately

Alex Miller (Clojure team)19:12:05

while I expect the spec api to stay pretty similar, the internals of spec are going to change, so whatever you write is almost certain to be broken. when we consider spec final, there may be more docs at that time on how to create custom spec types.

ido20:12:36

What's with those new cli tools released with clojure 1.9? What Gap are they trying to fill?

ido20:12:57

@alexmiller skimmed simple_smile . But, are they trying to replace lein/boot?

Alex Miller (Clojure team)20:12:24

They do not build or deploy artifacts

Alex Miller (Clojure team)20:12:32

They are for building classpaths and launching Clojure programs

ido20:12:42

Thanks @alexmiller . I'll read it through.

davidrupp22:12:33

@scknkkrer The answer to your earlier question -- about the difference in behavior of (list? (cons stuff)) in clj and cljs -- is basically due to how the Cons type is defined on both sides. In clj, (list? thing) asks if thing implements IPersistentList. clj Cons is java.lang.Cons, which does not implement that interface, or inherit from anything that does; that's why it returns false on the clj side. In cljs, (list? thing) asks if thing "implements" (`satisfies?`) IList. cljs Cons is explicitly defined to implement that interface, so it returns true.

mikerod22:12:22

@davidrupp good explanation. That brings up something I’ve wondered - why java.lang.Cons doesn’t impl IPersistentList

tbaldridge22:12:53

@mikerod because IPersistentList is counted and that demands O(1) counting. Cons cells can be lazy and are O(n) counted.

mikerod22:12:02

@tbaldridge where in public interface IPersistentList extends Sequential, IPersistentStack are they counted?

mikerod22:12:16

I know it has the IPersistentCollection.count()

mikerod22:12:53

however, I didn’t think that was the same as clojure.lang.Counted

mikerod22:12:04

I didn’t know it had any sort of stipulation that is

tbaldridge22:12:17

yeah all the interfaces are O(1), Clojure papers over that with count in clojure.core

mikerod22:12:31

Either way, I guess I’m getting the general idea that a Cons can be some unbounded lazy thing, where a “list” is expected to not be, I guess

tbaldridge22:12:11

all that is a bit cleaner in ClojureScript

tbaldridge22:12:17

sideffect of reimplementing the lib

mikerod22:12:17

Well, good to know. Thanks for the insight

scknkkrer22:12:07

@davidrupp I looked the documentations before but your message is so clear and it helped me to clear some questions on my mind. If you know any tricks like that. Please mesaage me, I am documenting these tricks.