Fork me on GitHub
#clojure
<
2018-04-19
>
emccue00:04:25

@qqq Depends on how much is shared IMO

emccue00:04:43

More shared -> cljc

benzap00:04:27

aren't there issues with having everything in the same folder when pulling macros into clojurescript?

emccue00:04:06

assuming there arent macros

emccue00:04:25

which I totally would have mentioned if you hadnt pointed it out why do you ask?

benzap00:04:54

i'm about to port a bunch of code to cljc, and i'm dreading it 🙂

benzap00:04:14

if I could keep it in the same folder, it would be ten times less hectic

benzap00:04:52

unfortunately, I have macros that are going to be used in clj and cljs, and I recall having issues in the past

mfikes00:04:17

The placement of files in folders won't hurt or help anything. (Source files are simply "on the classpath", and it doesn't really matter where they are.)

benzap00:04:30

I was going to have two differing classpaths between clj and cljs, where clj --> {src/clj, src/cljc] and cljs --> [src/cljs src/cljc]

benzap00:04:40

I could just be overthinking this, and preparing for nothing

emccue00:04:01

I know its not how the templates go, but I vote src/*

emccue00:04:25

theres probably alot of good reasons to have the sub directories

benzap00:04:41

ya, I prefer that as well. I suppose I would just be fighting with the extension types instead

emccue00:04:46

and I hope they are told to me

emccue00:04:53

but Im lazy as shit

benzap00:04:55

I'm going to test this out

benzap00:04:44

if you have foo.clj, foo.cljs, and foo.cljc, each with the same functions, which takes precedence in clojure and clojurescript when requiring?

mfikes00:04:07

The platform-specific files take precedence.

👍 4
andy.fingerhut01:04:24

I can't think of any reason to create all 3 of those files for the same namespace, since then the .cljc file would never be loaded.

benzap00:04:29

Thanks for the feed back @mfikes 🙂

mfikes00:04:47

> When finding a library in any Clojure dialect, the platform-specific resource will be found and loaded first (.clj or .cljs) before the portable file (.cljc) is found or loaded. This allows the opportunity to override a platform-agnostic file with a platform-specific implementation of a namespace. from https://dev.clojure.org/display/design/Reader+Conditionals

mfikes00:04:39

If you ever forget the details of the rule, just (require 'bogus) and the error message will tell you the order tried.

alice01:04:20

It was recently brought to my attention that JWT should not be in localstorage

alice01:04:33

How can I send the token to the browser in cookie form using Compojure instead?

qqq02:04:55

Is there a macro to make is better to write:

(let [x ...]
  (try
    (let [y ...]
      (try
        (let [z ...]
           (f x y z))
       (catch (release z))
    (catch (release y)))
  (catch (release x)))
this is almost like with-open, but I need to specify my own dtor function instead of just using .close

andy.fingerhut05:04:24

I am not aware of one, but it doesn't appear like it would be a difficult macro to write.

Alex Miller (Clojure team)02:04:13

there is a long outstanding request to make with-open work with a Closeable protocol

aleksandr03:04:58

How to rewrite that code to make It work?

(defn setupe-function
  ([db [slides sw-mod]] (assoc db :focus-slide 0
                                  :sw-mod sw-mod
                                  :slides-count (count slides)))
  ([db [slides sw-mod width]] (assoc db :focus-slide 0
                                        :sw-mod sw-mod
                                        :slides-count (count slides))))

aleksandr04:04:28

I did it so:

(fn [db [slides sw-mod & args]]
    (let [width (first args)]
      (-> (assoc db :focus-slide 0
                    :sw-mod sw-mod
                    :slides-count (count slides))
          (#(if (nil? width)
                %
                (assoc % :main-wrapper-width width))))))
but may be somebody know a more recommended way?

seancorfield04:04:59

@al.vyguzov You can simplify that with cond->

seancorfield04:04:28

(cond-> (assoc db ...)
  width (assoc :main-wrapper-width width)

seancorfield04:04:23

But depending on how you're using that hash map, just associng in :main-wrapper-width regardless is probably going to work. After all (:a {:a nil}) and (:a {}) are both nil.

seancorfield04:04:54

@al.vyguzov You can also destructure in the argument list to avoid the let:

(fn [db [slides sw-mod & [width]]]

aleksandr04:04:47

@seancorfield I didn`t understand your second message completely, but your suggested code looks great

seancorfield04:04:36

(defn setup-function
  [db [slides sw-mod & [width]]]
  (assoc db :focus-slide 0
            :sw-mod sw-mod
            :slides-count (count slides)
            :main-wrapper-width width))
that will almost certainly do what you need.

seancorfield04:04:22

(depending on how you use :main-wrapper-width elsewhere in your code -- but idiomatic Clojure would nil-pun on it)

Fereidoon12:04:40

Pressing c-h in Company completions says no docs are available, while using cider-doc works. Any ideas why?

mping12:04:51

Is it possible to have an anonymous function with multiple arity?

Fereidoon12:04:42

I think so. Expanding a defn just results in def-ing an fn form.

mping12:04:36

so the syntax should be something like (fn ([a] a) ([a b] (println a b)))

mping12:04:37

great tks

😃 4
Fereidoon12:04:42

I think so. Expanding a defn just results in def-ing an fn form.

Sallide14:04:51

Hi all, I don't know much about the theory, but was wondering why hot reload is so easy in clojure (e.g. with lein repl) and difficult in most other mainstream languages? Besides lisps I haven't seen any that support the same kind of easy hot loading out of the box

👍 4
borkdude15:04:10

@squarenegative It’s mostly because the language is set up to be reloadable. Clojure has a var indirection for every function or top level variable definition which you can mutate, so you can redefine just one function while keeping the rest of your environment the same and carry on

👍 4
Sallide15:04:49

gotcha, thank you

noisesmith16:04:39

following up on that - there's indirection when the function name is in the code, but for a long running function that took another function as an argument (eg. you passed a handler function to an http server process startup) you can get the benefits of var indirection by hand - by passing #'handler instead of handler

👍 4
noisesmith16:04:55

but otherwise you don't get the reloading (without restarting the process that took that arg)

borkdude17:04:38

right, and there’s also direct linking which takes away the indirection at compile time

Alex Miller (Clojure team)17:04:49

direct linking replaces var calls being compiled with direct calls

Alex Miller (Clojure team)17:04:29

the var path however still exists and NEW code can still invoke via the vars

Alex Miller (Clojure team)17:04:00

for example, the Clojure core namespaces are direct linked so calls from say clojure.set into clojure.core are compiled and direct linked. But if your own code makes calls into clojure.core, those calls are not direct linked (unless you compile your code with direct linking on)

arrdem17:04:27

Is there a good remote workers / remote rpc package floating around?

arrdem17:04:48

“clojure remote workers” on google is rather a lot of consultancies 😛

emccue18:04:06

Not to preempt a possibly better one in clojure, but have you tried a java library?

emccue18:04:31

That should bubble to google faster

emccue18:04:41

and then you can search X lib but for clojure

emccue18:04:06

or just use the java one if it works

sashton19:04:24

given the following function:

(defn my-inc [x]
  (let [inner-inc (fn [] (inc x))]
    (inner-inc x)))
Is it true that the inner-inc function is compiled once and attached to the Java class for the namespace, and a new fn isn’t “created” for every invocation of my-inc? Or, to the root of the question, is there any difference (in object allocation) between this example and the case where inner-inc is defined via defn? I thought I came across that in a conversation once, but I can’t find the answer in the codebase.

hiredman19:04:48

the exact nature of how it is compiled and the exact set of classes and how they interact sort of depends, there is not always a class for a namespace only when you aot compile, but yes each fn, def'ed or not is compiled to a single class, of which an instance is created as needed

hiredman19:04:45

you can imagine the compiler turning the above in to something like

(deftype SomeFnType [x] 
  clojure.lang.IFn 
  (invoke [_] (inc x)))

 (def m-inc [x]
   (let [inner-inc (SomeFnType. x)]
     (inner-inc x))) 

john19:04:34

@arrdem what are you trying to accomplish? Often times, just pushing data between nodes is good enough, if you can get the right functionality deployed a priori

sophiago20:04:23

Is anyone familiar with @dnolen's defunct delimited continuations library: https://github.com/swannodette/delimc ? I like his approach using atoms to store continuations, but it's hard to reconcile with Scheme examples that often don't have a reset outside of every shift. For a really simple example, I'm trying to implement call/cc using this library and an implementation cwcc from R4RS Scheme (https://github.com/tonyg/kali-scheme/blob/master/scheme/misc/shift-reset.scm) and use it to run the yin-yang puzzle: https://gist.github.com/Sophia-Gold/435b984be3a2e4509deea6956fd04242

hiredman20:04:22

I am pretty sure shift/reset is strictly less powerful than call-with-cc, so you can't implement call-with-cc using shift/reset

sophiago20:04:18

@hiredman you definitely can, but I'm not certain it's possible with this implementation

hiredman20:04:10

the scheme code you linked to seems to be going the other way, implementing shift/reset on top of cc

hiredman20:04:48

call-with-cc

sophiago20:04:54

The definition of cwcc in the Scheme code I linked to uses only shift.

sophiago20:04:37

In fact, I think that statement is exactly the other way around: you can always implement undelimited continuations with delimited ones. My guess is this library prohibits that because you'd likely end up just clashing with the JVM/OS/REPL (hence why "`call/cc` considered harmful").

hiredman20:04:48

we must be talking about different links

sophiago20:04:38

Oh, right. Line 121, not 150

hiredman20:04:29

right, so that is call/cc in the context of some outer reset, so it is still a delimited continuation

sophiago20:04:03

Yeah, the outer reset part is what I suspect to be incompatible with David's implementation.

hiredman20:04:33

because clojure doesn't have a native call-with-cc, you have to do code transformations to get any kind of call-with-cc, and generally that is done with macros, and macros are limited to operating on their literal arguments

hiredman20:04:05

they can't descend in to functions called and recompile them in to some cps style to make call-with-cc possible

hiredman20:04:26

this is very similar to what core.async's go macro does, it effectively captures the current continuation and attaches it as a callback to a channel

hiredman20:04:08

but because it is a macro, and can't do whole program transformation, it is limited in scope

sophiago20:04:48

I understand how CPS transforms work. core.async actually uses SSA form for go, though, although they're equivalent per Andrew Appel. Anyway, that doesn't preclude implementing cwcc.

hiredman20:04:56

I've been playing around lately with using the continuation monad as an alternative to having to do the kind of program transformations that core.async does, and it seems to work well

hiredman20:04:42

(work well in terms of working, being flexible, and avoiding having write a compiler in a macro, the performance is likely terrible)

sophiago20:04:51

Do you mean the one from algo.monad? Tbh I wasn't too impressed with that implementation from what I remember (also working in Haskell professionally, I don't see much purpose for monads in a dynamically typed language) but perhaps I should revisit it in this context. One thing I remember explicitly is it not using atoms, which is how I was doing ad hoc CPS in a Clojure project at the time.

hiredman20:04:17

no, I have my own implementation (I use the monad to also pass around a bundle of nio selector stuff too), I haven't looked at what is in algo.monad

sophiago20:04:00

Oh, cool. I've actually already implemented everything in that snippet I posted using cps; that was really easy.

sophiago21:04:00

The other person who contributed to David's delimc library wrote a CPS transform macro for Clojure around that time using tools.analyzer, but it's even messier than the parse-to-state-machine stuff from core.async. I may try dropping him a line to ask about the version with atoms.

hiredman21:04:01

the cwcc in your clojure likely doesn't work because you took the scheme definition and wrapped it in a call to reset, where the assumption on the scheme side is that you wrap the code in which you call cwcc with the reset

sophiago21:04:13

I did actually try that too. It didn't work either and made even less sense to me 😕

sophiago21:04:29

There's a Reddit thread on cwcc (only pertaining to Scheme) and it mentions exactly what you're saying now plus references the exact behavior I see from the first broken version I shared.

hiredman21:04:59

it likely doesn't work then because of the lack of inter-procedural analysis

sophiago21:04:31

Possibly something to that effect

sophiago21:04:52

"There is no implied reset here. The implied reset is around the entire program (in a REPL there is often another one around the current evaluation)."

hiredman21:04:39

clojure's calling convention is jvm method calls, and jvm method calls don't provide for continuations, so the only way to get them is to change the calling convention (continuation monad) or program analysis and transformation (delimc, the go macro, the cps compiler thing someone wrote)

hiredman21:04:20

the better way to put that would be: clojure's stack is the jvm's stack

hiredman21:04:03

https://github.com/positronic-solutions/pulley.cps/blob/master/src/com/positronic_solutions/pulley/cps.clj might be interesting, similar but more re-usable than core.async's machinery

👍 4
sophiago21:04:48

Cool, thank you. It's nice to see an actual documented production-ready CPS transform. defmacros do definitely have a legibility problem when they reach this level of complexity so there's just a limit to the extent I want to decipher them when it would take less time to just rewrite them myself. The Racket folks definitely do have a one-up on that.

sophiago21:04:04

I may just table the serialization idea and use this library for a blog post I've been meaning to write. It makes what I wanted to demonstrate almost trivial code-wise.

dpsutton21:04:37

i've said this before but i would love to read some stuff by you

sophiago21:04:04

You said that about this same thing I'm mentioning now a week later without having done 😛

sophiago21:04:28

The trick was I gave a really bad lightning talk first so it was easy to write up afterwards, especially with the conviction that people might actually care if I put it in written form 🙂

the2bears21:04:22

Thanks for such an interesting exchange @sophiago and @hiredman!

☺️ 4