This video demonstrates how to build a GUI application using OCaml by leveraging TyXML for type-safe HTML generation and reactive programming patterns, showing how to create a web-based interface with state management, database persistence, and native code interop through web view bindings.
Approfondir
Prérequis
- Pas de données disponibles.
Prochaines étapes
- Pas de données disponibles.
Approfondir
Learning OCaml by writing a GUI programAjouté :
Okay, so in the last video we had this F# app setup. So we've got the web view, some bindings for a function call, and then we've got the Fable front end which is using React.
Um, so if I just run it, I got the back end running here already.
Uh, so you could just see.
And yeah, there's a function call.
And but the thing is I've done a bit of F# before.
Um, I don't know, something about it just like wasn't calling my attention this time round. And so I I fancied doing something a bit more like with native code or I don't know, something something different with no real good reason cuz, you know, F# is a nice language. But anyway, I wanted to learn something new, I guess. So the core requirements really were be able to compile to sort of native or some kind of runtime, but also have a good story for outputting JavaScript code so that we can use the same code on the back end and front end and have more kind of single code base which targets both ends because you need native and JavaScript code for web view. In the past, I've done a a bit of Clojure, you know, not loads of Clojure, but it's been okay. I know that they have a good story for compiling to JavaScript cuz they've got ClojureScript which is pretty good. Um, there's some great talks by David Nolen on YouTube if you want to look at them.
It's impressive stuff. And also I love that kind of REPL, Lisp REPL development. And I think it works really well for desktop work. One thing I found with JVM based stuff is it's not my favorite thing to deploy. I'm not very familiar with the Java ecosystem or anything like that. And I tend to prefer kind of a single native executable as the output of the process. So well, I've tried to use Graal in the past, but it's not the easiest thing and that well, I had I had problems with JavaFX cuz it's not packaged with the JVM or JDK or whichever one of those it is. And so, you have to use a different runtime, and it's just complicated. And anyway, I just couldn't be bothered to get involved with that. So, thinking about F Sharp, I thought, "Well, what's similar?" You got Haskell and OCaml are the two major MLs, um two most common ones you see, I think.
And so, I thought, "Well, OCaml, it's got a good story for compiling to JavaScript with JSOO OCaml, um which I heard about a few years ago because um ReScript was kind of popular, uh well, it was it was called ReasonML back then.
And I think that was it might have been originally based on JSOO OCaml, or if it wasn't, then that was like being talked about at the same time because they were doing like similar stuff. And some people complained that uh the ReScript or Reason way of doing things was too similar to JavaScript, not similar enough to OCaml. And before I knew anything about OCaml, like it kind of looked a bit weird, and so I was more used to the JavaScript stuff. So, I went with the ReasonML stuff and played around with that a bit, and that also had like decent um bindings for React cuz I think it came out of Facebook. So, this time, I haven't done much Haskell in the past, but it seemed to me that perhaps OCaml was a bit more, maybe less kind of ivory tower, slightly. I'm not sure. It seems that after having this little project, it strikes kind of a similar balance that F Sharp does between the kind of high like if Haskell is like at this end of like uh category theory type stuff, then maybe OCaml sits about here, and then F Sharp's about here. So, it's like a slightly more on the practical side of things, but there is scope for fun type stuff, which I I do like, but like with Haskell, it feels like there's a lot of terminology required to get up and running. It's nice to like kind of ease into it a bit more slightly. And for whatever reason, I had the impression that OCaml's more lightweight and performant. From an outsider to Haskell, you tend to just hear about these performance issues like to do with lazy evaluations and stuff. Maybe because Haskell is like a bit more well-known, you hear more detracting voices, but I've never really heard anything negative about OCaml. So, it seemed like a good opportunity to give it a go.
I want to preface the rest of this video by saying I know nothing about OCaml.
I've got no idea what I'm doing. I'm just playing around with stuff, but with that said, what I did is I set up a kind of multi-package setup here. Don't know if this is correct or not, but we seem to have a top-level kind of project file that names our packages, and then these refer to each one of these Dune files here, and each one of these is like corresponds to a separate package, and then we have our executable one here.
So, we are cross-referencing using libraries. So, this wants the web view one.
In the web view, we can talk to the shared one, which I set up more as like um an example at the start for how the front end and the back end can talk to the same library code. Then we've got C types for the bindings. So, I just generated these bindings. I try and avoid like doing too much code gen with LLMs, but for something like bindings, I feel like it's a good use case. It doesn't really detract from the learning or the fun experience because writing bindings isn't particularly fun um it just seemed like I didn't want to mess around with like learning the syntax here. But it actually looks pretty nice. I mean, we have this kind of very simple syntax. So, we've got this foreign which is wrapping the C types. So, we specify dynamic library and then just the function name and the type that that function should have. So, for example here, web view create, this is the C function, and then the here's the type. So, I really like this way of specifying types like that. it it is just really clear and clean and one of the better C binding experiences I've seen. Then after the kind of low-level binding functions, we add some kind of high-level ones which wrap those calls, but it's really just like putting an OCaml function in front of a C call. So, if we look at the interface, this is what the user code actually calls and I am quite a fan of this encapsulation where anything that gets defined in the interfaces then becomes the public version and that's quite nice and something that I liked in C in C header files seem like a massive chore, but in something like Ada, for whatever reason, that just feels like a better way of doing it with the like the spec file and the the body file. So, the here's a similar thing reminded me of Ada with this kind of split, but I kind of like it. So, that's the binding.
In the uh user code, we've written some HTML which is get what's going to be put into our web view, a function which is calling the bound we've got a a bound method here, OCaml hello, just calls print F and then web view adds those bound functions to the window. So, that's how we call it from the JavaScript and then a button to say say hello. And the rest of this is just like the simple web view. This is what I like about web view is like very little code to actually set up a window. So, yeah, anyway, it's kind of nice. So, if we want to run this, I think we'd we'd build.
You can do Dune exec and then the package name.
And here we have our web view.
Just like that. So, it's like less than 40 lines of code here and then the web view which is literally just the binding to the C code. So, Uh, if we get the tunnel back.
So, we have JavaScript code with React web view.
That's from this.
Then we have the return which returns this string. And then we Here's the result and we set the content of output to hello from OCaml which matches that.
And this has to be JSON. So, that's why it's got the extra quotes in there. So, yeah. We You can see how we interface with the native stuff. We get results back into JavaScript. And it's just, you know, pretty simple. I like it.
Okay. So, the next step was after getting that basic window working, how can we kind of replicate the story we had with the F# and React where we can have some good foundations to build a kind of a rich front-end UI on top of.
And I kind of wanted to avoid pulling in like some kind of JavaScript library and doing um interop with that. Um, I wanted to use something more like kind of JSON OCaml native. So, I came across TyXML.
Not sure how that if that's how you're meant to pronounce it. But it basically is just a type-safe way of emitting HTML. So, if we start from the user code, what we've done is change the HTML. So, we're loading a script and a style. And so, to do that kind of web view related stuff, uh, we spin up a server alongside the web view.
Uh, which I think quite a lot of these kind of like Tauri and stuff that these web view based uh, frameworks do. So, maybe Dream is like too heavyweight for what we want, but it seemed like the easiest way to get an HTTP server up and running. Basically, what we do is we have this fork. So, we fork run server which starts the Dream server on whatever port you provide. So, we've got 8080 for the port here. Spin up uh, a fork and then we have this like hook to say when the pro when the main thread ends, call stop server, so we close that cleanly. And so, we just we've got three roots.
The home, which responds with our HTML that we specified here, and then two other ones which read files. We have the JS, which is going to be our output of our tie XML stuff, our full script, which replicates the application, the front-end application, and then style, which also reads. So, at the moment we are outputting this is the default location for the front end. I had a bit of an issue setting this up because what I wanted to do was output the kind of resulting JavaScript from js_of_ocaml into like a place outside of the build. You can do that with There's a functionality called promote in June, which allows you to kind of move files or access uh areas outside of the build, but I wasn't quite happy with where that could get me because what I wanted was if I had this kind of public directory, then I could get June to stick the resulting JavaScript in the public, but because it seems like this may be fixable, but I'm not sure. So, this June, if you promote, you can only promote to here.
You can't promote outside to higher levels. So, I couldn't say, "Oh, June, copy this output file from like relative to where you are out into the public, which is two directories above. So, in the end, I just left it in the default place. And I suppose if I wanted to deploy this, like package up a real app, I'll just figure it figure that out later. And the same thing with the style because I was outputting or because I was already reading this directory, I just thought I'll stick the style in the same place.
But I did change that later because June overwrites or can overwrite the contents even if they're files not related to Dune. So, like this one has nothing to do with the OCaml build process, but Dune can overwrite everything in this front-end directory. So, I had ended up having to move it anyway. So, for the style, we're just using Tailwind.
Just looking at all ML files. If I start the Tailwind process, Okay, so that's Tailwind running now.
So, that's more or less it. So, we spin up a server.
Server kind of serves the JavaScript and CSS and the HTML, which is just hardcoded string.
And then we kept the rest the same. So, in terms of the front-end code, it's pretty simple for now. We just have an app.
This follows like similar kind of pattern that you do in React where you have the like top-level app component.
So, we're just using some Tailwind styles and outputting some text. So, we read the root element out of the HTML and then we say, um type XML, create a element a DOM element of this app and then add it to the root. Then the actual main kind of main function of this front-end code is add an onload that says just call main.
So, if we run that. So, you can do Dune build and Dune exec. And Dune exec is like running the app and it builds it as well. But, the build is kind of inconvenient to like keep having to do that. So, what I've been doing is Dune build watch. So, they have this watch functionality, which is pretty nice.
This will build all the packages and then because Dune puts a lock when you're when you if you've got an ongoing build, it locks it so you can't call exec because that would build again. So, I've just been calling the binary directly.
And it's a good opportunity to see like what we're working with in terms of the binary. So, if we look at build default bin, uh XE is like 12 meg, which is pretty nice. I don't know how much of that is bloat from dream, but I think web UI bindings tend to be about 12 meg anyway or so.
So, we just call the XE.
And here we have our app.
So, this is all we've done is add some styles and put some text in there. So, that's it. And yeah, so we've got two kind of watcher processes for the CSS and the build. Another note is that it seems like if you're using OCaml LSP, if you start the build before the LSP loads, the LSP won't load. And I don't know if that's related to like a lock again or something. So, you have to like make sure that the LSP runs first and then start the build after. Although, the LSP uses the build to get more active type information or something.
So, bit confusing there, bit janky, but there we have some kind of front end and back end OCaml talking to each other, which feels really positive.
The next step was to kind of get some interactivity going in the front end.
And this is where it sort of started to blow my mind and I was really impressed with TyXML and and the JS version. So, it has bindings to sort of like a reactive library. They have some modules for like wrapping the reactive stuff. So, instead of having to do something like what I originally thought I was going to have to do is add virtual DOM and then write some kind of wrap uh JavaScript code to do DOM diffs and stuff. But, it turns out with this library, you can just do reactive stuff directly and have fine-grained updates. And it's not like Svelte where you need like separate compiler, it's just kind of built into the library itself. So, you get like performant Well, I assume it's performant. I don't know how well it scales. Performant fine-grained reactive updates like signals for free, basically. So, I was super impressed with that. So, what I initially went with is keep this the same. We've got We've changed our app a bit, so we have this dispatch message.
Like um Elm architecture kind of inspired. So, we go through dispatch.
Um and we have these globals for the model and the state and stuff. So, that's something that I wasn't really at least in this kind of specific representation I wasn't particularly happy with, but anyway. So, we have our model.
We create a signal using the reactive code, taking the initial model, which is our initial state.
And here's the type of the state.
Then, in dispatch, we take a message and we call update with a message and the current state of the model. So, we take the result of this and fully splat the value onto the model and just replace everything completely. So, in update, we're just looking at this increment message and we just say count plus one.
And then down here, we dispatch increment on this button click. So, we have this kind of a um I guess a the attribute and then these functions which apply the attributes to the DOM element. So, we've got classes and uh on click here. If you've used like um typed HTML libraries before, this is pretty familiar to you. Where you have like a function that's the HTML element and then the body and then optionally attributes if you want to add attributes on. So, that's pretty all pretty standard. If we run this, so we have hello app that counts at zero. If we click it, we're incrementing. This is insane. Like look at the code. We've got this reactive H So, normally we have this Tyxml HTML.
This gives us things like div. Uh but we also wrap the reactive HTML from Tyxml reactive HTML. So, here we've got reactive. And this is just means take a signal and then update when the signal changes. Don't exactly know how it does it, but it's sick. So, here's our count text. So, this is like a derived value from a signal.
So, we have our signal, which is the entire model, that gets passed here, and then we map a function onto the signal to say, "Take the state, which is the whole model, get count out of it, and then return this string." So, then this count text is returning string, and the reactive text here updates when the count changes. So, interestingly, this is a normal HTML tie XML HTML div, but we have a reactive text inside it.
So, we can kind of mix at any level of the hierarchy the reactive or not reactive stuff. And yeah, just dispatching that updates the text. So, this blew my mind. I was like, "It's just so, you know, we've added 10 lines of code to get reactivity."
And it's like all familiar stuff that you'd be used to if you've done any of this kind of like functional um Elmish UIs and things like that. And nothing changed in the web view binding code. I I just think that's really nice.
Right. So, after getting reactivity working, I mentioned before I wasn't really particularly happy with the global But it's not that it's a global, per se.
It's more like it's a a global variable.
I wasn't particularly happy with that. I don't think they scale too well. So, I wanted to create something similar to um Svelte stores or Zustand. Um I can't remember what they call them.
Um but anyway, uh basically the same thing, where you have In in the case of OCaml, we use a module to encapsulate state and operations together, kind of grouped in whatever way we want it. So, like here, we have a um what we're going to do is make like a little app that we can just store links in. I had the idea that maybe like if I keep doing these videos then a little app that can kind of manage references and research and stuff like that split into projects and so um if I come across like an article or something that's interesting I could store it in this program then like group them and reference them and and so on. Um so basically like a little program for managing kind of video work for the one or two videos I put out a year. That's a worthwhile investment, isn't it? Anyway, so we've got this links store where we're going to put all our links in uh in memory. So the store kind of abstraction itself is quite uh simple. So we have create which takes our initial state and then what we want to do is return this kind of type. So it's a signal and the set signal which is very similar if you used React uh use state. Um so yeah, take the initial value and then return these two operations, one to read and one to set.
Uh we have the signal. This is just like access cuz we don't necessarily want to we want to encapsulate, you know, whatever this may be. So a public accessor for signal if we ever need it which can be useful for if you're um uh if you want to do like ad hoc like before we had the react.s.map uh that takes a signal and so maybe you have some operation that isn't worth naming in your store and what I mean by that is here we have like all which just gets all the links. Say we had something else. Maybe it's not worth giving it a name. But we we still want it to be reactive. So we'll just expose the signal and we can use it directly there. Then get and set, this is get the whole thing, get the whole state object and this is set the whole thing.
And then update which is like fine-grained, take a function which updates the value in the state and then we update the signal. And select which is like if you've used uh Redux uh use selector. We take state signal and a function and get a signal out of that. So, here's how that's implemented. So, this map actually returns the signal itself.
One thing about Counter OCaml is I'm not super familiar with reading these type signatures. So, I mean, I understand them, but sometimes it can be a bit confusing. And sometimes there's like lacking documentation.
So, anyway, it takes a while like coming to OCaml from fresh takes a little bit of getting used to.
So, we have this kind of store functionality, but a lot of people talk about one of the best things about OCaml is functors, which is like composable modules. And I wondered if that's needed. Um, I don't really know enough about OCaml to like know whether we should be using a functor or like or if we should be like strictly adhering to the interface.
So, what we're really doing is like calling the module and doing our own like individual module. So, we can define the module in line. Sig is the public interface to the module. And struct is the implementation.
Um, it's kind of nice that you can just do it like in line. Really like that.
Instead of having like it would be kind of a chore if this was like two separate files when it's really not that much code to just stick in line. Our state is just a list of links. And here's our initial value. And this is like global, but that's the way it works in these other like Svelte and stuff. They're they're global values that are kind of hidden behind some kind of interface which lets you interact with them. And global is like really important in these kind of like JavaScript UIs because otherwise you have to do loads of prop drilling. And then I added a bit more markup. So, we have our button. We didn't necessarily need to make the button reactive here. We could have put the um use reactive text, but it's just like another way that you can do it. And I've added this reactive wrapper function. So, the if you're using RS HTML, they expect a reactive list of DOM elements. So, we've just got this to simplify the the syntax here, just a wrapper which takes a function and a signal and creates a list mapping over the signal with a function. So, here we can say here's an example of some local state not using a store using the React library directly, but it's very similar to use state and it's nice that we don't have to add a lot of machinery on top of anything. We can just say create a signal which is a single value and then use the signal here and say set adding by taking the value of the signal and inverting it, which toggles the form, and then the text at the top level, which activates this form, will respond. And then we also have the form itself here if the adding's true by reacting to it. And it just kind of reads more nicely. I don't think I described that very well, but what can you do? Okay, so if I just do a little demo of the state of it now.
Uh we've got this running still. Uh So, you can see add link, which is button here.
If you click it, that changes to cancel responding to the adding signal, which is the local state.
And then we show this form, which is like a separate component here. And the components are nice because they're just markup. You don't really have to do anything special on top of this.
So, this is just like labels and buttons, inputs, and so on. So, yeah, just like that.
So, yeah, the reactivity in terms of in terms of scaling out code here, like it is also not much overhead to add new components and not much overhead to render them even in like a reactive way. So, scaling quite nicely so far, I think.
So, we have that kind of bare-bones interface.
The last thing to do was add some kind of native interaction with it. So, we're working with the machine we're running on. The user code which deals with the web view needs to be built out a bit more. So, we're just going to do like a simple kind of database like thing which is just going to be a single JSON file.
So, we've made some adjustments to the startup itself.
First, we init the database um which just checks the file exists and then try and load it using this JSON library. And if it works, we return the links, otherwise return nothing. Then, we have some extra bound functions now. We've actually started to build out our native side of things. So, we got links. What links does is we take the ref of the database and put it into this sort of like DTO shape where we use this elsewhere. So, when we're passing like the links state between the front end and the back end, we just wrap it with this kind of object because it tends to be like if you if you're doing something like this or like um some kind of principle of API design is like stick it in an object and then it's more extensible. You don't have to like go and change everything if it was just expecting like a list in the past. Uh it's much easier to adapt with an object. Anyway, we we have the loaded database. We take everything out of the database, serialize it, and then pass it to the front end. That's how we talk to our front end. And so, in the actual front end code to call this function, we wrap the window and say we've got this method links. We specify the type, so we're not passing anything to it, and it's going to return a promise because all the web view bindings, if you call uh dot return, it returns promise and say this is a method on the window. And then when we start up the the main function, I'm using this promise uh library that I found on GitHub, which basically just like wraps the JavaScript promise cuz I can be bothered to write it myself. We say promise then final, which returns a unit. There's also then map, which like returns a a promise so you can chain them, but here we want then final cuz we don't want to do anything after. So we're saying call window.links, which is going to go through that process. If it completes successfully, then we pass the JSON that was sent from the native code to this.
It's kind of annoying that it has to be JSON. I suppose you could work around that by doing like a separate web socket and then ignore the binding completely, but it was I'm not sure what the like use case that justifies that is. Anyway, so then we talk to our store. We're finally using our store. So take all the links that have been loaded from the JSON payload, add them to our state, our global links store, and then do the same thing with setting up the DOM and like appending the the UI. So in this we have add all where we're just calling the set to splat the entire state of everything cuz all we have here is links. So we just stick all the links that we loaded into the state and that's like the state from then on. So that's like kind of how you can see we don't have to pass anything around.
It's useful to have these like global access to um stores so you can call them from any anywhere.
So this is not even particularly This is not even in the UI code. It's pre-UI code, but using the same interface that UI talks through to like kind of preload the state, which is nice. So that's like the loading and the reading kind of side of things. So the other side of things is the writing. What we want to do is in the link form, we're using this kind of local state pattern again and just saying we we're just sinking. Although it's not bi-directional sinking, so if you wanted to to programmatically update control values, you would kind of I think you need to have some kind of different mechanism reaching into like the DOM itself. So this way it's like unidirectional where the user types in the the component state is managed like a native input control would be where you don't really 100% know the representation. Then we just sync to the local state here. So on input set the title to be whatever the value of the input is. And so that means that down here when we actually click to add the link we can access these values instead of having to reach into the DOM at this point. Uh which I mean you probably could that probably could be beneficial anyway. If you wanted like a true representation of like what the actual value is, then maybe calling like get element.id.target.value, whatever, might be better here. But because I'm so stuck in my React ways, this is how I did it. Take the values for the title and the URL which are updated in these two controls and then add link and then reset the form.
So I was thinking to improve this, you could add like a form abstraction.
There's React Hook Form in in React code which kind of manages all that for you.
So adding an abstraction for that here could be nice. So add link, this highlights like another one of the issues I had with the JS of OCaml binding. Whenever I tried to put methods on here with underscores in, the the code wouldn't generate correctly and it would just generate like pre underscore.
So I I don't know, maybe I should be using camel case or or what. I'm not sure, but I got sick of like trying to figure it out, so I just do this unsafe method call on window.addLink which is bound from here. So, what we're doing here is if I go back to here, we have this we take a link and here we can see we're finally using some shared code. So, in the shared link module we have this like link type and then this is like the DTO type I talked about before where it's just like an object wrapping links as a list. And then we have this like preprocessor to generate functions using a preprocessor to work more nicely with types and JSON directly. And I have noticed that with this particular type of code, it seems like OCaml heavily relies on preprocessing and code generation, but compared to like the Go world where that generation is like very front of mind, the preprocessing stuff in OCaml is very like behind the scenes, so you never really see it. But, it does track in the LSP, so that's nice. Right, so where was I? So, we're using this shared code to use the link.
Uh and this would be somewhere where you put more like domain code in here, like working with links and so on, but I didn't really really have any use for that yet. So, we take a link which is created here, then get the JSON representation of it, which we're going to send to the back end through this web view interop code. Chuck the JSON in the argument, then in here this just gets like the rec is just like JSON a JSON string, so we deserialize that. There's a lot of like serialization and so another case of improvement could be uh abstract over that, so we work we can get a way of to work more nicely with like data transfer than having to define these these types of functions everywhere. Take the request, which is just a JSON string, and then deserialize it into a uh link type. So, we're very quickly working with links directly. We convert it back to a link type at the boundary, and then it's basically just calling add link. So, we have our database set up here. So, that's kind of closed over in this code here.
So, add the link to the database and this is like dereferencing.
Then try and write the file.
So, we basically serialize the entire database again.
Then write it to the database file.
Uh if that's okay, then we update the database reference.
And then return the the new links, otherwise give an error. And then in the successful case, we actually don't use the return value.
So, we could just return unit there or we could return the list and then update the uh database in here and then just like say return a promise that says it was added successfully. And everything else is just like error handling. And then here's where we actually deal with the result of that add link bound call. So, we don't actually do anything if it rejects anyway cuz I'm lazy. But if it's successful, then we add the link the newly added link uh to the global link store as well. And this could be like if you wanted to do optimistic UI, then you could you could actually just add it beforehand and then like do nothing on the fulfilled and then add link literally would just like do an update says take the state and then um append up pre-pend the link onto the existing links. I think that's more or less it. So, we ended up with like 150 lines of code.
And yeah, I'm just like feeling super impressed by OCaml. Uh and it it wasn't really particularly hard to learn.
Uh so, I'll just do a demo of what we ended up with anyway. Um I think it's still all running.
So, here we go. I've got a link loaded already.
Then add and that's kind of how the UI looks. If I open the links database, you can see here's what it looks like.
And then if we just add another one, it's not doing any validation so I could just put whatever in there.
Then you can see the database updates.
Like that. That's pretty much it. I expected OCaml to be It's better than I expected it to be. I expected it to be more janky for whatever reason.
Like I kind of had this impression that it was like a bit maybe slightly more on the like clunky when compared to like modern stuff. So, like if you think of like Rust tooling for example, it's like really good. I will say that the tooling is kind of slow and it kind of worried me because like everyone says, "Oh, OCaml is super performant." but like for example, compiling Dream, I think it took literally like 5 plus minutes just to compile Dream for the first time, which surprised me. Maybe I'm not using like parallel compilation correctly or or you have to like pass a J flag or something.
And the other thing is like couple of times this tooling like the complete June build watch caused my computer to like completely hang.
And I've literally I've had this computer for like 2 or 3 years. I literally no other program ever has caused it to hang. So, I don't really know what it's doing. So, it's slow in that regard. Some things to compile can be slow. The LSP's pretty slow.
A lot of the time it like goes heavily out of sync and like the UI is just hanging kind of thing. And sometimes if you get a successful build from June, it will like update quickly.
Sometimes it's a bit slower depends what it's doing. So, you will find that you're spending a lot of time like watching the watch output for type errors before you see them in your editor. Overall, in terms of a language, OCaml feels like really cohesive. It feels small, like in the same way that that F# feels like really good to write.
OCaml feels good in the same way. Like small language, everything composes nicely, everything kind of feels like it works well together. So, yeah. Um I really feel like if you're interested in this kind of thing, OCaml's worth a look at. Oh, another thing was this whole business of uh forking.
So, there's like a I think OCaml has a global interpreter lock or something. So, if you spawn thread for the server, it will hang on the server because that's running like the the OCaml runtime locks locks the locks the application to the server process. So, where you have web view create and launch, whatever, that will never get to it. So, that's why I'm having to use fork to keep it a separate process. Uh you can get around this by releasing the runtime lock manually, and there's like a binding for C types to do it. But when I tried that, couldn't get it to work. And also, I'm not sure how safe that is cuz we are passing stuff between uh OCaml and C.
So, I'm not entirely sure if it's actually safe to release that. But yeah, in terms of like deploying an app, obviously um it doesn't feel as good to like be spawning a fork. And also, we're limited to Unix systems. I mean, it's not like you can't do it on Windows, but it's just like another thing to keep in mind. Whereas if you had like everything in process in OCaml, then you wouldn't even have to think about that. So, that's something. But apart from that, I I that's more or less everything like more or less my thoughts. So, I might make another video like taking this project a little further. But, yeah, go check out OCaml if you think it seems good and play around with WebUI, and I'll post this code somewhere. So, tell me how badly I've set it up.
Vidéos Similaires
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 views•2026-05-28
How agent o11y differs from traditional o11y — Phil Hetzel, Braintrust
aiDotEngineer
450 views•2026-05-28
Re: 🗣️📍theprophedu📍2026 GST 103 CLASS (E-EXAM REVISION)
theprophedu
636 views•2026-06-04
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanation💯✅
LearnwithSahera
1K views•2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 views•2026-05-29
Search Algorithms Explained in 60 Seconds! 🤖💨
samarthtuliofficial
218 views•2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 views•2026-05-30
Instagram accounts got PWNed
EricParker
13K views•2026-06-03











