This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-04-26
Channels
- # aleph (2)
- # beginners (119)
- # boot (18)
- # cider (19)
- # cljs-dev (46)
- # cljsjs (1)
- # cljsrn (30)
- # clojure (101)
- # clojure-dusseldorf (12)
- # clojure-finland (1)
- # clojure-greece (7)
- # clojure-india (2)
- # clojure-italy (6)
- # clojure-poland (4)
- # clojure-russia (120)
- # clojure-sg (3)
- # clojure-spec (147)
- # clojure-uk (75)
- # clojurescript (86)
- # cursive (4)
- # datomic (50)
- # docker (1)
- # emacs (4)
- # juxt (51)
- # leiningen (16)
- # liberator (1)
- # luminus (1)
- # lumo (116)
- # mount (2)
- # off-topic (2)
- # onyx (38)
- # pedestal (4)
- # protorepl (2)
- # re-frame (44)
- # reagent (8)
- # ring-swagger (16)
- # schema (5)
- # specter (16)
- # test-check (226)
@sakalli if you come from the R area, that will be a little bit hard trip. I created many thing with R, like Apache without PHP and R.. websites. Here needed very different thinking
sb: thanks! that is my sense as well. I was referring to the functional aspects of r. Apply family functions and also some of the tidyverse stuff. I have for example literally not needed to write a for loop in past few years. (Although there are of course cases where one does need them)
Hello @sakalli, do you need at least 2-3 months to get great results with Clojure. I created few mistake I started with Nginx-Clojure.. so here is many “black hole” for a beginner.. so after 6 months, I dropped out.. and I use now httpkit, I think.. that is more closer for you too. Nginx-Clojure needed more java knowledge, lot of unit tests.. and very hard to manage sessions (really! - not just self-manage or Redis.. really manage..). Don’t give up! .. in this days, I don’t want to use R.. just Clojure. I really like this!
Ha! I figured out my issue from yesterday. (zip/root)
already returns the node view of the root node so passing it to zip/node
correctly returns nil
just like any other argument that isn't a zipper.
I feel a lot better now that I understand what was wrong with my code there hehe
I would like to stop sticking all my namespace imports in the topmost ns
of some of my source files
don’t fight it :)
It may seem easier to move functions around source files, eschewing the Java-ish notion that all imports equally belong throughout a source file. So not sure I should give up so fast
@matan you'll be giving up the dependency tree, particularly the one that is used by tools.namespace in order to reload dependencies in order. I'm pretty sure it doesn't work in cljs either.
it’s tricky to make those work in the ns macro though
you can always bind \ns\ and then (require... ). i have use cases for this, but then i'm meta-programming.
as a practice I'll be using for fast flexible spiking, I will practice this now and then, but I am not sufficiently familiar with require
to follow why :as
would not work for me:
(defn foo []
(require '[ :as io])
(let [paraphrases (io/file (io/resource "samples/paraphrases.txt"))]
(-> paraphrases slurp println)
))
Oh sorry about that, no I do not call it yet at all, but it breaks apart already during compilation (if I can say "compilation" in clojure in this context, probably I shouldn't)
the require happens when the function runs, the resolution of io/foo happens at compilation time
so it’s out of order
@matan saying compilation is fine, clojure always compiles code before running it
I suspected that. So other than including the require in a ns
, nothing like this would ever work right?
@matan there’s resolve, which basically screams “I am doing something foolish right now” but it works
it’s a hack tool, for a hack task, a perfect fit
@mobileink same problem with alias, it runs at runtime, so it doesn’t help the compilation error
@matan what you are trying to do is fundamentally against the grain of clojure usage of namespaces - it’s possible but it won’t be pretty, and it will fail in unexpected ways
if your issue is ease of refactoring, there’s a lein tool, slamhound, that can figure out what requires need to be added to your ns block to fix your namespace
@noisesmith I wonder what people do before unleashing slamhound against their source directory 🙂
@matan for things like that I run git add and make sure everything is staged - that way any changes made since the add are unstaged, so I can review them
Is there a clojure.core function to map the values of a map? so that for a map
{:a val1 :b val2}
and a function f I get {a (f val1) :b (f val2)}
? I found a nice list comprehension on http://stackoverflow.com/questions/1676891/mapping-a-function-on-the-values-of-a-map-in-clojure but it feels like there should be some kind of map-values function or other?rather than making a “noise” commit in my history
@rubek amazingly, this does not exist in clojure.core - but specter provides this and much more
@noisesmith thanks for sharing 🙂
to slamhound (now that I realize bringing in imports into scope within a function is a lost cause)
yeah, pretty much - but be aware require isn’t import, they both exist and they do different htings (and slamhound helps with both)
@rubek, I just do (zipmap (keys mp) (map f (vals mp)))
Whoa thanks @noisesmith - but I guess I’ll stick to plain clojure for this. Specter seems useful but a bit too powerful for my hacky parser script 🙂
@tbaldridge That’s actually really really neat! Looks much nicer than the for statement from SO
And another question, sorry: I’ve got strings like “09” and “14" and so on and want to read-string them to numbers. Unfortunately, read-string
doesn’t seem to like leading zeroes. Is there a better way to read numbers with a leading 0 than to drop all 0s from the String?
(Long/parseLong "09")
(that will also accept negatives though btw)
oh parseLong seems great! I was very close to using #(read-string (str "10r" %))
but of course parseLong (even parseInt) is much better and cleaner.
Clojure is just going to convert it to a long anyways in most contexts
curry is delicious
I mean that we cannot curry our functions very elegantly like in other functional languages 🙂
@matan, what does currying give you that something like partial
doesn't?
it's not exactly the same, but Clojure has multi-arity functions which I find much more useful than curried functions.
So here's the difference, assume we have this function:
(fn add [a b] (+ a b))
the curried form would be:
(fn add [a] (fn [b] (+ a b)))
which you could then call like ((add 40) 2) => 42
partial application takes a function and returns a function that takes less arguments because some of them have been already applied:
(defn partial [f a]
(fn [b]
(f a b)))
((partial add 40) 2) ; => 42
So in a very broad sense, currying modifies the definition of a function. partial
creates a new function that wraps an existing function.
@matan partial application fixes but does not apply the 1st arg. currying turns a multiarity fn into a proper fn (1 arg only) without fixing the 1st arg. or: curry applies to fns without args. partial applies to fns and args. i think. neither modifies fn defn, both produce new fns.
Right, it depends on the language implementation.
But as an example, this is why I like mult-artiy functions:
(defn add
([] 0)
([x] x)
([x y] (+ x y)))
In a language like clojure you then get (add 42) => 42
. In a language that is curried (like F#), (add 42) => <function add>
(ignoring the fact that you can't even do multi arity functions in most of these languages)
where you say "multi-arity" i wpuld say "variable arity", on grounds that anything more than 1 arg counts as multi-arity.
Well multi-arity is what clojure has, where you can have different logic for each number of parameters. And that doesn't even touch variadic functions which are when you have (fn [& rest] ...)
i guess i would say the nice thing about curry is you do not need to write one implementation per added arg.
explain?
so you define add for n args, and you're done. you don't need to make a bunch of defns.
taking this into a thread so we stop dominating the main chat
The problem is let's say you have (fn add [a b] ...)
as a curried function. There is no way to have that function take 2 or 3 args. You have to pick what the final number of args would be.
If you give the definition 3 args, and then only use two you get back a function...what use is that?
what do you mean by "as a curried fn"? my understanding is you def a multi-arity fn, and you can apply curry to it. i'm prolly mussing sth. heh.
no, there are actual languages that only implement single arity functions.
All functions take one arg, if you do (defn add [a b] ...) it compiles down to (defn add [a] (fn [b] ...))
that's essentially what functional means, afaik: one argument max. if you want more you need a mechanism like curry.
i could be wrong about this, but i believe it is not possible to define multi-arity fns in the lambda calc.
i think what was missing here maybe was a more concrete example? In clojure we can of course do (+ 1 2 3 4 5 6)
whereas in an ML you would have to do (1 + (2 + (3 + (4 + (5 + 6)))))
ML doesn’t have variadic functions as I recall. But ML doesn’t need parens in calls, so fun add a b = a + b
defines a curried add
function, such that add 1
is an increment function and add 1 2
returns 3.
And the variadic function issue is what @tbaldridge alluded to above — you need to define the fixed maximum arity.
nutty question: any theoretical reason why we could not curry variadic fns? if we treat numbers as fns (which is not a rad concept), why not? (((curry add*) 1) 2) produces a fn, which evaluated with no args gives 3. applied to 3, it gives (a fn which...etc) gives 6.
I dont seem to grok the meaning of keywords. I see how their used, but i feel like i could just use Strings instead. I’m trying to understand this answer, but it seems to just circle the subject. https://stackoverflow.com/questions/11655080/in-clojure-why-have-strings-keywords-and-symbols
The answer seems to be that their are ways you can use keywords where you can’t use strings. Or maybe its about being backwards compatible with how java thinks about strings?
I suppose, specifically i dont understand this line in the answer: > Strings do not implement the required interfaces to look themselves up in maps.
@drewverlee (:foo {:foo 42}) returns 42, you can only do that by having keywords implement an interface
Yea that answers that specific question. Thanks!!! So you can’t use strings as functions. But sense you can use the map as the function to the string they don’t seem practically different in use. Or i’m i missing something?
im trying to write a tutorial for my company and i just realized i dont have a strong grasp on this 🙂
what if you are mapping lookup on a sequence of hash-maps
eg. (map :foo [m n o p])
(a very common pattern in my codebase)