This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2015-11-17
Channels
- # admin-announcements (9)
- # beginners (96)
- # boot (77)
- # cljs-dev (23)
- # cljsrn (18)
- # clojure (206)
- # clojure-austin (7)
- # clojure-conj (5)
- # clojure-japan (7)
- # clojure-poland (13)
- # clojure-russia (130)
- # clojure-taiwan (1)
- # clojurescript (125)
- # cursive (13)
- # data-science (2)
- # datascript (3)
- # datomic (2)
- # hoplon (24)
- # immutant (5)
- # jobs (4)
- # ldnclj (3)
- # ldnproclodo (2)
- # off-topic (2)
- # om (70)
- # onyx (12)
- # re-frame (6)
- # vim (2)
Hey all, I’m very new to Clojure and I’ve been learning it by following through Clojure for the Brave and True, but right now I’m having an issue with one of the end of chapter exercises
The task they put forth is to implement a function mapset
which works like map, but returns a set instead of a vector
@dvcrn Are you at Clojure/conj by any chance? Stop by the Cognitect table for free stickers and extra parens.
There’s http://clojure.org/swag if you’re not opposed to throwing down some cash. Take the spares to a clojure/fn-al programming meetup, you’ll make some friends.
@progzilla Hit me up.
Colin Fleming made a nice talk about PEG grammars today at the conj... coincidentally I have been talking to him about a Parsing Library I have been working on based on PEGs. It is almost ready to release.
https://github.com/ghadishayban/pex/blob/master/src/com/champbacon/pex/examples/json.clj
I really like Lua's LPEG library, which this is somewhat derived from. I just wanted to bring the VM approach to Clojure. An extensive README is forthcoming.
@ghadi: does this generate JVM bytecode?
hehe, bytecode VM on JVM, on AWS VM, on real hardware
basically a grammar begins life as PODS (plain ol' data structures) -> then a compiler turns it into an AST -> then to "parsing bytecode" -> then it's run inside a virtual machine, built for parsing
the VM was...fun. We all know mutable state sucks. implementing mutable state itself is like the worst hell.
I'll write up a better rationale (hi @donaldball) but I think there is a very nice space between regexes and Instaparse.
Can anyone explain this behaviour?
user=> (def f ( "/Users/clumsyjedi/file"))
#'user/f
user=> (def s ( f))
#'user/s
user=> (.delete f)
true
user=> (slurp s)
"lol\n”
the file being slurpable after the file is deleted? I suspect this only works on files up to a certain length
and is not something one can rely on
@clumsyjedi: This is conjecture, but I assume that the stream in this case is at least a little bit eager. That eagerness is probably an implementation detail. Slurping f in the above example fails, correct?
yes, FileNotFoundException
Yeah so I think clojure generally uses Java’s buffered streams - probably on construction of that it’s ripping in the first n many bytes to it’s buffer.
ok cool, thanks
it would be great to figure out what that n
is, but I’m too lazy to go look at the BufferedStream code
going off unix foo, not knowledge about the java classes: deleting a file unlinks it from the file system, but doesn’t close open file descriptors. I assume this is what you’re seeing here
many file systems basically work of something garbagecollection esque
delete is merely removing a single reference to the datum on the filesystem
interesting point mj_langford , and calling the attached script as
[email protected] ~ $ echo lol > foo; perl ~/test_delete.pl
backs you upHmm, vectors are recommended over lists, but functions like concat
return a list and there's no concatv
.
Actually APersistentMap extends AFn so you can use a map to lookup a key regardless of whether the key is a keyword BUT you need to put the map with the key first i.e.
(a-map {:a 1})
assuming a-map has {:a 1} as a keykeywords are also fn that look themselves up in maps.
so you can use
(:a {:a 1})
or
({:a 1} :a)
but only
({“a” 1} “a”)
for a String keyas String is not a fn so
(“a” {“a” 1})
doesn’t workQuestion: say I have a data structure [1 2 3 (identity 4)], is there any way I can make a macro receive [1 2 3 4] as its argument (not a symbol with [1 2 3 4] as its value, because I need access to parts of it at compile time) ?
100% of what macros receive is data, @moxaj. the whole idea is that you can manipulate the code as data before its’ compiled as code
i can’t recommend this book enough: https://pragprog.com/book/cjclojure/mastering-clojure-macros
@robert-stuttaford: I think i'm trying to have the cake and eat is as well 😞. Take the following example:
(defmacro foo [bar]
`(fn [x#]
(+ x# ~(:x bar))))
Now, (foo {:x 10})
compiles, but (let [bar {:x 10}] (foo bar))
does not (because bar
is just a symbol inside the macro). A solution would be to make foo
a function and use eval
on the result, but for reasons I cannot use eval
.sorry new to slack didn't format that right ;( but you need to reference bar directly before acting on it, and this works
@hellofunk works, but I'd like to 'inline' (:x bar) into the body of the function to avoid looking it up everytime the function is invoked
@hellofunk thus the outer ~
you have no choice but to look it up at runtime. there is no value of bar at compile time, right
remember, your macro is running and returning new code before your program even runs
@hellofunk I guess i'll have to return to eval and somehow make it run on clojurescript as well (which is complicated)
@moxaj never use eval unless you have no choice.. and here you have many other choices
@moxaj the entire idea behind clojure involves looking up data in collections, so I'm not sure why you don't want to do this at runtime, that is kinda the underlying point of the language.
@hellofunk I'd like to generate functions for user provided 'schemas', and the performance of these functions is a major concern
@moxaj: and you have strong evidence already that the very basic process of lookin up a value in a clojure map, which is fundamental to the entire language, is a performance problem for you?
@hellofunk well, i'm trying to squeeze out whatever I can, so if possible i'd like to avoid lookup up those keys for the millionth time, since it's already known at compile time (and here lies my problem, it's not exactly known, wrapping it in an identity or something like that can break it..)
@moxaj: you are unnecessarily complicating your work, and you are working against the language. you shouldn't worry about a basic key lookup in map -- thousands of heavy production performance-sensitive apps catering to thousands of users real-time simultaneously around the world are using the core language as it was designed, and so should you. If you feel that strongly about a basic key lookup, I'd say maybe you're using the wrong language 😉
@hellofunk it's not that I have something against it - I was simply curious if there was a way to spare it . And you are perfectly right, this may be completely unnecessary, I was only trying to see how far I can push.
@moxaj there will always be ways to make any program faster, there is never a point at which you can say "my program is as fast as possible." therefore, the principle is that you should simply not worry about making your program faster until you have reason to spend your precious development time to do so. concentrate on your big picture ideas first
@hellofunk I know about the saying "premature optimization is the root of all evil", but when you set off with a goal to make a simple library which is as performant as possible, you can't just say: "alright, now that this thing works, let's see how I can make it faster". Or at least that's not how I was thinking in this case.
@moxaj: well, you should be thinking that. first, make your program actually work, and don't get up caught up on something as simple as a key lookup in a map. that is just not a good use of your brain to worry about. after you make your program actually work and do what you want it to do, and prove to yourself that your idea is effective, then and only then you can question if it is fast enough for you. 99% of the time, it probably will be, because computers are pretty neat little machines 😉
@hellofunk yeah, and then there's the jvm, which is a lot smarter than me regarding optimizations, so I may be shooting myself in the foot . Also I'd like to add that it's not just simple key-value lookups, it's complex functions being called on various parts of the data, which is 'more or less known' at compile time.
@moxaj: and how is it that your data is mostly compile time? you just have a bunch of map literals def'd in your source and you reference them?
@hellofunk well, you say (defconfig something x)
where defconfig is a macro of mine and instead of x you put a big fat data structure, and then it proceeds to generate some tailor-made functions for your cases.
@hellofunk something is just a symbol you pass
@moxaj: yes but how can you say with certainty that your data is known at compile time? where is the "big fat data structure" coming from, how is the data itself generated?
@hellofunk the x
is provided by the user. And I cannot say with certainty that the data is known at compile time, which is why I had to resort to eval
.
@hellofunk if the user provides something that evaluates to itself, I'd be happy, but I cannot make that assumption.
are there any really good open source examples of hybrid clojure/clojurescript projects that use the new reader literals or even better use the approach recommended in the docs? > The primary mechanism for managing platform-specific code is to isolate that code into a minimal set of namespaces, and then provide platform-specific versions (.clj/.class or .cljs) of those namespaces.
Not really answering your question, but I've used the reader conditionals and it all worked fine.
@timvisher: I used conditional read in the latest release of "Component" https://github.com/stuartsierra/component
@stuartsierra: thanks!
Also tried cursive but there I could not find out how to add more lein task to the lein task screen
I still use light table - I don't hit any issues on the daily workflow, and still feels very elegant
@albaker thanks, my main issue was that some of the error messages stays even if I solved the problem
Second one I could not find out how to do something like lein eastwood within Light table. I do not like that I have to use a seperate terminal for these sort of things
unfortunately, using a separate terminal is a fact of life with most editors. You get used to it though, cmd-tab or alt-tab becomes part of your muscle memory. Having a nice shell like zsh helps, too.
when you feel comfortable with that, then start looking into other editors that might give you the ability to do everything (almost) from within its confines.
It's important to have a REPL in your editor environment though. Without that, REPL Driven Development would not be possible. I wouldn't run lein repl in a terminal, I would take the time to get the REPL working in your editing environment.
if I look at http://nitrious.io running lein repl takes a few seconds
yes I use the instarepl in lighttable, and sometimes connect the files for evaluation as well so I can have the full classpath/file to eval/edit as I go.
yeah, I think one of the issues @roelof was having was trying to run lein plugins from within the repl
yeah, those are lein plugins, you need to run them with lein, from the terminal. Unless you develop a plugin for your editor that does that.
Emacs has some plugins that help you run some lein plugins, but that is very Emacs specific
ah, yeah, lein plugins are a different beast than running the repl. I thought I saw lein repl
mentioned earlier.
@roberto: thanks, maybe in the future. Otherwise I have to learn two things , clojure and making light table plugins
@roelof: I think emacs + cider is fine. I think prelude is a reasonable start distro for it as well (if you don't like spacemacs)
Emacs Live is also another option. http://overtone.github.io/emacs-live/
Hello! Just a stupid question: how to add an element to the end of the list? Any simple way? Like (some-f '(1 2 3) 4) -> (1 2 3 4). "conj" adds to the beginning of the list, but when one writes macros it's better to be able to add something to the tail of some expression.
^^ Although sometimes you end up doing silly things like putting a list into vec, and then conj'ing...
concat returns a lazy seq though, which is probably fine but something to be aware of
although be aware that concat
returns a sequence, not a list
(update-in a [:b] + 2) NullPointerException clojure.lang.Numbers.ops (Numbers.java:961)
@staypufd: Not related to update-in
but +
. It is called with the current value which is nil and (+ nil 2)
throws NPE. You need to use a function which can handle nil value, e.g. (fnil + 0)
.
So @juhoteperi when I changed it to a function that wasn’t doing something to nil it worked
So thanks @juhoteperi
anyone know what i should reference regarding building a new project.clj
file for a clojure contrib project? for now i'm going with core.async
Don't use that one
Contribs don't actually use their project.clj at all
But async is one of the most customized contrib projects
@alexmiller: thanks for the feedback! i'm attempting to act on http://dev.clojure.org/jira/browse/DPRIMAP-8. i think i need to add cljsbuild
to be able to test it. i think my only option is project.clj?
does async have an equivalent of 'cat'? I have n channels (c_0, c_1, ..., c_n), and I want to produce a channel C which is the concatenation of all c_0's events, followed by c_1's, etc
@timvisher: yes you will need a project.clj for that. And yes tools.reader is a better example.
Projects like tools.reader support Clojure versions older than 1.7 and do not use cljc
So, going that direction means dropping support for older Clojure versions
That should not (yet) be done lightly
The only contrib that has moved to cljc is is test.check so that is the best example for that
Cljc requires a newer version of the Clojure maven plugin which requires a newer version of maven than is supported by the contrib ci server. This is a problem I have been working on.
@alexmiller: oh that's interesting. i hadn't considered the back porting. it doesn't appear to me that data.priority-map
as of yet has any testing for prior versions or really any testing declared at all?