This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2017-09-15
Channels
- # aleph (14)
- # aws (5)
- # beginners (144)
- # bitcoin (1)
- # boot (14)
- # chestnut (13)
- # cljs-dev (58)
- # cljs-experience (1)
- # cljsrn (47)
- # clojure (107)
- # clojure-dev (9)
- # clojure-finland (12)
- # clojure-gamedev (4)
- # clojure-russia (2)
- # clojure-sanfrancisco (1)
- # clojure-spec (5)
- # clojure-uk (28)
- # clojurescript (34)
- # cursive (9)
- # datomic (3)
- # emacs (11)
- # garden (16)
- # graphql (9)
- # hoplon (3)
- # jobs (2)
- # juxt (6)
- # off-topic (32)
- # om (10)
- # onyx (1)
- # pedestal (4)
- # proton (1)
- # re-frame (14)
- # reagent (8)
- # ring (1)
- # ring-swagger (34)
- # shadow-cljs (19)
- # sioux-falls (1)
- # spacemacs (16)
- # testing (14)
searching on the internet doesn't reveal the clojure.java.api.Clojure class. I though aot was the best way to create interop
So I'm making a program in clojure that creates a java-accesible api. Should my api class be written in java that uses clojure.java.api.Clojure to call the clojure namespaces?
You can use aot of course - but there are complications (as we were discussing) so it's not always the most convenient option. You can also make a small java class that uses clojure.java.api.Clojure internally and exposes a more normal java api to your callers, this is useful for example if you also want your code to be usable as a clojure lib
because using a library that aot-compiles itself from clojure is a pain
yeah I've been noticing that. I planned to use require inside functions so that only the "main" namespace and the java api (not clojure api) namespace use aot. Does that seem reasonable?
yes, this is what I do with my primary app
but sometimes just using clojure.java.api.Clojure is simpler (I'm considering switching to that in my app but haven't needed to)
right, or if you need annotations...
That macro is was working on with you in #clojure is for the aot api class, so yeah a little more complexity. I think I'll try the java class and see how it goes. It seems to be the preferred way on http://clojure.org
this is my WIP (I'm planning on changing the name) https://github.com/noisesmith/clj-jsvc-adapter/blob/master/src/java/org/noisesmith/Cljsvc.java
oh man - it's so rough I just noticed a dumb typo
oh is it still private - one moment I can change that
should be fixed now - it's very raw but should be a decent example already
What's the scope for require
in the context of a java class. Will a static block like this one allow all (static) functions in the class to use the require namespace?
static {
IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read("oss-world.api"))
}
right, yes
and yeah that code actually runs
oh, I should have put that require in a static block, now that I do a little research
@donyorm I am finding all sorts of problems - this code is not as tested as I thought but I should have working code pushed soon
I'm really just wrapping function calls to the clojure api to my program, not doing anything very complex so I should be fine
OK - the code on git actually compiles and runs now
the code still doesn't make sense yet, but is no longer blatantly erroneous
Hey all! Is it okay if I ask about why Clojure would be good for implementing a card game? I'm very new to the whole idea of Clojure, and it seems it can really shorten things (The http://jinteki.net repo has some very short implementations of things I expected would be much longer in nigh any language), but the syntax and all those brackets kind of pain me some - along with (from what I can see) it being pretty slow. Apologies if this should be in #clojure-gamedev, but I haven't got a reply there after a few hours
I can't imagine a card game being played fast enough that speed of language would come into play
and that's accepting, for arguments sake, that clojure is slow, which i disagree with
Thatâs a fairly broad question, but Iâll try to take a stab at it. Clojure could be good for implementing a card game if you wrote it in a functional style, in that you would be passing the game state around explicitly, and could verify that your functional operations on it implemented the game invariants correctly.
Thank you! The speed point is quite a viable one Yes, functional is the style I was thinking (as I'd quite like to get more familiar with it), and am currently debating using either F# or Clojure
As a new clojure programmer, the syntax may be challenging to become adjusted to, but most folk find that within a week or two and with the use of an editor that provides support for managing paren structures (e.g. with paredit and friends) the syntax becomes a desirable feature, not a hindrance.
@dpsutton Ah sorry, I meant in terms of it not mattering either way in a card game
as to the syntax, structural editing makes lisps much nicer to work with, provided you have an editor that indents and formats correctly. the parens make it easy to work with and make it easier to digest what's going on. perhaps counter-intuitive at first but i would really miss it if i went back to a {}
scoped language
Structural editing? As in representing scope, etc with indentation more than anything else?
More in terms of automatically balancing parens, not letting you unbalance parens (easily), allowing you to manipulate the content and position of sexps easily
so in a C type language, an if statement looks like
if (condition) {
some random statements;
} else {
some more statements;
}
and to move or edit things you have to grab all the lines and there's no structural way to grab or delimit the entire if statement.
but lisps ensure that the form (if whatever else may be in here)
has a balancing paren on the other side. editors are aware from the source code, rather than compiler output, the extent of this expression and can easy add more things to it, delete the whole thing, copy it for moving, whateverand within a form, its easy to have a notion of "delete the rest of this if statement" which cannot exist in other languages without your editors delete asking the AST the extent of the rest of the if statement
That does seem like it'd ease the parenthepain quite a lot, especially while starting. Oh okay! So editors find it very easy to manipulate individual (and groups of) statements, instead of being down to the level of characters? That's actually pretty awesome
right. in emacs, when i say "delete the rest of this line", it won't haphazardly erase characters, it will kill until the end of a logical expression. the parens remain balanced which mean i have deleted a semantic object rather than characters. it's trivial to know the extent of expressions since an expression has the form identifier
| (list of identifiers)
. that's the shape of everything in the language, except that sometimes for clarity clojure uses []
or {}
for delimiters
Ah okay! That sounds like something it'd be hard to come back from once you've started. Is the difference in ease-of-use less stark when compared to a language that depends mostly on indentation, eg Python/F#? As opposed to curly craces
play around and find out đ write your game in both f# and clojure and compare for your own sake. ML style languages have a lot to like as well. find out where you are. there's no right choice in language. find out what gels for you and then build use only that language for a year
That's a really good way of trying it I think. Porting ought to be much easier than writing from scratch, and having experience in more things can only be good
i learned a lot of languages for a while but its always superficial. gotta spend some time with a language, it doesn't matter which one. but get used to how one language works, its idioms, its strengths. do that for a year. learning syntax and simple operations in a bunch of languages doesn't lead to real insight, in my opinion. but i've been wrong before so who knows
I learned a lot about writing good clojure from writing a small haskell app
I get what you mean - personally, I think that if you can nail down syntax and such for a language that very much shares a lot with one you already know a great deal of (eg C#/Java), but ones that aren't so close, you've gotta stick around until it really clicks @donaldball How so? I haven't used Haskell, but I've been using F# some and from what I hear it takes its roots there
Forcing myself to consider to describe the population and succession of types was a good exercise
You've lost me there - describing population and succession of types?
The set of types the program needs, and how the needed functions will transform types into other types
Ah, I think I've heard that called data-driven programming or something like that? I've only seen much about it recently, but it does seem like it'd be really good for another way of thinking about things
Hi all, macro's keep confusing me. I have the following macro:
(defmacro defschema
[name conn label & constraints]
`(do
(update-schema ~conn ~label [email protected])
(def ~name (output-schema ~label [email protected]))))
And usage like this:
(defschema something connection "SomeLabel"
(unique "someproperty")
(unique "someotherproperty"))
The unique
function is supposed to do something with the property and return a simple map, all very straightforward. However it doesn't get called in the macro. Can someone explain to me why this is and what a good solution would be? Thanks in advance!(macroexpand '(defschema something connection "SomeLabel"
(unique "someproperty")
(unique "someotherproperty")))
I suspect that it's doing something like passing the 2 unique calls as 2 list arguments to update-schema, rather than calling the unique function and passing each result to update-schema
@carr0t yes I think you're right. But how to correct it so it calls the unique
function?
@jlmr I find that when writing macros it is helpful to write out an example of how you want to call it together with the code you want that call to expand to.
If that macroexpansion isn't what you want, what code do you want your macro to write?
@madstap that actually looks correct, but it seems the unique function doesn't get called after the expansion
Right, so the backquote qualifies update-schema
and output-schema
with the namespace where the macro is defined, while the code in constraints
is passed as-is. So if you call the macro in another namespace foo.baz
, it will look for foo.baz/unique
. If you want that to be foo.bar/unique
you could just require it from foo.bar
: (ns foo.baz (:require [foo.bar :refer [unique]]))
@madstap the funny thing is that update-schema and output-schema get prefixed with the namespace while unique does not. Might it have something to do with the unsplice-quote?
You are right about the unquote-splice being the reason for unique
not being qualified with the foo.bar
namespace. But that doesn't explain why unique
is not being called at all. It doesn't really make sense to qualify code that the user of the macro passes in.
Added a println
call to unique and it is indeed being called. So the error is happening somewhere else. To some extent a relief: it seems I have written the macro correctly which would be a first đ.
Fixed it, lots of sloppy errors elsewhere in the code... đŹ Thanks for your help! đ
what would be the idomatic way of error signaling and handling? for example if a function has failed how would it return the value/error reason and how should that be propagated across function chains. In case of nil-puning, I am having trouble sending the error cause, should I look for monadic approaches like Failjure.
@shakdwipeea there are various options but sadly since we are on the jvm, we need to handle Exceptions no matter how we design our apps. Which means that any other abstraction is an extra complexity added to the complexity of Exception handling. A good compromise in my experience is to use ex-info
to create an exception that has data attached, and use ex-data
to extract the attached data if any in a catch
clause.
this is largely an issue of taste / opinion though, there are definitely other approaches (including various Monad libraries that have Option types or Maybe to represent failure states)
another thing to pay attention to is that if you use future
(or tools that build on top of it) you wonât see exceptional conditions if you donât access the return value of that future, which in some cases might mean putting a try/catch inside every future to ensure the errors are logged properly instead
no because the future code captures and isolates the exception in order to deliver it to you when you dereference the return value
so the exception doesnât get thrown if it gets as far as the future code
(or, more precisely, future captures the exception unconditionally, and rethrows if/when you dereference, in the context where you tried to use the return value, but only if you ever do so)
I was afraid of this. Wouldnt it make sense to capture and rethrow, so that the default handler could optionally be used. Not sure if clojure under the hood uses Java future, if so, it wouldnt be possible to change, but if not, would there be downsides?
who would rethrow? when? how can it do this from outside the future?
would you run a separate thread with the express job of reading exceptions off a queue and throwing them?
and yes, clojure is using java Future to implement futures (and one way around this is to use Thread instead, which would throw to the uncaught error handler, and then add on the binding conveyance for *dynamic-vars*
you would also want to use a promise
or something like it to replicate the deref behavior I guess
but also implement Thread future-cancel would work (via the interrupt method)
oh wait, future-cancel uses a method on Future, so you would need to implement Future to do this cleanly
itâs in Futureâs contract to throw on get
(what deref calls in clojure) so you have to choose between throwing the same exception twice (once to the global handler, once to the one accessing the data) or break the expected behavior (I donât know what the consequences of that would be, probably depends on what third party libs you are using?)
The future would capture the exception, but also rethrow it. If you don't put a default handler, that rethrow just disapear in the ether of uncaught thread exception, but when you get on the future, it was captured and gets thrown. But, you can also choose to set a default handler, and handle it when its rethrown, which would be useful for side effecting futures.
In case of using ex-info and ex-data,what I am looking for is chaining multiple expression ,sth like some-> but also get back the error reason. Also if I want to handle java specific exception then should I wrap that in a ex-info ?
wrapping in ex-info and re-throwing is definitely an option, if you arenât in a position in that code to know how to recover but a caller might want to recover
fundamentally a nil in Clojure is not an erroneous condition - itâs considered normal
@dimovich the simplest thing is to use is the clojure socket repl, which can be started via a simple setting provided to any app running a relatively recent clojure version (1.8.0+) https://clojure.org/reference/repl_and_main#_launching_a_socket_server
that doesnât provide readline or other editor specific integrations like nrepl does though
if you need nrepl, you can pull in nrepl as a dependency - itâs a lot bigger, takes longer to start up, and has a lot more features https://github.com/clojure/tools.nrepl#embedding-nrepl-starting-a-server
@noisesmith thanks for the info!
@noisesmith using a macro to create sth akin to some-> and return the error or value in a map, this should then also catch any Java Exception. Is going along this line a good way?
for certain usages I could see that - one option to consider is to make an instance of reduced
with the ex-info object in it if you hit an error, since thereâs already a number of things that stop and return something early if it is wrapped in a reduced call
for something thatâs a functional abstraction, consider not using a macro (for the logic at leastâŚ) because macros are for creating syntaxes and donât operate on the level of runtime values
if you also want to make it easier to use via a syntax, write the macro last as a wrapper
@noisesmith I see this seems like a good approach, I will try to make a function for handling the shortcuting and a macro for threading through multiple s-expressions using the function.
@shakdwipeea itâs also worth looking at cats from funcool, which has Maybe and Either built in, and I think Either pretty much encapsulates the semantics you want already - the impression I get is that cats is more usable, more maintained, and has more users than the other clojure monad options http://funcool.github.io/cats/latest/
something that operates on Either can return a left which âbottoms outâ from all other Either operations, or a right, which is passed in as a value for normal operation etc.
Looks interesting, will go through this.
Thanks
but just to be clear, you started out asking about âidiomaticâ which would be using ex-info / ex-data instead of these other haskell-inspired options, just FYI
Actually, that was my very doubt. I was able to find multiple error handling attempts using various monadic constructs, so I was wondering if I should look along that way or use a custom function to shorcuit as necessary and return the error as necessary. The main aim in both the cases remaining a sane way to thread multiple s-expression and build a value.
Can't you just thread as normal, and where you get tje returned value, have a try/catch around it?
(try (-> wtv (somefn) (anotherfn) (somemorefns)) (catch Exception e "error occurred"))
So it returns either the successful result or the string "error occured" otherwise. Or wtv you want to return on error instead.
Does anyone have a good resource on 1) The boring bits of clojure? Maybe something like file structure? e.g why are things in a src/ directory⌠or docs/ vs having a readme. I recently had to do a small project and realized i really dont understand some of the basics that get taught probably via mentorship. No one is writing hot blog posts on this stuff.
lein help sample
will tell you a lot of things about lein, but specifically if you look in âFilesystem Pathsâ you will find some good info about typical project structure
I think this is covered in one or both of the two Prag books Iâve worked on Clojure Applied and Programming Clojure, 3rd ed
kind of blurred together now with time :)
@drewverlee in case it isnât clear, having a src directory and docs directory are not Clojure design decisions, and you can get by just fine without either, they are things leiningen sets up as defaults
what Clojure looks for is a resource or file somewhere on the classpath with a relative path to the classpath root matching the namespace - lein happens to name that classpath entry src in default projects and thereâs not much reason to second guess it
(though sometimes youâll see it subdivided if you are using more languages in one project)
hey guys, playing with doing stuff in clojure again. anyone got any advice to clean this up? This nested if stuff is pretty gnarly, is this idiomatic clojure style?
(def user {:age 100})
(def user2 {:name "Noman"
:addresses [{:street "123 Ashland St"
:city "Boston"
:state "MA"
:zip-code 12345}
{:street "456 Old St"
:city "Oakland"
:state "CA"}
{:city "Bobtown"
:zip-code 12345}]})
(def user3 {:name "Jan"
:age 44
:addresses [{:city "Mashville"}
{:street "Pratt St"}]})
(defn greet
"Greets a user"
[{[{curr-street :street :as curr-addr}
{prev-street :street
prev-city :city :as prev-addr}] :addresses
name :name :or {name "there"}}]
(str
"Hi "
name
", I see you "
(if (nil? curr-addr)
"don't have a place to live "
(str
"live on "
(or curr-street "an unknown street")
" "))
"right now, and you used to "
(if (nil? prev-addr)
"not live anywhere before this."
(str
"live "
(and prev-city (str "in " prev-city))
(if (nil? prev-street)
"nowhere at all"
(str (and
prev-city
", ")
"on "
prev-street))
"."))))
(println (greet user))
(println (greet user2))
(println (greet user3))
here's a link to it http://replit.net/LIYq/1if my addresses
list is a list of current address followed by previous addresses, it should probably be a list, right? not a vector? so it has quick access to the head?
(first some-vector)
is fast. Vectors are O(1) access to all elements (by index) and some of the functions are optimized to use index access. Lists are only O(1) for the first element (and essentially O(n) for the rest). So using vector is probably what you want here.
(I also offered some suggestions in the main channel)
@noman If you expect to add to and read from the front a lot, I'd just reverse it, with the current address last. Then you have quick access to the current one by using peek
(for vectors prefer this over last
) and quick addition of the new current one by using conj
.
That's an interesting point. There's an argument on both sides for the order of the addresses in the list/vector: current at the head (most recent to least recent) or in actual date order (least recent to most recent) so the current one is always last.
See the docstrings -- it's about performance on vectors.
BTW, for big pieces of code, use a snippet (via the +
to the left of the input box in Slack) or just post a link with the code somewhere else. That's "friendlier" that posting it all inline with triple-backticks.
@noisesmith good point. Those are specific to lein.
thanks @alexmiller iâll take a look at those again.
@noman It's more idiomatic to just use the value in conditions rather than explicitly test for nil: (if curr-addr ...)
rather than (if (nil? curr-addr) ...)
(and swapping the then/else expressions -- or else use (if-not ...)
Also, although (and prev-city ...)
works, I think it would be clearer to use (when prev-city ...)
in both cases.
You could break the main greet
function up a bit, with helper functions for current address and previous address -- and then you could simplify the destructuring as well, since you'd only need [curr-addr prev-addr]
in greet
and you could destructure for street/city/state/zip in each helper, without needing to rename parts.
@seancorfield ah great suggestions, thank you. i'll take your advice and refactor a bit