This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-05-18
Channels
- # aws (3)
- # beginners (18)
- # boot (3)
- # cider (47)
- # clara (54)
- # cljs-dev (62)
- # clojure (104)
- # clojure-berlin (1)
- # clojure-denver (1)
- # clojure-italy (1)
- # clojure-nl (22)
- # clojure-russia (30)
- # clojure-spec (28)
- # clojure-uk (95)
- # clojurescript (31)
- # cloverage (1)
- # cursive (1)
- # datomic (17)
- # duct (4)
- # emacs (27)
- # fulcro (36)
- # graphql (1)
- # hoplon (1)
- # jobs-discuss (1)
- # lein-figwheel (1)
- # lumo (2)
- # off-topic (44)
- # om-next (5)
- # onyx (29)
- # precept (1)
- # re-frame (8)
- # reagent (7)
- # ring (1)
- # ring-swagger (2)
- # schema (4)
- # shadow-cljs (185)
- # spacemacs (21)
- # specter (59)
- # tools-deps (7)
- # vim (15)
- # yada (1)
hello everyone, I'm trying to learn more about macros and want to replicate elixir with
statement ..
(hope the code is self explanatory)
I' want it to look like this
(defn f1 [] [:foo "bar"])
(defn f2 [str] [:ok (str "hello " "bar")])
(defn ferror [str] [:error :vishh])
(with [[:foo str] (f1)
[:ok str2] (f2 str)
[:ok str3] (ferr str2)]
;(do-stuff-case-succeed str3)
:else
[:error err] :stuff
[:error :vish] :another-stuff)
Im sure i will have to use core.match
, but i dont know where to begin... any similar macros so I can look into the source?Which you can mimic naively by creating functions involved with their binding. Ie (let [x 3] ...) Is ((fn [x] ...) 3)
This kind of makes me think of better-cond https://github.com/Engelberg/better-cond
If let doesn't branch on the successful destructure though which is required here. I was playing around with a "let-if" macro recently
Seems like you could rewrite this as successive match calls where you propagate the error catches as the wildcard matches in each match form
hmm, i'm not sure then. The guy who made better-cond was pushing pretty hard to get his stuff in clojure.core, but the clojure devs chose to include as->
and cond->
over his advanced conditional stuff. So I wonder if it could be done succinctly with cond->
and as->
What you're doing is similar to a Monad, so you could try checking out a clojure library that implements monads and monoids
If you try the nested match version I mentioned above I think it would work but you would be flirting with method size limitations. Match can get pretty big in the decision trees it generates
maybe i can try to CPS the match chaining inserting the fetched data in the context of the next match with a let?
https://stackoverflow.com/questions/2407912/code-too-large-compilation-error-in-java
Would anyone care to guess what I actually get if I specify lein-release "1.1.3"
in my project.clj
under :plugins
?
There is a lein-release
plugin, but that's in version 1.0.9. Then there's a lein-release plugin that now is lein-tar
which has version 1.1.3.
I need to do synchronous IPC between two microservices - I was looking at Thrift but it doesn't seem that the Clojure community likes it much What would be a better option? Would ZeroMQ be good for this?
sure -- I can just repeat the call
just wanted to know what options are there - I can try them myself
zeromq works pretty good and is tcp so you dont typically have to worry about dropping packets
youâll still need to do your own serialization/deserialization though, 0mq doesnât provide those facilities the way thrift does
why
(match [1 2 3]
[a 20] :foo
else 1))
fails while
(def list [1 2 3])
(match list
[a 20] :foo
else 1))
succeeds?assuming match is from core.match, every test for core.match and every example I've seen passes match a literal vector
CompilerException java.lang.AssertionError: Pattern row 1: Pattern row has differing number of patterns. [a 20] has 2 pattern/s, expecting 3 for occurrences [1 2 3],
so why
(def list [1 2 3])
(match list
[a 20] :foo
else 1))
does not raise the same exception?I haven't used match at all, but I suspect the 2nd example is matching against the list as a single thing, rather than destructuring and looking for 3 elements>
I dunno, but given that every example and doc and test I've seen passes a literal vector, I would expect that is "undefined behavior"
`(defmacro match
(let [[vars clauses]
(if (vector? vars)
[vars clauses]
[(vector vars)
(mapcat (fn [[c a]]
[(if (not= c :else) (vector c) c) a])
(partition 2 clauses))])]
.....
~(clj-form vars clauses))))
source code of the match macro. When [1 2 3] is passed in the if clause returns true, whereas '[1 2 3] will results in false. In the latter case, the transformation will further wrap vars and patterns in clauses, a step that makes them pass the checks in a later stage. What I don't understand is that (vector? '[1 2 3]) returns true, but in the macro (type vars), given vars is '[1 2 3], results in clojure.lang.Cons.
@wolfgangshi '[foo] is (quote [foo]), outside a macro it's simplified to ['foo], inside a macro it remains a list
Clojure 1.9.0
(ins)user=> '[foo]
[foo]
(ins)user=> ''[foo]
(quote [foo])
(ins)user=> '''[foo]
(quote (quote [foo]))
user=> (defmacro ttt [v] (if (vector? v) [:yes (class v)] [:no (class v)]))
#'user/ttt
user=> (ttt '[1])
[:no clojure.lang.Cons]
but
user=> (class (quote (quote [1])))
clojure.lang.PersistentList
didn't expect clojure.lang.Cons here.
This is irrelevant to the original question, but something puzzles me.@wolfgangshi: a cons is a list-like thing, the processing of args likely transforms the type
any code that works on PersistentList but not Cons is insufficiently general, but there's lots of code that's legitimately picky about list vs. vector
I wouldn't expect (def foo '[a 0])
(let foo a)
to work and return 0 either, and that's effectively what you are trying to do to match
how could i write a macro which nest lets ? the output would be something like
(nest-lets 3)
;=> (let [a 1]
(let [a 1]
(let [a 1] )))
i used the let as an example but id really like to nest match
but that is beyond my question, i simply would like to now how can I nest an expression inside the body of the other, for n levels, using macros
The simple way to do it is a recursive helper function. A macro is just a function that has its return value evaluated to create a new form (plus the metadata to tell the compiler to treat it that way and some magic args)
almost had it...
right, recursive macros are tricky, much simpler to do a recursive function inside a macro, returning the same thing you'd have the macro return
(defn nest-form* [n form]
(if (= n 1)
form
(concat form [(nest-form* (dec n) form)])))
(defmacro nest-form [n form]
(nest-form* n form))
does clojure have a mechanism for interning a ns kind of behind the scenes? my particular use case is that I donât want each of my propert tests to have to require:
[cljs.spec.alpha :as s]
[cljs.spec.gen.alpha :as gen]
[clojure.test :as t :refer [deftest testing is are]]
[clojure.test.check :as tc]
[clojure.test.check.clojure-test :refer-macros [defspec]]
[clojure.test.check.generators :as g]
[clojure.test.check.properties :as prop :include-macros true]
[testing-util :refer [passes?]]
and itâd be much more convenient if these could be made available âgloballyâ for all sub modules like test/feature/foo_test.cljs
make a namespace that requires all those files and then require that namespace in all the other ones
that still doesn't make the aliases
you could cobble together a helper function that calls require
and alias
manually, add that to a helper file, and call that first thing in each namespace that needs them
ah but i dont think i can do that in cljs, since require canât be dynamic ( at least im pretty sure)
these things are possible, but don't seem like good style for clojure code. I might make an exception for dev-time only tooling, but for actual namespaces used in the codebase it obfuscates things
https://github.com/ztellman/sleight does this work on cljs?
haha -- from the readme.md
is this a good idea?
Maybe!