This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-05-13
Channels
- # beginners (202)
- # boot (7)
- # cider (14)
- # clara (2)
- # cljs-dev (7)
- # clojure (56)
- # clojure-italy (9)
- # clojure-spec (6)
- # clojure-uk (12)
- # clojurescript (40)
- # core-async (3)
- # datomic (6)
- # duct (1)
- # editors (10)
- # emacs (5)
- # fulcro (24)
- # off-topic (16)
- # onyx (4)
- # pedestal (1)
- # planck (8)
- # portkey (2)
- # re-frame (31)
- # reagent (23)
- # tools-deps (8)
- # vim (3)
Hey there, I'm learning clojure right now and I'm trying to figure out why the following doesn't work as expected:
=> (def addem #(apply + %&))
=> addem 1 2 3
I would have thought it would add the numbers but it prints
1
2
3
Heya clojurians, I'd like to take a structure like [1 3 2 1 1 3 1 1 1 2]
, and return a nested structure with all runs of equal data in their own vector, like [[1] [3] [2] [1 1] [3] [1 1 1] [2]
. I'm struggling with the best way to do this. Ideas?
A lot of the inbuilt functions like split-by
or take-while
, which is what I'd think of using for this, won't work because I need to compare elements with previous elements. Which implies using reduce
, but I was hoping their would be a cleaner way, especially since updating nested data is kind of confusing.
That produces a sequence of sequences, so you'd need to (mapv vec ...)
if you really want a vector of vectors...
Oh, woah, nice
yeah I'm not particular about the output in this case
(this is just one of those cases where years of exposure to Clojure gradually teaches you more and more of the core functions 🙂 I'm still learning after eight years!)
🙂 totally
Glad I asked here for help, wouldn't have thought of this.
Reminds me that someone created some code where you could give example inputs and outputs that you want, and if there was a known existing function that could do it, it would tell you. Anyone remember where to find that?
Found what I remembered, but haven't tried it out yet to see if it would answer the question above: https://github.com/Raynes/findfn
Is anybody familiar with 'async/map'? Any resources would be really helpful
Not sure what you're talking about, do you have a link with more context?
Are there any libraries that implement common spec’s? e.g. email telephone postcode?
perhaps you are looking for this: https://github.com/ioRekz/spectator ?
How do people feel about the use of :as
vs :refer
in a require expression these days?
in our team we tend to :as
everything, as it makes it easy to know where things are from, visually
But are there any performance differences?
Does :as
load the entire namespace or does it simply create an alias?
it's just an alias, the namespace is loaded by requiring it
We're talking about the require expression
the fact that you add :as
or :refer
has no performance impact, the namespace has already been required
Say (require clojure.string :as str)
. Is the entire clojure.string namespace loaded or only the functions you use
Well no
:refer
explicitly only loads the supplied vars
those are just aliases, the vars are available anyway
Ok you aren't following me then
there is no way to partially load an ns
there's no such thing
thanks
I beg to differ
in clojure, there's no such thing
:refer [foo bar]
is much different than :refer :all
it just changes aliases, it doesn't change what's loaded and accessible
Uh...
you don't need refer or as
I'm calling bs on this
it's just extremely bad style not to use them
you are wrong
:refer [foo]
and then try to use bar
from that namespace
you just need to use the full ns prefix
this is only about names
(don't do it that way, it's bad style, but there's no way to "partially load" an ns, it's all or nothing)
That doesn't seem right at all based on the philosophy of Clojure
That's like doing import * from foo
in Java
I can literally show you things working that way in a repl
yes, it's a bad idea don't do it
what I'm saying is partially loading an ns doesn't exist, it's not a clojure feature
What you're saying would be the same thing
+user=> (require 'clojure.set)
nil
+user=> (clojure.set/map-invert {:a 0})
you can do this with any ns and function - just don't do it
:as and :refer are tools to make your ns cleaner
That's not what I'm talking about
what do you mean by "partially load" then?
:as creates aliases with a prefix, :refer creates aliases to specific symbols, neither changes what's loaded
So if we are in agreement that import * from foo
is bad practice, how is Clojure loading the entire namespace good practice? It's the same thing
@whoneedszzz in java you can load classes separately, in clojure you can't load parts of a namespace separately
like literally, in java, you only load the classes in a package that have been referenced
if you don't mean loading, use a different word
if you just mean creating aliases within a different scope, that's different - the whole thing is loaded, it's just that only certain aliases are made
it might be a bad choice? I can't think of any language that loads up only parts of a file - in java each class is one file so that's the modularity of loading
And it would be impossible to determine statically which parts of a namespace would or could be used
right, your ns file would need to have some kind of database format maybe, with metadata about granular dependencies? not sure how it would work
I guess I'm just not understanding how Clojure can load the entire namespace and not have the same problems Java has with import * from foo
because it doesn't change scope
even in java, you can use all of foo just by using the full name of each class
because we avoid refer (or only use it for specific symbols) and we use :as to qualify the names, we avoid implicit scoping - but that's not a loading issue, that's a naming and scope issue
Ok let's try a different approach
Why is import * from foo
bad?
because I see symbols and I don't know where they came from
:as avoids this issue by applying a prefix
:refer mititages it slightly by only bringing in a small list of symbols and not everything
"And not everything"
How is that not partial loading?
because that's not what load means
loading is taking a resource outside the program and turning it into part of your program
that's partial import, import implicitly loads but isn't identical to loading
these names mean very specific things
Ok so if you corrected me on the word from the start we would be on the same page
I did, multiple times
The word I meant was "import"
Does using :as
in a require statement import everything in that namespace?
it aliases everything with a prefix into the current ns
That does not answer my question
import is for classes, it has nothing to do with other namespaces, it creates an alias to a class in the current ns
alias is for namespaces, it creates a prefixed alias for each public var in the target into the current ns, and yes, it does this for all of them
in practice, refer is worse than as in terms of explicitly knowing where things come from, because as makes it clear via the prefix that something is external
So if you are only using 1-2 vars in a namespace that has 20 vars why would you want to use :as
then
but, sometimes refer is worth it because you use something enough that the prefix is too noisey
in practice I do, yes
that's normal in the clojure community
to know where it's coming from. :refer
hides this info
exactly
But as you said that't not all that is happening
:refer
is only referencing what is supplied to it
Not the entire namespace
but it ambiguates all its args
when I'm down further in the ns, I need to remember the names of all referred items and where they came form
If you use sensible naming conventions that shouldn't be a problem
as makes the provenance explicit, it's never ambiguous
if you named everything with 60-char names, sure
Uh, no
update
vs updateStatusBar
That's poor naming
That makes it necessary to use the namespace
then if you are right, clojure uses poor naming. It works out for me. Best of luck!
How so?
no, status-bar isn't the full namespace, that's a shitty namespace name, it's the alias
why would you prefix all vars inside a namespace with the name of that namespace?
I wouldn't and didn't suggest that
@whoneedszzz what do you mean by, "use the namespace"?
inside the com.whatever.app.status-bar
namespace, of course everything is related to status-bar
, so you can have an update
fn there, and refer to it as status-bar/update
, with :as
(:require [foo.bar.status-bar :refer [update-status-bar]])
means I can now do (update-status-bar ...)
and know exactly where it came from and what it does
so you suggest suffixing every fn in status-bar
with status-bar
You keep putting words in my mouth
Why would you want to repeat "status-bar" in the name? It's already there in the namespace?
Is it the only component of this hypothetical app that has an update function?
of course, that's why you use :as
So what you guys are talking about means that you must use :as
because they are both called update
Generally I don't do my naming with accommodating people who use :refer too much as a concern
What is "too much"?
if a var isn't used in at least half the functions in my ns, I don't refer it
From what has been said here it is purely a stylistic choice
even then, I only refer if the refer makes the code significantly easier to read
Stylistically, it's probably best to only use :refer for things that are repeatedly used in a ns, and I also strongly disfavor :refer-ing in anything that's domain-related
So I consider using the alias repeatedly in the code as noise
When the namespace is given when you use :refer
every mainstream library out there disagrees, if you read the source
Good for them?
Doesn't make it the best choice
we don't have to argue about naming, I doubt anyone here is going to change their mind
it's a beginners channel for learning clojure, we can tell you what's normal, idiomatic
if you want to change the whole community, this isn't the venue
if you want to justify your own naming practices, why?
Again, putting words in my mouth
Par for the course for text communication I suppose
cheers, have fun learning clojure
I'm not a beginner. I just thought it was a beginner question
Strange that you would assume that
The point is to help beginners. I posed the question in case any beginners were wondering the same thing and if I asked it in #clojure they would likely never see it
Hence why it is a poor assumption
@whoneedszzz It's also possible to rename symbols that you refer in, if you prefer to do things in your style but are dealing with symbols that don't have prefixes in their names. require
supports a :rename flag
How is that my style?
just for clarity, this is how the discussion started
07:54:26 WhoNeedszZz | How do people feel about the use of `:as` vs `:refer` in a require expression these days? │
07:55:27 joelsanchez | in our team we tend to `:as` everything, as it makes it easy to know where things are from, visually │
| (edited) │
07:55:47 WhoNeedszZz | But are there any performance differences? │
07:56:01 WhoNeedszZz | Does `:as` load the entire namespace or does it simply create an alias? │
07:56:15 joelsanchez | it's just an alias, the namespace is loaded by requiring it
imho the discussion could have stopped there, everything was resolved
It wasn't resolved then because my actual question wasn't understood
it was understood and answered - there's no performance difference, it's a naming alias
beyond that what is there to do but argue about subjective style questions?
a more interesting thing is - holy crap, it's 8AM in there! 🙂
haha, west coast US and I don't tend to sleep in
@whoneedszzz from the original question, not sure what you mean by "loaded"
I was drawing a comparison to Java where using import wildcards imports everything in that package and causes multiple issues because of that. One of them is a performance issue because the compiler has to search through the entire package of any wildcards to find the occurrence of the reference
require
will cause the namespace to be compiled and instantiated if it's not already, regardless of :as or :refer
So that's what I was getting at
And now understand that
Clojure handles it differently
Another benefit to using :refer
is that you can look at the top of the file and know exactly which functions and/or macros are being used in that namespace at a glance
I’m using lein-figwheel and trying to write a pixi.js application in clojurescript. I can’t get hot-reload to work correctly. If I mount my application to the dom using replaceNode, I have to do a hard browser refresh in order to see changes
(dom/replace-node
(oget js/document "body")
(oget app "view"))
On the other hand, if I mount it using appendChild, then every time I save a change, another canvas is appended to the page without removing the previous. Why does figwheel work so well with reagent and how can I make it work better for pixi?are you doing the replace-node at the top level of the ns? figwheel has to load your full ns so anything in a top level form will run
usually there's a specific callback for figwheel that you tell it to call after each reload
the reason things work so nicely with reagent is that you set up a piece of data that will cause a re-render of the mounted node when chaned
(which means figwheel needs no special callback - if the data changes when reloading the code, the page refreshes)
Ah, I am using it in the top-level. I think the figwheel template’s default name for that callback is on-js-reload
. So, it sounds like I should put my reload logic in there
right, and whether in cljs or clj, doing things that have side effects at the top level of a normal ns will cause problems
clojure doesn't have a "compile only" mode, if there are side effects in your ns outside something like fn or delay that defer them, they run when your ns loads
@grierson that really depends on what you are trying to do - there's no direct analog as clojure doesn't enforce types during compilation
but depending on what you are attempting, it could be a multimethod extended to multiple keywords, or a protocol extended to multiple records, or a multimethod extended to multiple values of a magic key in a hash-map
@grierson another important difference is that clojure doesn't really do "closed types" - so the natural solution to most things involving datatypes is going to leave it open to runtime extension
@noisesmith I’m watching “The Power of Composition - Scott Wlaschin” presentation now. https://youtu.be/vDe-4o8Uwl8?t=1456
from a brief glimpse, we'd use a multimethod or protocol for that
if you try to apply ml patterns to clojure (beyond the very basics) you'll learn a lot, but you'll end up with very weird clojure code - ml and clojure have some incompatible base assumptions
what mls and lisps mean when they say "functional" is distinct
(btw I'd love to be using OCaml at work, but Clojure is pretty cool too)
Have ocaml got their threading model done yet? Last I heard it was essentially single threaded with one or two proposals of how to accomplish it but nothing official yet
as far as I know there's already a proposal that's been accepted which is under active development (multicore under ocaml-labs). Looks like there's been a lot of thought put into it which is why it's taking a long long time.
It is dependent on other things like the addition of typed effects as well from what I remember/understood
yeah, that is a problem with ocaml - it has good ipc so for a pool you can viably use a fixed number of instances on one machine, but it doesn't have shared-resources threads
but f# (which is what was specifically being referenced) can use c# threading and is based on ocaml - I don't have experience with it though