Fork me on GitHub

I need some clojure stickers, any suggestions where to find/buy them from?


Looks like this is the official place:


Is there a product/service that I can sign up for that handles the backend of google/apple/amazon in-app purchases and subscriptions? I'd like something where I can basically pass a user-id and a receipt and get to know if a valid product should be given, as well as an api call to find out what a user-id is owed


if I don't care about reconciling between apple/google/amazon, I can just use the platform apis for this, but if I want the purchases to port between platforms, I didn't see any already baked service. Did I miss something?


also, the service would give me a webhook url that I could feed into play store/itunes/amazon and would manage the lifecycle of the subscription on my behalf (for things like returns/pauses/reups)


I know I've built this at a previous job, but I'd kinda like to not build this again if there is someone I can pay to care about it for me


Anyone here tried Elm and/or ReasonReact? What's your experience compared to Reagent/Rum?


I got quite a bit into Elm a couple of years ago, built a decent sized app with it, and loved it. Once I groked Elm I felt I was very productive with it and had 0 runtime exceptions. 🙂 Then about a year and a half ago I started doing Clojure at a new job, mainly on the backend but a bit on the UI with Reagent, and didn’t touch Elm for a while. Couple of weeks ago, when Elm .19 came out, I decided it would be a good time to revisit Elm for a small side project. It was very slow going… The changes to Elm .19 and the lack of practice with the language were partially to blame but the productivity gains that Clojure(script) bring just make everything else feel slow. I spent two days getting a small MVP up in Elm and was able to churn out the same in Reagent in just a couple of hours. So… my impressions: For a codebase of real size with several developers working in it, Elm still seems very appealing . However, for MVPs and smaller projects, Regent is blazing fast and tough to beat. Hope that helps! Have not tried Reason or PureScript


I’ve heard a lot of mixed stories about Elm, especially on the stability front. They tend to change the language or remove features (FRP) every year or so.


if I was going to try typed FP frontend, I’d choose PureScript or Reason


I looked at Reason some time ago, when they were making a lot of breaking changes to the syntax itself. Haven’t looked again as it just failed my stability test, though the underlying tech (OCaml) is old and stable.


PureScript also looks interesting. Do you feel you get the same amount of "safety" with core.spec compared to typed languages? I have coded up the same UI now in Reagent+re-frame, Rum and Elm but I think it's too small (~600 lines of code) to really tell the major pain points of each language/library


If you do, is there any specific reason you use ClojureScript, besides maybe familiarity with Lisps


@mail228 right now we have a 16k lines cljs app. refactoring is sometimes painful. spec helps. having said that, I only have some experience with a large typed FP codebase (only some Scala and I went back to Clojure from that).


@borkdude are you using Rum or Reagent?


Spec is not enforced and not inferred. So your friends aren’t going to write them in places where you would have liked them and you have to manually place them at strategic places. But it does help a bunch if you use it well.




I haven't tried Clojure on the backend yet, I have instead been checking Elixir out. ElixirScript seems very immature compared to everything though


Haven’t touched Elixir yet


Any particular nice to know reason for picking Reagent over Rum?


@mail228 it’s pretty much the default. it’s simple, easy to start with.


That's fair, re-frame is also a really nice library


I like your db can easily be checked with spec so it doesn't get corrupted


I think in Elm and PureScript the type system does that for you, right


and infers for you


Yeah, pretty much


I would say spec is maybe more flexible but Elm enforces it upon you


Elm and PureScript have anonymous record types. This is a feature I think I’d like a lot, especially coming from Clojure.


So, like a map that you can extend some type constraints too?


A map sorta feels like an anonymous record


yes, a map with arbitrary data. you type only the thing that’s important for your function and ignore the rest


maybe an extend-type on a map?


no, a statically verified input


in PureScript’s case these are normal javascript objects. the type system takes care of the immutability and correctness aspect


Well, if we were checking types statically (like the stuff Mike Fikes is working on) then extending a type to a map might check constraints on that, I'd imagine


But if we had a static analysis tool like that, then wouldn't extending a particular type to a map sorta be like an anonymous record?


In cljs we also have specify


I’m not sure what you mean. maps already are “anonymous”


it’s not a property of the data structure how it gets checked by a static type system


Right, I think you understand my meaning then. I'm probably just lacking some of your context, because I don't fully grok the code you dropped on clojureverse. The benefit in purescript's case in that code is that the anonymous record can bend the type of a thing in a local place, to satisfy the type checker?


In typed language you normally have something like data Person { name :: String, address :: Address, dogName :: String }. In Clojure this would be {:name ..., :address {...}, :dog-name ...}. In Clojure you can pass around keys and value combinations arbitrarily without giving this combination a name. In typed languages you have to always name these combinations, unless you have support for anonymous record types. Or you can stick them in a Map, but then you lose static guarantees (you don’t know at compile time which keys are surely in the map).


If it is anonymous, then is the idea that you need to define the required 'fields' and type checking behavior where such an anonymous record type is used?


yeah, in purescript, does this "anonymous" record typing attach the type info in a way more ad-hoc than you'd otherwise be doing in purescript?


i.e. if field x you wanted to be the same type Int in 10 different anonymous record types, you would need to repeat the Int type in each of them?


I suggest going to and playing with it:

f :: forall whatever. { x :: Int | whatever } -> { x :: Int | whatever }
f whatever = whatever { x = whatever.x + 1 }

main = render $ p (text (show res.x) <> text res.y)
      res = f { x: 1, y: "whatever" }


I ask because it seems to have some similarities with Clojure spec defining the 'types' (actually specs) of keys, but in spec the recommendation is to make the key names globally unique so that you can spec their 'type' only once, and it will always be the same no matter what other keys happen to be in the same maps together with it. That and Clojure spec checking/enforcement is run-time, not compile time.


no, there is no attaching to data structures. the data structure is just an ordinary JS object. it’s compile time, nothing gets added at runtime.


Is 'whatever' in that code snippet a name that could be replaced with anything else? Or is it a keyword / reserved word?


@andy.fingerhut yes, the name whatever is arbitrary and represents whatever else might be in that record


you can introduce a record type with fields that have a name and type, and then extend those with new fields with types


this is generally called row polymorphism as far as I’ve seen it discussed.


in Purescript this was arguably explicitly a reaction to how Haskell does it, which isn’t very flexible


Can I write f :: forall foo. { x :: Int | foo } -> { x :: Int | foo } then f foo = foo { x foo.x + 1 }, and it has the same meaning as the code you showed?


Haskell doesn’t have row polymorphism built in, but it can be done as a library, but this makes the compiler very slow.


yeah I don’t mean to suggest there aren’t a lot of great solutions to it in Haskell actually, it’s just not “baked-in”


If I can use foo in place of whatever, and represents a name, do you know why they call it "anonymous"?


@andy.fingerhut it looks like you just swapped variable names?


I renamed t to whatever since I found that name more appropriate in the context of Clojure 😉


So, could one say that these anonymous records make a static language a little more dynamic, by allowing you to delay specification of some types until some data arrives at a given location (as seen at compile time, obviously)


@john no. it’s still as static as before. it’s all compile time checked


I didn't mean to imply otherwise


it’s not delayed to runtime


I didn't mean to imply that


^ maybe helpful John


oh sorry, I misread. then I think you understand correctly


By "delay" I mean, specify type information later in the code walking sense. Instead of where a type is originally defined or instantiated (wrt the compile time view)


Do you know why they call them "anonymous" if they have names?


@andy.fingerhut this is probably the closest you’re going to find to an answer:


> An anonymous record is similar to a data type, but instead of defining it up front with a data declaration we can declare/use it on the fly.


Ah, the wikipedia page on row polymorphism says it's a structural check.


i think here the type itself has no name and is anonymous. { x: 1, y: "whatever" } The function f has to say what type it operates and it gives it a throwaway name and just says it must be a record with a parameter named x of type Int


if i understand correctly


yeah, that’s my understanding @dpsutton, and consistent with how that superrecord post uses it


Ah, the whatever is like a named local parameter in the type definition, because it is scoped by the forall


yes. i think it's naming basically a constrant. forall things that satisfy this, f is defined as ...


forall types, it just means, could be anything


The whatever in the first two lines of code don't have to be the same name, I think. I believe I took the use of whatever in those two lines of example code to mean that they had to be the same, and named the same thing.


@andy.fingerhut true. but that’s incidental. the type variables have no relation to argument names


I just called it whatever again. you can also name it foo or bar.


I don’t know purescript but I’d assume that type sig says, the function f, forall whatever (record types), takes a whatever with an Int-valued x, and returns a whatever with an Int-valued x


So Purescript, like Haskell, can at least in some cases infer the type of a function from its definition. The type it is inferring from the function definition here is one that says "I take any kind of map (map in the Clojure use of the term) as an argument -- well, almost any kind -- it has to have a key x with a value that has type Int".


right, but the whatevers must line up, so whatever fields there were in that map, also have to be returned


maybe @borkdude knows but I’m not sure if there is additionally some assumption that whatever definitely has a field named x, I would assume so however


ah yeah, sounds like you just confirmed it


yeah and the main distinction between Haskell and Purescript wrt record types is that in Haskell, they are fixed (leaving aside all the libraries that do crazy type-level stuff and whatnot to get around this)


And any later code you write that calls this function is statically checked to see if the arguments it passes to the function satisfy that constraint.


and those constraints can 'bubble up' to become constraints on the keys and types of their corresponding values of their parameters.


My first reaction is that if anyone makes something like this for Clojure, it would be Ambrose Bonnaire-Sergeant


I've never used core.typed, so don't have a good guess whether it has such a capability.


honestly not sure it makes much sense in Clojure, which is coming at this from the complete opposite angle


I don’t know much about core.typed though, maybe makes sense in that context?


It makes as much sense as static type checkers like core.typed added to Clojure do, yes?


You can always do some structural checks (or arbitrary other checks) using :pre, if you're willing to wait for runtime checks.


@john that’s where spec also comes into play


ironically, it is roughly consistent with how the core team seems to conceive of map semantics though, vis-a-vis how keys in clojure.spec works


which I hate, haha…but I digress


I doubt core.typed has gotten as much adoption as Ambrose might have wished, but I believe he is working on other ideas that he thinks may have properties that might be more desirable to Clojure developers.


I’d love to see something that made it easy to integrate compile-time static checking into Clojure. I haven’t really given core.typed much of a test to be fair


just read about CircleCI dropping it a while back


maybe it’s not all that easy. I just asked in the PS channel how to do this:

f :: forall whatever. { x :: Int | whatever } -> { x :: Int, y :: Int | whatever }
f whatever = whatever { x = whatever.x + 1, y = 2 }
Reply: > I think you need to prove that whatever doesn’t include y, probably through RowCons?


not sure, I haven’t used PS in anger yet 🙂


yeah I don’t know PS so ¯\(ツ)


it’s interesting, but clojure.spec isn’t a type system so I’m less enthusiastic about that


hmm, wouldn't a spec similar to the above anonymous record, which validates value types for keys, used with spectrum, sorta accomplish a similar thing?


probably it would be something like:

f :: forall whatever. 
  RowLacks "y" whatever =>
  { x :: Int | whatever } -> { x :: Int, y :: Int | whatever }
f whatever = whatever { x = whatever.x + 1, y = 2 }


@john yes if you’re talking about that particular thing in isolation


the difference between talking about it in a PS or Haskell context vs. Clojure (outside of core.typed) is the rest of the type system it fits into


and really as I said above clojure.spec/keys is basically exactly these semantics


right, s/keys and s/def combined, to get your type relation


That whole story is moving along. I think Ambrose is humming along towards his dissertation defense. He's been doing some exciting stuff in the CLJS codebase, I believe. And Mike Fike's work is related here as well. Somebody mentioned that static analysis thing might be portable to clojure too.


yeah, I’ll be interested in seeing how this all plays out. But I’m not sure there’ll ever be much of a future for static typing approaches in Clojure considering how much the core team has doubled-down on spec and seems…unenthusiastic about considering static typing approaches, even in terms of providing useful comparisons for those of us who are interested in both


but, we’ll see


Well, I'm super excited to see more static analysis tools. As long as I'm the one imposing it on my system, where it makes sense, rather than me trying to restructure the whole world around a static checker tool. I guess there's some benefits you only get though when you do the latter.


joker is a lightweight linter that does gives some useful hints


just to be clear: I’m sure there’s a lot of utility and a strong future in Clojure for static analysis/linter/specs-at-compile-time kinda stuff. I was simply talking about core.typed and static type-checking though.


static type checking built-in to the default Clojure compiler, not as an option provided by a 3rd party, sounds very unlikely.


veeery unlikely


oh yeah I hope it’s obvious I’m not assuming that would ever happen or even that it’s surprising that it wouldn’t…haha


I’m more just talking about better integration with core.typed, in particular resolving some of the issues talked about in this post:


granted, I haven’t been paying close attention to what Ambrose has been doing lately so I could be way off-base


although, I suspect solving some of the problems highlighted in that piece would take some coordination with the core team less so than further effort on his part, which is where my skepticism comes in