This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-06-20
Channels
- # announcements (1)
- # beginners (164)
- # calva (70)
- # cider (26)
- # cljs-dev (6)
- # cljsrn (1)
- # clojars (3)
- # clojure (123)
- # clojure-berlin (1)
- # clojure-dev (5)
- # clojure-ecuador (9)
- # clojure-europe (2)
- # clojure-italy (14)
- # clojure-nl (21)
- # clojure-nlp (5)
- # clojure-portugal (1)
- # clojure-spain (3)
- # clojure-spec (26)
- # clojure-uk (47)
- # clojurescript (17)
- # clr (1)
- # code-reviews (7)
- # core-async (5)
- # cursive (8)
- # data-science (2)
- # datomic (28)
- # emacs (23)
- # events (1)
- # fulcro (43)
- # graalvm (6)
- # graphql (8)
- # immutant (5)
- # jackdaw (17)
- # jobs (1)
- # jobs-discuss (20)
- # joker (3)
- # leiningen (8)
- # luminus (12)
- # off-topic (61)
- # overtone (5)
- # pathom (2)
- # quil (1)
- # re-frame (15)
- # reagent (2)
- # reitit (23)
- # remote-jobs (1)
- # schema (1)
- # shadow-cljs (26)
- # tools-deps (56)
- # vim (4)
Hello @U0DHQ67U5 I think project.clj stay C:\Users\{username}\.lein
or C:\Documents and Settings\{username}\.lein
, sorry for my horrible english
General rules on using extend-type
vs extend-protocol
? I am anticipating extending several types and that the bodies of the extensions will be pretty meaty. Should I use an extend-protocol
and call separate functions in each implementation body or just use several extend-types
? Sorry if my wording isn't clear
@mitchell_clojure Hard to say without more details... what problem are you trying to solve here?
Hey Sean, so I am extending a POI class (XMLSlideShow) to implement datafiable
. However, since it is an object that is composed of many other objects (and those are composed of other objects in turn), I am finding that I will need to implement the protocol for a large number of class
extend-protocol
expands into calls to extend-type
so it's mostly going to be about readability I guess...
yeah, working through it myself, it seems like there are classes that it is natural to group together, so I am putting those in extend-protocol blocks
OK, you have just one protocol and lots of classes to extend it to to... yes?
extend-type
sounds slightly more appropriate here then I think.
(because you have large implementations)
If your implementations are small, extend-protocol
would make more sense (one protocol, lots of types).
extend-type
is normally one type, several protocols.
yeah, it be kind of redundant to use extend-protocol
just to call a functions that have the implementation elsewhere, when I can just group in extend-type
blocks
Will this code be published as open source? I'd love to see it, when it's done.
And you'll be implementing Navigable
too for some things?
yeah, definitely. It's my first project and I want to make sure I am hitting all of the right marks (test coverage, thorough documentation, extendability, idiomatic design) and I am working on this after my day job so it might be a bit before we have something working
but the promise once it is on github will be to stay current with the development of POI on the java side, as their API isn't stable yet
As for Navigable
, that will probably be a consideration further down the line. First objective is to represent slideshows as data, as I have a use-case at my current job for slideshow generation from a template
I'll let you know once significant progress is made. Thanks for all the help so far! You are the man!
@mitchell_clojure Sounds like it'll work great with REBL 🙂
(speaking of which, I spent a bit of time yesterday and today getting REBL and Liquid to play nice together -- Liquid is a very interesting Clojure project: an in-process, vim-like editor that runs inside your project... because I love REBL so much!)
(cond-> coll test (conj x))
We're here to help :rolling_on_the_floor_laughing:
hey Folks, due to my poor english, I’m facing some difficulties to get right the meaning of this paragraph:
Note that recur is the only non-stack-consuming looping construct in Clojure. There is no tail-call optimization and the use of self-calls for looping of unknown bounds is discouraged. recur is functional and its use in tail-position is verified by the compiler.
`
What does this mean exactly? recur is the only non-stack-consuming looping construct in Clojure. There is no tail-call optimization.
?
Which loop constructs in clojure are stack-consuming
? stack-consuming
is that a bad or good thing?
references: https://clojure.org/reference/special_forms#recur@quieterkali a simple recursive call of the function would be stack-consuming.
Recursion can be used to do loops, and recursion in Clojure causes the stack to grow
If you use recursion in a way where processing each element of a sequence does 1 recursive call deeper, and call that function with a sequence containing 100,000 elements, then the stack will grow by 100,000 stack frames before you are finished, or more likely with the default settings for maximum stack depth in most JVMs, you will get an exception.
Here is a simple example of writing a recursive function like that in Clojure. It only adds up a collection of numbers, but the point is that it does so with a recursive function call on the rest of the sequence:
user=> (defn total [coll]
(if (seq coll)
(+ (first coll) (total (rest coll)))
0))
#'user/total
user=> (total [1 2 3 4])
10
user=> (total (range 1000))
499500
user=> (total (range 10000))
Execution error (StackOverflowError) at user/total (REPL:3).
null
Thank you very much for the example and explanation guys.
So the only way to avoid stack consuming in clojure is by using recur
function. Am I right? and All others recursive approach are stack-consuming
.
@quieterkali Yes, except for Trampoline
There is another approach that is not often used, called a trampoline
Most built-in Clojure sequence processing functions are implemented internally in a way that is not stack-consuming, so loop/recur is not used as often as you might guess, either. But more than trampolines.
There simply aren't as many use cases that tend to come up where a trampoline is useful.
trampoline is more challenging to use, and has some quirks you need to be aware off, and people rarely have use cases that the simpler recur can't cover
Its even hard for me to come up with an example right now which wouldn't work with recur, and you'd need trampoline for
In 10 years of professional Clojure use, I’ve used trampoline exactly once.
mutually recursive functions need trampolining instead of loop/recur. That is where a calls b calls a calls b and so on... can implement finite state machines with this approach.
Is there a way to require npm module in .clj
file to define macros using it, So, I can require those macros and use them in .cljs
file.
I want to make a wrapper for antd-mobile
similar to antizer
.
I'm using shadow-cljs
as build tool.
It is giving errors. What am I missing here?
Antizer uses (def antd-module 'js/antd)
at the top of antizer/macros.clj
namespace and uses antd-module
variable everywhere, in the places where I'm using antd-mobile
.
You can’t use the string require in a .clj file. And you don’t actually need to, since the macro will generate just code which is symbols etc. So you just need to make sure you use the correct symbols in your macro, and it is the job of the consumer to make sure that antd-mobile
is required.
An example use of the macro and how you expect to use it would be helpful, it’s hard reading macro code as it is, and macro code that goes from CLJ->CLJS is a little bit harder 🙂
These macros would be required by another namespace antmob/reagent.cljs
and called like (export-reagent-components)
.
best practice with cljs and macros now is not to use a macros namespace, but put them in a standard .clj namespace. Then (:require-macros ...) that namespace in the same namespace as a .cljs file. Once you do this you can just import the .cljs namespace with (:require ...) and you will get the macro to use, no need to individually require-macros
if you don't do this, and your expanded macros contains cljs side calls to cljs function in the same namespace, then the user of you macro will also have to know to :require those other namespaces for the expanded macro call to work
I understand what you said above. But not this one.
say i have a seperate macros.clj file that contains a macro (defmacro foo [&args] `(bar ~args))
about something undefined. I forget the error. But it's a little obtuse in the reporting wording. anyway....
if your macro expands to say (some.other.namespace/somefunc ...) then the client will also need to remember to (:require ...) that namespace
there will be all these "a list of namespaces I need to require to get the macros functioning fully"
by :require-macro'ing the clj namespace from the same cljs namespace, you get all those cljs requires specified bought in by the client when they :require your new namespace
so for example in your code, the client using the export-reagent-components macro needs to also :require reagent.core and (possibly) goog.object namespaces. Or the macro won't work. They might already have them :required, so not notice it. But they need to know about it or the error will be utterly confusing. goog.object? I didn't use any goog.object? where is this coming from? (its coming from inside the expanded macro)
and in the component.cljs file, you require-macros these macros. and you also (:require [goog.object] [reagent.core])
then anyone wanting to use the macros or any func inside components.cljs, just (:require [antmob.component :refer [export-reagent-components some-other-cljs-func]])
I understand most of what you are saying. I think you are talking about Two File ClojureScript Namespace Pattern: https://blog.fikesfarm.com/posts/2018-08-12-two-file-clojurescript-namespace-pattern.html
@UKH2HDSQH Thanks. I did arranged namespaces as you said and it works.
if they are in the same namespace, you can define these dependedncies in the .cljs file and it will all just work
heres an example from some code of mine: https://github.com/infinitelives/infinitelives.pixi/blob/master/src/cljs/infinitelives/pixi/canvas.cljs#L1-L18
when you (:require [infinitelives.pixi.canvas :as c])
in a cljs file, you will automatically get the macros that are in the infinitelives.pixi.canvas
clj file here: https://github.com/infinitelives/infinitelives.pixi/blob/master/src/clj/infinitelives/pixi/canvas.clj
the code these macros expand to use functions from namespaces that are imported at the top of the .cljs file without needing to be explicitly imported by the client
example expanded client side call https://github.com/infinitelives/infinitelives.pixi/blob/master/src/clj/infinitelives/pixi/canvas.clj#L62
why doesnt this work? https://repl.it/repls/BeneficialRottenModulus
@jason821 do
is a special form that you can't take the value of. https://clojure.org/reference/special_forms#do. This might be close to what you're trying to achieve:
(def mylist `((println 123) (println 456) (println 789)))
(eval mylist)
I am not sure what code you are responding to, but the documentation about do
that you link to explicitly says: "and returns the value of the last". A do
form does return a value -- but only the value of the last form inside of it. The return value of all except the last form inside of the do
are discarded, that is true.
Oh, I see the code example now. Yes, apply
cannot be used with macros, nor with special forms, only functions.
i am only trying to return the last item in the list, exactly how do works
and eval seems to return all the values in the list and return the list
This is probbly closer to what I’m trying to do:
(def mylist ['(str 123) '(str 456) '(str 789)])
(eval mylist)
I think this is what I’m looking for (last (eval mylist))
I do not know what the purpose of the code you are working on is, but just a note that if the data you are passing to eval can be provided from an untrusted source into a system, you are pretty open to lots of attacks.
If all of the eval'd stuff you trust not to attack you, then no worries.
What are you trying to do? I had assumed that you had a sequence of expressions that you wanted to execute, perhaps I missed the mark? It's pretty rare that you need to use eval
.
`;; What I would like to do:
; Take javascript as input and return javascript
(defn parseJS [name args & body]
; Define a new function
(def name
; Convert arguments to clojure
(let [d (js->clj args)
; Execute body using the new arugments
; This is the part I don't understand
result (last (exec body))]
; Convert back to javascript
(clj->js result))))
; Defines a function that takes javascript as input and returns javascript
(parseJS some-function [args] body)
; Calling the function that takes javascript as input and returns javascript
(some-function data)
im wondering if i need to create a macro to do this, but even so, i tried that and im not sure what im doing.
This is my current working solution:
; Converts data to clojurescript
; Sends the clojure data to the callback
; Converts data back to javascript
(defn parseJS [data callback]
(let [d (js->clj data)
newData (callback d)]
(clj->js newData)))
; Take javascript as input and return javascript
(defn ^:export some-function [& args]
(parseJS args
(fn [args]
; This is where the actual logic goes
args)))
I think I found a solution. I am just going to create wrappers for my functions that work with javascript
(defn do-something-with-cljs [data]
; This is where the actual logic goes
data)
(defn parseJS [data callback]
(let [d (js->clj data)
newData (callback d)]
(clj->js newData)))
; Take javascript as input and return javascript
(defn ^:export js-wrapper [js]
(parseJS js do-something-with-cljs))
I sometimes use private functions in namespaces for obvious reasons. Is there a way to easily load a file into the repl with the private functions being accessible?
You can use the function var to access the private functions: (#'other-namespace/private-fn arg1 arg2)
Cheers!
How is situation of Clojure/ClojureScript development on windows and specifically windows 10? I've previously worked with Ubuntu.
@ahmed1hsn See here: https://github.com/clojure/tools.deps.alpha/wiki/clj-on-Windows
I haven't seen a lot of discussion on it so far, but I believe there are people using it. Another option I have heard of is installing Clojure through the Linux Subsystem for Windows, which I believe others have had success with
Thanks. That helps.
I have a desktop box at work with Windows 10 installed on it. I usually stick with my linux laptop but for when I need to use the desktop, I use WSL with Ubuntu to get my work done. It's much better than using windows directly
Thanks @U0DHQ67U5 How is experience when using WSL as compared with original Ubuntu?
I'll always prefer to use a full linux system of WSL. With WSL, I wind up in a funky filesystem setup in order to keep my C: drive mounted to the WSL disk. I also find myself running into issues of productivity since I'm always stuck in tmux. I start to miss my window manager and better terminals like urxvt
@U0DHQ67U5 What is full Linux system of WSL?
How to run full Linux system over WSL?
By full linux system I mean installing Linux on your computer or running it in a VM. Windows, as an OS, doesn't lend itself well to my development workflow. I'm very terminal based and Windows doesn't provide a good terminal system by default, has no good package managers based in a terminal, and is generally difficult to maneuver. Pile on top of that the differences between running the app on windows vs. linux, and I'm completely turned off to the idea of working on it.
However, the Windows Subsystem for Linux can make it much less painful. You can install a 'mini' Linux system on Windows 10 now that will provide you with good enough terminal support and whatnot. It's not quite pretty to look at so I also use ConEmu (a terminal emulator for windows) instead of the built in terminal for WSL to get everything looking correct. I still run into a fair bit of lag though, especially if I have to remotely control my desktop.
Thanks. I was using Ubuntu on my previous laptop. Now I've got HP Envy with Windows 10. So, I'm weighing options to do Clojure (Script) development.
I'm going to speak in the hypothetical 'you' here. If you're comfortable with using Ubuntu, I'd always recommend switching to Ubuntu (or whatever Linux you'd prefer). You don't have to completely wipe the disk, you can always do a dual boot. Windows and Ubuntu is a very common dual boot system. If you're not super comfortable, I usually recommend trying Ubuntu via VirtualBox. No worries about deleting an OS or losing files and if you blow up your Linux system, you just exit out of VirtualBox, delete the bad virutal disk, and then try again. Now speaking directly to you. Clojure has infinitely better support when you're working on Mac or Linux. The tooling, help provided, documentation, etc... It all favors Mac and Linux. Food for thought!
Thanks. That makes sense. Dual boot seems better option, so I can set up a permanent working environment. As running VirtalBox would put extra load on laptop.
I've used Ubuntu 16.04, Now I think it's better to move to 18.04.
If you're going to use Ubuntu, in my opinion, it's always best to stick with the latest long term support (LTS) version, so yeah 18.04 is definitely the move. If your computer is struggling to run the OS because of low system resources (ram, cpu), then Xubuntu is a good choice too. It's the same Ubuntu system but with a much lighter desktop environment called XFCE. It's very quick on older and low resource computers
Is there a nice alternative to update
which also receives the respective key as argument? Right now I have to fiddle around with reduce
and have some redundancies in my code that I'd like to see get wiped out 😏
there isn't but it's straightfoward to make one @linkerfelix
Straight forward in the sense that you can use update
or would you rely on reduce
?
Ah, well. Yeah, it's plain simple. I always forget that update
is not a map-type equivalent of map
Hello guys, I'm trying use coverage at clojure project but
I can not do it.
I'm using that lib (
and this is the exception: (Caused by: java.lang.AssertionError: Assert failed: Cannot expand '[#Interceptor{:name } #Interceptor{:name :pedestal-api.content-negotiation/serialise-response})
Can someone help me?
@U050ECB92 I'm use command line to execute coverage: lein cloverage
Exception in thread "main" java.lang.AssertionError: Assert failed: Cannot expand '[#Interceptor{:name } #Interceptor{:name :pedestal-api.content-negotiation/serialise-response} #Interceptor{:name :io.pedestal.http.body-params/body-params} #Interceptor{:name :pedestal-api.request-params/common-body} {:name :route-swagger.interceptor/coerce-request, :enter #object[route_swagger.interceptor$coerce_request$fn__22876 0x5be38ef2 "route_swagger.interceptor$coerce_request$fn__22876@5be38ef2"]} {:name :route-swagger.interceptor/validate-response, :leave #object[route_swagger.interceptor$validate_response$fn__22882 0x7a3655b4 "route_swagger.interceptor$validate_response$fn__22882@7a3655b4"]}]' as a route. Expected a verb map or path string, but found a class clojure.lang.PersistentVector instead false, compiling:(/tmp/form-init5604330725587642492.clj:1:73) at clojure.lang.Compiler.load(Compiler.java:7526) at clojure.lang.Compiler.loadFile(Compiler.java:7452) at clojure.main$load_script.invokeStatic(main.clj:278) at clojure.main$init_opt.invokeStatic(main.clj:280) at clojure.main$init_opt.invoke(main.clj:280) at clojure.main$initialize.invokeStatic(main.clj:311) at clojure.main$null_opt.invokeStatic(main.clj:345) at clojure.main$null_opt.invoke(main.clj:342) at clojure.main$main.invokeStatic(main.clj:424) at clojure.main$main.doInvoke(main.clj:387) at clojure.lang.RestFn.applyTo(RestFn.java:137) at clojure.lang.Var.applyTo(Var.java:702) at clojure.main.main(main.java:37) This is all exception:
Caused by: java.lang.AssertionError: Assert failed: Cannot expand '[#Interceptor{:name } #Interceptor{:name :pedestal-api.content-negotiation/serialise-response} #Interceptor{:name :io.pedestal.http.body-params/body-params} #Interceptor{:name :pedestal-api.request-params/common-body} {:name :route-swagger.interceptor/coerce-request, :enter #object[route_swagger.interceptor$coerce_request$fn__22876 0x5be38ef2 "route_swagger.interceptor$coerce_request$fn__22876@5be38ef2"]} {:name :route-swagger.interceptor/validate-response, :leave #object[route_swagger.interceptor$validate_response$fn__22882 0x7a3655b4 "route_swagger.interceptor$validate_response$fn__22882@7a3655b4"]}]' as a route. Expected a verb map or path string, but found a class clojure.lang.PersistentVector instead
false
seems like you have something broken there > expected a verb map or path string, but found a class clojure.lang.PersistentVector instead
I'm using same as this example: https://github.com/oliyh/pedestal-api
@linux.soares use *e
to print the entire stacktrace. I suspect the problem is not in cloverage at all
(Throwable->map *e)
if you're in some environment that prints exceptions in a weird way
if you're running from the command line and don't have a full stacktrace available, that's a naughty tool.
You might want to figure out how to call cloverage directly from a REPL if the stacktrace is absent or not useful
Hi all!
I’m trying to implement this function, print-later
that will wait for 5 seconds, then print something, like “abc”. And more importantly, if I call this function again, it will cancel the previous invocations, and so only prints once.
For example,
(print-later) (print-later) ;prints "abc" only once.
-----------------
(print-later)
(Thread/sleep 6000)
(print-later)
; this should print "abc" twice.
Now most importantly, is there a way to do this without introducing a global state?I mean, you can quibble with definitions of global, but print-later is going to need some shared way to interact regardless of the scope it is in
This is probably in the area of quibbling about whether state is global or not, but you could have a let-bound symbol whose value is a stateful thing like an atom, and then defn a function inside of that let, which makes the stateful thing only accessible by calling that function. Example:
user=> (let [x (atom nil)]
(defn read-x-return-old-and-new [val]
(swap-vals! x (constantly val))))
#'user/read-x-return-old-and-new
user=> (read-x-return-old-and-new 8)
[nil 8]
user=> (read-x-return-old-and-new 20)
[8 20]
user=> (read-x-return-old-and-new -5)
[20 -5]
Me, too, until I looked up the atoms section in the cheat sheet.
I was pretty sure there was something that let you get the original value
Finally touching it up for Clojure 1.10, a few months later
This is pretty good for my usecase!
Although I wonder if it’s bad practice to have defn
in a let
.
Depends upon what you mean by bad practice. I have seen it done, occasionally, when it is helpful. I would say it is no better or worse than making a function stateful, i.e. the same warnings and cautions apply.
I'd say it's more bad than good. :) Just pull out the atom to a private var.
For better debuggability of the resulting system, I guess?
yeah, data hiding is arguably an antipattern when most values are immutable anyway - misusing your atom if you've marked it private to the namespace is already hostile, and by closing over it you lose the access for debugging
someone wrote a good article on this about four years back, maybe five. Maybe it was cgrand or stuarthalloway?
avoiding top level effects seems like a good enough reason
This is pretty good for my usecase!
Although I wonder if it’s bad practice to have defn
in a let
.
overriding static variables is not a thing