Fork me on GitHub
#beginners
<
2019-05-21
>
Michael Stokley00:05:15

Error printing return value (ClassCastException) at clojure.core.logic.Choice/bind (logic.clj:1094).
clojure.lang.LazySeq cannot be cast to clojure.lang.IFn

hiredman03:05:33

map returns a lazy seq, core.logic programs are made up goals (== returns a goal, as does permuteo, etc) you cannot mix and match them like that

hiredman03:05:16

your map call is returning a lazy-seq of goals (because the maping function returns the goal returned from the unification)

hiredman03:05:18

so you need something that takes a seq of goals and returns a single goal, in this case conjunction of goals (the other option is a disjunction) which I don't entirely recall the name of

hiredman03:05:40

everyg or all

hiredman03:05:30

but you are likely to run into other issues too

hiredman03:05:36

your filter call won't work either

hiredman03:05:57

you just can't mix non-logic stuff into logic programs like that

Michael Stokley17:05:49

thanks @U0NCTKEV8 - makes sense.

Michael Stokley00:05:36

clojure
(l/run* [out-list]
  (let [lvars (repeatedly 3 l/lvar)
        pairs (map vector (list nil nil 3) lvars)
        important-pairs (filter (fn [[x _]] (not (nil? x))) pairs)]
    (l/fresh [lvars]
      (l/== out-list lvars)
      (l/permuteo (list 1 2 3) out-list)
      (map (fn [[x y]] (l/== x y)) important-pairs))))

Michael Stokley00:05:57

anyone know why that last map is throwing the above error?

noisesmith00:05:07

which call to map?

Michael Stokley00:05:14

in the last line

Michael Stokley00:05:29

sorry, l is clojure.core.logic

Michael Stokley00:05:29

is important-pairs lazy or something, as produced by let?

noisesmith00:05:22

filter is always lazy

noisesmith00:05:36

I don't know enough about core.logic to get much further than that though, I thought it was macro based and I wouldn't expect those macros to work with lazy-seq args, but I could be totally off track here

zlrth00:05:38

i’m using sente, and on a successful server-update, i want to notify only the client that sent the update. but on a failed server-update, i want to notify all clients (all tabs) associated with a user. I believe the docs, which say >Each user-id may have zero or more connected clients at any given time but if connected-uids is just a set of uids, how does my app know which user-id (“alice” with several tabs, “bob” with 1), goes to which connected-uid (“uuid” “uuid” …. “uuid”) https://github.com/ptaoussanis/sente#what-is-the-user-id-provided-to-the-serveruser-push-fn

zlrth00:05:26

maybe i have to track it myself? i can do that, but i naively thought “each user-id may have zero or more connected clients” meant sente had a place to but user-ids and connected clients.

noisesmith00:05:52

when I used sente I did my own server side bookkeeping to map user ids to connected socket ids

👍 4
noisesmith00:05:41

I don't think sente makes any assumptions about users and ids - for all it cares every socket connected could be anonymous / unauthenticated, or every socket could be the same user

noisesmith00:05:18

yeah - unless you know you only have one server instance running ever, you do need something that spans multiple instances (eg. your db)

zlrth01:05:34

thanks again. rereading those paragraphs with the thought “sente doesn’t make any assumptions about users and ids” makes it more sense.

Daouda02:05:36

hey folks, is there any authentication client for clojure rest api project? I am starting to build a project and i need some help. Actually my first one.

Daouda12:05:07

exactly @U04V70XH6, thank very much 😄

thumbnail07:05:53

I have an record implementing an specific protocol. I’d like to wrap the protocol calls to have certain behaviour before/after the protocol-function is called. How’d i go about it? I messed around with proxy; but that doesn’t seem right

thumbnail08:05:07

I it working with reify. cool

Kevin10:05:02

Does anyone have a working example of GraphQL subscriptions in Lucinia?

jumar10:05:45

perhaps better to ask in #graphql

Kevin11:05:47

Thanks for the tip!

David Savoie14:05:52

Hi! I'm trying the simplest thing, launching a development environment with Figwheel-main and Clojure CLI. I'm following [the Figwheel tutorial](https://figwheel.org/docs/installation.html) to the letter, but when I launch clojure -m figwheel.main, a browser window opens, but no repl in the terminal (although there should be one started). I don't get any error messages either... Any advice? Thanks!

lepistane14:05:35

which browser? I only ask cause terminal doesn't popup for me on firefox but it does on chrome

David Savoie14:05:57

I'm using Chrome on Linux. I open a shell at the root of my project, in which I created the proper deps.edn file, then type in the starting command. The browser window opens, and it says I should be "returning to the REPL and typing", but there's no actiive repl running in the shell. Last message I have is Opening URL . 😕

eskemojoe00715:05:36

Super noob question, I see a test that has a structure that looks like (deftest ^{:some-key "Some-value"} similar-to-key ...) What is the map all about?

Alex Miller (Clojure team)15:05:35

it's like in the name and everything :)

rschmukler16:05:25

Is there any way to determine whether code is being executed by a go block? I'd like to conditionally apply <! or <!! based on whether I'm inside a go block.

Daouda16:05:55

Hey Folks, can someone help me to understand difference between compojure-api and pedestal?

noisesmith16:05:03

@rschmukler given how the go block compiler works, that's not going to work

rschmukler16:05:05

I figured as much, but I was hoping perhaps behind the scenes it set a thread variable or something (on the executor threads)

noisesmith16:05:10

the portable thing is to create a go block in your function and return its channel

noisesmith16:05:25

go blocks are cheap

rschmukler16:05:31

Yeah, the problem is that it feels like a bit of a leaky abstraction

rschmukler16:05:49

ie. Concurrency is an implementation detail - making the caller aware of its semantics feels dirty

noisesmith16:05:57

changing behavior when inside vs. outside a go block is a much bigger leak

rschmukler16:05:41

It'd be encapsulated by a function though. ie. callee's responsibility, instead of caller

noisesmith16:05:59

core.async's model can't abstract that

rschmukler16:05:25

But I do get why it's not done. Stringing channels through all my APIs just isn't worth it though. I'll see if I can find a different way.

noisesmith16:05:41

using go works in both contexts - you never end up blocking a thread

noisesmith16:05:02

channels are the price of the core.async model though

rschmukler16:05:35

Where are my JVM fibers 😞

ghadi16:05:51

passing channels as arguments is the right thing to do

ghadi16:05:00

i don't know what the original problem is here

4
rschmukler16:05:05

I understand that it can be done that way. But it forces everything into a different paradigm - namely, using channels instead of function application

ghadi16:05:04

using channels is a great way to decouple parts of your system

rschmukler16:05:05

The problem is strictly semantic - not a big one, only seeing if there was a more elegant solution afforded somewhere.

ghadi16:05:02

you're not being specific about problems

ghadi16:05:08

what problems?

rschmukler16:05:15

Okay, I'll try and explain

noisesmith16:05:44

if you have a channel and need a blocking or callback function, use take! right?

rschmukler16:05:10

I have a function which preforms a large computation and relies on an army of workers to execute it

rschmukler16:05:35

Traditionally it is called from outside of a goblock (eg. the repl, a dedicated threadpool, whatever)

rschmukler16:05:36

ie. the impl of do-work takes from a channel with all the results <!!

hiredman16:05:50

the scope of the go blocks is static, not dynamic

rschmukler16:05:20

I want to clarify, I know how they work, I'm just trying to showcase how they can leak

rschmukler16:05:31

Now, I've got a new system, also implemented with go blocks, each one calling do-work with slightly different arguments

rschmukler17:05:23

The problem is now that these go blocks are calling a function (`do-work`) which actually blocks (instead of parking). So now I have to either create a function that returns the channel directly (not a big deal, but it forces the caller of the system to be aware of its concurrent implementation detail) or expose a variant that parks instead of blocks (again, leaking the internal implementation of what do-work does out to the caller, that also happens to be implemented with go blocks.

hiredman17:05:53

the parking variant will also need to return a channel

hiredman17:05:09

otherwise the caller cannot park

hiredman17:05:20

so just return a channel

hiredman17:05:56

do-work or a variant of it cannot park, even if called from a go block

hiredman17:05:22

it can only park if it has its own go block, which will require returning a channel

rschmukler17:05:58

My point is, but for the fact that these systems share a goblock runtime, these variants would never exist. It's not a big deal at all, but it does force an all-or-nothing type of constraint on the system. Either channels are used at system boundaries, or they aren't - it's difficult for two independent systems which happen to be implemented w/ go routines (a strict implementation detail) to coordinate with functions.

rschmukler17:05:36

I do buy that not much better can be done until fibers come to the JVM though

hiredman17:05:54

if you want to do core.async kinds of things without core.async then use callbacks

hiredman17:05:05

(which are terrible)

rschmukler17:05:21

Yeah, this is definitely better than call backs

ghadi17:05:32

thanks for explaining

ghadi17:05:21

I don't think this is a <! vs <!! thing as much as a channels vs. not channels dilemma

hiredman17:05:37

or a function vs. machine dilemma

💯 4
rschmukler17:05:46

Yep. Systems are hard 😛

hiredman17:05:09

e.g. make do-work start a do-work server that you send work to via a channel

rschmukler17:05:35

True, but it's also a consequence of this specific implementation of do-work-servers. ie. Runtimes with actual support (again, not Clojure's fault, Project Loom for the JVM is coming) enable you to put the machines back behind the function boundary (either via a preemptive scheduler ala erlang) or full run-time level support (golang) where all functions end up "parking".

ghadi17:05:22

i still wouldn't put the focus on the execution machinery -- the essential thing here is conveyance

ghadi17:05:38

work being distributed, answers being collected

ghadi17:05:53

even with Project Loom we'll still want channels

rschmukler17:05:10

Yes, they are a fantastic coordination mechanism

rschmukler17:05:43

But, without the runtime handling parking, they leak. Ie. golang doesn't have <! and <!! because the runtime handles it for you

rschmukler17:05:29

I won't even say leak, as it comes off too harshly - they just can't be mixed well with functions

hiredman17:05:24

which is my point, a lot of people start with a function calling and returning kind of design, and want to sprinkle in little bits of core.async and it is annoying because it isn't transparent

hiredman17:05:46

so like, you invoke functions and then park on the channel returned

hiredman17:05:57

instead of just invoking functions

hiredman17:05:45

which is kind of a dissonance, but if you approach core.async systems as more machines to start with, you get a model of calling (create-do-work-server) once at start up, and doing client/server style request response stuff

hiredman17:05:20

which is definitely not just invoking functions, but you don't get the dissonance

rschmukler17:05:33

Absolutely - and erlang / Exlixir have that paradigm pretty strongly. But, because there is a preemptive scheduler, you can put the semantics of request / response back under functions.

rschmukler17:05:35

Functions have a lot of advantages, at the highest level. They are highly composable, can be partially applied, can represent lazy execution (thunks), have great tooling for exploring their results, have great tooling for jumping to where they do, etc. Channels could have tooling at that level

rschmukler17:05:44

Anyway, I appreciate everyone engaging. I'll return the channel and deal 😛

ghadi17:05:57

I know we love FP but functions can be automatic coupling

ghadi17:05:17

sounds like clickbait but call chain coupling is a real issue

ghadi17:05:41

A calls -> B calls -> C -> D -> E, etc

eval-on-point17:05:42

What's the issue with this? trying to follow the conversation here

eval-on-point17:05:44

Nevermind, looks like it is all in this talk linked below

leonoel08:05:21

I admit I'm failing to get the point being made here too

ghadi17:05:10

orchestration via channels can avoid that. There's a good talk from Rich Hickey that deals with this

rschmukler17:05:24

Absolutely. I did Haskell for about a year professionally and it's the king of creating compositional coupling

rschmukler17:05:03

@ghadi Are you referring to "The Language of the System"?

rschmukler17:05:30

I haven't seen that one. I'll give it a go

ghadi17:05:33

near the end there's a part about direct vs. indirect that is relevant

rschmukler17:05:46

Wonderful, thank you!

dangercoder17:05:43

What http-server do you guys recommend? I have a really hard time deciding which one to go with. Clojure JVM.

dangercoder17:05:03

Can someone point me in a direction on what I should think of when deciding between e.g Jetty, Http-kit, Aleph, Immutant..?

dangercoder17:05:23

Also having a look at clojure-nginx

donaldball17:05:55

Performance, features, stability, project longevity are all important factors to consider. Personally, when all else is equal, I’ll reach for jetty as it’s popular and performant.

seancorfield17:05:28

Start with the embedded Jetty, and if it doesn't satisfy your needs, try something else.

seancorfield17:05:38

At work, we use Jetty in production for most everything.

seancorfield17:05:52

(we used http-kit for a while but the integration with New Relic is lacking)

dangercoder17:05:06

Thanks for the answer, since I have some experience with Jetty i'll use it for my production app. Previously I had a toy-project using Sente (for websockets) and immutant. 🙂

dangercoder18:05:19

@U04V70XH6 are you using websockets together with jetty, and if so- which library? Or did you build one yourselves?

Griffin Lacek18:05:19

@UBN9SNVB4 One of my coworkers wrote this. https://github.com/RutledgePaulV/websocket-layer pretty lightweight, but we’ve used it in a few projects!

👍 4
seancorfield18:05:29

@UBN9SNVB4 We're not using WebSockets with Jetty. We're using Netty and http://Socket.IO in one app that is not Jetty-based tho'.

gklijs18:05:47

I really like https://github.com/nginx-clojure/nginx-clojure for 'including' Clojure to Nginx, but it has little recent activity.

Kari Marttila20:05:31

While reading Programming Clojure, 3rd ed. I realized in page 70 that you can use clj command line tool as a substitute to my standard file tools find & grep. E.g. in code examples directory start clj and then: ` (import java.io.File) (def my-file (File. ".")) (def my-files (file-seq my-file)) (def my-file-names (map #(.getName %) my-files)) (require '[clojure.string :as clj-str]) (filter #(clj-str/includes? % "clojure") my-file-names) ; => ("clojure.js" "clojure-deps.xml") Yihaa! 🙂 Of course that's a lot more writing than: find . | grep clojure ... but using clj you have all the power of Clojure to manipulate the files further. I wonder if clojurians are really using clj like that (as a command line tool to manipulate files).

eval-on-point20:05:38

I think you would be interested in the Clojure/north talk related to this

eval-on-point20:05:56

I think someone has made some sort of bash script analogue for Clojure

rakyi20:05:00

I haven’t used it, but there is also https://github.com/dundalek/closh

eval-on-point20:05:05

I agree though, it's awesome!

Kari Marttila20:05:22

Interesting, thanks for sharing! 🙂

lilactown20:05:24

specifically they were talking about lumo which is a CLI environment that executes ClojureScript

lambdalove 4
papachan21:05:51

I tried to get info about ,,, at end of functions but without any success

papachan21:05:36

(->> (range 10)
        (filter odd? ,,,))

eval-on-point21:05:16

In what context do you see that?

hiredman21:05:40

comas in clojure are whitespace

hiredman21:05:59

so that code is the same as (->> (range 10) (filter odd?))

hiredman21:05:11

the ,,, are used as a place holder

eval-on-point21:05:19

I've seen code like that in Alex's book when the rest of the code is unimportant for the example, for instance

Alex Miller (Clojure team)21:05:39

in this case, I don't think that's it

Alex Miller (Clojure team)21:05:20

some people call that the Fogus comma to mark where the values are threaded in examples

hiredman21:05:21

to illustrate how the ->> macro works

Dave Compton23:05:33

I'm trying to get started with clojurescript, so far unsuccessfully. Is there a good "how to" guide that someone could point me to? FWIW i'm on linux ubuntu 16.04 .

athomasoriginal23:05:40

Having trouble getting CLJS installed?

Dave Compton23:05:42

To tell the truth I'm not sure. Is that what I'm supposed to install to compile a clojurescript file?

Dave Compton23:05:07

I have clj but not cljs

Dave Compton00:05:16

yes, and I was able to get a repl going. But what I was hoping to do is just to compile a file to javascript/html and load the results in the browser.

Dave Compton00:05:50

Can that be done?

athomasoriginal00:05:45

Yup. The guide that mike showed will be able to do that. Here is another guide as well: https://betweentwoparens.com/deoploy-clojurescript-to-github-pages

athomasoriginal00:05:03

And if your interested in more examples of small web site projects to use as examples: https://github.com/tkjone/clojurescript-30

Dave Compton00:05:21

Thank you. Those pages look pretty helpful. I'll take a look .

Dave Compton00:05:14

You asked if I was having trouble getting CLJS installed. What is CLJS . I looked over the examples you showed me and they all seem to be using clj ( not cljs ) on the command line.

Dave Compton00:05:53

What is CLJS ? ( this time as a question ) 🙂

felipebarros00:05:19

It's a programming language and a Clojure program that reads this language and spits out JavaScript 🙂 That's why you use clj and give it the path to the program ClojureScript and to your ClojureScript source files.

athomasoriginal00:05:28

@UJSU0AR9U The idea is this: ClojureScript is a library that is run by Clojure. This is why you have to specify it as a dependency in the deps.edn file. So when you run clj -m cljs.main ... you are telling clojure to run the ClojureScript library. Then, whatever you feed cljs.main (e.g. a .cljs file) will be passed into the ClojureScript library and the compiled result, javascript, will be returned to you.

Dave Compton00:05:10

got it ( i think ). That's very helpful and informative.

felipebarros00:05:51

So, installing CLJS is just adding it to your deps.edn file and then running clj -m cljs.main .... It will download it for you the first time you run it.

Dave Compton00:05:14

I'll take some time to go through https://betweentwoparens.com/deoploy-clojurescript-to-github-pages . That looks like what I was looking for.

👍 8
Dave Compton00:05:06

With luck that will be enough to get me going. If not, I may be back with more questions later. Thanks again!

Dave Compton23:05:18

Or perhaps someone could just tell me how to get started.