This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-06-01
Channels
- # beginners (133)
- # boot (59)
- # cider (5)
- # cljs-dev (30)
- # cljsrn (23)
- # clojure (212)
- # clojure-austin (3)
- # clojure-brasil (1)
- # clojure-chicago (5)
- # clojure-italy (10)
- # clojure-russia (5)
- # clojure-serbia (1)
- # clojure-spec (34)
- # clojure-turkiye (2)
- # clojure-uk (132)
- # clojurescript (163)
- # clojutre (1)
- # cursive (5)
- # datomic (58)
- # emacs (42)
- # events (1)
- # graphql (26)
- # hoplon (16)
- # jobs (1)
- # lumo (27)
- # numerical-computing (3)
- # off-topic (127)
- # om (9)
- # onyx (24)
- # re-frame (20)
- # reagent (20)
- # ring-swagger (14)
- # sql (19)
- # unrepl (28)
- # untangled (3)
- # vim (8)
- # yada (17)
there is some java API i’m using that wants a byte[]
— I’m using (.getBytes mystring)
, which the REPL tells me is a [B
— is this the same type ?
Yes, that is the same type, see (type (byte-array 1))
. count
is the polymorphic way of counting collections in clojure. You might see a minor speed improvement by using alength
which is specific to arrays.
could anyone give me a hint about this macro question? https://stackoverflow.com/questions/44315467/clojure-macro-perform-action-only-if-a-symbol-is-defined 😬
nvtf: One solution, don't bother with the macro:
(defn mk-printer [pattern]
(fn [input]
(if (:color input)
(prn (str (:color input) "-colored " (get input pattern)))
(prn (get input pattern)))))
(def print-lemons (mk-printer :lemons))
(print-lemons {:lemons "lemons" :color "red" :not-printed "void"})
;cljs.user=> "red-colored lemons"
Then maybe sprinkle macros on top.But it's nice having the plain functional version around, in case you need the flexibility.
@john the thing is that I want to be able to do something like (let [color "black"] (defprinter ...))
or the pattern can even be [to-print color]
, doesn`t necessarily need to be on a dict
and I'm more interested on the why it doesn't work rather than the best solution tbh. mainly: 1) eval doesn't seem to capture local scope. is there a way to do that? 2) is there a way to write a macro that: tries writing some code and in case that doesn't compile tries to write another? how or why not?
You can grab the local scope in clojure, but working with outer scoped variables in ClojureScript is non-trivial.
As such, I haven't explored 1 much. I believe try/catch should work while compiling macros, but we do have some macro wizards around here, so hopefully someone will know the answer.
@nvtf clojure would be a much messier language if eval had implicit access to locals, and we indulged in writing code that exploits that. This is a pretty basic element of clojure’s design and relates to problems that came up constantly in common lisp code
if there are values a macro should use, pass them as args to the macro
also your code would work if you got rid of the eval - color would capture a local binding of color - but it’s still not a good way to do macros
@noisesmith isn't it more idiomatic to simply rebind some *global*
in some local let binding, in those cases when you want to grab from outer scope? Within a function?
>also your code would work if you got rid of the eval - color would capture a local binding of color - but it’s still not a good way to do macros
only if color
is present in the pattern, otherwise it's a compile error. and it feels like there should be a way to recover from that, which I couldn't find :thinking_face:
implicit access to globals is a thing, of course, that’s what “global” means. But we don’t do implicit access to non-global parent scopes, and that’s on purpose, and it’s a good thing.
@nvtf well, the patterns is data when your macro runs, you can check what’s in it
(a form, but data if it’s a literal…)
and you can emit code that does an explicit lookup in the data object
(with a sensible default)
yep, thought about that, but that doesn't solve me wanting to do (let [color "black"] (defmacro ..)
@nvtf right, and what I’m saying is that code like that is terrible
if the macro should know about color, pass it in or make it global
I don't care about how terrible it is and I don't intend to actually use it, it's more a question of "can I? if yes, how? if no, why not?" to understand the language better :P
I’m doing my best to explain why
upword scope reach leads to weird and hard to understand bugs
not without some serious hacks
right, it’s by design
it’s a simpler hack (but still a hack) if you get rid of the eval
> some serious hacks that's pretty much what I want/can't come up with one/it's bothering me haha
there’s an infinitude of ways to do it, none of them leverage clojure’s actual intended programming features
for example macros have an implicit &env arg, 90% of the things you do to it will just make everything crash, but it’s possible to use it to access locals.
A function at runtime could check to see if color
is defined and branch on that condition.
@nvtf as long as we are clear that there are very good reasons that we don’t write code this way
@ghadi, @noisesmith to pick a nit: what is a lazy data structure? to me, laziness always and only refers to evaluation. maybe "clojure's lazy evaluation is not global, but restricted to the evaluation of certain data forms" or sth like that?
a lazy data structure avoids computing data that isn’t accessed
if you call first on it, you get VALUE, if you call next on it, it will realize the thunk
i don't see how that could be true. obviously we cannot strictly eval an infinite list, right?
sure - just don’t access contents - you just get the list back
it doesn’t compute elements until you access
@noisesmith that can only work if part of the data is represented as a fn. which must be lazily evaluated. no?
no - it’s not called until you call next on it’s parent
that’s not lazy evaluation, it’s just a funny definition of “next” that includes function calls
(and caching)
no more than any other function call is?
I mean it kind of cheats by hiding a function call inside a supposed data accessor
but that’s not the same as lazy evaluation as a language semantic
I think this makes much more sense (and you get a more accurate view) if you treat this as an OO thing
the .next
method of the data structure object is a memoized function
of no args
ah, i don't think of evaluation strategy as semantic. it does not affect the meaning of a program.
thinking in terms of Haskell evaluation will not help here. Lazy seqs just delay computation of the rest part of the seq
It's almost like each new link in the list is wrapped in a deref. Therefore realizing the whole sequence requires the repeated dereferencing of each tail.
@dpsutton i don't see why. couldn't one implement inifinite data in a java program?
> thinking in terms of Haskell evaluation will not help here > it does not affect the denotatuon of the program text afaik. > doesn't that require purity to be true?
the term "lazy evaluation" is causing confusion -- i'm not going to use it anymore. Clojure uses strict/eager evaluation, like Javascript, Java, Ruby... Clojure exposes a mechanism for delayed realization of sequences.
to me it looks like clojure implements lazy eval as a language feature, but only in a restricted form.
@mobileink when in doubt, sicp it: http://sarabander.github.io/sicp/html/3_002e5.xhtml#g_t3_002e5
i guess i don't see why we should call the kind of eval needed for lazy seqs strict. seems contradictory to me.
(delay (reduce f ...))
vs (map f ...)
so (fn 2 3 (+ 3 4) lazy-seq)
evalues 2, evaluates 3, evaluates (+ 3 4)
and evaluates lazy-seq
which turns out to be an object implementing public final class LazySeq extends Obj implements ISeq, Sequential, List, IPending, IHashEq{
no. the first thing application does is determined by the eval strategy. in tools like coq you can explicitly set this.
@seancorfield haha. and how are those forms evaluated?
but it just turns its list argument into (list 'new 'clojure.lang.Delay (list*
^{:once true} fn* [] body))`
it's essentially (fn* [] (reduce f ...)))
so notice that it's lazy and immediately evaled, it's just put into a thunk
delayed eval just is lazy eval, afaics. the question is whether there is language-level support for it.
evaled and put into a thunk. isn't that always how lazy eval works in languages that support it?
@dpsutton i'm not talking about Delay or any other fn in clojure but about computation.
@john exactly my point. it seems misleading and confusing to say that clojure eval is always and only strict.
What works like merge
and conj
for hash-maps but keeps the left element as the first element of the seq? Like (function {:a 1} {:b 2}) ;=> {:a 1 :b 2}
Maps aren't supposed to be treated like they have an order. You could make a custom sorted map with a comparator.
But then you would need to ensure the left most object parameter is correct with respect to the ordering, being less-than the parameter on the right.
hm I don't know if this would work for my function
(defn my-frequencies-helper [freqs a-seq]
(if (empty? a-seq)
freqs
(let [el (first a-seq)
el-freq (merge freqs {el (count-elem el a-seq)})
new-seq (remove #(= el %) a-seq)]
(my-frequencies-helper el-freq new-seq))))
(defn my-frequencies [a-seq]
(my-frequencies-helper {} a-seq))
there’s at least one lib that has a hash-map that preserves insertion order
but you probably don’t need it
@john I'm not sure if I understand your question. My current function (posted above) returns
(my-frequencies [:a "moi" :a "moi" "moi" :a 1]) ;=> {1 1 "moi"3 :a 3}
but I wanted it to return according to how the elements show in the original sequence, for example {:a 3 "moi" 3 1 1}
That is how the exercise asks me to return. I don't know if the tests will try for that though
whose exercise?
@noisesmith http://iloveponies.github.io/120-hour-epic-sax-marathon/recursion.html a course from helsinki university, I had asked for opinions before if you remember.
OK - because equality for maps in clojure ignores order
if it’s meant to be a clojure task, your code will pass regardless of order