This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2016-02-27
Channels
- # beginners (106)
- # boot (124)
- # cider (11)
- # clojure (105)
- # clojure-poland (2)
- # clojure-russia (28)
- # clojurescript (89)
- # core-async (14)
- # cursive (10)
- # datomic (7)
- # emacs (12)
- # garden (5)
- # hoplon (345)
- # immutant (127)
- # mount (2)
- # off-topic (24)
- # om (24)
- # onyx (8)
- # parinfer (51)
- # proton (2)
- # slack-help (4)
- # spacemacs (1)
Given '(f1 f2 f3)
and '(1 2 3)
, how can I get ((f1 1) (f2 2) (f3 3))
? ie I want to call the 1st fn on the 1st arg, the 2nd fn on the 2nd arg, etc. I feel like I'm spacing out on some really obvious core fn here.
Yeah, that works. Thanks! Still, it seems like there ought to be a one-worder there, eg (juxtmap '(f1 f2 f3) '(1 2 3))
...
@mikeb @eggsyntax, weird, I tried this with (map #(%1 %2) '(dec inc inc) '(1 2 3))
and getting (nil nil nil)
as a result. Any ideas why? And why I’m not getting (0 3 4)
?
Try [dec inc inc]
By quoting you're getting symbols not functions
So then you get ('dec 1) - when invoked symbols look themselves up in their value. For non maps, will return nil.
@mostr: in that case the result of map is a sequence, where each item is the application of a symbol to a number, which is nil
, so you get a sequence of nil
s
Yeah, I wasn’t happy with how I phrased that above. I wanted to say “given that I have a list of functions f1, f2, f3…” Writing it as “given (f1 f2 f3)
” suggested that I was calling f1 with f2 and f3 as args. And “given '(f1 f2 f3)
" causes the confusion that just happened. Maybe I could have done it with syntax-quote and unquote, but that seems unnecessarily cryptic. “Given [f1 f2 f3]
” is misleading because it wasn’t a vector, it was a list. I was a bit stumped. [Tangential Q: is there a way to represent a literal backquote without the space in Slack?]
I probably should have just spelled it out as “given that I have a list of functions f1, f2, f3…”
eggsyntax: usually there's no reason to care that something is a list not a vector. Unless your question is about doing associative actions or laziness, the difference is typically irrelevant
@noisesmith: fair enough, especially given that the closest core fn analogy, map, is equally happy w/ vector args.
@eggsyntax: one generalization of your question I find interesting is binary functions
(map apply [* + -]
(map list [1 2 3] [4 5 6]))
eggsyntax: and this fact (that map works with vectors) is not accidental or coincidential, it's part of clojure's protocol first design, and that design is why, until you do things in the ILookup interface, or expect the behavior of LazySeq, the difference between vector and list just will not matter
(with few very obscure exceptions I guess)
@mfikes: wow, interesting. I tried some stuff with apply
, but hadn't thought of mapping the args into lists.
I think I learned that trick from @noisesmith IIRC
Is there a cljs fiddle or bin website running anywhere? http://Cljsfiddle.net seems to be a circuit simulator now
http://clojurescript.io is a REPL
@mkfines thanks, but I was hoping for more the bin kind of thing (neglected to pack my laptop so trying to practice on my iPad... 😐)
@danlucraft: try Replete on your iPad
Ok I will, thanks!
Got it, cheers.
Someone should resurrect cljsfiddle though :)
how would you peeps re-write this expression
(= "Rich Hickey aka The Clojurer aka Go Time aka Macro Killah"
(let [[first-name last-name & aliases]
(list "Rich" "Hickey" "The Clojurer" "Go Time" "Macro Killah")]
(clojure.string/join
" aka " [ (clojure.string/join " " [first-name last-name]) (clojure.string/join " aka "aliases)]))
the last 2 lines 😞
well (clojure.string/join " " [first-name last-name])
is better as (str first-name " " last-name)
well, isn’t that what I’m doing?
> (clojure.string/join " " [first-name last-name])
?
oh wait misread your comment
thought of that
is there string interpolation in clojure?
yes, clojure.core/format and clojure.pprint/cl-format
there's probably some dark magic you can pull off with cl-format (it's mostly compatible with common lisp format)
I would do:
(let [[fname lname & aliases] ["Rich" "Hickey"
"The Clojurer"
"Go Time"
"Macro Killah"]]
(str fname " " lname " aka "
(str/join " aka " aliases)))
I think it captures the logic fine without adding any intermediary structures or adding dynamic string interpolation.
👍 @potetm more or less what I was after
but can’t see that as a massive improvement over what I first wrote
I think @noisesmith format
would be handy next time
Yeah it’s marginal at best. Not actually worth a ton of time improving. format
is handy, though not as much when you have a dynamic number of args.
I can say, as an experienced clojure programmer, adding extra data structures and manipulations can cloud your intent.
The more I can assemble with my eyes, and the less I have to assemble in my brain, the better.
potetm: cl-format actually does smart expansion of lists and other such craziness
=> (clojure.pprint/cl-format nil "~{~a~^ aka ~}" [(str "Rich" " " "Hickey") "The Clojurer" "Go Time" "Macro Killah"])
"Rich Hickey aka The Clojurer aka Go Time aka Macro Killah"
I always have to go look it up.
but it does it
@potetm: definetly agree with your last sentence
I’m just finishing up the koans
5 files to go I believe
@noisesmith: OR (clojure.pprint/cl-format nil "~a ~a ~{~a~^ aka ~}" "Rich" "Hickey" ["The Clojurer" "Go Time" "Macro Killah”])
indeed!
there's lots on the web about common lisp format tricks, they should just work with cl-format usually
for parity with the original and all
(let [[fname lname & aliases] ["Rich" "Hickey"
"The Clojurer"
"Go Time"
"Macro Killah"]]
(clojure.pprint/cl-format nil "~a ~a ~{~a~^ aka ~}" fname lname aliases))
dayum
so @mfikes @eggsyntax I’m still playing with this one https://clojurians.slack.com/archives/beginners/p1456579132001031 and eval
-ing first arg works fine (map #((eval %1) %2) '(dec inc inc) '(1 2 3))
. Is there any other way than using eval
to make it working?
mostr: any particular reason to use '(dec inc inc)
(symbols in a list) instead of [dec inc inc]
(functions in a vector)?
mostr: ('any-symbol x y)
will return nil for most x and y
symbols are not the same as the values they could resolve to
not sure, just playing with quiestion asked by @eggsyntax to learn some stuff
('any-symbol x y z)
will most always return z
mostr: the trick here is that '(x y z) is a list of symbols, quoted so they are not resolved, so you get the symbols themselves
right
of course you could also use (list dec inc inc)
but here [] is just better
not at all
list doesn't quote things
well, the list function gets evaluated
and its args are each individually evaluated - getting the function from the symbol
but it has to stop at resolving the function - no calls to resolve
substitution model!
it’s getting clear, thanks @noisesmith
np, glad I could help
@mostr: Since you are considering evaluation with respect to symbols and functions, pondering this one might be instructive: (map #(%1 %2) [#'dec #'inc #'inc] [1 2 3])
@mfikes: wow, I never thought to check how deep the var resolution would go
@noisesmith: Turtles of vars and symbols down until you hit a concrete fn
it makes me sad slack does not let me add a turtle reaction to the turtle reaction itself
@noisesmith: One very interesting thing to me was the concept of a function value evaluating to itself, which makes complete sense, but which never occurred in regular ClojureScript. I encountered it when adding eval
to Planck. Bottom half of this post if interested in the twist: http://blog.fikesfarm.com/posts/2016-01-22-clojurescript-eval.html
oh - one could theoretically make a non-terminating loop using a var that resolved to itself
or a stack overflow or something
user=> (declare turtle)
#'user/turtle
user=> (intern 'user 'turtle #'turtle)
#'user/turtle
user=> (turtle)
StackOverflowError clojure.lang.Var.invoke (Var.java:375)
oh, it lets you do that, much easier
Var indirection can actually be useful:
cljs.user=> (def f inc)
#'cljs.user/f
cljs.user=> (def fs {:f #'f})
#'cljs.user/fs
cljs.user=> ((:f fs) 1)
2
cljs.user=> (def f dec)
#'cljs.user/f
cljs.user=> ((:f fs) 1)
0
If instead the symbol were used—`(def fs {:f f})`—the map value would be the function value at the time the map was evaluated.@mostr: just saw this, I've been afk all day. Yeah, I'd just go with the vector. In the context of the original question, I had a list of fns being returned by something else, but if I were specifying them by hand I definitely would have gone with square brackets. Boy, that turned into lots of really interesting discussion