This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-09-10
Channels
- # beginners (151)
- # cider (41)
- # cljdoc (7)
- # cljs-dev (6)
- # clojure (92)
- # clojure-dev (5)
- # clojure-italy (26)
- # clojure-losangeles (1)
- # clojure-nl (10)
- # clojure-russia (3)
- # clojure-spec (23)
- # clojure-uk (82)
- # clojurescript (56)
- # clojutre (1)
- # core-async (3)
- # cursive (15)
- # datomic (26)
- # editors (3)
- # emacs (3)
- # events (2)
- # figwheel-main (192)
- # fulcro (66)
- # leiningen (12)
- # mount (1)
- # off-topic (131)
- # portkey (6)
- # re-frame (38)
- # reagent (10)
- # reitit (7)
- # ring-swagger (55)
- # shadow-cljs (21)
- # spacemacs (11)
- # tools-deps (48)
Looks like this is the official place: https://clojure.org/community/swag
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.
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).
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
Elm and PureScript have anonymous record types. This is a feature I think I’d like a lot, especially coming from Clojure. https://clojureverse.org/t/anonymous-record-types/2812?u=borkdude
yes, a map with arbitrary data. you type only the thing that’s important for your function and ignore the rest
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?
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 http://try.purescript.org/ 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)
where
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?
here’s more documentation of how Purescript does this: https://github.com/paf31/purescript-book/blob/master/text/chapter8.md#extensible-effects
@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)
^ maybe helpful John
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: https://www.athiemann.net/2017/07/02/superrecord.html
> 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.
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
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 ...
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 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
@andy.fingerhut correct
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?
fair enough
You can always do some structural checks (or arbitrary other checks) using :pre
, if you're willing to wait for runtime checks.
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
?yeah I don’t know PS so ¯\(ツ)/¯
there's also https://github.com/arohner/spectrum
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
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.
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.
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: https://circleci.com/blog/why-were-no-longer-using-core-typed/
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