SF Scala: Jon Pretty, Rapture: Better Type Safety across the Seam
Recording: SF Scala: Jon Pretty, Rapture: Better Type Safety across the Seam
what I want to do is is keep it as informal as possible tonight so if if while I'm talking you have any questions at all or you wonder what happens if I if I do something else or can I can I do I don't know some some random thing that you think should be possible just ask shout out uh if you're on this side of the room um I I've become deaf in this ear since uh since I flew in a week ago uh which is a little bit concerning but I'm I'm sure it'll I'll either get used to it it'll go away um shout louder from this side uh this side can sort of quieten down a bit but so first first of all um go to this go to this URL up here and uh if if you if you're planning on following along uh follow the instructions I'm I'm not using SBT uh partly because I had various issues making stuff compile consistently so I've just grabbed a snapshot of all my current work in progress I've thrown it into a single jar file and what I'm going to show you is is running on the on the Scala 210 repple um by the way who who's planning on on going long okay so yeah maybe maybe about 10 people uh any any problems so far cool so okay uh a question who who knows anything about uh Rapture the the software Library rather than few cautious hands some someone at the back there very very keen so R Rapture is um it's a collection of libraries uh the most the most complete of which is a is a is a Json Library so I'm going to show you a lot of Json examples today uh and it also has an IO Library the general theme of of the libraries is to to deal with sort of the the mismatch between Dynamic the dynamic world and the static world so Scala everything is or hopefully most things are statically typed but we have to deal with stuff that that that we don't we don't have types for and the the philosophy is to try and be as as type safe as possible take advantage of the Scala type system try to be as intuitive as as possible so talks I've given before uh H have have sort of had 50 or or 60 slides Each of which has a single line of code on that that that does something that's intuitive you can read read that line of code and have a reasonable expectation as to what that will do I've put a lot of effort into well i' i' I've used quite a lot of uh Advanced features in Scala in in developing the Rapture Rapture modules but they're not so much visible for me for from from the point of view of of someone using that so that there's I hopefully uh hopefully quite a quite a good abstraction over the the ugly details uh but hope hopefully you you'll see today that uh uh you you can write quite quite beautiful code at the at the application Level and and hide a lot of the details you might you might need to write if you for example use the uh the java.io or the Javan net uh live um standard libraries or um or indeed many of the uh many of the other Jason libraries out there for Scala so is everyone is everyone ready with uh a working repple in Scala 210 it's got to be scar 210 otherwise you'll get a no sorry I I didn't I didn't I didn't make a build for uh so R Ryan's Ryan's been good and just just asked me a question so this follow his lead okay so um I've got I've only got about uh I've got a list of about 30 30 lines here so I'm I'm going to I'm going to type stuff in I'm I'm going to see where it takes us I've I've not got much of a plan beyond the first half an hour I don't how long have I got Lexi an hour an hour okay yeah so so beyond beyond the first I don't know how long it'll take let's see so I'm going to start by importing some stuff uh two things rapture. uncore and rapture. netore and I'll tell you why I've imported these this will allow us to create a URL so if I type in let's call it sample now I'll show you show this uh by the way I don't have the ability to to talk and type at the same time so there will be moments of silence as the words appear on the screen so I'm I'm going to put this URL in here and does this look does this look odd to anyone particularly the the URI prefix for the the string there you all seen that before has anyone seen that before hand should at least be up for one of those questions so which one um so this this is a string context so this means that this string in here will be interpreted in a special way and you can see that because the result type we get is an HTTP URL so this is what I will in a very vague sense call a resource resource is a is a it's a concept from raptor iio it's not a trait there there's no methods it needs to implement but it's it's for example an endpoint it might be a an HTTP URL might be a file might be a port on your on your computer um something that that that will have IO type operations done on it without without actually specifying what those are so I'll call that a resource and in particular this is an HTTP URL okay so this I think is quite a neat way of writing it because you get to you get to specify the URL in in its exact terms there used to be a way of doing it by um this this is actually an alternative that's still available you can write that so if for example you had the last part as a some sort of uh variable there you you could you could write that if you wanted to that's an option yeah um it it doesn't fail as it should do uh I've got so I've got work in progress on a macro that will uh well it it'll fail at run time I would love it to fail at compile time so if if for example uh what's what's a bad here okay well this this will compel it um fa it let's if I do htpp there we are that that won't work and this is a compile error because it knows that actually it doesn't know how to deal with an htpp resource so we get some we get some compile time checking what I would like to do is actually at compile time read that string split it into into into the slashed parts and have that checked so so um checked and verified so you don't accidentally include something you shouldn't do like a space a space would B this is this is a I could do yeah um I wouldn't want to make that part of my compile process though um I wonder if that could that could actually be an I I could have an import that says check URLs and it could it could send a request and check send a head request yeah that's a possibility I I probably don't want to do that though but uh yeah if if if you wanted to do you could so uh we've got this sample uh that's still working now that's what that's one way of writing a uh well I'll show you something first uh what if we wanted to read the contents of that into a into a string so we can actually use it I can call slur uh sample do slurp oh well if if I import rapture. I can I can I can call sample. slurp ah well there there's an error here now the error says uh cannot find implicit reader for etc etc etc maybe you need an implicit character encoding okay so it's saying I won't I won't read this data into into a string unless I know what the encoding is this is a common thing in in Rapture it will it will force you to import things to specify or in in a very declarative way uh what what you're what you're actually doing so let's import oh I need to import loads of stuff let's import Rapture codec so you'll notice that there are lots of imports I use them very extensively so we we've imported in coding now we've imported uh encoding from the the codec project if I go back up here in one line all bit with with some some Prelude declaring how we're going to make it uh make sense of it we should if I've got a Net Connection have you guys got net connections oh there we are okay we've got we've got some content and that's just pulled it into a string and uh that that was pretty easy should we should we try a different URL let's someone tell me their favorite URL uh that that sounds like it might be a good suggestion or a bad suggestion um oh we've got an exception uh unknown host did I misspell it let's let's go for one I Know Have I Lost My I've maybe lost my connection uh sorry so I I I I it seems like I can't actually access URLs at the moment uh no I've got no net okay um no I I was connected oh no it's pinging now but it looks like a DNS issue oh okay that's working now so I've slurped I've slurped Google as characters now one thing you might notice is that I specified the type here character because I'm I'm the the units I'm I'm slurping each one is is going to be a character that requires a uh and encoding what I could do is slurp bytes instead and what do we get we get something of type bytes so this one came back as a as a string this one came back as bytes so this is using scala's uh dependent method types to work out what the what the what the the accumulating type should be uh and and we get we get this return type called B which is just a a wrapper around the around an array of btes which gives you a nice two- string method and uh um does equality properly as well so that's just a convenience is that all okay so far not seen anything too useful yet have we so uh was it Source um let's let's call this let's call this Source okay so this is just a string but we we probably recognize this as as Json so what should we do should we should we try and pause it yeah sorry uh you you can't yet but uh I think that's not too difficult to do so that that's that's something I could well maybe not no there's one issue with that in that the the the type on the slurp method is the the sort of unit type each thing it gets and each thing is not adjacent each thing is a is a character or a bite the return type is is gener generally something completely different so string or bites so I could so I I I thought about this before I I I wondered whether I could actually make the the the type parameter to slur string or bites rather than character and bite but that there was some issues with that I can't remember what they were but it's only it's only one other method cool so hopefully not a not a massive thing should oh well no no there is better there is another way and I'll show you later yeah that that's about uh in a way that you consum it is so yeah I I'll show you that working in a in a different way without using slurp I'll show yeah I'll show you that in um probably 10 minutes or so so first of all we need to we need to um import Raptor Json so we'll probably spend a little while with raptor Jason just to see what what we can do um Raptor Jason is is the most complete of all the modules uh it's the only one I've released as a version one point something so far so the first thing I'll import is is Raptor Jason itself now the library does not you you probably noticed that there are variety of of libraries uh of of Jason libraries the Scala who who uses um who uses spray anyone so so there probably about six or seven people using spray anyone using play Jason more okay so that's probably maybe uh anyone using Jackson yeah uh anyone using Argonaut just you Ryan uh anyone using lift Jason okay uh what else is it anyone using JN yay it's it's like my name in your accent but not in my accent um J A WN so John John is written by Eric osheim and uh it it's it's pretty fast it's uh it's um one of several different backends you can use with Rapture in the in the snapshot jar I sent you you can use Jour in in in the real world on published on cotype you can actually use any of those Jason libraries I've uh I I mentioned before as a back end now that is that is a paa and it is uh an as representation so Rapture is deliberately very agnostic about how the how the Jason is represented internally and how you pass it because there might be subtle differences which matter which in my abstraction I don't want to worry about I don't want to to to to make a feature of of of rapture so in order to use in order to do anything with with Rapture you do need to uh you do need to import a back end if for example I try and pass just some simple Json it will tell me it can't find a paa for Strings so what I'm going to do is import Json backends dojour doore and then that same line should work and indeed I should be able to pass that Source there okay is that is that working has anyone encountered any problems yet with uh sample sample is that sorry you need to shout on this side how how do I how do you get the the the content from the sample so if you if you type this uh sorry if you type URI and then a string and then that dot oh you you'll need some imports as well um that will give you the sample but actually see see seeing as you you you missed the you missed the first bit maybe if you go to that URL um just using curl and then copy and paste it into a string that's probably easiest rather than going over the material again is that okay all right so uh how far did we get we we had did I try and pass that yeah I did so I'm going to say Val Json equals I'll do it again json. pars Source okay so this has Type Json now Json fundamentally is a dynamic thing it represents dynamically typed content now we can see here that we've got we've got for example a Jason object that's got a groups a groups key so one thing we can do is we just do json. groups we can just type that that name whatever it happens to be from the from the runtime object and Scara is happy to to compile that and it will dreference that inside the Json object and give you give you this content here which is the same content that starts there yeah I'll show it there that one that that is actually I I'll show you the full one it's rapture. json
that sorry I I'm deaf in this here I can't hear the first so okay uh maybe if you do this rapture. uncore _ codec doore encodings do uh utfa doore uh what else did I have uh iio doore uh netore is that all of them so that that's that's a list so while while you're doing that I'll I'll just talk about Imports uh briefly Rapture is is quite import heavy and I've I've I've gone along the route of taking advantage of what Scala provides for scoping of of imports and it's it's a very convenient way of of delimiting where you want something to apply where in particular maybe you want an implicit to to apply so a lot of these packages contain implicits that that maybe change the behavior for example the the encodings uh there that encoding will be applicable anywhere within the scope that that import applies so if you import at the top of the file that file will um uh will use throughout uh utf8 as as the encode as the assumed encoding and I use this for configuration uh and and a few few other things you you'll see several examples later is everyone doing okay sorry if this is a bit slow for the the people who aren't following law so we had our Jason let okay let me repa it we have we have this Json value we can call Json dot anything we like which which could be a a a key in this object so I showed you groups before and we can you can see this is now a adjacent array we can for example get the first element of that and this is an object and we can then get the members key this is another list so we can then get say the the first one there's uh there's Paul McCartney and we can get the name and that's that's a string but this is all done entirely in the dynamic world so this uses scara's Dynamic trait to to allow you to basically type any method name and it will happily compile now Raptor guarantees that that won't actually ever cause a problem at runtime it won't it won't throw an exception yeah you you got to shout out no no hands up uh any um something similar to The X where like all names you can yeah so if if I did Jason slash groups as a string that will do the same thing if you wanted to use that St to get everything uh so uh so what you wanted to oh um I wonder if that works let's have a look I I I can't remember if I implemented this uh it gives us an empty list uh which means it probably hasn't worked but it's had to go um I I I suspect I suspect what's happened is I've I've not implemented it across arrays I think if you had just try something else so if I did um that that will work and it comes up as an array of arrays which is top well it happens to be in the top level unfortunately everything else let let me do it with a okay this this is a good opportunity to um to show you some uh adjacent literal by the way this this is all really good because it gives me an opportunity to show different things that other other people might be thinking at the same time so we can write a Jason literal uh like this and anything inside here can be can be Json so that's that's some Json so I can I can for example do Fu bar this is all fine well I I'll answer your question in a second one one thing you might do is accidentally make aake M AK what will happen here pa pa failure it's a PA failure but it happens at compile time so this uses a macro to actually check that your Json is the right format and even if you had uh Val x equals Fu in there and we were to write dollar X it knows that that is okay and it will substitute Fu in there if for example I put the dollar X in that position this is this is also a compile failure so it makes sure that you substitute things in the right place and that they are of a suitable type I couldn't for example if if this if this substituted value was say um new exception that that clearly won't work it can't serialize exceptions because there's no there's no sense in in in in in that uh it's also in the wrong position but uh but the the serialization problem occurs first so back back here where we have a literal that maybe contains somewhere nested deep within a quux now we're wondering if we can do res 32 back SLB slash quars yeah there we are so you've spotted a bug which is great if anyone wants to go to the GitHub page and please do yeah uh I can't remember how many of those are are meant to be not that many let's just fix it like that and we do res 35s okay so that that was a little bit of a surprise to me that that worked it's interesting now you have two tabs so if you okay so yeah I haven't actually shown you how to do anything useful with this yet because you you will have noticed that I always get a Json type back and you might wonder how do you call a method on ajason type when actually that consistently just D references the object so like how could you if you've got a string if we've got this one and we go for the the first first element there got hello this is obviously a string if you were to do substring of three what would this what would this do you might you might hope it would just return l o but substring looks like accessing a a key in an object called substring and the three looks like accessing the fourth element of of the array that's at that key so this this won't work we get back undefined I'll talk a bit about undefined in a second so what we but what we have to do is we have to move from the dynamic world to the static world and there's one method called as which will take you there so get this as a string and we've got a string it's a real genuine string the ad is the single point where a a failure can occur yes you go back to you use this can I use oh my my hearings just come back I've been waiting a week no no it's gone again s sorry I'm I'm I'm hearing can can you use like a functional combinator on these like Json objects that W collection do a map or a filter or a flat map not not on the Json objects themselves you have to move to the static world first yeah as something right you have to do as as something yeah exactly as whatever yeah yeah but you could you could do it as a a an iterator say and make it lazy but yeah uh I my hearing is coming in and in and out now um so we had this example here we made it a string and this is this is a real string now if if for example we we Tred to get an integer this will be a failure this is a this is an exception it's type mismatch and it expected a number but found a a string uh maybe there's a better example example in this I can show you if we go json. groups 0 do members one dot now something that doesn't exist is Fu now this didn't this didn't fail there's no exception thrown I don't I don't want to have the possibility of an exception being thrown for every Dynamic access I do because that's that's kind of unsafe what I want to do is find out at the at the single point where I move from Dynamic to static that that that something was wrong so if I try and get a string here that is where I get a failure and furthermore have I gone past gone through two erors no it's just a massive stack trace it says that the value is missing and it gives us quite conveniently a path to the thing that that that was missing now in this particular example it was it was fu if for example I tried to get element 10 from the groups and I go back to that the top of that stack Trace we get we get told that it's element 10 that doesn't exist even though we're accessing Fu the first point of failure was was element 10 of of groups so hopefully that's quite useful when you're when you're trying to debug why your Json hasn't hasn't passed yeah can you take uh your as an option yeah so in in the um in the published version of rapture that works in my Snapshot here I think that will fail but let's give it a go so we would hope to get none back here we actually get an exception but the the API the the the design is that you can you can request an option and you'll get none back in the cases where it fails so this this is work in progress It's it's actually taken because I I I wanted to show show some things that aren't actually released yet um but I couldn't I couldn't separate them from some other work in progress that's actually broken some existing features so uh that that I think is the the biggest single thing that that's not working at the moment but the the released version that will work you can also get a try so you can you can you can request a try of string it'll either give you a success of the answer or a failure okay um so this is this is dynamic access which is fine when you're accessing a single single element and it's quite convenient when you're working in the reple just to sort quickly navigate through and the the syntax is is pretty straightforward um it it's it's like the only difference between uh Rapture Json syntax and and plain JavaScript is that you need to have the as call at the end that that that does the static transformation yeah can you define I was going to do that next actually yeah uh so we had uh let's go back to this Jason value here we've got we've got groups here so uh well it looks like there's a there's there's a a repeated object type here that has a name and a a an integer for for the born date so let's create a case class uh called member which has a name which is a string and born which is an INT okay then let's say json. groups my my ear is doing all kinds of things at the moment uh do M uh first one do as member so we literally just Define the case class I said we'd literally just Define the case class uh I have no idea why that's not working it might be because I've imported stuff twice let me let me just restart this and get back to where we were okay case Class M actually somewhere up here should be that definition now Jason dot let's see if we can find that one again as well that's very odd this has worked fine for ages let me uh no it it it should be let uh I'm going to try it with a slightly different uh I've just I've R all sorts of stuff there haven't I um right last last try before I give up on this case class member name string uh born in oh this is a Scala bug actually I I think I I I made some changes to macros to use uh to use quasi quotes and um it used to work fine in the reppel then didn't work in the when I ran exactly the same code in Scala C so maybe we'll see that again but last last try oh thank you yay okay so the snapshot jar I built for you especially for today has some sort of issue with it um that that means that this doesn't work May oh maybe I've missed off macro Paradise do you shouldn't you shouldn't need macro Paradise at runtime should you anyway I leave that as an open question the option option works for you yeah remarkable maybe oh I don't know I I've I've put something when when I when I knock together that that that that jar file for today I obviously did something wrong but uh or something right in your case yeah so so we can uh you asked about extracting members we can extract a member by the way this this is all this is all happening because I I I cobbled together this uh this Snapshot from my work in progress so if you use the uh if you use release version 1.1 then then this this largely doesn't happen uh now we we've grabbed a member there what we could do is try and get more than one let's try and get a set of members because the Beatles were a set and just by defining this uh this member case class we can we can therefore extract immediately any any collection of these so we can do a set who's got a favorite collection type from the standard library at least sorry stream never tried stream before there we are there's a stream uh red six do what is it next what what's the um let's just do that there they all are so you can extract any any collection type uh that that works with can build from now we we've still had to write groups do members do as and so on maybe we can define a group as well so case class group now that had a name I think uh was it called name or band name anyway let's let's try and get name um and we've got a set of members which is a set of member like that we Define the group and then uh let's remind myself so this this Json contains several groups so json. groups. as uh sorry group name uh oh thank you let I if I if I redefine this it will it will override the previous version this is fine to do in the repple group z. as group and that's worked we've extracted successfully a a statically typed case class yeah this is an open Bug I would like to provide that feature because I think it would be quite useful um there are ways to do it at the moment but they're a bit convoluted so yeah I mean it would be nice to have a case class that uh that doesn't have everything defined and just substitute in the values that uh that AR specified at the moment it'll just fail to match unfortunately okay uh now we can Define one more case class which will be uh I don't know what should we call it it's the something that's going to be the whole the whole thing um data why not and that has a groups which is a sorry Vector yeah let's do Vector why not and we can just do json. as data so this so by defining three case classes given some some already pass Jason in in this short command here we can actually transform that from dynamically typed Json to statically typed Scala now that's not to say it'll work there might be a problem so there might be there might be a mistake in the Json for example so if I if I try and try and get an empty object as data we'll get a failure uh who who likes exceptions as a solution to things going wrong wrong nobody's put their hand up good How would how would you rather deal with an exception or a failure did someone say either yeah someone said try scol disjunction can't actually do that but uh I I need to write some code that allows that uh all the others you you you have as as options available to you as to how how failures are are handled now this is a feature which is uh part of rapture core which is project that's common to all of the Rapture modules and and sort of defines how they work they're all written to to allow you to choose how things are returned how how your failures are are handled so if I import Rapture do core we then have a number of modes available to us so if I import modes dot return try doore this command exactly the same as we did before we now return a try is that weird little bit weird yeah the return value of as so the um well that that's it it's it's a path dependent type well it's a dependent method type based on an implicit mode which it gets from scope um and it involves a higher kinded type and it's quite quite complex so this I'm sort of telling you the the implementation of modes which is the the it's like I said at the beginning there's there's some complex stuff behind the scenes that you don't normally see but in in in use you get this magic where you just import a a mode and uh you your return type magically changes if for example I change this return turn try to return either we get either here so this allows you to to to pull in an import to some scope maybe a file maybe a whole application and you get to you get to decide how your errors are handled so in in the repple it's probably most of the time very convenient to just just have the raw value returned or an exception thrown if an exception is thrown no Harm's really done you can change the line that you just typed in fix it as you want to and then maybe it'll be successful the next time in production that's something you really you really don't want to do you want to have want to take advantage of the type system and the ways it it provides to to to safely handle exceptions so is anyone feeling uneasy about modes excited what did I do to get it to work for as so the the implementation of I I'll I'll just see if the implementation of as is that the same problem said error can cor how did you get around that error you were experiencing earlier around us ad how do I get around the error oh I must be in a different state I'm trying to do json
adds data and it's just saying cannot extract type data from oh yeah so so this this is the this is the I I got around it by using my local copy rather than the the the jar that that I I gave you what you can do is try and get it as a string and you'll see the same you'll see the same issue so the Primitive types you can extract as using the the jar I bundled up case classes uh I think because of macros don't work unfortunately yeah with each other oh okay so so there's there's a way around that um so you'll see that I imported two different modes here and it happily just went for the most recent one the way well it's it's I had to I had to work hard to make this to make it work like that what what used to happen in in the old implementation was that you would import one then you'd import another one and then you'd get ambiguous implicits because there's two in scope at the same time and it just didn't know which one to use it uses a cunning trick so you'll notice that almost all my imports I think in fact all my imports are wild card Imports return return either and return tribe both contain a single implicit value which has exactly the same name in both cases so when you import this one it will Shadow any any previous ones with the same name so they aren't seen now it's impossible to access them if you just type the name in but it's also impossible for them to be found by implicit search so this is this is maybe the one single time in in Scala that shadowing is actually something you want it's it's it's kind of convenient to to be able to Simply switch between different modes by just importing a new one that that works fine outside the reppel as well why is itable sty overlo of overloading as as in sh well shadowing not overloading that's that's the thing uh it's desirable because you can you can pick and choose um in in sequence without having to introduce a complete new scope so normally to get this Behavior otherwise we'd have to sort of stick curly braces around a chunk of code uh and import the mode exclusively within that in the reppel i i frequently want to change mode and I've already got is it just for the ra that this works it certainly Mo no it works it works everywhere so if you had just a u a single method implemented in in a file you could import things in turn and it would always pick the most recent one and so if you have different developers writing different modules in different modes try and move a function from one module to the other so has new copy paste doing some kind of refactoring you're doing you're doing refactoring yeah this function really so maybe the maybe the return type changes but it's statically typed stally checked so the compiler will tell you it it won't be a won't be a surprise but I mean in some cases that doesn't matter or at least in some cases it's not a big issue because for example uh try uh is is monadic at least in the sense that you can put it in the for comprehension uh another mode you can use this future so I I I actually um I I I discovered this that you you can you can uh you can use return future provided you've got an implicit um execution context so uh Scala do concurrent come on T completion there we are oh it's gone really slow concurrent dot can remember the uh the path it's execution content isn't it execution cont Dot Global dot it's just Global okay so now if we if we call that oh we got a failure what's happening there I don't know what's going on there um it's reverted back to the uh sorry back to the default yeah it's rever back to the default I'm not sure why I'll I'll uh I'll have to look at that um anyway you can you can in theory uh let let me just recover back to where we were uh you can in theory use a future and and have everything execute on the uh the fork join pool which is kind of cool that it only takes an import to do that it doesn't magically transform synchronous code into asynchronous but it will execute that code asynchronously let's try it again um Global and is it is that definitely the right thing um actually it's not new is it this it's implicit stock Global that's the problem that's why it didn't work before sorry what you say you have to Define yeah okay oh I see right okay uh import rapture. core. mode. return futurecore and then jason. that that will be done asynchronously we get a future back can you well it's a future Jason oh so you're saying can you can you have a try within a future you can you can you can actually compose these things so um I I I won't show that because it's it's kind of complicated and it probably won't work on my first attempt but what you can say is um return Futures compose return try make that implicit that is your mode and then it will return a future of a try and you can compose several of these together and and uh get it to do all sorts of things like it can for example log every time as well as a side effect of of of of some operation um yeah can I interrupt it sorry to ask no no you're welcome to that's what you're meant to do I'm not I'm not Rapture savy so before we run out of time can you just say a few High Lev words about kind of high level okay is where it stands in the ecosystem what it is in terms of stability and release put some context yeah yeah okay um so I I can point you to the I like to point you to the website my my browser has stopped working uh so you can you can go to the uh so there's a lot of information on the GitHub page for Rapture um okay right my my browser is is freaking out well like in your own words you see fit in the ecosystem what what I wanted to do is is sort of show the I've got a a philosophy page which uh kind of describes a little bit about that um which act as a queue for me to sort of remind myself what the right things to say are so uh rapture. is is the website it's a little bit incomplete but uh so I I've listed six things here um which is sort of guiding uh guiding Philosophy for for the library it's it's meant to be intuitive uh it's it's meant to be possible to read a line of rapture and and understand what that does just by looking at it separating for example the uh the the sort of Glo globally scoped declarative stuff from the actual actions you want to perform it's meant to be configurable so you can you can for example import different things to uh to to to make it work in different ways type safety is probably the number one thing I'm doing as much as I can all the time to to to make it more and more type safe and to use the type system rather than be be be um constrained by it uh extensible if if features aren't there you can you can add type classes to to provide functionality um idiomatic yeah it's meant to be idiomatic unopinionated this this is this is quite important because I and it kind of answers your question I hope will answer your question about um how it fits into the ecosystem Raptor doesn't by default have any dependencies any external dependencies what I wanted to do is provide better ways of using existing things that are out there so as with the the Jason Library it can use any of seven or eight different backends for for Jason now if if you're already using play or or you're already using Argonaut you can use Rapture with them just by changing an import so import Json backends dot something and and it will provide you with with a a nicer front end for for working with those those libraries while still still allowing you to access the excuse me the the existing uh the existing functionalities from from those particular Json libraries you don't have to convert the types you you simply wrap them in in uh in adjacent type there's an XML Library which is work in progress but but close to close to uh completion which takes kind of the same philosophy at the moment it it allows you to use the the standard Library XML paa and and and structure but you could you could write a type class that that allows it to work with um one of one of the the the Java XML libraries instead so unopinionated is is kind of a key key thing I I don't want to tell people how to use it I don't want to say if you're using Rapture then you've got to you've got to use scaly or you've got to use shapeless th those are deliberately not dependencies I've got an HTML uh Library that's that's much more experimental one day it might see the light of day but at the moment it's it's uh it's not uh not ready for for for for public use I really but I I i' I've made it so that it doesn't uh it it'll work with Jetty it'll work with netti it will work with uh spray if if you want to use those so I've tried to be as agnostic as possible and to to accommodate other people's libraries without interfering as much as I can um what was was there more I could I could answer what's the what's the stability is it do you for commercial environment yeah okay so so the Json the Json Library uh version 1.1 which is released and has passed the test Suite unlike the stuff I've shown you today that uh that is ready for use and you can you can use that already with with the seven or eight different uh different backends the modes if you wanted to use that that mode functionality in in your own libraries that is useable that works and you could do that but that that's more from the point of view of a library developer uh you can't you can't use modes unless the unless the methods have been written to to expect expect to use them obviously um the io library is very much um guinea pig material people using it I use it I used it in production but I I sort of know the ugly details that that that maybe I the thing the things that concern me more are the apis will change rather things aren't implemented correctly so as as develop as development's gone on i' I've sort of noticed things which I want to change which which aren't aren't quite uh how I want how I want them and at the back of my mind I know I don't want to release it and call it version 1.0 when I've got intentions of of changing these things so that's um th those those IO and Jason are the two main libraries Jason is production ready uh the others I would say I would say not unless you're unless you're willing to to become part of the development in in posting bu reports uh other libraries are there's a a command line interface that that does um deals with paing command line arguments and we'll also do tab completion uh it's got quite a nice way of uh of of allowing you to do that uh there an HTML library is web web server Library the there this the the the kinds of things I work on are are things where we there's an interaction between something untyped and something typed that's that's where I'm I'm hoping to sort of provide intuitive apis that that help make that transition easier and give you better type safety around them does that does that kind of answer the question um gen generally I've not gone with a 1.0 release until I'm I'm happy to say that this this is at least as I wanted it at the time uh if I'm uncertain about the the implementations or or the uh the apis then I I I I've I've been reluctant to to release it that hasn't stopped many people using it though there there are people who are uh braver than braver than maybe they should be yeah uh I I'm probably out of time aren't I yeah so I I can answer I can answer more questions uh rather than probably going through rapple examples if if anyone has them no I don't know I've had I've had big problems with SBT which is why which is why I dumped that jar on on you rather than uh rather than just just providing a simple SBT build I I find very frequently that I I rebuild things and it caches something in older versions and I have to delete my when when I'm when I'm developing with S spt I have to delete my IV cache before I build anything so I I frequently find myself rebuilding the whole world I mean maybe the problem is that Rapture is a collection of about it's probably 30 to 40 modules projects Each of which is a compile step the reason there's so many is that I've separated out the dependencies between them so for example the Json library and the uh the iio library you can for example this was the question someone over here asked Can you can you pause straight from a URL you can you can write json. type the URI URL in in in there and that will work but should I to provide that functionality question is should I provide a uh a depend should I have a dependency from my Json library on on the io library or should my IO Library depend on my Jason Library well I don't want either of them to depend because I I don't want people to have to pull in tons and tons of dependencies just to use uh to use Jason so what I do is I have a a third project which depends on both Jason and and on iO and that that provides the that where were we going okay I'm Wonder it's my ear again yeah so I I have a a third project which is a which depends on each of those if you want to use that particular functionality you need that additional dependency that links the two but this this this this problem is that what it ends up being multiplicative over all the different libraries essentially so that so I have many tiny little projects that are just type classes that depend on two others we end up with 30 or 40 of them rather than six or seven um and I think for some reason spt gets tied in knots trying to trying to work out what it needs to recompile and what it doesn't and I've had I've had big problems I've had I've had problems with build systems my whole life I've been using Scala 10 or 11 years and like build build systems it it's still an unsolved problem going 2 say again uh it all works fine on 211 it's just that the jar I provided uh is is 210 only um so the so version 1.1 of of rapture J is is out for 210 and 211 I do most of my development in 210 because then I'm I'm I'm naturally backwards compatible it's easier well it's easier to be forwards compatible for two 211 than it is uh going the other way um any any other questions questions not relating to Rapture no okay thank you