diff --git a/asset/feed.xml b/asset/feed.xml index b9fdb85d67..57339827f6 100644 --- a/asset/feed.xml +++ b/asset/feed.xml @@ -1,5 +1,5 @@ -https://ocaml.org/feed.xmlOCaml.org blog2023-07-13T05:47:28-00:00https://tarides.com/feed.xmltarides<p>OCaml-CI started with the goal of making a better continuous build system for OCaml projects. When we began in 2019, the goals were clear: it should provide a zero-configuration experience for OCaml projects using opam and Dune, and it should use an incremental architecture to avoid expensive recomputation of builds. We're delighted to announce that we achieved these goals, and OCaml-CI is currently tracking over five hundred repositories and processing over a hundred thousand jobs daily. This is inspiring news to those already using OCaml-CI or developers looking for a CI solution for their OCaml project.</p> +https://ocaml.org/feed.xmlOCaml.org blog2023-07-14T05:47:25-00:00https://tarides.com/feed.xmltarides<p>OCaml-CI started with the goal of making a better continuous build system for OCaml projects. When we began in 2019, the goals were clear: it should provide a zero-configuration experience for OCaml projects using opam and Dune, and it should use an incremental architecture to avoid expensive recomputation of builds. We're delighted to announce that we achieved these goals, and OCaml-CI is currently tracking over five hundred repositories and processing over a hundred thousand jobs daily. This is inspiring news to those already using OCaml-CI or developers looking for a CI solution for their OCaml project.</p> <p>Throughout 2022, the Tarides CI team worked on rennovating OCaml-CI, focusing on improving the usability of the website, adding build history for branches, supporting new platforms, and launching experimental build support. We will cover all of those things in this blog post and hope you find them useful.</p> <p>There is also a <a href="https://discuss.ocaml.org/t/best-practices-for-continuous-integration-ci-in-2023/12380">Discuss thread on CI Best Practices</a>.</p> <h2 style="position:relative;"><a href="https://tarides.com/feed.xml#what-is-ocaml-ci" aria-label="what is ocaml ci permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>What is OCaml-CI?</h2> diff --git a/data/planet/0branch.xml b/data/planet/0branch.xml index 33f6dd7250..f910b32583 100644 --- a/data/planet/0branch.xml +++ b/data/planet/0branch.xml @@ -1,5 +1,5 @@ -https://blog.0branch.com/rss.xml0branch2023-07-13T05:47:28-00:00https://blog.0branch.com/rss.xml0branch<div> +https://blog.0branch.com/rss.xml0branch2023-07-14T05:47:25-00:00https://blog.0branch.com/rss.xml0branch<div> <div class="span-22"> <div class="span-12"><h1>vile 9.8u</h1></div> <div style="text-align: right" class="span-10 last"> diff --git a/data/planet/ahrefs.xml b/data/planet/ahrefs.xml index 39a5e9894c..20cd6b1637 100644 --- a/data/planet/ahrefs.xml +++ b/data/planet/ahrefs.xml @@ -1,2 +1,2 @@ -https://medium.com/feed/ahrefs/tagged/ocamlahrefs2023-07-13T05:47:24-00:00https://medium.com/feed/ahrefs/tagged/ocamlahrefs<iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fo2u9irv1tnE%3Fstart%3D9%26feature%3Doembed%26start%3D9&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Do2u9irv1tnE&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fo2u9irv1tnE%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/aef5aa9cb9b71aaafb0a07cb48cb312d/href">https://medium.com/media/aef5aa9cb9b71aaafb0a07cb48cb312d/href</a></iframe><h3>Transcript</h3><p><strong>David: [00:00:00]</strong> Hello, my name is David. I run <a href="https://emelle.tv/">EmelleTV</a>. It&rsquo;s a talk show about OCaml, ReScript, and Reason. I often bring guests from the community to talk about them and meet them and asking a lot of questions about the language or what they&rsquo;re working on, and of course having fun with Hindley&ndash;Milner type system. That&rsquo;s part of the show. I work for Ahrefs, it&rsquo;s actually this&nbsp;company.</p><p>Today I&rsquo;m interviewing a coworker, so it&rsquo;s going to be a little bit a branded stream. Hope you understand. It&rsquo;s a lovely company. Apply if you&rsquo;re looking for a job to work on OCaml or Reason. Aside from that, I maintain styled-ppx and implementation of React on server, but that&rsquo;s just enough about me, and I&rsquo;m going to introduce our guest, Louis. Hello, Louis. How are&nbsp;you?</p><p><strong>Louis: [00:00:59]</strong> Good, and&nbsp;you?</p><p><strong>David: [00:01:01]</strong> Good. Very good. You obviously work at Ahrefs. At what team do you&nbsp;work?</p><p><strong>Louis: [00:01:10]</strong> This is recently changing, but I have been in the back-end forever, since like seven years ago and I still have some of the projects that I had when I joined. This was stable. I&rsquo;m in this new team called middle-end. Ahrefs is not very good with naming. We say that it&rsquo;s the hardest thing in computer science. We have front-end that is actually full stack, then we have a back-end, which is more like data, and now we have middle-end, which is somewhere in the middle. I&rsquo;m supposed to lead this new middle-end team.</p><p><strong>David: [00:01:48]</strong> Nice.</p><p><strong>Louis: [00:01:49]</strong> We&rsquo;ll see how it&nbsp;goes.</p><p><strong>David: [00:01:49]</strong> Nice. Today I think we&rsquo;re going to answer a few questions about Ahrefs, I think has been a mysterious company, if you look at it from the outside. When I joined, I think you helped me understand a lot of things that I didn&rsquo;t know about Ahrefs. I might just fire the same questions that I did, just recorded so everybody can understand them. Aside from from Ahrefs, who are you and can you present a little about yourself?</p><p><strong>Louis: [00:02:21]</strong> This is a tough question. Who am I? I grew up in France. I&rsquo;m French, still I&rsquo;m French, but I&rsquo;ve been living in Singapore for seven years, with Ahrefs for seven years. I&rsquo;ve been working in OCaml my whole life basically because my first job was in OCaml, and Ahrefs which is my second job, is in OCaml too. I cannot say that it&rsquo;s better than the rest because I never tried the rest. I&rsquo;ve been involved with OCaml, like the OCaml meetup in Paris for some&nbsp;time.</p><p>I&rsquo;m on the online community. I&rsquo;m part of the OCaml Code of Conduct committee, which is an effort that was started last year, I think. So far we don&rsquo;t have a lot of work, so that&rsquo;s good. I&rsquo;m one of five doing this. Then outside of that, I&rsquo;m a pretty normal person. I&rsquo;m 31 years old, and that&rsquo;s about it, I would&nbsp;say.</p><p><strong>David: [00:03:35]</strong> That&rsquo;s the whole idea. You have been been writing OCaml for a long, long time. That&rsquo;s fair to&nbsp;say.</p><p><strong>Louis: [00:03:40]</strong> I&rsquo;ve been writing OCaml since I&rsquo;m 16 or 17 was when I wrote my first line, like 14 years ago, something like this. There was no Merlin at the&nbsp;time.</p><p><strong>David: [00:03:52]</strong> There was no LSP. The first question is, 15 years, this is a long time, but how do you see the evolution of entire language? Would you split it in chunks? How have you seen the progress of the language?</p><p><strong>Louis: [00:04:08]</strong> It&rsquo;s hard to say. When I joined the OCaml world, it was because of people who nowadays are fairly important like Gabriel Scherer, who&rsquo;s working in Inria, I think, but he&rsquo;s one of the main maintainer for OCaml. He was in this French forum, pushing very hard people to try OCaml and I got convinced. I started just writing a few lines here and there, and then I just stick to that for a long time. I&rsquo;ve been mostly a user like this. My usage has extended over time, but I&rsquo;ve never been called a contributor. My point of view is more as a&nbsp;user.</p><p>The biggest difference is the size of the community, I would say. It&rsquo;s much more dynamic than it used to be. We used to install packages like OCaml libraries, using Debian packages. It was apt install something. There was no opam, there was no Merlin, there was no vscode,&nbsp;right?</p><p><strong>David: [00:05:25]</strong> Right.</p><p><strong>Louis: [00:05:25]</strong> LSP didn&rsquo;t exist, so way less library. I think you can see today how it was in the past because you can see, we have 10 different libraries to do HTTP 1.1. We have 10 different standard libraries, and it&rsquo;s legacy of what OCaml was in the past. We used to have all those smart people, but they had no way to collaborate. There was no opam, there was no way to share your work. Everyone was smart enough to rewrite&nbsp;&mdash;</p><p><strong>David: [00:06:04]</strong> Build your own library for&nbsp;http.</p><p><strong>Louis: [00:06:05]</strong> Yes.</p><p><strong>David: [00:06:06]</strong> Right. That&rsquo;s always interesting for me, how OCaml got so many different things that are hard to create, like standard libraries. I think recently, Containers reached 10 years, so it&rsquo;s like what? [chuckles] It doesn&rsquo;t make much sense. If you look at now, it doesn&rsquo;t make much sense, but if you look at historically, it does make&nbsp;sense.</p><p><strong>Louis: [00:06:35]</strong> When you have no choice, you do it. You don&rsquo;t know that it&rsquo;s harder, you just see &ldquo;Oh, I can do it,&rdquo; and you do&nbsp;it.</p><p><strong>David: [00:06:42]</strong> Yes. You need to think it&rsquo;s easy. You need to start a standard library or http library saying, &ldquo;Oh, it&rsquo;s easy.&rdquo; Then, you start a little bit, and eventually, you create something. Last week&#8202;&mdash;&#8202;Oh, sorry, go&nbsp;on.</p><p><strong>Louis: [00:06:57]</strong> No, go&nbsp;ahead.</p><p><strong>David: [00:06:59]</strong> Last week, I tweeted that OCaml suffers a lot from the Python Paradox. The Python Paradox, I think somebody write it, I think it was, I don&rsquo;t remember the name of the guy, but somebody write it in 2004, that when you use Python for a company, and you get the smartest people that they want to innovate, and you have the pioneers of the language. Then, by default, you try to hire people that are in love with software, so eventually, they create good software or they are willing to suffer from getting out of the comfort zone and create software. I believe the combination is the same spot. Can you see, is that true? Do you&nbsp;agree?</p><p><strong>Louis: [00:07:49]</strong> I don&rsquo;t know if that&rsquo;s true. Partially, it&rsquo;s a strategy of Ahrefs, so I have to say it&rsquo;s&nbsp;true.</p><p><strong>David: [00:07:55]</strong> [laughs]</p><p><strong>Louis: [00:07:58]</strong> Yes, I think it&rsquo;s partially true, but it&rsquo;s not completely correct. For OCaml, at least it&rsquo;s a bit different from Python, because OCaml has this strong academic influence, so a lot of people are actually researcher. There is a big benefit that they have, not free time, but they manage their time, they manage what they work on, and they decide what is important. They got all this time to actually write this complicated code many times because actually, it&rsquo;s part of their job to just redo the same thing in better ways. It&rsquo;s normal you have to explore a&nbsp;subject.</p><p>It&rsquo;s okay to do it multiple times. It&rsquo;s a combination of those people are working in the right place, they have the right time, and they have the correct background. A lot of people were working on subjects that allowed them to do it. Some, it&rsquo;s because they were very strong in writing languages. Some, it&rsquo;s because they have this strong Unix background, I would&nbsp;say.</p><p><strong>David: [00:09:05]</strong> Right. It&rsquo;s very unixy. The start of OCaml is very unixy. That&rsquo;s&nbsp;true.</p><p><strong>Louis: [00:09:14]</strong> Xavier Leroy wrote LinuxThreads, I think that was used in Linux forever, so there is this background. Probably, it&rsquo;s a bit different in Python because it grew more in the industry rather than in an academic setup. For sure, if you try to target people who live in a niche, you find people with a different interest from the main programming community, I would say. At the same time, I think some of the best meetup or conference I&rsquo;ve been to were Java&nbsp;meetup.</p><p><strong>David: [00:09:59]</strong> All&nbsp;right.</p><p><strong>Louis: [00:10:00]</strong> They know that their language is boring. The language is the same since 20 years or 30 years. There are some changes but they don&rsquo;t really care about the language too much. It&rsquo;s a huge, huge community. Basically, everything already exists. There is no big bragging, everyone can do everything. There are 10 versions of everything, whatever. The benefit is that they are super open-minded.</p><p>Oh, something is new. Something is different. Okay. Let&rsquo;s see that. You go to that meetup and they will not talk only about all the fancy new feature in Java. It&rsquo;s like, &ldquo;Oh, I saw this new git tool. Oh, it&rsquo;s funny. Okay, let&rsquo;s try to use this.&rdquo; A new way to do web development. Okay, let&rsquo;s study the subject. It&rsquo;s not about Java itself because the language is not interesting enough. It&rsquo;s about other programming stuff. It&rsquo;s very fun to&nbsp;attend.</p><p><strong>David: [00:11:03]</strong> That&rsquo;s a good one. Actually, many people that now are starting to hear OCaml for the first time, after they leave or they got disappointed with the Rust policy drama. These people cannot get into OCaml because some influencer wanted to bash on Rust. They started exploring all the languages and of course Ocaml was one of those. Aside from Zed or whatever you compare it with, low level programming languages. Do you see those influencers move people to actually try the language and deploy it into users and doing serious stuff, or it&rsquo;s more like vain marketing?</p><p><strong>Louis: [00:11:56]</strong> I&rsquo;m not a big Twitch person. I don&rsquo;t know [crosstalk] modern influencers.</p><p><strong>David: [00:12:02]</strong> That&rsquo;s&nbsp;true.</p><p><strong>Louis: [00:12:03]</strong> I think it exists in two forms. In the past it existed in two forms. You had influencers, you had Rob Pike and- who&rsquo;s the other person? The two person who are behind Go. They do not make a good language but they are influencers. They were like, &ldquo;Oh, yes. We did UTF-8 and a Plan 9 in the past and we work at Google. Oh, it&rsquo;s going to be amazing.&rdquo; No, it&rsquo;s a crappy language, but they are influencers. They move&nbsp;people.</p><p><strong>David: [00:12:32]</strong> [laughs] Okay. Would you say that Go is&nbsp;crap?</p><p><strong>Louis: [00:12:38]</strong> Go is a language. I haven&rsquo;t used Go 2 extensively.</p><p><strong>David: [00:12:42]</strong> This is recorded. This is not a beer in Singapore. This is recorded. You can obviously bash go, that&rsquo;s part of the&nbsp;game.</p><p><strong>Louis: [00:12:50]</strong> Let&rsquo;s say Go is not the most modern language there&nbsp;is.</p><p><strong>David: [00:12:54]</strong> Right. Thank you. This is just for the headline. We don&rsquo;t want the headlines- because Ahrefs is going to be like&#8202;&mdash;&#8202;No, I&rsquo;m joking. [crosstalk] Yes, go on.&nbsp;Sorry.</p><p><strong>Louis: [00:13:10]</strong> On the same topic of influencer, we saw it with Reason. When the Reason comes, it&rsquo;s not just a random person creating Reason. It&rsquo;s Jordan and he comes with a React background, and he comes with followers. He is not doing videos online but it&rsquo;s the same idea. I think yes, it has definitely an influence and OCaml grew a lot when Reason&nbsp;started.</p><p><strong>David: [00:13:38]</strong> Yes, that&rsquo;s&nbsp;true.</p><p><strong>Louis: [00:13:39]</strong> I definitely think it has an influence.</p><p><strong>David: [00:13:43]</strong> That&rsquo;s true. From the community, how have you seen the Reason creation and adoption from your point of view? You can bash Reason if you&nbsp;want.</p><p><strong>[00:13:43]</strong> [crosstalk]</p><p><strong>Louis: [00:13:56]</strong> At that time I think the OCaml community was one IRC channel. It was a bit different from now. I think what I was not super convinced by when Reason to syntax arrived, I think the original claim by Jordan was he&rsquo;s making a better syntax. I was not super convinced that the syntax was better. It was developed independently from&nbsp;OCaml.</p><p>By experience I already knew at the time that if you start to fork or develop on your side and don&rsquo;t integrate fairly quickly with upstream it&rsquo;s actually never going to be integrated with upstream.</p><p><strong>David: [00:14:53]</strong> Right.</p><p><strong>Louis: [00:14:54]</strong> I don&rsquo;t know why exactly, but it has happened a few times. Then there is a question of bucklescript because if you write Reason it&rsquo;s two sides. There is a syntax which I only partially understood too because I was not a web developer, I&rsquo;m still not a web developer. I did not know about JSX. I did not know how powerful it was and I think React was not as big at the time too, but I think JSX is a nice idea and there are a lot of things in the syntax that are nice, like parentheses around arguments is a problem but it has some benefits, too.</p><p><strong>David: [00:15:42]</strong> Yes, I think some trade-offs from OCaml, or at least some edge cases from the syntax from OCaml got resolved in Reason just by adding more- like the parentheses or the braces or the semicolons. But yes, the others are, can remove some problems from the syntax. Not problems, but just the edge cases from the cleanness for&nbsp;OCaml.</p><p><strong>Louis: [00:16:10]</strong> Yes. Even sometimes it&rsquo;s not edge case but it&rsquo;s nice to see very clearly for example, when you apply a function, where are the arguments? Where it starts where it ends? There are benefits, obviously, like the OCaml syntax or Haskell syntax is lighter, we will say, have some benefits. The other one is nice,&nbsp;too.</p><p><strong>David: [00:16:36]</strong> Yes, definitely and you mentioned BuckleScript?</p><p><strong>Louis: [00:16:40]</strong> Yes. BuckleScript, they didn&rsquo;t have&nbsp;&mdash;</p><p><strong>David: [00:16:42]</strong> That was not so well received.</p><p><strong>Louis: [00:16:47]</strong> Yes, I think because there was Js_of_ocaml idea. There was js_of_ocaml and so again, it was like yes, I do something different and- I think Bob developed it fully inside Bloomberg at the time. Basically, he came out and he had, &ldquo;Oh, yes, I have a new project and it&rsquo;s working already.&rdquo; He didn&rsquo;t start to develop it in public. The community was much smaller, too so every time you split efforts like this, it&rsquo;s kind of costly. People will say, &ldquo;Yes, we will try to collaborate. We&rsquo;ll try to make the two projects work together,&rdquo; or whatever and it never works. Never works. I don&rsquo;t think I understood all the trade-off. I&rsquo;m happy that I invited Bob to the OCaml meetup in Paris which retrospectively, it was a good thing to&nbsp;do.</p><p><strong>David: [00:17:50]</strong> Yes, for the record, Louis was running the OCaml Paris Meetup, I think. Yes, go on with the&nbsp;story.</p><p><strong>Louis: [00:18:00]</strong> Yes, so when I moved to Singapore, I still organized one meetup, even though I was in Singapore and I invited Bob to present BuckleScript. At the time, it was a bit controversial, because many people were a bit unhappy with what he was doing, but I&rsquo;m happy that I did it. I didn&rsquo;t understood what I was doing exactly but at the end, I think it was the right thing to do. Even if the project died later on, you have to give such projects a&nbsp;chance.</p><p><strong>David: [00:18:35]</strong> Yes, I think I wouldn&rsquo;t say that BuckleScript died. It&rsquo;s more like BuckleScript has been working for seven years, I&nbsp;think.</p><p><strong>Louis: [00:18:42]</strong> Yes, no, even if it was a failure, which it was not, but maybe like six months later, it could have died and disappeared. Yes, I think when people have a drastically different approach, usually they have a reason. It&rsquo;s worth listening. A lot of what Bob defended, I&rsquo;m not sure I completely agree with it. He wants a very stable compiler, for example. He said, in Bloomberg, they are using GCC 3 or 4, I don&rsquo;t remember, since&nbsp;forever.</p><p>So they don&rsquo;t need to upgrade the compiler, the GCC compiler, for example. He thought the same idea can apply to OCaml, we don&rsquo;t need to follow the upstream compiler all the&nbsp;time.</p><p><strong>David: [00:19:27]</strong> Right.&nbsp;Yes.</p><p><strong>Louis: [00:19:29]</strong> Most companies actually they don&rsquo;t want to change compiler version. They want something stable. They want no surprise, which has some value, or the stability has some&nbsp;value.</p><p><strong>David: [00:19:40]</strong> Yes, that&rsquo;s true but I think when he mentioned about the compatibility with the compiler, I think it&rsquo;s mostly OCaml has been very stable since, what 6, 7 years ago, I think. I think there were some small changes or some addition features, but nothing really break, but mostly the syntax. Then he complained about the parsing, like the AST modifications, those were present, those were changing between versions. He wanted to not- because BuckleScript is a fork of the common compiler and embedded into ReScript&nbsp;now.</p><p>Yes, he was complaining about the AST transformations because every version changes a lot. There are migrations. You could write some logic to migrate from one to another. It&rsquo;s painful if you maintain a fork of this, you might suffer a lot from updating from one compiler to&nbsp;another.</p><p><strong>Louis: [00:20:41]</strong> Yes, and I think for him, even as an end user, the stability has some value. It&rsquo;s interesting for him to have a stable compiler and even for his target, the people he&rsquo;s targeting, the stability has some value&nbsp;too.</p><p><strong>David: [00:21:00]</strong> After you mentioned that people were installing or sharing libraries through Debian packages, which maybe- I&rsquo;m as old as you, but maybe I&rsquo;m too young to see how those package managers could work with apt get. What&rsquo;s the position of the tooling? Right now I think we are in a state where we have two bigger players such as opam and dune, as Package Manager and Build Infrastructure, we&rsquo;d call it, I don&rsquo;t know. Now dune is exploring installing packages. How do you see the tooling these recent&nbsp;years?</p><p><strong>Louis: [00:21:48]</strong> It&rsquo;s amazing. It&rsquo;s completely incredible. Then people will have different opinions on is opam perfect or whatever. If you compare to what it was before, it&rsquo;s incredible. I think even if you compare to other languages, it&rsquo;s a fairly solid experience now. Opam is working well. You just need to learn the UI, but it&rsquo;s working fairly well. Dune is relatively fast, easy to use. The LSP is pretty magical. Merlin is a very solid tool. It was one of the first, I think I would say, like a small language with a tool as powerful as&nbsp;Merlin.</p><p>It&rsquo;s not only powerful, it&rsquo;s avantgarde. It understood already that you had to be able to do error recovery and that you had to change the way you parse files to be able to work with something that is half&nbsp;broken.</p><p><strong>David: [00:22:57]</strong> Yes, that&rsquo;s&nbsp;true.</p><p><strong>Louis: [00:23:00]</strong> The people behind Merlin are super smart. In a way, it&rsquo;s not a surprise.</p><p><strong>David: [00:23:05]</strong> Right. You actually contributed to the LSP and dune, to both projects, I saw your contributions.</p><p><strong>Louis: [00:23:13]</strong> Yes, I have commits on many small- it&rsquo;s mostly small contributions, but I have commit on everything, I think at some&nbsp;point.</p><p><strong>David: [00:23:19]</strong> Right.</p><p><strong>Louis: [00:23:21]</strong> LSP, I participated in putting some ppx deriving stuff and I wrote a bunch of commands. I implemented some Merlin behavior inside LSP. If you hover multiple times on the same value, the type will be more and more verbose. I took this behavior back to LSP. Dune I have mostly bug fixes, probably small documentation, nothing&nbsp;big.</p><p><strong>David: [00:23:58]</strong> One of the things that you mentioned as well, I think we talked about this before. When OCaml was very young, all features that got added into the language were PhD projects, where it&rsquo;s a student that is very passionate or maybe just his guidance is OCaml fan, he just explored with a language in the theory on academia. Then he worked on a paper and eventually it gets released as part of the language. That was the times where maybe Jane Street not even started using OCaml seriously. Do you see that now? Do you see that those features or academic features got into language? Do you think it&rsquo;s a weird mix now or they compose well together? How do you see language after these contributions?</p><p><strong>Louis: [00:25:04]</strong> I was looking today at the OCaml change log because I was wondering when was the release of OCaml 4, and that was 11 years ago because OCaml 4 is- before to OCaml Multicore is the last time there was a big change which was GADT. In the meantime there was mostly small changes. I don&rsquo;t think the language changed much. If we look what were the big features we could say like the objects in OCaml, GADT, OCaml Multicore.</p><p>They all were developed by people in a research setup and somehow it seems to work. I&rsquo;m not a maintainer on OCaml. I think it works also because they don&rsquo;t have a lot of energy to integrate a lot of new features, they are very, very picky on what they actually accept in the compiler. Only the most solid implementations will get&nbsp;in.</p><p><strong>David: [00:26:36]</strong> Yes, that&rsquo;s true. I think the quality is something that everything core team members says all the time that all these things would be amazing to do but our quality bar is very high. Yes, you need to work on it much more to let us just even look at it. Yes, that&rsquo;s&nbsp;true.</p><p><strong>Louis: [00:26:54]</strong> Then there are things that do not compose super, super well. There are part of the module language and part of the object language that do not compose very well. You can make the compiler more or less blow up or the compilation time will become crazy. Actually, those are parts that I don&rsquo;t know very well. I very seldom combine first-class modules and&nbsp;objects.</p><p><strong>David: [00:27:21]</strong> Objects, yes. That&rsquo;s something I haven&rsquo;t done yet. I think the only experience with that combination might be ppxlib maybe, because you have the traversers. Yes, you use them. You instantiate the traverser. You don&rsquo;t do anything with internal states of anything. Good point. One thing that maybe it&rsquo;s worth saying is that right now you work at Ahrefs for seven&nbsp;years.</p><p>At the beginning when Ahrefs pick OCaml or Igor, our CTO came with OCaml in the back, there were not many companies working on- using it, using OCaml. Now we have Tezos, Tarides, Ahrefs of course, LexiFi, Bloomberg, BeSport. Many companies that have- even some of them have their own forks of OCaml that they are experimenting and deploying it or whatever. Seven years ago, do you think it&rsquo;s a risky decision? The second question is how can you convince your boss about using&nbsp;OCaml?</p><p><strong>Louis: [00:28:35]</strong> For sure, I think picking OCaml at the time was a risky choice because who do you hire? It&rsquo;s like there were five OCaml developers. In Paris, you can find people. In Paris, you can find students. You go to the OCaml meetup and socialize and you can more or less build a company, which is what the previous company I was in called Cryptosense was doing. This is how BeSport came to life. BeSport just picked a few people around Vincent Balat and then you meet people. You steal one or two person from the OCaml meetup and you tell them, &ldquo;Oh, join my company,&rdquo; and now you have enough people to push a project forward. How do you do this from another country? Even today, I think it&rsquo;s not an easy&nbsp;choice.</p><p><strong>David: [00:29:35]</strong> Somehow risky, yes. That&rsquo;s&nbsp;true.</p><p><strong>Louis: [00:29:38]</strong> Today, you can hire, but even if you have, I don&rsquo;t know, 2,000 packages on opam, the tooling is still- the libraries are not, there are not libraries for everything like you have in some other languages.</p><p><strong>David: [00:30:00]</strong> Right. It&rsquo;s big enough, but it&rsquo;s not populated with everything.</p><p><strong>Louis: [00:30:07]</strong> I don&rsquo;t know if we have full support of GRPC. I&rsquo;m not sure that we have complete support of http2 or 3. It&rsquo;s not that small, but many things like this. I would say, today I would say it&rsquo;s a risk. How would I convince my boss to move to OCaml? I would&nbsp;&mdash;</p><p><strong>David: [00:30:34]</strong> Would you do it? Maybe you would not do it. Maybe you say, &ldquo;It&rsquo;s fine, we can do with whatever,&rdquo; with Java you said that you enjoy the Java meetup, then you join your company writing Java. Would you be happy writing Java? Would you be fine? Or you would say &ldquo;Oh, OCaml here makes sense, let&rsquo;s try to change it.&rdquo; How would you do&nbsp;it?</p><p><strong>Louis: [00:30:57]</strong> I think if I was in a small company, it would definitely make sense to use OCaml. It&rsquo;s interesting because in a small company you could say all the Java tooling has more value than in a big company, but at the same time you have less hands. You need to be more productive per person and you have less time for maintenance, and those are two things for which OCaml is very strong. You can write few lines of code that do many things, so it&rsquo;s very expressive. At the same time, it&rsquo;s solid enough that when you write your code, you can launch it in prod and you can leave it there for some time and hopefully nothing&nbsp;breaks.</p><p>The language is stable, the compiler is stable, so there will be no big surprises. I think that&rsquo;s very valuable, and then you compare, what are the alternatives today? Rust is incredibly hard. It&rsquo;s very, very hard language to use. You can do fancy stuff, you have incredible community but it&rsquo;s a super hard language to use. You have what, Python, but then you are losing all the type safety. You have Go, which is a bit in between those. You have a fast Python I would say. Then you have Java. Java which has a huge community, and is a fast language.</p><p>In a way I think OCaml is closer to Java. It&rsquo;s one easy language to use, solid, no surprises. The feature set is not incredible but it&rsquo;s working well enough and you can do more or less what you want with it. You can do work in the back end, work in the front end, it&rsquo;s approachable. To me it&rsquo;s a replacement to Java. It&rsquo;s a light&nbsp;Java.</p><p><strong>David: [00:33:04]</strong> I&rsquo;m mostly front-end. Now I&rsquo;m doing some back-end stuff but I mostly am experienced from front-end. You are experienced from back-end of course and when I&rsquo;m talking to back-end persons from OCaml, every time I talk with a back-end person who only writes OCaml they mention then the runtime. From the front-end, it&rsquo;s a problem that I have never, ever thought. I know that the problem exists because I studied computer science and all these things, but it&rsquo;s something that in the front-end I never think about&nbsp;it.</p><p>How could you describe to me that- I know a little bit about the memory presentation and about the stack, the heap, how memory works, even the O(n) notation, O big notation. How can you describe the runtime of OCaml, from someone who doesn&rsquo;t know much about runtimes, so has nothing else to compare, rather than notes, for example. That&rsquo;s my experience.</p><p><strong>Louis: [00:34:08]</strong> Yes, I&rsquo;m not an expert either, but it&rsquo;s an interesting point, actually, because if you go on, for example, the real-world OCaml, there is a whole chapter on the runtime. I think it&rsquo;s important for the OCaml people because of their background. We have those unixy people, so they have experience with C before and because in C you need to know what is a representation in memory of everything you manipulate, they took that from C and bring it to OCaml. Those people, they like to know, when I have an integer, it&rsquo;s going to be nowadays, 64&nbsp;bits.</p><p><strong>David: [00:34:56]</strong> 63 right? That&rsquo;s the&nbsp;&mdash;</p><p><strong>Louis: [00:34:59]</strong> Yes, one bits for the right GC, and then we have 63 bits for the&nbsp;value.</p><p><strong>David: [00:35:05]</strong> Right. Yes, people love the runtime. I think it&rsquo;s like those things when&#8202;&mdash;&#8202;You guys started talking about the front-end. For me, I love CSS. I can talk all the time about CSS, but if you never have experience with a language or with designing the UI, CSS means nothing. You understand what they are saying because the thing makes sense, but semantically it doesn&rsquo;t. When you talk about the run time at the beginning, for me it felt like I have never, ever thought of&nbsp;this.</p><p><strong>Louis: [00:35:41]</strong> I guess it&rsquo;s two sides. There is the technical side, how it&rsquo;s actually implemented that when you allocate a value, where do you put it in memory? What is the representation of that value in memory? For example, we said that the int are 63 bits actually, that when you allocate the value, you allocate by words in OCaml. You have one word, for example, if you allocate the values that is on the heap, you have potentially two words. You have one word, which is a pointer to the actual value, and then the values, which is like a number of words afterwards.</p><p>You have the GC, so when is it triggered? Actually, the GC can be running every time you can allocate a value which means that you can write code that will not trigger the GC. It means you can write code that is very fast because there will be no interruption, and I think that&rsquo;s critical for companies like Jane Street. Then yes, the other side is the runtime from a user perspective. I see it two way. I see one way that it&rsquo;s like no one knows about the runtime because it&rsquo;s very, very simple in OCaml. You don&rsquo;t need to deal with the runtime very&nbsp;often.</p><p>You just know that you pass values by reference, so you don&rsquo;t make many copies, and then the GC is fairly fast and will not stop for too long. That&rsquo;s probably what 99% of the normal OCaml people know about the runtime. Then an interesting fact that comes with that is that the OCaml compiler is bad by modern standards, that it&rsquo;s not doing any kind of optimization or very little optimization, yet the native code is fairly fast. The native code that is generated for an OCaml program is fairly fast. I think if you look at the benchmark it&rsquo;s not too far away from C++, which is surprising, and it means that the language is pushing you to write code that by default is fairly efficient.</p><p><strong>David: [00:38:06]</strong> That&rsquo;s exactly my experience.</p><p><strong>Louis: [00:38:09]</strong> The types that are offered and the functions, the APIs that are offered, somehow allow you to write code that is not too, too bad. I think it&rsquo;s a miracle, but it&rsquo;s an interesting one.</p><p><strong>David: [00:38:23]</strong> Yes, that&rsquo;s exactly my experience. At Ahrefs, the formula of the Coca-Cola of Ahrefs is like the crawler, the thing that navigates the internet and saves data. After that, we have storage and all of these pieces that are complex. What can you explain about the secret sauce of Ahrefs? What are they from the outside? Many people would never, ever write a crawler or a very dummy one, but for one that indexes 9 billion pages, 1 trillion? I don&rsquo;t know the numbers but insane amount of numbers. What can you&nbsp;explain?</p><p><strong>Louis: [00:39:10]</strong> I guess the first question is what is a&nbsp;crawler?</p><p><strong>David: [00:39:13]</strong> Yes, yes, because you read the webpage, you scrap a webpage, that&rsquo;s fairly simple. You can do it in any language, but then what do you extract about this page, and more importantly, how you navigate to the next one. I think that these are the two main questions.</p><p><strong>Louis: [00:39:35]</strong> What you extract, depends. Ahrefs, we care about the links. What is Ahrefs building is more or less a map of the internet. The crawler is running all the time. It&rsquo;s downloading, I don&rsquo;t know, like 4 million pages per minute or something like this. There is a counter. Every minute we crawl 5 million pages. We have been talking for 40 minutes. You can count how many pages we have downloaded in a period of time. We download those pages and then we extract the links. That is the main information we care about. This is not the only information.</p><p>First is how do you parse HTML and how broken is HTML on the internet? This is horrible. The internet is broken. You have to extract all the links in a page and then you have to store all those links. When you store links, because&#8202;&mdash;&#8202;What is a crawler exactly? Where does it start and where does it end? Is it only the part that is downloading the html? Or is it actually the parsing too, and it&rsquo;s influencing how you are storing your data, because&#8202;&mdash;&#8202;Let&rsquo;s say you download a page and you have a 100 links in it, you do at least two things with those 100 links that you want to reuse them in your scheduler to decide what do I crawl&nbsp;next.</p><p>You also want to update counters, because you want to update your map of the internet. You downloaded a page, you know that there are links and you want to update the map. How do you update the map, because you have a 100 new links? What do you do? You update a 100 small counters, a 100 small integers. Then can you do it 5 million times per minute? Then can you do it in many direction, because it&rsquo;s a&nbsp;graph.</p><p><strong>David: [00:41:48]</strong> You would loop. If you don&rsquo;t do it properly, you would loop&nbsp;forever.</p><p><strong>Louis: [00:41:55]</strong> You have links between pages, but then you want to also count links between domains and you want to count the links inside the domain. Then how do you decide it&rsquo;s an interesting link or not? Then when you index a link, what do you index? You need to index the link itself, but you want to index the text that is attached to the link, maybe the paragraph that is around that specific link. You could look where it is in the page. Is it visible or not? You have&#8202;&mdash;&#8202;It&rsquo;s an open question.</p><p>That&rsquo;s an interesting question, because there is no one that can say, &ldquo;I&rsquo;m doing a crawler and this is the right way to do it.&rdquo; Even big companies like Google, they make tradeoffs. They decide, &ldquo;We do it in one way.&rdquo; Then they gather information they can gather. They cannot download every page on the internet all the time. They cannot download and process stuff fast enough. There is more content that is created than content that can be downloaded.</p><p><strong>David: [00:43:00]</strong> It&rsquo;s interesting, because if you think about fixing a bug on the crawler, it&rsquo;s usually when you have a database, you can run migrations or you can get out data. You can store data broken or whatever. You can fix it. If you have the history of internet, that&rsquo;s another source of data. It is life. I don&rsquo;t know the right metaphor, but it&rsquo;s&#8202;&mdash;&#8202;If you have to fix a bug on the crawler, that means that you stored information wrongly. That can affect the next version of your map, because it&rsquo;s not only a map, it&rsquo;s a map and a timeline. You can just look it up. It&rsquo;s an archive as well. I think internet archives, they don&rsquo;t have a crawler. I think they don&rsquo;t have a&nbsp;crawler.</p><p>It&rsquo;s the idea of&#8202;&mdash;&#8202;You can improve the crawler. Something that you didn&rsquo;t look before, now you are going to look it up now. I don&rsquo;t know, when&#8202;&mdash;&#8202;I think at some point we&#8202;&mdash;&#8202;At the beginning, either we started indexing, I think videos was&#8202;&mdash;&#8202;I don&rsquo;t remember. Some media, I don&rsquo;t know. That, of course, blowed up immensely, everything- they complicated everything.</p><p><strong>Louis: [00:44:14]</strong> Yes. That&rsquo;s an interesting question. Actually, Because, it is right that your database is very big so you cannot just migrate stuff. The big data page says we have 170 trillion rows in the database, so we cannot just push this to somewhere else.</p><p><strong>David: [00:44:35]</strong> First of all, what technology is that running&nbsp;on?</p><p><strong>Louis: [00:44:40]</strong> I think that&rsquo;s a combination of different technologies. That will be a ClickHouse and then some internal database. Custom&nbsp;stuff.</p><p><strong>David: [00:44:52]</strong> At Ahrefs, correct me if I&rsquo;m wrong, we like to build our own things mostly. When I have it in other companies, you would use Sentry for reporting, or you would use PagerDuty for live crashing, or you would use whatever tool that you- or a web server, like a framework that runs your server. I think we implemented all of this by ourselves. That sounds both crazy from the outside, but when you join Ahrefs, if you ever join the company, you understand perfectly why has it been done like that. Yes, we have our own database. It&rsquo;s&nbsp;scary.</p><p><strong>Louis: [00:45:41]</strong> It&rsquo;s not completely our own database, it&rsquo;s more like a wrapper around existing database. It&rsquo;s partially because we have no choice. The problem is large enough that you don&rsquo;t have a ready made solution. Google was like this for a very long time. They had MySQL, I think that they used very extensively MySQL and it&rsquo;s just that they used it in a way that was working for them. They don&rsquo;t have a giant MySQL database, but probably they just sharded the&nbsp;problem.</p><p>They have one small database per server and they have a smart way to send the tasks to the right server to retrieve the data they want. Because you have to build on top of something, we are a small company. The total number of employees, I don&rsquo;t know, it&rsquo;s 100 plus now, but the back-end team is still 15 people or something like this. We don&rsquo;t have too many&nbsp;hands.</p><p><strong>David: [00:46:43]</strong> Yes. That&rsquo;s&nbsp;insane.</p><p><strong>Louis: [00:46:47]</strong> You ask what you do when there is a bug in the crawler and it affects how you conceive the programs because you know that something will run forever. The strategy becomes, I don&rsquo;t want to fix bug by hands. It&rsquo;s, you have an auto healing index. You crawl a page for the first time, and let&rsquo;s say you make a mistake. The number of links you counted is off by one. You know it was like this for three days because you deployed, it was broken. Three days later, you notice it, and you cannot go back in time. It&rsquo;s already too&nbsp;late.</p><p>Instead, what you do is that you fix your crawler. The way you store the data, you make sure that the next time you crawl the page, it overrides the previous version with something that is correct now. You have to have those auto healing processes, and you cannot attend to every small detail by hand, and the full rebuild of the index will be the last resort. Only if you have absolutely &mdash;</p><p><strong>David: [00:48:01]</strong> Did that ever&nbsp;happen?</p><p><strong>Louis: [00:48:06]</strong> It partially happened. Not everything, but there are things that were rebuilt once in a while. We were storing two things because we download pages, we download the HTML that we store, and then we have two counters. We have the counters we extract from the page. Let&rsquo;s say you have one link that you see twice in a page. You have this link and the number two attached to it, and then you have diff. You store diff, let&rsquo;s say, because you downloaded that page that belongs to the domain ahrefs.com. Now you see that that specific URL, for example, has three links that were not present&nbsp;before.</p><p>You store somewhere plus three, and later on you will aggregate all those plus three, plus one, minus one together. There are two different things. You have the absolute numbers and then you have those diffs. Once in a while, we have a bug that we didn&rsquo;t compute the diff correctly. Then we will rebuild the diff from scratch. We will go back to those absolute numbers, process them altogether and then restore it. Then when it happens, it can take a month, but it hasn&rsquo;t been done in a long time. It&rsquo;s a long&nbsp;process.</p><p><strong>David: [00:49:28]</strong> Right. That&rsquo;s interesting.</p><p><strong>Louis: [00:49:32]</strong> This is where OCaml is shining, too, because it&rsquo;s very easy to have multiple versions of the same type, for example. If you store data, with a version number in the database, you have a&nbsp;variant.</p><p><strong>David: [00:49:48]</strong> Yes, you treat it differently or?</p><p><strong>Louis: [00:49:50]</strong> It&rsquo;s fairly automatic and-&nbsp;yes.</p><p><strong>David: [00:49:59]</strong> Yes, as well we have diffing on HTML. One of the big features that we did, I think that was last year, that we have diffing for the content of the page, or the diffing of links, we have as well diffing of content. That&rsquo;s very&nbsp;good.</p><p><strong>Louis: [00:50:18]</strong> We have a lot of small funny features. We are one of the first company after Google, obviously, to render pages at scale. We have hundreds of servers running chrome, and as much as possible, when we download the HTML of a page, which is the raw HTML, then we will put it in Chrome, let it run for a while and then get the rendered version of that. Which is incredibly expensive time-wise, because it&rsquo;s much harder work than just downloading the HTML. We couldn&rsquo;t do this if there was no project like Chrome that would be open source and usable for free. We are standing on the shoulders of giants for&nbsp;this.</p><p><strong>David: [00:51:08]</strong> Imagine trying to create a web engine just to see a page from the server. That&rsquo;s very good. What&rsquo;s the favorite part of working at&nbsp;Ahrefs?</p><p><strong>Louis: [00:51:26]</strong> To me, is the people. I&rsquo;m not a SEO expert, and I&rsquo;m not a SEO fan either. I didn&rsquo;t join Ahrefs because I love to study the internet, that was not my goal, and I&rsquo;m not a marketing person, so I don&rsquo;t have a big use for SEO by myself. At first when I joined, the technical challenge was fun, but nowadays to me, the value is more the people. You get to meet smart people who work on complicated projects. I spend a lot of time dealing with interns, for example, which is super gratifying, I feel. I try to spend a good amount of time sharing with other people, working on the tooling or stuff like this. I really like that part, you can see the influence you have on other people when you make their life&nbsp;easier.</p><p><strong>David: [00:52:32]</strong> That&rsquo;s good. What&rsquo;s your favorite part of&nbsp;OCaml?</p><p><strong>Louis: [00:52:37]</strong> Of&nbsp;OCaml?</p><p><strong>David: [00:52:38]</strong> Yes. You can say the&nbsp;people.</p><p><strong>Louis: [00:52:41]</strong> When it compiles, it works. That&rsquo;s the key point. Unlike Go, we have some&nbsp;types.</p><p><strong>[00:52:41]</strong> [laughter]</p><p><strong>Louis: [00:52:59]</strong> If we are a bit serious, maybe not the language itself, but the LSP is super, super good nowadays. It&rsquo;s definitely a very good experience. We have to thank Tarides for all the work they are doing on the tooling over the past three years now, because it&rsquo;s&nbsp;crazy.</p><p><strong>David: [00:53:21]</strong> I think Tarides is carrying most of the boring work. Not boring work, but work that is always hidden. That you don&rsquo;t get any fame, but you will only get the trash. When the toolings don&rsquo;t work, you complain, and when tooling works, you just don&rsquo;t celebrate it. Tarides is behind, for sure. You have been going to ICFP, ICFP is international conference for functional programming, for quite some time. One of the verticals, or one of the parts of ICFP is&nbsp;OCaml.</p><p>Last year we outgrow our neighbors, our language neighbors, I think it was Scala, maybe, Haskell. I think we outgrow them. What do you think about the conference?</p><p><strong>Louis: [00:54:20]</strong> Same thing, it&rsquo;s amazing to go there and meet the people actually, because ICFP, it has multiple parts. The main track is a bit more academic. Even though some people who work at Ahrefs, they published there, but they were students when they did it. It&rsquo;s a bit more academic. Then you have all the workshops that are a bit more approachable, at least for me, but you spend one week with smart people who are very excited by what they&rsquo;re doing. This is the amazing part. Once a year, everyone is super happy to meet each other. This is very much a good experience, but it&rsquo;s- about conferences, I think the ReasonML ones were very, very nice&nbsp;too.</p><p>Again, I&rsquo;m a back-end person, but it was super cool to attend a conference on a different topic where people have different interests, and it was the early days of the language for people who were super interesting, the people who attended were curious and wanted to see something new. They had different ideas. I think that was super&nbsp;good.</p><p><strong>David: [00:55:36]</strong> Yes, those conferences were very good. I haven&rsquo;t attended any, actually, but yes, I heard Javi saying amazing things about them. Almost everybody who attended said good things. Why there&rsquo;s no OCaml conference?</p><p><strong>Louis: [00:56:00]</strong> This is a multifold answer, because it&rsquo;s actually a question that was asked. There is this, how is it called, the OCaml Software Foundation, because if we can explain how OCaml, the management of OCaml is that&nbsp;&mdash;</p><p><strong>David: [00:56:23]</strong> Please do. As core contributor of the code of conduct, please&nbsp;do.</p><p><strong>Louis: [00:56:27]</strong> There is the core group of contributors for the language, and out of that before there was something called the OCaml Consortium, I think, where companies could pay few thousand USD a year and it will give them a license to use OCaml not as an open source project. You could get the compiler and do changes on it and you didn&rsquo;t have to publish the changes again. It was also a way to just sponsor the OCaml development. They took it to a different level. They created this OCaml Software Foundation that is pushing some efforts around&nbsp;OCaml.</p><p>One question was, do we want to have an OCaml conference or do we want to have OCaml- maybe not conference, but smaller events but that could happen more often. Where will we put those events in the world? You need people with time, you need people with money, and you need to find the right place for the right people to attend. I think no one has all those resources, including the mental space to build fancy ideas on what to put in a conference. I cannot provide a definitive answer because I&rsquo;m not the one deciding on all those things, but I think it&rsquo;s a combination of all those that makes the ICFP the place to&nbsp;be.</p><p><strong>David: [00:58:05]</strong> Right, because this year is on Seattle. Every year it changes the location.</p><p><strong>Louis: [00:58:13]</strong> Yes.</p><p><strong>David: [00:58:16]</strong> Last year we released we- I didn&rsquo;t but yes, OCaml released multicore and effects or handling effects. We chatted a bit, a lot at work about this, and I think you said multicore was not something that needs to happen, but you are not very excited. On the contrary, you said the effects are a big deal. Thinking about the person that doesn&rsquo;t know a bunch about what effects are, could you do a short summary and then explain why those are exciting?</p><p><strong>Louis: [00:59:01]</strong> I&rsquo;m not a specialist with effects either but to me, a parallel will be to talk about Rust. In Rust, you have those ways to, how is it called? Borrow checker. You have a way to know to who one value belongs. It heavily affects how you are writing code because then you need to architecture your code in a way that is safe. Do you know that, for example, that value can only be used by one bit of code at a&nbsp;time?</p><p><strong>David: [00:59:45]</strong> Right. Otherwise, you would have crazy bugs. Data corruption</p><p><strong>Louis: [00:59:56]</strong> That would be C. Rust came in and was provided this safety. That&rsquo;s a bit the same idea in OCaml. It&rsquo;s like you come with effects and I think it has many usages that I do not completely understand, but some of them allow us to change the way we do concurrent or parallel computations, and it makes it safe. Like the borrow checker makes the Rust code safe. This is definitely affecting the way you write code because now you have one more tool to express your ideas. I think this is definitely changing the way the language will be&nbsp;used.</p><p>While the multicore, it&rsquo;s just in the background, it is happening, but this is not the tool. This is just a mean, so it&rsquo;s like, how do we do fast computation? Do we need to split stuff on different cores and how do you do it? Either you fork or you do multicore. In a way, it could be completely hidden behind a magic API and I will not know if it&rsquo;s fork or multicore, and it&rsquo;ll be fine to me as a user. If you have something like the borrow checker in Rust, this is actually a language feature, and this is something I see day to day and it is affecting how I can think and what I can&nbsp;express.</p><p><strong>David: [01:01:36]</strong> Right. I see, I see. Yes, because right now one of the features that Jane Street, the famous company that does the Wall Street and whatnot and pushes OCaml for the next level, they have a team working on the OCaml compiler, and one of the big fears that they want to work on, I think, they call it locality or local, global variables. Would that express, I have no idea about those rather than watching Stephen Dolan at the presentation on last ICFP, but would that allow some of the users of OCaml that they do care about the memory layout or the owner of the variables to express those different changes regarding using multicore?</p><p><strong>Louis: [01:02:34]</strong> I don&rsquo;t know exactly&#8202;&mdash;&#8202;My own&#8202;&mdash;&#8202;I mean, I have a light understanding of that. To me, I think it would be interesting even if there was no multicore, the stuff they&rsquo;re doing local/global because we already had concurrency with lwt or stuff like this. It has benefits because you control your allocations too. You can decide what is allocated on the stack versus what is allocated on the heap. It can have big performance implication.</p><p>This is an exciting feature, but this is maybe where you see my C background that when I was in uni, the first year was just writing some C code and we had to rewrite Bash. We had our own version of Bash. We spent two months writing in Bash or stuff like this. We had to deal with many of the small like&#8202;&mdash;&#8202;You are launching a bunch of processes together and you have to manage your memory or whatever, or we had to rewrite malloc, so we&nbsp;&mdash;</p><p><strong>David: [01:03:53]</strong> Okay.</p><p><strong>Louis: [01:03:56]</strong> I know little bits about memory management and how to deal with pointers because I did those projects in the past. These local, global things seems appealing, but at the same time, it&rsquo;s probably not critical. It&rsquo;s not going to change the vast majority of the code that is written in general. All my small personal projects or even most of the code that is running at Ahrefs, performance is not key. I care more about the fact that the code is readable and stable rather than performance, I would&nbsp;say.</p><p><strong>David: [01:04:42]</strong> Yes. Only in somewhere else. Yes, I see your point. Usually, code, for example, just like a web API were way, way fast enough. There&rsquo;s no point to optimize the endpoints. Most of our endpoints I think we have 500 endpoints. That&rsquo;s optimizing one by one or optimizing 10% of them, they would not change absolutely anything.</p><p><strong>Louis: [01:05:10]</strong> We spend so much time doing queries to different databases or http query to gather whatever we need to gather before to answer a request. This is so expensive compared to what we do most of the&nbsp;time.</p><p><strong>David: [01:05:28]</strong> Right. That&rsquo;s true. That&rsquo;s true. Why do you think Ahrefs is such a different company? When I have experience with the&#8202;&mdash;&#8202;It&rsquo;s because of the culture maybe? Here we don&rsquo;t have real management, we don&rsquo;t have product owner. We don&rsquo;t have many things that when you come from working on the SaaS companies that are from the culture of US maybe, or some Europe companies. In Ahrefs we don&rsquo;t have anything like that. Can you say that it&rsquo;s good or bad and&nbsp;why?</p><p><strong>Louis: [01:06:07]</strong> It&rsquo;s good and bad. There are definitely some downsides. Why it&rsquo;s like this, is also because the company is young and small too. It&rsquo;s what? 10 years old so it takes time. Every time you want to make a change company-wide, it probably takes two years to actually make change&nbsp;happen.</p><p><strong>David: [01:06:33]</strong> Okay.</p><p><strong>Louis: [01:06:35]</strong> This is not the only company with a structure that is not well&nbsp;defined.</p><p><strong>David: [01:06:44]</strong> Right.</p><p><strong>Louis: [01:06:44]</strong> What happens is that there is a structure, it&rsquo;s just people don&rsquo;t have the title because actually when you have been in the company for a long time, you own some bits of codes and there are people who are expert on the subject. Then there are people that you trust for something and people that you trust for something else. Even though there is no direct management, there are people taking decisions, so who is taking the decision, right?</p><p><strong>David: [01:07:16]</strong> Right.</p><p><strong>Louis: [01:07:17]</strong> It&rsquo;s good to be flexible and it allows more or less anyone at some point to take a decision if they want to and if they dare to. The downside is that sometimes you don&rsquo;t know if you can take the decision or not, and you don&rsquo;t know who you should talk to and then there are some hidden politics because some products, some features there, they belong to someone. You don&rsquo;t want to offend that person so you can&rsquo;t go and touch this or stuff like&nbsp;this.</p><p><strong>David: [01:07:51]</strong> Well, I need to interrupt here. I think you have been way too long at Ahrefs to realize what politics&#8202;&mdash;&#8202;What it means because in Ahrefs there&rsquo;s literally zero politics or not politics, but battles or discussions for the sake of discussion, it&rsquo;s nearly zero. I think that&rsquo;s one of the things that at the beginning of like, are we not talking about this and somebody said no need to. It&rsquo;s the culture of getting very direct and very technical focus.</p><p>I think when you work in a company that you can be weeks without knowing what to do or just months working on so many processes that are close to useless from your point of view or maybe very beneficial from an individual contributor, you feel like you are losing your time. In Ahrefs I don&rsquo;t think I have been noticing a layer I thought I&rsquo;m losing time because of the company it&rsquo;s the other way around. Oh, my peer is asking me to implement something that needs to be done and I haven&rsquo;t finished yet. That&rsquo;s more the feeling of the work,&nbsp;right?</p><p><strong>Louis: [01:09:09]</strong> I guess it&rsquo;s not politics looking for power because there is no power to&nbsp;gain.</p><p><strong>David: [01:09:16]</strong> Exactly.</p><p><strong>Louis: [01:09:17]</strong> What do you want to own? There is nothing to own. You can try, but there is nothing to win at the&nbsp;end.</p><p><strong>David: [01:09:26]</strong> Getting to the last questions now, but have you been following a little what Javi and Antonio and a little bit of myself having worked in Melange. What&rsquo;s your opinion about&nbsp;Melange?</p><p><strong>Louis: [01:09:43]</strong> I know what Melange&nbsp;is.</p><p><strong>David: [01:09:46]</strong> Definitely.</p><p><strong>Louis: [01:09:47]</strong> Okay. What do I think about Melange? Again, it&rsquo;s a question that is hiding other questions. Let&rsquo;s say technically, for example, this is pretty impressive. What the four of you have been able to do in a few months is amazing. Because just to give some context, it&rsquo;s like moving&#8202;&mdash;&#8202;Okay, Melange was not super, super alive, six months ago. The project was moving but slowly. There was no Dune support, there was not much stuff happening. Then six months later, you have the whole Ahrefs front-end, which is like, hundreds of thousands of lines of code that are written by what? 30 people maybe&nbsp;now.</p><p>It&rsquo;s completely moved to Melange. This is amazing. I&rsquo;m able to compile all this code in one comment. I go in the repo, I do &ldquo;make dev&rdquo; and everything works.</p><p><strong>David: [01:10:56]</strong> These and many more advances, but yes, that&rsquo;s the part that it&rsquo;s&nbsp;funny.</p><p><strong>Louis: [01:11:04]</strong> Yes, it&rsquo;s amazing. It automatically works and it didn&rsquo;t break the experience of anyone so it&rsquo;s compatible with what was bucklescript or rescript beforehand. It&rsquo;s compatible with native code at the same time. It&rsquo;s amazing. What do I think about the project? Another side of the question will be, was it the right thing to do to fork rescript? Or, is it the right way to do it? Is it good to have a fork of the compiler inside of Melange to achieve that project? I don&rsquo;t have a strong opinion on&nbsp;it.</p><p>I don&rsquo;t have enough experience. After all those years of seeing Reason and Bucklescript evolving, I believe that the experience of the end user, so the developer that is using these tools, is more important than the technical implementation. Is it the best way to do it? I don&rsquo;t know. Does it give a good end user experience? Yes, then that was the right thing to&nbsp;do.</p><p><strong>David: [01:12:21]</strong> On those tools, you would always prioritize the developer experience, rather than technical merits? How would you choose&nbsp;&mdash;</p><p><strong>Louis: [01:12:33]</strong> As a user or as a developer of those&nbsp;tools?</p><p><strong>David: [01:12:36]</strong> As a developer of those&nbsp;tools.</p><p><strong>Louis: [01:12:39]</strong> As a developer of those tools, given the target, given what I see of how you build a community and it&rsquo;s like the early days of Melange, I would prioritize user experience. I think, for example, all the efforts that have been put into making Dune work, I think the target was the user experience at the end. Because we couldn&rsquo;t make it work another way. If we didn&rsquo;t have this, I&rsquo;m not sure that we would have moved to Melange, for&nbsp;example.</p><p><strong>David: [01:13:19]</strong> I&nbsp;see.</p><p><strong>Louis: [01:13:20]</strong> What&rsquo;s the downside was that for example, this is not the fastest implementation there is. I think there is some many different calls to this Melange compiler that are not the fastest way to do it, but the UI is good so we still use&nbsp;it.</p><p><strong>David: [01:13:44]</strong> What I would like to feature, knowing that at the start Bucklescript got born, even though they were like js_of_ocaml. Now, I think, eight or nine years past, Rescript got its own path, but then Melange is trying to again, be part of the OCaml to Javascript compilation, or Reason to Javascript compilation. How do you see the future? Because eventually, nobody wants to have two ways to Javascript.</p><p><strong>Louis: [01:14:16]</strong> I&rsquo;m not sure that&rsquo;s true. Why would people not want many ways to do the same thing? It&rsquo;s like if you look at other languages, actually, many of them have different ways to do the same thing. Why not OCaml? As long as the projects don&rsquo;t die, it&rsquo;s not like Melange is attacking jsoo or jsoo is attacking Melange. It&rsquo;s like, people don&rsquo;t hate each other. They are not fighting for users; I think the targets are a bit different.</p><p><strong>David: [01:14:53]</strong> You would want different ways of combining to Javascript? Because the sane competition? That&rsquo;s&nbsp;true-</p><p><strong>Louis: [01:15:03]</strong> To me it&rsquo;s not the sane competition. It&rsquo;s more that I think it targets different audience. It tries to do different things. One example will be during one of the Reason conferences, we wanted to do a workshop and we wanted to show atdgen which is a tool we&rsquo;re using a Ahrefs lots to parse and write JSON. It&rsquo;s protobuf but for&nbsp;JSON.</p><p><strong>David: [01:15:34]</strong> Yes, it would give us type safety from front end all the way down. Sorry, backend all the way&nbsp;down.</p><p><strong>Louis: [01:15:43]</strong> Yes.</p><p><strong>David: [01:15:43]</strong> Sorry, go&nbsp;on.</p><p><strong>Louis: [01:15:46]</strong> You have as with protobuf or with Graphql too you have a definition, you have a file with type definitions and from the definition you derive OCaml code or Python code or TypeScript code. It supports multiple languages. To do so you need an atdgen binary. In the Reason conference, you have people using Linux, Windows, Mac, different version, whatever so how do you give a binary that everyone can use? In two minutes, I just went into the atdgen repo and I enabled js_of_ocaml compilation inside Dune and now my binary is actually JS file that I can run in node&nbsp;JS.</p><p><strong>David: [01:16:34]</strong> Right.</p><p><strong>Louis: [01:16:35]</strong> I don&rsquo;t think that Melange aims to do that. Because then&nbsp;&mdash;</p><p><strong>David: [01:16:41]</strong> I think that&rsquo;s the magic. Yes, I&nbsp;agree.</p><p><strong>Louis: [01:16:44]</strong> In Melange you will have one file per module or something like this, which means I will need to run through webpack or something like this later&nbsp;on.</p><p><strong>David: [01:16:51]</strong> Yes, you could but you would face a few problems. Marshall for example, that it&rsquo;s the encoding/decoding on bytes, that doesn&rsquo;t work in&nbsp;Melange.</p><p><strong>Louis: [01:17:01]</strong> Well, it doesn&rsquo;t work in js_of_ocaml I think&nbsp;too.</p><p><strong>David: [01:17:05]</strong> Yes, but I think you can stub it, right? I think you can&nbsp;&mdash;</p><p><strong>Louis: [01:17:10]</strong> But I would say most of the time actually you don&rsquo;t care because it&rsquo;s corner cases, it&rsquo;s just that the UI they provide is good enough for OCaml people and Melange, it provides the nice, what? FFI, for example, to interact with the JavaScript code. The way it outputs code is closer to the JavaScript way too; I would say so it&rsquo;s easier to make webpack or other tools like this work&nbsp;together</p><p><strong>David: [01:17:39]</strong> Yes, I agree that those are different targets. It just my point of view was more like, okay, js_of_ocaml the crazy thing is that you have entire project in OCaml. You add one line say in Dune compile to node JS please and then you have a single file that is compiled to JavaScript. That&rsquo;s insane so if you have, for example, a compiler written in Menhir it&rsquo;s a language to write compilers in OCaml, you can compile it to JavaScript in one line or any library, even drivers, even anything that you can imagine. That&rsquo;s the valuable position or thing that gets people to try js_of_ocaml very fast. But on the contrary, the documentation is very&nbsp;bad.</p><p>It&rsquo;s the classic OCaml project that you need to understand 50% of the project to even start it so that&rsquo;s like&#8202;&mdash;&#8202;For people like me, I invest a lot of time trying js_of_ocaml and even try to write bindings to React and succeed but I did not succeed convincing people in Ahrefs, front end of Ahrefs to try js_of_ocaml. For me, that was the&#8202;&mdash;&#8202;That technology is not good enough for prime time or not good enough to convince my team, then yes, there&rsquo;s no way to convince any&nbsp;other.</p><p>On the opposite, Melange fits together the low barrier to try and good documentation and at some point, it gets complex but the ease of experience I think it&rsquo;s much better. But yes, you don&rsquo;t have a one line&#8202;&mdash;&#8202;You need to meddle it a bit on building the integration with your front end or your pipeline but yes, once it is done, it works. But yes, you would never do that with atd. The experience in atdgen that&rsquo;s not going to happen in&nbsp;Melange.</p><p><strong>Louis: [01:19:41]</strong> It&rsquo;s funny how you say it and it&rsquo;s true that it&rsquo;s easier. Many things in Melange are easier to experiment with and at the same time it&rsquo;s more complicated. For example, in js_of_ocaml you have a clear separation between OCaml types and JavaScript types. String that is an OCaml string is a different type from JavaScript string.</p><p><strong>David: [01:20:10]</strong> You have like a wrapper,&nbsp;right?</p><p><strong>Louis: [01:20:12]</strong> It&rsquo;s very explicit and it&rsquo;s good for the OCaml person because then you know when this is a part of the language you are comfortable with and then when it starts with JS, it&rsquo;s okay, be careful because you don&rsquo;t know what you are doing. This is easy and in js_of_ocaml. Because it&rsquo;s very easy. You see JS dot and then you know now I have a JavaScript value. In Melange it&rsquo;s your string is what? And you have to deal with the encoding. What is the actual encoding of a string in&nbsp;Ocaml?</p><p><strong>David: [01:20:57]</strong> Do you remember that I said that every time that I&rsquo;ll talk with a backend person, they always mention the runtime. Exactly that moment. You always think about the&nbsp;runtime.</p><p><strong>Louis: [01:21:06]</strong> Actually, I&rsquo;m not&nbsp;sure.</p><p><strong>David: [01:21:08]</strong> It&rsquo;s not the runtime itself, but the encoding. In Melange for example, of course, all the types not of course, but all the types that you have in language are the same representation as a JavaScript value. For example, a string is in a string, integration is a number, float is a number and so on and so forth. Variant is an object; a record is an object. Melange maps perfectly or as good as possible to JavaScript values. It&rsquo;s cool that you said that when every time that you work with js_of_ocaml, once you see JS dot, whatever this is the namespace and you know that you&rsquo;re treating with things that come from the&nbsp;client.</p><p>For example, that&rsquo;s a barrier for people that tried rescript or tried Melange in the first place because they don&rsquo;t understand why do I need a wrapper? Why do we need a generic for at type that already have? Because it&rsquo;s the mentality of why do I need to care about the&nbsp;runtime?</p><p><strong>Louis: [01:22:17]</strong> Yes, basically you pay a cost but at a different time, like in js_of_ocaml, you pay the cost very early because as soon as you write code you need to make the difference between the two words. In Melange you will only pay the cost if you write FFI and you need to care about the representation. It&rsquo;s if there is a string with something weird in it, you don&rsquo;t know the encoding of the string, for example, then you need to be&nbsp;careful.</p><p>The experience by default is much easier. It&rsquo;s just that when you are dealing with the boundaries then things can be a bit more implicit and probably you need to know the language better to do things the right way. It&rsquo;s easier and it&rsquo;s actually more complicated in some&nbsp;bits.</p><p><strong>David: [01:23:08]</strong> Yes, I think if you look now, js_of_ocaml and Melange are very drawn line. You can draw a line between the tradeoffs. One side is very clear, one side is very clear. Now, I would say that I&rsquo;m comfortable saying that both are balanced for the users, even rescript now. For me now, I have a feeling the three of projects are in the right column. You can classify them perfectly now. If you get into, &ldquo;Oh, I want to try this ML or like OCaml, whatever language as a whole,&rdquo; you can choose&#8202;&mdash;&#8202;Based on your team or your decision. You can choose clearly one&nbsp;another.</p><p><strong>Louis: [01:23:57]</strong> Yes. Actually, you said you couldn&rsquo;t sell js_of_ocaml to Ahrefs, but we can probably talk a bit about what was the discussion, what happened, because Javi and you, you actually tried to do something so that it could happen. You work on the React bindings and then you try to show that it could work. In a way, I think that js_of_ocaml, it could fit what we do because we don&rsquo;t depend on a lot of external code. One very interesting thing in Melange is that the FFI is very good. It&rsquo;s easy, convenient, to interface with other existing JavaScript libraries.</p><p>In Ahrefs, we have bindings to what, React, and then maybe one or two library to deal with the timestamps and charts. We don&rsquo;t have millions of bindings. We have maybe five big libraries we have bindings for, and then a bunch of smaller stuff. We don&rsquo;t bind to so many things and we don&rsquo;t need FFI that is amazing. It&rsquo;s not a priority. js_of_ocaml could have&nbsp;worked.</p><p><strong>David: [01:25:14]</strong> Could have worked. I&nbsp;agree.</p><p><strong>Louis: [01:25:16]</strong> The fact that even in this perfect setup for js_of_ocaml it fails is interesting. You find the right company with many OCaml people, many people who understand js_of_ocaml, and you don&rsquo;t need one of the best features of Melange and still, this is not actually the tool that won at the&nbsp;end.</p><p><strong>David: [01:25:42]</strong> Yes, that&rsquo;s true. The experience, I think that&rsquo;s exactly what you said, it could work, theoretically if you look at the direct from the outside or even if you look at far from the front end, it makes a lot of sense. Once we were working on this, I was working on this middle-end team, before it was not called middle-end. I was working on the middle-end, and most of my assumptions were like, &ldquo;It&rsquo;s going to work perfectly.&rdquo;</p><p>Because of what you said, right? Then when we try to&#8202;&mdash;&#8202;How can we write React, we are married to React. I think we like the model of components. We like the model of data; we like the composition. We&rsquo;re not going to change React. Let&rsquo;s bind it to React, so we create the same PPX and the same library to React. I think that was how Javi started and then we end up finishing.</p><p>did the emotion binding, so I know the CSS, everything worked and we felt like js_of_ocaml was very mature, but there were a few problems that you could not solve easily at the time. At the time js_of_ocaml didn&rsquo;t have Unicode support. Now they have some Unicode support or the parsing, I haven&rsquo;t followed that closely, but you would need another library to run to get the Unicode support that in Melange or Bucklescript at the time was natively. That was an issue. The other issue or biggest issue that you can&rsquo;t bypass is that js_of_ocaml, you compile it in one file, one gigantic&nbsp;file.</p><p>Incremental migrations were very hard or very difficult to iterate over time. You could migrate parts of the app, but then you would need to compile everything in both, have two duplicated apps. It was definitely not&#8202;&mdash;&#8202;The migration plan was impossible. We could try. I think we tried in one of the small apps, I think we could try wordcount, is one of the verticals we have at Ahrefs, with js_of_ocaml, and once we were trying those, we find the wrapper, it was very hard to&nbsp;sell.</p><p>The wrapper is like the Js.t that we call it in Recript, in js_of_ocaml I think it&rsquo;s JS.object. It&rsquo;s unsafe. You have JS.unsafe. There are many, yes, many constructions you can track with JavaScript differently from what we do with the bindings. That part was&#8202;&mdash;&#8202;With these three things that I said Rusty, which is one of let&rsquo;s say the only Tech Lead at Ahrefs, like the only person that&#8202;&mdash;&#8202;He&rsquo;s the CTO in the frontend, how I call&nbsp;it.</p><p>He was the person who we would need to convince to migrate to the frontend. He was definitely not on board with the idea. I think that&rsquo;s the main reason. He would chat with our people and people would say, &ldquo;Yes, fine, if Javi and David are happy, then we are all happy,&rdquo; but even though we migrate one small app, the experience was worse. The user experience of iterating over React components was worse or even the data was worse because you had this&nbsp;wrapper.</p><p><strong>Louis: [01:29:23]</strong> There were too honest in the way they named functions in the API. For example, all those unsafe functions, they exist in every FFI, it&rsquo;s just not called unsafe, but because it&rsquo;s called unsafe, people are like, &ldquo;They&rsquo;re not going to use this, you are not supposed to use it.&rdquo; Yes, you&rsquo;re supposed to use it. Just be careful when you do&nbsp;it.</p><p><strong>David: [01:29:47]</strong> I think you explain to me that anecdote, is that somebody asked Xavier Leroy the creator, the author of OCaml, they ask, &ldquo;What do you think about Objec.magic?&rdquo; Right? Object.magic is the method of OCaml that you can, like unsafe, coerce any variable, right? You can light the typechecker and say, &ldquo;Trust me, this is whatever, an array and it&rsquo;s a list or whatever&rdquo;. His answer was, it is like when you are working in the street, would you inject&#8202;&mdash;&#8202;How is that called? I don&rsquo;t remember the thing, but would you become a&nbsp;junkie?</p><p>You get a syringe, I don&rsquo;t know how to say in English, but would you inject some random thing on the street? That&rsquo;s not part of the language. I think you&rsquo;re explained me the anecdote, or maybe it&rsquo;s Javi, How do you see the purity of OCaml? Do you think that the OCaml is very pure or has some pragmatism on safety? Because of course it&rsquo;s type safe, of course, the compiler when it compiles it works, but you can bypass it from time to time. What&rsquo;s your&nbsp;opinion?</p><p><strong>Louis: [01:31:10]</strong> I don&rsquo;t think it&rsquo;s pure in any way, shape, or&nbsp;form.</p><p><strong>David: [01:31:17]</strong> You can write pure code,&nbsp;right?</p><p><strong>Louis: [01:31:20]</strong> Yes. You can write pure code. But for example, you have exceptions that are very pregnant, that are everywhere and you don&rsquo;t have any way to know if a function can raise an exception or&nbsp;not.</p><p><strong>David: [01:31:37]</strong> Right.</p><p><strong>Louis: [01:31:38]</strong> Okay, it depends what program you write, but basic things, you run your program, like a CLI that is running&#8202;&mdash;&#8202;I don&rsquo;t know, downloading something and you press control C like you want to stop your program. There is&#8202;&mdash;&#8202;It&rsquo;s a signal, and in OCaml it&rsquo;ll raise an exception that you need to&#8202;&mdash;&#8202;You can catch and you can do something with it, right? At any point in time, the user of your CLI can come and interrupt the program, right? Which means at any point in your program, you need to be able to deal with this interruption.</p><p><strong>David: [01:32:18]</strong> Right.</p><p><strong>Louis: [01:32:19]</strong> It&rsquo;s like as soon as you have these where is the purity, what is&#8202;&mdash;&#8202;You have no good way to protect yourself against all these issues. At the same time, I&rsquo;m probably biased because I have been using the language for long. It provides you what is good enough. There was some improvements because, I don&rsquo;t know if you remember, but at some point, the strings were mutable in&nbsp;OCaml.</p><p><strong>David: [01:32:51]</strong> Yes.</p><p><strong>Louis: [01:32:53]</strong> By defaults, the strings were actually what is called Bytes nowadays. It has been a big change. People had to fight to turn Bytes into string, because it was breaking code, obviously. There was more mutability. It was not as pure as it is nowadays, I would say that the balance is not too bad. Could it be more? Probably. There are some things that we can&rsquo;t really express in OCaml, like ownership of a&nbsp;value.</p><p>Like you open connection to a database, you have a handler or something like this that you want to use only at one point in time and you don&rsquo;t want to share. You have no way to express it. Then you can&rsquo;t really protect yourself against the steal. The code can take that value, put it in a global reference, and it can be suddenly reused elsewhere. This is where, for example, the local/global stuff&nbsp;&mdash;</p><p><strong>David: [01:34:06]</strong> Yes, solve exactly that&nbsp;issue.</p><p><strong>Louis: [01:34:09]</strong> Yes. This kind of issue. Is it a problem? Yes. Is it a problem that we face at work? Yes. For example, we see like&#8202;&mdash;&#8202;We have one problem where people can open the connection to a DB using one of those&#8202;&mdash;&#8202;A common pattern in the ocaml to do like &ldquo;with_db&rdquo; for example. Then you pass a continuation, you pass a function, and then this with_db function will create a DB handler and pass it to your function later&nbsp;on.</p><p>Inside your function, you can do one more with_db. This is something that you probably want to forbid because you don&rsquo;t want to open connections after connection after connection when there is already one available.</p><p><strong>David: [01:34:57]</strong> Right.</p><p><strong>Louis: [01:35:00]</strong> For now, how do you fix this? This is an actual problem and you have no good solution. But maybe you write different code than I do. You write code that is in the browser or just behind the browser so maybe you have different views. You have to deal with more mutability than I do, for example the whole DOM, before React. Yes, but before React no one assumed that anything was immutable in a browser. Everything could be changed at any point in&nbsp;time.</p><p><strong>David: [01:35:43]</strong> Yes. That&rsquo;s why in the browser many APIs were pushing for observables, right? You accept mutability into all your values and then you say any value can change in any time and you need to subscribe to&#8202;&mdash;&#8202;Listen to the changes or not and that&rsquo;s the trend of&#8202;&mdash;&#8202;I think that was one of the biggest inclusions of ES4 that didn&rsquo;t get published and they tried with ES5 and they didn&rsquo;t get to the language neither that are like these observables concept. I think they come from React JS and they come from reactive programming from, I don&rsquo;t know, 30 years ago where sometimes reactive is very useful. Before React, I would say that not many people did&#8202;&mdash;&#8202;The immutability was not part of their fashion of writing&nbsp;code.</p><p>We are very far from those problems. We do immutability in a few places, for example, we have a global theme, a CSS theme, right? You can have a dark or light theme. We interact with the browser directly. We opt out from React to do that because the performance is better. You can load that at the beginning, you can then allow React later. But the way it&rsquo;s just very self-contained, right? You will never want to write your data reactive.</p><p>Maybe you want, but for example, for Ahrefs it doesn&rsquo;t make any sense because our data is you have tabular data that never changes on your session, right? It&rsquo;s not live data. It&rsquo;s like you open a report and the report is the moment time that you request. There&rsquo;s no live thing. Nothing is very reactive in nature so yes, for us it&rsquo;s just like a perfect&nbsp;sense.</p><p><strong>Louis: [01:37:41]</strong> You would be happy with more&nbsp;purity?</p><p><strong>David: [01:37:45]</strong> Would we be happy with more purity? No, I think&nbsp;&mdash;</p><p><strong>Louis: [01:37:49]</strong> Would you wish to have a language that is closer to Haskell that is like&nbsp;&mdash;</p><p><strong>David: [01:37:54]</strong> No, I don&rsquo;t think so. I think no, because purity makes&#8202;&mdash;&#8202;Purity in some places makes your life so much better, right? But often you want the tools to be pure so like libraries that you create or you consume need to be pure but your application needs to do all sort of things, right? Your application or when you are a product engineer, you want to just ship fast and if something gets you in your way and you store it globally and deal with it later or store it globally and be safe and then forget about&nbsp;it.</p><p>You need to do things perfectly and draw the line and architect things that slows you down insanely. I think the line&#8202;&mdash;&#8202;OCaml is very well position where you can opt out, do your life easy and then move back and run fast. But yes, my tools to be pure or libraries that I&rsquo;m using or even&#8202;&mdash;&#8202;I know I&rsquo;m working on styled-ppx so making types safe, like your styles. I think that&rsquo;s something that I&rsquo;ve been pushing but yes, you want that tool to be type&nbsp;safe.</p><p>You don&rsquo;t want to do all your things on your app perfectly, to demand it perfectly mostly because on the web, everything is changing all the time. On the backend it&rsquo;s a little bit different but on the web, iterations are just much more common than in the&nbsp;backend</p><p><strong>Louis: [01:39:31]</strong> I find it interesting that everyone is pushing for immutable stuff. At least my impression is that in the front end React maybe didn&rsquo;t create this trend but made it popular. My understanding is that you deal with the DOM as an immutable object. You never manipulate the DOM directly anymore. You do it through React. You have an immutable object, more or less, which goes against many things that happened, historically in a browser, the way the DOM is implemented is completely not like this. It has some interesting benefits.</p><p>You can have any extension in your browser that are changing part of your page. I&rsquo;m using one daily. I&rsquo;m using Dashlane to store my passwords. It does stuff for&#8202;&mdash;&#8202;If there is an input field, it&rsquo;s creating a popup and I can click, input my password in that specific&nbsp;field.</p><p>To do this, it has to inject HTML in the page actually. But it breaks. Some apps are crashing because of this. Some apps, some websites, they&rsquo;re not crashing. They will just see that there is a change coming from my extension and they will just discard it and rerender without my&nbsp;stuff.</p><p><strong>I</strong>t goes against many things that happened for 20 years, more or less. You have to make both of those worlds still somehow work together.</p><p><strong>David: [01:41:18]</strong> I think React did&#8202;&mdash;&#8202;I think not even React, Meta did that all the time. They pushed for a solution that is way better in some areas but destroys previous effort insanely. For example, with GraphQL, I think it&rsquo;s happened the same. They say, &ldquo;You&rsquo;re going to have one endpoint. It&rsquo;s going to be through POST.&rdquo; You would call this endpoint all the time, which goes against completely about REST what we were doing&nbsp;before.</p><p>Of course, with all the tradeoffs, if you go 10 times&#8202;&mdash;&#8202;10 years back and you say to a person, &ldquo;No, we call all the time same endpoint.&rdquo; You will say, &ldquo;You guys are&nbsp;stupid.&rdquo;</p><p><strong>Louis: [01:41:58]</strong> RESTful was a&nbsp;trend.</p><p><strong>David: [01:42:00]</strong> Exactly. The RESTful, you will need to add the link to go to the next resource. Of course, all the people would scream at you. Similarly, it happens now with server components. I don&rsquo;t know if you are following the thing. Again, they are pushing for a new concept that they have mined in their business and works well. The rest of the people are like, &ldquo;No, that&rsquo;s just insanity.&rdquo; I think React, the first concept is you&#8202;&mdash;&#8202;The insert and update are the same operations.</p><p>There&rsquo;s no create the DOM and then update the DOM. It&rsquo;s always like, &ldquo;Do the thing.&rdquo; It&rsquo;s just rerender. Just because they push for that approach and they delay, of course, the first load is going to be slower. You don&rsquo;t have serialization. Then later updates are going to be&nbsp;faster.</p><p><strong>Louis: [01:42:58]</strong> Actually, even the later update are slower, because you need React to do this diff between the two version and to only update the relevant part of the DOM. React is doing what the browser was actually doing. You are duplicating the work and you are doing it in JavaScript, which is slow. The browser was doing it in a very optimized C++&nbsp;code</p><p><strong>David: [01:43:26]</strong> Fair point, but the DOM is fast enough. I think I read a lot of articles about anti-React that the DOM is fast enough. I think that&rsquo;s&#8202;&mdash;&#8202;These benchmarks are nonsense. Those benchmarks&#8202;&mdash;&#8202;Even the benchmarks that&#8202;&mdash;&#8202;I would call it micro-benchmarks. Even microbench like&#8202;&mdash;&#8202;I don&rsquo;t know, work faster, implement some charting library mutable to DOM and using whatever, Vanilla JavaScript or using React. Of course, you can outperform React but at what&nbsp;cost.</p><p>The cost of creating two charts, two components of a chart, the API nicely, blah blah blah blah rather than mutating the DOM all the time. That&rsquo;s super expensive. When you&rsquo;re working, for example, for Ahrefs, I think we have&#8202;&mdash;&#8202;I don&rsquo;t know, 2 million lines of code in reason. I don&rsquo;t know, 5,000 components. Some insane amount of number of components. If you do that in mutable or maybe not mutable but maybe just going to DOM and listening to DOM and hoping that everybody is a good citizen. It&rsquo;s just you would slow down development so hard that it doesn&rsquo;t make any&nbsp;sense.</p><p>I think React draw this line where virtual DOM is like if you know how to create the structures, know how to trigger the renders, I think can be as good as the DOM, of course. In general terms, I think it&rsquo;s good enough. I think the balance is very OCamly. [laughs] You know that Jordan was behind, when&#8202;&mdash;&#8202;Jordan is an OCamler that knows this balance, that&nbsp;&mdash;</p><p><strong>Louis: [01:45:23]</strong> It&rsquo;s funny, because you could say that for example Facebook has enough resources to make it work, right? They could have decided it is going to be a more troublesome for our developers, but we are going to offer a faster experience for the customers, the people actually visiting the website. But even them with their infinite resources, they decided to go in a different direction. Is it because it&rsquo;s a tech company? I feel that some big tech company, they run the way they do, because they are led by technical people, so they can make technical choices instead of business choices sometimes.</p><p><strong>David: [01:46:08]</strong> React is that, exactly that case. I think I saw the documentary about React, and it&rsquo;s more the idea just spreaded everywhere. I think they have that competing library; I don&rsquo;t know how, I think it&rsquo;s called Jacks or something. I don&rsquo;t the name, but they have a competing library that was written with PHP and XML, and the whole stack on meta back in the days. The idea of React spreads everywhere. The point that you made before of developer experience leads everything in the early days. I think that it just applied exponentially, because at some point they released publicly, everybody hated JSX. Then after one year it was the most famous library used. Then from now on, the monopoly went for, I don&rsquo;t know, six, four years, I don&rsquo;t know. So many years that now everybody has the component model, the hooks, the state. It spread the idea everywhere. It&rsquo;s interesting, but I think it&rsquo;s just like <strong>[unintelligible 01:47:11]</strong>&nbsp;,&nbsp;so.</p><p><strong>Louis: [01:47:13]</strong> How smart do you need to be to Jordan and be correct about React was the right thing to do, and to do it properly, and then Reason was the right thing to do, and to do it properly?</p><p><strong>David: [01:47:25]</strong> How smart need to do. I don&rsquo;t know. Uncountable, I would say. Hard to quantify smartness. It&rsquo;s hard to quantify smartness, but I think it&rsquo;s even harder when you look at what Jordan has been doing. I think Jordan is the kind of person when you speak with him, he talks, or he says things that doesn&rsquo;t make sense at the beginning. It&rsquo;s his way of thinking. He&rsquo;s thinking three, five years ahead, and when he explains the idea to you, you are like, &ldquo;I got the sense that I didn&rsquo;t understand anything.&rdquo; After a few months you start saying, &ldquo;Oh, right, it made sense.&rdquo; I think everybody on the React team only says how brilliant Jordan is. So,&nbsp;yes.</p><p><strong>Louis: [01:48:18]</strong> It&rsquo;s interesting that you interviewed Rudi, the author of Dune, and he said that even him, for example, originally when he saw the Reason syntax, he was like, &ldquo;meh,&rdquo; like, &ldquo;What is this thing?&rdquo; Like, &ldquo;Yet again?&rdquo; He say, &ldquo;Yes, at the end it was right to make it more approachable.&rdquo; This was from a user experience perspective. It&rsquo;s a clear&nbsp;benefit.</p><p><strong>David: [01:48:44]</strong> Yes. I love that interview, because Rudi said exactly that, like, &ldquo;Oh, at the beginning Reason felt like a toy, but then we were doing tooling for OCaml, and the language and a lot of work on the actual language. Reason was the thing that bring more people on OCaml, than we never, ever did. Even though it&rsquo;s not a competing language, even though the person that created has so much power into the frontend people, even that the number of people that got into OCaml community, it was bigger than any other effort that we made. [laughs] Which for me is super funny at the end of the day, because most of us came from the JavaScript and end up doing OCaml and mixing everything. That was the&nbsp;idea.</p><p><strong>Louis: [01:49:40]</strong> It&rsquo;s funny how you need a little bit of luck for all those things to work. You need, for example, Rudi to decide early on, &ldquo;Okay, I don&rsquo;t really trust this thing, but I still I&rsquo;m a good citizen, so I will add the support inside&nbsp;Dune&rdquo;</p><p><strong>David: [01:49:56]</strong> Yes. That&rsquo;s very&nbsp;noble.</p><p><strong>Louis: [01:49:58]</strong> It&rsquo;s like if you don&rsquo;t have those people who are able to compute this is maybe good or maybe bad, and are able to balance their opinion, versus the community thing. They have to do it early enough, at the right time. It&rsquo;s interesting that somehow&nbsp;&mdash;</p><p><strong>David: [01:50:24]</strong> Of course, not what everything Jordan says is correct, I think in the sense of, of course, he created stuff that was definitely not on shape or not on the area of success of React, of course. I think he created React and then React native. Of course, they both are insanely successful. Reason I would call it successful as well, but actually, push the idea of Esy. Esy is the package manager that is still somehow used, and some people love it. Even myself, I have a lot of respect for Esy, and use it from time to time. That you can consume JavaScript libraries, npm packages as well as OPAM packages.</p><p>This project has been suffering for long, that it&rsquo;s definitely not the right solution, or at least, it didn&rsquo;t create these ideas, this sudden idea to the rest of people to continue pushing for&nbsp;it.</p><p><strong>Louis: [01:51:27]</strong> This is one of those tools where I think the technical implementation was good, but the UI was not great. The output is just not nice, for example. You run it, and then it displays&nbsp;some-</p><p><strong>David: [01:51:44]</strong> You mean, the actual UI, the&nbsp;CLI?</p><p><strong>Louis: [01:51:46]</strong> Yes, because opam, which is not the most fancy tool ever, but still when you opam install, it has some colors. It doesn&rsquo;t display one line production. It&rsquo;s some kind of somehow clean output that Esy doesn&rsquo;t have. You had to learn this weird JSON syntax to put your package, and it outputs ugly text after that. The idea was very good, but the UI was not completely working.</p><p><strong>David: [01:52:24]</strong> I think Esy has some, people call it state-of-the-art ideas, the end goal of our package manager, what do you want to do, or we want to use. The efforts of maintaining the overrides or being on top of all the libraries or even compiles Esy, there&rsquo;s a lot of maintenance that needs to get done. At some point, we have a team of, I think, six, seven persons working on it, and that experience was very good, but from when Reason got a little bit lost, this team, those people&nbsp;&mdash;</p><p>Of course, when the blockchain companies started hiring all of them to work for Web3 and paying them insanely amount of money, then the project got a little bit carried over, got a little bit less maintenance then is likely in a stale mode that you can use, but you could get not as good as&nbsp;opam.</p><p><strong>Louis: [01:53:35]</strong> This exactly why there is no Rust code inside Ahrefs, because all the developers got stolen by the blockchain companies.</p><p><strong>David: [01:53:45]</strong> That&rsquo;s fair. That&rsquo;s fair. I think, Louis, we are running out of time. For me is daytime, I can do stuff, but for you is definitely night time. I can work, talk with you for hours and hours, but I think the show is reaching to a point to finish. It was a pleasure to have you, of&nbsp;course.</p><p><strong>Louis: [01:54:07]</strong> It&rsquo;s a pleasure.</p><p><strong>David: [01:54:09]</strong> If somebody attends to ICFP, please go to Louis, I think he&rsquo;s the party manager, and as well, a person very interesting to talk to. Please, bother him. I think he&rsquo;ll be in Seattle on September.</p><p><strong>Louis: [01:54:26]</strong> Yes, Seattle, September 4th to 9th, I think, something like that. It will be online too, this year. I think it will be online and for free. All the talks, at least all the ML, or maybe not ML, but the OCaml workshop will be online of free. There is no need to travel all the way to Seattle to see the talks, at least to see the OCaml workshop.</p><p><strong>David: [01:54:52]</strong> Makes sense. In this era of internet, I think that makes sense. Cool. Thanks everybody for being here. You&rsquo;re having a little bit late day, but that was perfect. Thanks, Louis, to spend time with&nbsp;us.</p><p><strong>Louis: [01:55:07]</strong> Thank for having me. That was&nbsp;fun.</p><p><strong>David: [01:55:10]</strong> See you&nbsp;guys.</p><p><strong>[01:55:13] [END OF&nbsp;AUDIO]</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=7767afbfbdb9" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/emelletv-talking-with-louis-roche%CC%81-about-ocaml-and-ahrefs-7767afbfbdb9">EmelleTV: Talking with Louis Roche&#769; about OCaml and Ahrefs</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/emelletv-talking-with-louis-roche%CC%81-about-ocaml-and-ahrefs-7767afbfbdb9?source=rss----303662d88bae--ocamlEmelleTV: Talking with Louis Roché about OCaml and Ahrefs2023-06-29T14:32:40-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<h3>OCaml, all the way&nbsp;down</h3><figure><img src="https://cdn-images-1.medium.com/max/1024/0*cGDQZKJ2bKMARpj9" alt=""/><figcaption>Photo by <a href="https://unsplash.com/ja/@lg17?utm_source=medium&amp;utm_medium=referral">Lance Grandahl</a> on&nbsp;<a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h4>Some history</h4><p>In 2021, we decided to evaluate <a href="https://github.com/melange-re/melange">Melange</a> as an alternative to <a href="http://rescript-lang.org/">ReScript</a> for compiling Ahrefs&rsquo; frontend codebase. We wrote about the reasons that led us there, as well as the limitations we encountered at the time, in <a href="https://tech.ahrefs.com/building-ahrefs-codebase-with-melange-9f881f6d022b">a previous&nbsp;article</a>.</p><p>After this experiment, discussions continued inside the team. Switching to a different compiler, which was in a very early stage, involved quite some risk. But so did the continued use of ReScript, which seemed to be diverging further and further away from&nbsp;OCaml.</p><p>Finally, in September 2022 (during <a href="https://icfp22.sigplan.org/">ICFP in Ljubljana</a>), we decided to bite the bullet and kicked off a project to deepen the integration between <a href="http://dune.build/">Dune</a> (OCaml&rsquo;s most used build system) and Melange. This better integration was the key to solve two of the three limitations we had encountered during our initial exploration of&nbsp;Melange:</p><ul><li>Build speed would increase due to less work needed to parse dune files, and more efficient rules planning and execution.</li><li>Developer ergonomics would get better, as Melange would become a first-class citizen in Dune, with concepts like Dune <a href="https://dune.readthedocs.io/en/stable/dune-files.html#library">libraries</a> and other stanzas becoming available to Melange&nbsp;users.</li></ul><p>Ahrefs&rsquo; leadership backed the project and agreed to financially support the development of this tighter integration. With this support, we set about building a team that included Rudi Grinberg, who maintains Dune as part of its development team, and Antonio Monteiro, who created Melange and is also part of the Dune development team.</p><h4>Heads down</h4><p>During the following months, we focused on two tasks, iterating over multiple cycles where the progress on one task would inform the next steps to take for the&nbsp;other:</p><ol><li>Evolve Dune to add stanzas, fields, and documentation to support Melange projects.</li><li>Migrate Ahrefs&rsquo; frontend codebase to use the Melange compiler and Dune, adapt third-party libraries and bindings to Melange, and polish the editor integration, build scripts, and other aspects of the development experience.</li></ol><p>We believe that tackling these two tasks in parallel led us to better results, compared to a more waterfall-based approach. As we applied the changes over Ahrefs&rsquo; large-ish frontend codebase&#8202;&mdash;&#8202;it will soon reach 5000 modules&#8202;&mdash;&#8202;we kept finding and fixing bugs, improving the ergonomics of the Dune and Melange integration, and in general making the solution more robust, real-world ready, and developer-friendly.</p><p>Another upside of the way the project was implemented is that we developed it initially in stealth mode, keeping it quite private. By working on it within a tight-knit team, before making a public release, we could make progress faster. We believe that this approach saved future Melange users a lot of churn and burn caused by the multiple changes in Dune stanza options, Melange flags, and other configurations we changed along the way, as we learned more about this integration.</p><h4>Migration strategies</h4><p>Initially, our plan was to progressively migrate Ahrefs&rsquo; code to Melange. As the frontend codebase is divided into different tools, each being self-contained, we thought we could introduce Melange to build one tool, then another tool, gradually migrating them one by&nbsp;one.</p><p>However, this approach turned out to be too complex because configuring a development environment that works on both Melange and ReScript is challenging. As developers could be working on multiple tools during the same week, or even within the same day, we realized that it was unfeasible to reconfigure the environment every time a developer switched from a tool built with Melange to a tool built with ReScript.</p><p>Therefore, we changed our minds and opted for a one-shot migration. We would ensure that CI, development, and staging environments were working with Melange and Dune. And we would do this on separate branches, while still using ReScript on our main branch CI and development scripts. Once we were confident everything was building and functioning correctly with Melange, we switched all CI and development scripts to use the Melange and Dune commands. We tried to keep the PR that applied this switch as small as possible, with just a few hundreds of lines of changes so that we could switch back to ReScript if needed. In fact, after a first attempt in March, we had to switch back to ReScript due to some issues on the developer experience side, related to build performance and ergonomics, which took a few more weeks to&nbsp;solve.</p><p>In terms of package management and third-party Melange dependencies, we followed a more gradual approach. Dune is quite flexible when it comes to <a href="https://dune.readthedocs.io/en/stable/dune-files.html#vendored-dirs">vendoring</a>, so in the initial phase, we downloaded Melange libraries with npm, and had Dune include them in the project as if they were local sources. Now we have started migrating some of these libraries so that we can consume them using opam, the OCaml package manager. This will involve first publishing them in our private opam mirror, but the plan is to have them published in the <a href="https://ocaml.org/packages">public opam repository</a> in the future so that other Melange developers can also use&nbsp;them.</p><h4>Timings</h4><p>You may be curious about the performance differences between the previous and current approaches. Measuring performance is tricky, but we attempted to measure a few different scenarios with both setups. The results can be seen&nbsp;below.</p><p>Keep in mind that Ahrefs frontend setup has specific characteristics, which affect the performance measurements:</p><ul><li>Before migration: Dune generated ml files from atd files, then ReScript build tool bsb built all hand-written source files plus the ones generated from atd&nbsp;files.</li><li>After migration: everything is built with Dune and&nbsp;Melange.</li></ul><p>All measurements were taken on a node with 2x AMD EPYC 7742 cpu @3.2 GHz (nproc=256), 1TB RAM, Debian 11 x86_64 GNU/Linux. The build target is always the entire Ahrefs frontend codebase.</p><p><strong>Cold build:</strong></p><ul><li>Before: real 0m28.232s, user 9m23.883s, sys 13m33.939s</li><li>After: real 1m14.208s, user 10m33.708s, sys 5m45.644s</li></ul><p><strong>Warm build</strong>, noop (no file is&nbsp;built):</p><ul><li>Before: real 0m14.687s, user 3m17.058s, sys 3m57.903s</li><li>After: real 0m21.895s, user 0m20.528s, sys&nbsp;0m1.372s</li></ul><p><strong>Watch mode, modifying an &ldquo;edge&rdquo; file</strong> with almost no reverse dependencies:</p><ul><li>Before: 1002ms</li><li>After: 1576ms</li></ul><p><strong>Watch mode, modifying an &ldquo;inner&rdquo; file</strong> belonging to a library, with many reverse dependencies:</p><ul><li>Before: 7032ms</li><li>After: 15394ms</li></ul><p>In general, Melange and Dune are slower than ReScript for cold builds in our setup. However, the differences are smaller for warm builds. For watch mode, the difference gets reduced when modifying edge&nbsp;files.</p><p>There is room for improvement in the way the Melange and Dune rules are arranged so that cold builds can get faster. For example, delaying some <a href="https://github.com/melange-re/melange/issues/464">optimizations in Melange</a> might allow to parallelize more&nbsp;work.</p><h4>Conclusions</h4><p>The results so far are quite encouraging. These are some of the things that are possible thanks to the deeper integration between Dune and Melange, and its application within the Ahrefs codebase:</p><ul><li>The same OCaml compiler is used on both frontend and backend codebases.</li><li>Access to all the bug fixes, error improvements, and new features that the OCaml compiler team added between versions 4.06 and 4.14 of the compiler.</li><li>A shared developer environment across teams, including editor extensions, OCaml LSP server, etc. No more need to maintain a different set of tooling for backend and frontend.</li><li>Removal of hand-written CI checks that were ensuring different tools in the frontend codebase would not access components from other tools. This is now solved by Dune libraries, and the OCaml compiler will complain if logical units try to reach outside their&nbsp;bounds.</li><li>Frontend and backend shared dependencies, such as <a href="https://github.com/anuragsoni/routes/">anuragsoni/routes</a>, can now be defined in a single place: an opam&nbsp;file.</li><li>Faster rebuilds and better watch mode, as Dune now controls all the build artifacts. Previously, Dune and ReScript were sharing responsibilities, which was leading to unnecessary rebuilds of some artifacts. Or alternatively, rebuilds were not starting when required due to the build system not tracking changes in some subsets of the&nbsp;sources.</li><li>Easier <a href="https://ocaml.org/docs/metaprogramming">PPX</a> maintenance, as there is no longer a need to publish pre-built versions of these&nbsp;tools.</li><li>Melange allows to run all ppxs <a href="https://github.com/melange-re/melange/pull/171">from a single executable file</a>, which has some nice performance benefits.</li><li>All the other advantages of using Dune: virtual libraries, watch mode, leverage integrations with tools like&nbsp;odoc&hellip;</li></ul><h4>What&rsquo;s next?</h4><p>We are excited about this project becoming a reality, and we believe that the deeper integration between OCaml and Melange through Dune, together with Melange&rsquo;s ergonomic integration with the JavaScript ecosystem through its bindings, can enable projects that were previously impossible to imagine. For example, full-stack React by hydrating components that are rendered <a href="https://github.com/ml-in-barcelona/server-reason-react/">server-side using native&nbsp;OCaml</a>.</p><p>Now, we have to make it easier for other people who are willing to try and use Melange and Dune. So our focus is shifting to documenting how Melange&nbsp;works.</p><p>There is a section for Melange in the Dune manual that will be included in the next stable release, and that can be consulted today in the latest branch: <a href="https://dune.readthedocs.io/en/latest/melange.html">https://dune.readthedocs.io/en/latest/melange.html</a>.</p><p>The next step will be to design and create a site where everyone can read and learn about what is needed to create and maintain a project using Melange and Dune. This site will include a playground, in the spirit of the <a href="https://reasonml.github.io/en/try">ReasonML one</a>, so that we can share snippets, see the resulting JavaScript compilation output, and iterate on ideas together.</p><p>Besides the above, we have plenty of other things we will be working on in the next months. We will share more information about the roadmap as soon as Dune 3.8 and its respective Melange version are published in the main public opam repository, which should happen in the next&nbsp;weeks.</p><h4>How to contribute?</h4><p>If you want to be a part of this, or you want to write or port your libraries to Melange, the best way to do so is by reaching out on the <a href="https://discord.gg/reasonml">ReasonML Discord</a>. There is a #melange dedicated channel where one can get help and advice on how to get&nbsp;started.</p><p>Otherwise, if you are missing features, find bugs, or run into confusing errors, please open an issue <a href="https://github.com/melange-re/melange">in the Melange public&nbsp;repo</a>.</p><p>We hope you share our excitement about this update. Our journey to integrate our frontend stack more naturally within the incredible language and ecosystem of OCaml will be well-documented. Stay tuned for further updates in the&nbsp;future!</p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=b14f5ec56df4" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/ahrefs-is-now-built-with-melange-b14f5ec56df4">Ahrefs is now built with Melange</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/ahrefs-is-now-built-with-melange-b14f5ec56df4?source=rss----303662d88bae--ocamlAhrefs is now built with Melange2023-05-03T19:06:58-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<h3>Intro</h3><p>There has never been a better time to learn OCaml, one of the premier statically-typed functional programming languages used in industry. We at Ahrefs have used it on our backend since the early days of the company, and <a href="https://tech.ahrefs.com/one-and-a-half-years-of-reasonml-in-production-2250cf5ba63b">since 2018 have even used it extensively for our frontend code</a>. Today we&rsquo;re very excited to share with you our favorite recommendations for getting started with&nbsp;OCaml!</p><h3>Best resources for learning&nbsp;OCaml</h3><p>If you have little functional programming experience or are even a beginner to programming, the place to start is <a href="https://ocaml-book.com/">OCaml from the Very Beginning</a>, a book that is now free thanks to generous funding from the <a href="https://ocaml-sf.org/">OCaml Software Foundation</a> (which Ahrefs is a sponsor of). The book can be viewed directly from its website and can also be downloaded as a PDF. While advertised as being approachable even to new programmers, this doesn&rsquo;t quite seem to be true, at least based on feedback we&rsquo;ve received. The text itself introduces concepts in a structured way, but the exercises require a little background in programming to complete. Such background info can be obtained by watching the opening videos in <a href="https://www.youtube.com/playlist?list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU">this series of lectures</a> from Cornell&rsquo;s OCaml programming course. Speaking of the Cornell course, their official online textbook <a href="https://cs3110.github.io/textbook/cover.html">OCaml Programming: Correct + Efficient + Beautiful</a> is an excellent resource for learners with some programming experience under their belt (specifically, you should have written some code using a mainstream imperative language like Python or&nbsp;Java).</p><h3>How to install&nbsp;OCaml</h3><p>The <a href="https://ocaml.org/docs/up-and-running">official installation instructions</a> are entirely adequate. It shows you how to install the compiler and some useful dev tools like dune (build system), utop (interactive read-eval-print loop), and ocaml-lsp-server (useful for editor integration).</p><p>Actually, if you are working through <a href="https://ocaml-book.com/">OCaml from the Very Beginning</a>, you do not need to install OCaml during the first several chapters, as you can execute code snippets directly on the <a href="https://try.ocamlpro.com/">Try OCaml</a> page, or create a notebook at <a href="https://sketch.sh/">Sketch.sh</a>, an interactive OCaml notebook site maintained by Ahrefs through our monthly Open Source Friday&nbsp;program.</p><h3>Editor support</h3><p>For most beginners to the language, we recommend the <a href="https://marketplace.visualstudio.com/items?itemName=ocamllabs.ocaml-platform">official OCaml Platform Visual Studio Code extension</a>. The official OCaml installation guide has a <a href="https://ocaml.org/docs/up-and-running#editor-support-for-ocaml">good section on setting it up</a>. There is also great support for users of <a href="https://github.com/ocaml/tuareg">emacs</a> and&nbsp;<a href="https://github.com/ocaml/vim-ocaml">vim</a>.</p><h3>Tips</h3><p>Even early on, it&rsquo;s a good idea to start saving your code into&nbsp;.ml files and learning how to run it. The easiest way to run a simple program is to start up utop and inside of it run #use &quot;name_of_your_program.ml&quot; as <a href="https://ocaml.org/docs/first-hour#running-ocaml-programs">described here</a>.</p><p>When creating a new notebook in <a href="https://sketch.sh/">Sketch.sh</a>, the default syntax is ReasonML (it&rsquo;s not a different language, just <a href="https://en.wikipedia.org/wiki/Reason_(programming_language)">an alternate syntax that more resembles JavaScript</a>). Click on ML in the top left corner to switch to the original OCaml&nbsp;syntax.</p><figure><img src="https://cdn-images-1.medium.com/max/1024/0*EgPCQlLR4C54N3Ge" alt=""/></figure><h3>Conclusion</h3><p>OCaml originated from French academia more than 25 years ago, and from there spread to elite universities and forward-thinking companies around the world. Now the OCaml community has produced high quality learning material that is both free and easy to access. So take the initiative and learn you some&nbsp;OCaml!</p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=2f22b578b984" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/how-to-get-started-with-ocaml-in-2022-2f22b578b984">How to get started with OCaml in 2022</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/how-to-get-started-with-ocaml-in-2022-2f22b578b984?source=rss----303662d88bae--ocamlHow to get started with OCaml in 20222022-10-31T16:13:10-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<h3>Monorobot: a notification bot for monorepos</h3><figure><img src="https://cdn-images-1.medium.com/max/1024/1*BQNCNLNPxGV3eXajYe6y2g.png" alt=""/><figcaption>Monorobot enables configurable directory tree notifications for your monorepo.</figcaption></figure><p>A few years ago, we decided to move most of our code into a monorepo. Many <a href="https://danluu.com/monorepo/">advocates</a> have highlighted its upsides, which include better cross-project coordination and simpler dependency management.</p><p>But one problem remained: <strong>none of the available GitHub integrations for Slack work nicely with monorepos</strong>. Slack is vital for day to day communication among Ahrefs&rsquo; globally distributed team, so a Slack integration was a must-have feature. We needed a service that could map activity from our various subprojects to their corresponding Slack channels&#8202;&mdash;&#8202;something existing solutions didn&rsquo;t&nbsp;offer.</p><p>That&rsquo;s why we built our own integration: <strong>Monorobot</strong>, a notification bot for monorepos. We&rsquo;ve improved it iteratively since the monorepo transition, incorporating real time feedback from our engineers over time. Today, Monorobot is an active member of Ahrefs&rsquo; Slack workspace, dutifully routing GitHub activity notifications to different channels based on the relevance of each activity.</p><p>And now we&rsquo;re <a href="https://github.com/ahrefs/monorobot">open-sourcing Monorobot</a>, for anybody to use in their monorepo setup! The package is available via&nbsp;<a href="https://opam.ocaml.org/packages/monorobot/">OPAM</a>:</p><pre>opam install monorobot</pre><p>Read on for more details about the motivation, an overview of the main features, and what&rsquo;s in the pipeline.</p><h3>Existing Slack integrations lack monorepo&nbsp;support</h3><p>Within a monorepo, multiple projects have their code located in separate, nested directories. Correspondingly, each project&rsquo;s Slack channel is only interested in activity from that part of the overall repository. The issue with most GitHub-to-Slack integrations is that once you subscribe a Slack channel to a GitHub repository, the channel receives <em>all</em> activity from that repository.</p><p>Suppose we operate various camel-related services, and we&rsquo;re planning to launch a new camel ride-sharing app called Camel Ride. The directory structure could look like&nbsp;this:</p><pre>monorepo/<br/>| frontend/<br/>| | camelride_ui/<br/>| | | mobile/<br/>| | | web/<br/>| | cameldance/<br/>| backend/<br/>| | camelride/<br/>| | | routing/<br/>| | | pricing/<br/>| | camelfood/</pre><p>As you can see, both the frontend/ and backend/ directories contain code for our fictitious ride-sharing service, along with code from other projects.</p><p>If we were to connect the <a href="https://slack.com/help/articles/232289568-GitHub-for-Slack">GitHub for Slack</a> integration to this repository, notifications for activity from all projects would be sent to the same channel. Even if I were only interested in activity from the Camel Ride project, I&rsquo;d need to sift through notifications from the other, unrelated projects. Imagine the volume of notifications this would create for a larger monorepo with dozens of projects. What a&nbsp;mess!</p><h3>Enter Monorobot</h3><figure><img src="https://cdn-images-1.medium.com/max/1024/1*ZHkBDdpNcMMw29BmHirM_A.png" alt=""/><figcaption>Monorobot, hard at&nbsp;work.</figcaption></figure><p>Monorobot enables more granular control over where notifications from the same repository get routed, depending on the type of activity. This routing behavior can be defined in a configuration file named&nbsp;.monorobot.json, which should be committed to the root of the monorepo. Once you create a <a href="https://docs.github.com/en/developers/webhooks-and-events/webhooks/about-webhooks">GitHub webhook</a> from the repository to a running instance of Monorobot, it will use the configuration file to route notifications to relevant channels based on the webhook event&nbsp;payload:</p><ul><li>For pushed commits, it checks the path prefixes of the files modified in the&nbsp;commits.</li><li>For activity related to PRs and issues, it checks their&nbsp;labels.</li><li>For status updates on pushed commits (e.g., CI builds), it uses the same path prefix logic as pushed&nbsp;commits.</li></ul><p>Additionally, Monorobot supports unfurling GitHub links shared in&nbsp;Slack.</p><h4>Path prefix routing for commit push notifications</h4><p>Continuing with our example, suppose we want to route all commit activity related to the Camel Ride project to a Slack channel called <em>#camelride</em>. Our configuration file might look like&nbsp;this:</p><pre>{<br/> ...,<br/> &quot;prefix_rules&quot;: {<br/> &quot;rules&quot;: [<br/> {<br/> &quot;match&quot;: [<br/> &quot;frontend/camelride_ui/&quot;,<br/> &quot;backend/camelride/&quot;<br/> ],<br/> &quot;ignore&quot;: [<br/> &quot;frontend/camelride_ui/images&quot;,<br/> ],<br/> &quot;channel&quot;: &quot;camelride&quot;<br/> }<br/> ]<br/> }<br/>}</pre><p>Each rule &ldquo;matches&rdquo; a file path to a channel. Whenever someone pushes a commit touching files with either of these prefixes, the <em>#camelride</em> channel will be notified. All other commits will be&nbsp;ignored.</p><p>If a file prefix appears in a rule&rsquo;s optional ignore field, the rule won't be matched even if the prefix is is also in the match field. In the above snippet, the Camel Ride frontend team has decided to silence notifications for activity in the images/ subdirectory.</p><p>Now, let&rsquo;s say the project&rsquo;s price optimization team is growing, and they&rsquo;ve decided to create their own separate Slack channel called <em>#camelride-pricing</em>. We can simply commit an update to the&nbsp;.monorobot.json file, and Monorobot will detect the configuration change:</p><pre>{<br/> ...,<br/> &quot;prefix_rules&quot;: {<br/> &quot;rules&quot;: [<br/> {<br/> &quot;match&quot;: [<br/> &quot;frontend/camelride_ui/&quot;,<br/> &quot;backend/camelride/&quot;<br/> ],<br/> &quot;ignore&quot;: [<br/> &quot;frontend/camelride_ui/images&quot;,<br/> ],<br/> &quot;channel&quot;: &quot;camelride&quot;<br/> },<br/> {<br/> &quot;match&quot;: [<br/> &quot;backend/camelride/pricing/&quot;<br/> ],<br/> &quot;channel&quot;: &quot;camelride-pricing&quot;<br/> }<br/> ]<br/> }<br/>}</pre><p>Since Monorobot will match the rule with the longest matched prefix, only commits related to the price optimization aspect of Camel Ride will notify <em>#camelride-pricing</em>, and all other general Camel Ride commits will notify <em>#camelride</em>.</p><p>There are additional configuration options for prefix rules (and for label rules discussed in the next section) that aren&rsquo;t mentioned here. Visit the <a href="https://github.com/ahrefs/monorobot">repository</a> for the full&nbsp;details.</p><h4>Label-based routing for PRs and issue notifications</h4><p>For activity related to pull requests and issues (opening, closing, merging, commenting, and reviewing), Monorobot uses labels to determine routing. The format is largely the same as for path prefix&nbsp;routing:</p><pre>{<br/> ...,<br/> &quot;label_rules&quot;: {<br/> &quot;default_channel&quot;: &quot;notifications&quot;,<br/> &quot;rules&quot;: [<br/> {<br/> &quot;match&quot;: [<br/> &quot;Camel Ride&quot;<br/> ],<br/> &quot;channel&quot;: &quot;camelride&quot;<br/> },<br/> {<br/> &quot;match&quot;: [<br/> &quot;Price Optimization&quot;<br/> ],<br/> &quot;channel&quot;: &quot;camelride-pricing&quot;<br/> }<br/> ]<br/> }<br/>}</pre><p>Here, all PRs and issues with the &ldquo;Camel Ride&rdquo; label will have activity sent to <em>#camelride</em>; those with the &ldquo;Price Optimization&rdquo; label to <em>#camelride-pricing</em>; and those with both labels to both channels.</p><p>The default_channel field provides an option to fall back on a channel if no rule is matched; this option is available for prefix rules as&nbsp;well.</p><h4>Status notifications</h4><p>Monorobot also supports build status notifications for CI pipelines. When it receives a status update for a pushed commit, it routes it to the relevant channel(s) by applying the prefix rules to the commit associated with the build. Further filtering based on status (e.g., ignoring canceled builds, and only notifying for a successful build when preceded by a failed one) is also possible.</p><h4>Link unfurling</h4><p>Finally, Monorobot can unfurl links to GitHub repositories shared on Slack (including private ones, if a personal access token is provided). This applies to commit, issue, and pull request&nbsp;URLs.</p><h3>What&rsquo;s next</h3><p>Monorobot is actively used at Ahrefs today, but there are lots of promising future directions it could take. Here, we list a&nbsp;few.</p><h4>Unifying GitHub and Slack identities</h4><p>It would be useful to allow GitHub user IDs to be mapped to Slack ones. This would enable more personalized features for Monorobot, such as direct messaging a user when their review is requested or when a CI build fails on a feature branch they authored.</p><h4>Consolidating notifications</h4><p>Sometimes, a collection of multiple GitHub webhook events makes sense to be grouped and delivered as a single Slack notification. For example, pull request reviews generate discrete webhook events for each review comment, but it would make more sense to pool them together, so as not to spam a channel with many notifications.</p><h4>Better status notifications</h4><p>A CI build failure can have multiple potential causes:</p><ol><li>A bad&nbsp;commit</li><li>A previous bad commit that has yet to be&nbsp;fixed</li><li>An issue with the pipeline itself (this is out of scope for Monorobot)</li></ol><p>It can be quite tricky to discern between the first two causes from the GitHub webhook event alone. Cause 1 is handled well by our current approach of using path prefix routing on the commit associated with the build. But with cause 2, that same approach doesn&rsquo;t always send the build failure notification to the channel where it is actually relevant. In that case, the originator of the initial bad commit won&rsquo;t be nagged about all subsequent failures, and Slack channels with no relevance to the cause of failure will get polluted with unnecessary notifications.</p><p>How can we best determine whether a status notification is &ldquo;relevant&rdquo; to a Slack channel? This is still an open question, but one possible direction is to track build state per <em>build step</em> rather than per <em>status</em>, and route notifications based on that. For example, if an overall build fails due to a backend build step failure, then it could be sent to a channel where the frontend team won&rsquo;t be notified.</p><h3>Wrapping up</h3><p>The overall goal of Monorobot is to make Slack notifications more <em>relevant</em> for all teams in a large <em>monorepo environment</em>, using the information available from GitHub webhook events. We&rsquo;ve had fairly positive results with our own internal usage, and now we hope others find it useful as&nbsp;well.</p><p>Monorobot is written in OCaml. <a href="https://github.com/ahrefs/monorobot">We welcome your feedback and contributions on&nbsp;GitHub!</a></p><p>P.S. If anyone does make an actual ride sharing service for camels, do let us&nbsp;know&hellip;</p><p><em>Thanks to Feihong, Igor, and Louis for feedback on this&nbsp;post.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=374260e2ca43" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/monorobot-a-slack-bot-for-monorepos-374260e2ca43">Monorobot: a Slack bot for monorepos</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/monorobot-a-slack-bot-for-monorepos-374260e2ca43?source=rss----303662d88bae--ocamlMonorobot: a Slack bot for monorepos2021-12-09T15:19:04-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<figure><img src="https://cdn-images-1.medium.com/max/1024/1*tYLUO4FDmJ6bzlsPp14LdQ.jpeg" alt=""/><figcaption>Photo by <a href="https://unsplash.com/@madebyjens?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Jens Lelie</a> on&nbsp;<a href="https://unsplash.com/s/photos/fork-road?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>At Ahrefs, we have been using BuckleScript and ReasonML in production <a href="https://tech.ahrefs.com/one-and-a-half-years-of-reasonml-in-production-2250cf5ba63b">for more than two years</a>. We already have a codebase of tens of thousands of lines of code, with several web applications that are data intensive and communicate with backend services written in <a href="http://ocaml.org/">OCaml</a>, using tools like&nbsp;<a href="https://github.com/ahrefs/atd">atd</a>.</p><p>Given our investment in these technologies, we have been following closely the recent changes in <a href="https://rescript-lang.org/">ReScript</a>, with its rebrand and renaming, and the split with the ReasonML project, explained in the project <a href="https://rescript-lang.org/blog/bucklescript-is-rebranding">blog&nbsp;post</a>.</p><h3>ReScript: becoming its own&nbsp;language</h3><p>We are excited about the way ReScript is unifying the experience and making it easier for developers who are getting started to find documentation in a single place, as well as continuing its strong focus on performance and readable JavaScript output.</p><p>On the other hand, we are trying to figure out the implications of this change in the mid- and long-term, especially regarding the integration with the OCaml ecosystem. And more importantly, what this evolution will mean for production users like us who rely on this integration.</p><p>ReScript integration with OCaml has historically been seamless, as BuckleScript started originally as a <a href="https://www.reddit.com/r/ocaml/comments/4enok3/bloombergbucklescript_a_back_end_for_the_ocaml/">new backend for the OCaml compiler</a>. However, in recent months, there have been several hints that ReScript wants to evolve towards becoming its own language:</p><ul><li>It has now <a href="https://github.com/rescript-lang/syntax">its own parser</a>, incompatible with OCaml native applications</li><li>Official repository guidelines for technical writing mentions explicitly that <a href="https://github.com/rescript-association/rescript-lang.org/blob/master/CONTRIBUTING.md#technical-writing-documentation">no reference to OCaml</a> should appear in&nbsp;docs</li><li>Upgrades to the latest version of OCaml compiler, which <a href="https://web.archive.org/web/20210208054855if_/https://github.com/rescript-lang/rescript-compiler/wiki">used to be part of the roadmap</a>, have been <a href="https://forum.rescript-lang.org/t/some-thoughts-on-community-building/1474">deprioritized</a> recently.</li></ul><p>So, even if officially ReScript has not announced that they will break backwards compatibility with OCaml, just the fact that it is sticking with an old version of the OCaml compiler poses some challenges for us in terms of tooling. The uncertainty about the future and the pace of changes add some risk to the high-level goals we have for our teams and codebase: we would like to share <em>more</em> code between frontend and backend, not&nbsp;less.</p><h3>Melange: a fork of ReScript, focused on OCaml compatibility</h3><p>When Ant&oacute;nio Monteiro <a href="https://anmonteiro.com/2021/03/on-ocaml-and-the-js-platform/">announced Melange</a>, a fork of ReScript but with a strong focus on keeping compatibility with OCaml, we decided to try it out and see how it could work for&nbsp;us.</p><p>Ultimately, the experiment was successful. We managed to build all our frontend applications with Melange, while keeping the existing bundling setup, which currently uses&nbsp;Webpack.</p><p>Throughout this process, we had to modify some parts of the code. We will now go through the most relevant parts of the&nbsp;process:</p><ul><li>Upgrade to OCaml 4.12: the most relevant part was the deprecation of Pervasives module to use&nbsp;Stdlib.</li><li>Use ppxlib in our ppxs: we had to upgrade the two ppxs that we use in the frontend codebase to the latest compiler version, <a href="https://github.com/ahrefs/bs-emotion/compare/master...jchavarri:ocaml4.12-ppxlib">bs-emotion-ppx</a> and an in-house <a href="https://github.com/ahrefs/bs-react-intl-ppx">ppx for internationalization</a>.</li><li>Configure esy: we were already using esy to bring the editor tooling into scope of the developer environment, so we just had to make sure melange would also be included in the json configuration.</li><li>Upgrade to Reason 3.7.0: a quite simple change too, as the whole process is automated by using refmt. As a side note, we ran into <a href="https://github.com/reasonml/reason/issues/2636">a small bug</a> with some type annotations, that we were able to work&nbsp;around.</li><li>&ldquo;Lift&rdquo; dune workspace to the root of our monorepo: this is probably the most intrusive change. Because we have shared code between backend and frontend, and Dune needs to have access to all sources under its workspace, we had to &ldquo;lift&rdquo; the Dune workspace from the backend directory to the root of monorepo.</li></ul><h3>The good</h3><p>This experiment allowed us to experience what a project like Melange could offer for our use case. Here are some of the things we might be able to leverage in a codebase built with&nbsp;Melange:</p><ul><li>Recent version of the OCaml compiler: at some point, we could pin compiler version between backend and frontend teams, making upgrades more straightforward as they would happen atomically.</li><li>Shared editor tooling: the official OCaml <a href="https://github.com/ocamllabs/vscode-ocaml-platform">vscode extension</a> works great with Melange, as well as any other OCaml editor integration. Having backend and frontend teams use similar editor setup removes a lot of maintenance work for&nbsp;us.</li><li>Consuming ppxs from source: Melange allows to consume ppxs from source, which also removes issues with pre-compiled ppxs (like this issue with the recent <a href="https://github.com/ahrefs/bs-emotion/issues/53">M1&nbsp;Macs</a>).</li><li>Melange allows to run all ppxs <a href="https://github.com/melange-re/melange/pull/171">from a single executable file</a>, which has some nice performance benefits.</li><li>Use Dune for atd files generators: ReScript &ldquo;generators&rdquo; are unfortunately <a href="https://web.archive.org/web/20200710044513if_/https://reasonml.org/docs/reason-compiler/latest/build-advanced">not documented anymore</a>, but we use them extensively for atd file generation. Being able to share Dune rules in backend and frontend would make our build setup&nbsp;easier.</li><li>Access to OCaml documentation tooling: Melange allows to leverage existing tooling for generating documentation, like&nbsp;<a href="https://github.com/ocaml/odoc/">odoc</a>.</li><li>Async syntax: the latest Reason version <a href="https://github.com/reasonml/reason/pull/2487">supports &ldquo;let op&rdquo; syntax</a>, which is handy for client-side code.</li></ul><h3>The bad</h3><p>While there are many things that are exciting about Melange, there are some other parts that can be improved.</p><ul><li>Build performance: We already knew that performance would be far worse than ReScript, as Melange uses Dune in a way that it was not designed for. In our tests, builds with Melange are roughly 1 order of magnitude slower than ReScript&nbsp;ones.</li><li>First-class Dune support: if there was a deeper integration between Dune and Melange, we could explore features like shared libraries or shared rules between backend and frontend. As of today, Dune has no knowledge about Melange environment, so it can perform basic rules execution, but there is no access to high level stanzas like library in&nbsp;Melange.</li><li>Two-headed goal: finally, we see a more strategic risk in Melange proposition. Right now it has two goals: keep compatibility with both ReScript and OCaml. But we don&rsquo;t know how long these goals will be feasible. If at some point ReScript decides to move away from the OCaml compiler fully, then Melange users would not be able to consume any updates to the ReScript ecosystem anymore.</li></ul><h3>Alright, but are you migrating to Melange or ReScript?</h3><p>With all the information available, the answer is: we don&rsquo;t know yet. &#128516; We want to keep exploring all the available options and have as much information as possible before committing further. So for now, we are upgrading the codebase to recent versions of ReScript, but we are holding up on features that only work one way. For example, we have not migrated our codebase to the ReScript syntax yet, as <a href="https://github.com/rescript-lang/syntax/issues/405">there is no way to translate back to Reason&nbsp;syntax</a>.</p><p>In the meantime, we will keep exploring how far the limitations of Melange can be mitigated. To be continued! &#128640;</p><p><em>Thanks to Igor and Feihong for reviewing and improving earlier versions of this&nbsp;post.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=9f881f6d022b" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/building-ahrefs-codebase-with-melange-9f881f6d022b">Building Ahrefs codebase with Melange</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/building-ahrefs-codebase-with-melange-9f881f6d022b?source=rss----303662d88bae--ocamlBuilding Ahrefs codebase with Melange2021-05-18T15:24:20-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<figure><img src="https://cdn-images-1.medium.com/max/1024/1*Nl5vYk_k-mC4j32XEjryHQ.jpeg" alt=""/><figcaption>Photo by <a href="https://unsplash.com/@willianjusten">https://unsplash.com/@willianjusten</a></figcaption></figure><p>The first <a href="https://reasonml.org/">Reason</a> application at <a href="https://ahrefs.com">Ahrefs</a> went online on January 31, 2019. Since then, many more applications have been either rewritten in Reason, are being slowly migrated from React to ReasonReact, or are conceived from the start as Reason projects. It is safe to say that the bet placed on Reason paid off big time. We will never go back to doing pure JavaScript again, with the possible exception of simple backend&nbsp;scripts.</p><p>In the past few years, it&rsquo;s come to light that there are a number of other <a href="https://www.messenger.com/">large</a> <a href="https://www.onegraph.com/">Reason</a>/<a href="https://darklang.com/">BuckleScript</a> <a href="https://onivim.io/">codebases</a> in the wild, but there still isn&rsquo;t a ton of information out there about what it&rsquo;s really like to work with Reason in production. To help remedy that, we thought it would be instructive to ask each of our frontend team members what their Reason journey has been like so&nbsp;far.</p><p>We gave them the following questions as starting points (but they were free to talk about anything they&nbsp;wanted):</p><ul><li>How does Reason compare to other languages you&rsquo;ve used in the&nbsp;past?</li><li>What&rsquo;s your favorite thing about&nbsp;Reason?</li><li>What&rsquo;s your least favorite thing about&nbsp;Reason?</li><li>How does ReasonReact compare to other frameworks you&rsquo;ve&nbsp;used?</li><li>Was it easy to pick up Reason? Why or why&nbsp;not?</li></ul><h4>Javi</h4><ul><li>How does Reason compare to other languages you&rsquo;ve used in the&nbsp;past?</li></ul><p>In the past I worked with languages like Java, C, or less known like Pascal or Prolog. But the languages I&rsquo;ve spent more time with are Objective-C and JavaScript. The main difference between all those languages and Reason is the exhaustiveness that you get from OCaml type checker. This is maybe awkward, but it feels like you stop coding alone and suddenly you have a sidekick always sitting next to you, that is helping you notice the things you forgot about, or found new code that is not consistent with code you or someone else wrote&nbsp;before.</p><p>In a world that is moving towards remote work, where many of us spend hours every day coding physically far from our colleagues, it makes the experience much more delightful. Plus, it allows for teams working on different time zones to keep a healthier work-life balance, because there is less need to have synchronous communication than with more dynamic languages, as more assumptions and design decisions are &ldquo;embedded&rdquo; into the&nbsp;code.</p><ul><li>What&rsquo;s your favorite thing about&nbsp;Reason?</li></ul><p>Can I pick two things? It&rsquo;s hard to choose only&nbsp;one.</p><p>The first one is the exhaustiveness and quality of the type checker, as mentioned above. Sometimes it takes a bit longer to build a feature than what it would in other languages, until the types are figured out. But this is largely compensated by the confidence one has when shipping code to production, or diving into large refactors.</p><p>The second one is the speed of the BuckleScript build system, which is built on top of <a href="https://ninja-build.org/">ninja</a>. I had never worked with such fast build system. As an example, we have recently started to use remote machines to develop at Ahrefs. In one of these machines that has 72 cores, BuckleScript takes roughly 3 seconds to clean build <em>all</em> our Reason code: application, libs, decoders&hellip; everything. Many tens of thousand lines of code! We thought there were something wrong, but we realized the compiler is just So Blazing&nbsp;Fast&trade;&#65039;.</p><ul><li>What&rsquo;s your least favorite thing about&nbsp;Reason?</li></ul><p>I guess we&rsquo;re going through a necessary stage until things stabilize in the future, but there is a lot of fragmentation at the moment between &ldquo;Reason native&rdquo;, which tries to stay closer to OCaml, and &ldquo;Reason web&rdquo;, which has a goal to become friendlier for JavaScript developers.</p><p>I am excited to see what <a href="https://reasonml.org/blog/bucklescript-8-1-new-syntax">BuckleScript new syntax</a> will lead to, but I would also love to see a &ldquo;universal&rdquo; solution that works for the main use cases out of the box, becoming sort of Rails for Ocaml or Reason. <a href="https://github.com/oxidizing/sihl/">sihl</a> is a project that seems to go in that direction and looks very promising.</p><ul><li>How does ReasonReact compare to other frameworks you&rsquo;ve&nbsp;used?</li></ul><p>I consider ReasonReact mostly like React + types on top, because the bindings layer is very thin. The thing that I like most about React is that it follows the Unix philosophy: it does one thing and it does it really well. Maybe we have forgotten already today, but having to maintain and mutate UI based on data updates was one of the main sources of bugs in the past. The other nice thing is that there is so much good content about it: blog posts, documentation, etc.</p><ul><li>Was it easy to pick up Reason? Why or why&nbsp;not?</li></ul><p>It took some time, as with any other language. We have things like syntax or semantics much more ingrained into our brains than we think, so there is always some &ldquo;rewiring&rdquo; time that is needed to learn a new language, even if Reason makes an effort to stay close to JavaScript syntax. The most challenging part was probably the bindings one, because coming from JavaScript, there are no previous knowledge that one can use as foundation to build upon, it&rsquo;s all &ldquo;new knowledge&rdquo;. glennsl <a href="https://github.com/glennsl/bucklescript-ffi-cheatsheet">BuckleScript ffi cheatsheet</a> was a huge help for&nbsp;me.</p><h4>Ze</h4><p>I really like working with Reason, and have wanted to do so for a while. I was quite happy to see that working with it matched my expectations.</p><p>You get so much support from the type system, and still have a lot of flexibility to represent your domain model. Coming from other languages or paradigms, you don&rsquo;t feel limited at all in what you can&nbsp;achieve.</p><p>The language has such a strong type system that you feel much more comfortable with your&nbsp;coding.</p><p>The OCaml type system is there to make sure you code with assurance. This is especially true when refactoring code. You can be sure that everything will work fine after it compiles. If it compiles, it works&nbsp;:)</p><p>It&rsquo;s also very helpful when working on a monorepo. You don&rsquo;t have to keep reading the source code of everything you use to make sure you don&rsquo;t have types mistakes. Changes in code in one lib reflect immediately in all the others. This makes the feedback loop much shorter and&nbsp;safer.</p><p>The editors integrations with the type system are quite good and help a lot to write code better and&nbsp;faster.</p><p>Also, compilation times are super&nbsp;fast.</p><p>Last, but not least, ReasonReact is, for me, the hidden gem of ReasonML. The newcomers that have some difficulty with the language should start with it. IMHO, ReasonReact is simpler and has a better developer experience than React itself. It should be the gateway drug frontend developers need to get started with Reason/OCaml &#128516;</p><h4>Liubomyr</h4><p>To me, all those language features boil down to one essential thing, and it&rsquo;s the easiness of refactoring. New business requirements popups all the time, and often your initial code assumptions are no longer correct. It was such a pain to modify code in a large JS codebase, as you never know how many things you potentially break in the process. With Reason, it has never been easier. If you need to change your data shape or some component API, you just do it, and from there, the compiler will guide you through all the places you broke, and help to fix&nbsp;those.</p><p>Coming from the JS world, it feels like the initial development is slower, because of the learning curve, missing bindings, less StackOverflow answers, but in the end, you are getting a stable software which is way easier to maintain and add features&nbsp;to.</p><h4>Egor</h4><p>I switched to Reason when I joined Ahrefs team about a year ago, before that I worked mostly with Ruby language.</p><p>The first thing that impressed me in ReasonML was code refactoring. Refactoring in language with a strong type system, like ReasonML and OCaml, is much easier than what I am used to. If your program compiles after your refactoring&#8202;&mdash;&#8202;most likely you did everything right, if it doesn&rsquo;t compile&#8202;&mdash;&#8202;you can immediately see what you forgot to change. This can be achieved in languages with a dynamic type system only with a huge amount of code tests (supporting big test suite is a time consuming process as well as code support).</p><p>The other thing that I really like about ReasonML codebase&#8202;&mdash;&#8202;how readable it is. When you just enter into ReasonML world&#8202;&mdash;&#8202;some things can be unfriendly from the first sight, for example, immutable let bindings, but in the end, you realize that these language decisions help you to write cleaner and simpler&nbsp;code.</p><h4>Seif</h4><p>The programming language I used the most in the past is JavaScript. I switched to Reason when I joined Ahrefs a few months ago. From the start, I worked mainly on the code shared by the majority of the tools and I don&rsquo;t think I would have had the same confidence making changes if I was doing it with JavaScript. I love JavaScript&rsquo;s developer experience and accessibility. Reason provided me predictability without hurting these very same things I like about JavaScript.</p><h4>Bryan</h4><p>Reason (and OCaml) is, by far, one of the easiest languages to work with. Easy in the sense that the compiler helps eliminate an entire class of errors so you don&rsquo;t have to worry about them. Additionally, in most other web-centric languages, it&rsquo;s a pain to add features to existing code that you&rsquo;ve not touched for a long time. With strong static typing, I can usually add the feature I want in either the backend or frontend, and then let the compiler tell me what needs to be&nbsp;updated.</p><p>Pattern-matching is one of my favourite features in Reason. To me, it makes more sense to be able to explicitly specify conditions that I&rsquo;m interested in a clear and concise manner, and let the compiler tell me if I missed out a particular condition. Records go hand-in-hand with this. As software programs are made up of data and instructions, records are the perfect data containers. They are quick to define and query, focusing on data rather than behaviour (think classes and instance methods).</p><p>It definitely took a while to pick up Reason mainly because it takes time to become familiar with idiomatic OCaml. But once I crested that learning curve, everything just made sense and all the features of the language that made Reason seemingly difficult to learn&#8202;&mdash;&#8202;strong typing, the functional paradigm, etc, became assistants that helped me to write better&nbsp;code.</p><h4>Feihong</h4><p><a href="https://reasonml.github.io/reason-react/en/">ReasonReact</a> is a great library for making complex UIs in a large codebase because you get the familiarity of React coupled with the type safety of OCaml. Having two well-established technologies in its foundation is a big advantage that ReasonReact has over other functional UI libraries/frameworks in the transpile-to-JS universe. I didn&rsquo;t have any professional OCaml experience before joining, yet the ramp up was made much easier by my existing knowledge of React and the (somewhat superficial) similarity of the Reason syntax to JS. Oftentimes it was possible to correctly guess the intent of existing Reason code without knowing all the syntax, because most React concepts carry over pretty directly. And even though the documentation is incomplete and not perfect, it&rsquo;s quite usable already and among conceptually-similar frameworks is second only to the Elm documentation.</p><p>The compiler errors were difficult to get used to at first. The compiler is fairly good at pointing out the location of the error, but not necessarily as good at explaining the nature or cause of the error. As such, having a REPL would be extremely useful. Actually, OCaml does have its own REPL, but BuckleScript (the compiler used by Reason to translate OCaml to JS) does not at the moment. Nonetheless, the <a href="https://reasonml.github.io/en/try">Try Reason</a> page is a really good tool to try out small snippets of code and is extremely useful while learning the language (we will still occasionally post Try Reason links in our slack channel).</p><h3>Summary</h3><p>The reality is that Ahrefs has always been an OCaml shop, but in the past OCaml was only used to build the backend. Now that we are also using it on the frontend, we get the benefits that our backend colleagues have enjoyed for many years: the expressiveness afforded by pattern matching, the ease of refactoring in large codebases, the stability of a mature programming language, and the confidence of &ldquo;if it compiles, it works&rdquo;. To make a shoddy nautical analogy, it is as if we had built a wooden ship powered by a turbo engine. But now the wooden parts are being replaced with steel and plastic, bringing the exterior of the ship up to modern standards as well. As a result, the ship runs faster and more reliably, making the passengers (our users) more satisfied. Also, pirates (bugs) have a harder time hijacking the ship because it&rsquo;s sturdier and defended by well-disciplined camels. Because the ship keeps getting more and more passengers who want to experience a delightful ride and take pictures with enigmatic camels, we require a constant influx of willing and able boat engineers (who aren&rsquo;t allergic to camels) to extend and maintain the ship. (Yes, that means that <a href="https://ahrefs.com/jobs">we are hiring</a>&#65039;.)</p><p><em>Thanks to Raman and Louis for fact checking this&nbsp;post.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=2250cf5ba63b" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/one-and-a-half-years-of-reasonml-in-production-2250cf5ba63b">One and a half years of ReasonML in production</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/one-and-a-half-years-of-reasonml-in-production-2250cf5ba63b?source=rss----303662d88bae--ocamlOne and a half years of ReasonML in production2020-07-26T15:19:31-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<p><em>Written with </em><a href="https://twitter.com/javierwchavarri"><em>Javier Ch&aacute;varri</em></a><em> and </em><a href="https://github.com/feihong/"><em>Feihong&nbsp;Hsu</em></a><em>.</em></p><p>The first <a href="https://www.reason-conf.us/">Reason Conf US</a> just ended. Many talks mentioned native compilation. Sharing code between BuckleScript and native artifacts is a use case which is more and more common. This blog post is an introduction on how to set up a library available for both worlds, sharing as much code as possible.</p><h3>The goal</h3><p>What we try to produce is a library with an identical interface for BuckleScript and native. But without duplicating code. It should also be possible to have some parts of the library that are a different implementation depending on the target, as we want to be able to leverage existing libraries that are working only in one of the&nbsp;worlds.</p><h3>The build&nbsp;systems</h3><p>For BuckleScript, there is only one build system: bsb. It is driven by a bsconfig.json file. And is installed as part of the bs-platform.</p><p>On the native side, there are a lot of different build systems that are available. But recently one of them became a de facto standard: dune. It works with a very minimal amount of configuration. And it supports the reason syntax by&nbsp;default.</p><p>These two tools are working in a way which is pretty similar. They share a lot of concepts. And it is easy to set them up so that both are working in the same codebase.</p><p>The main similarities that interest us&nbsp;are:</p><ul><li>The ability to work on specific source directories</li><li>Namespacing in bsb and wrapping in dune are both putting all the<br/>files of the library under a single module&nbsp;name</li></ul><h3>The source code file&nbsp;tree</h3><p>The code of the library is split into 3 directories.</p><pre>&#9500;&#9472;&#9472; js/<br/>&#9500;&#9472;&#9472; native/<br/>&#9492;&#9472;&#9472; shared/</pre><ul><li>shared is meant to host most of the code and all the code in this directory will be compiled in both&nbsp;modes.</li><li>js contains the parts that are specific to BuckleScript.</li><li>native contains the parts that are specific to native&nbsp;OCaml.</li></ul><h3>Set up the build&nbsp;systems</h3><p>Once we have our basic skeleton for the library, it is time to set up the build systems. We want to have two configurations as similar as possible to make them easier to understand. Once we are done, the tree will look like&nbsp;this:</p><pre>&#9500;&#9472;&#9472; bsconfig.json<br/>&#9500;&#9472;&#9472; dune<br/>&#9500;&#9472;&#9472; dune-project<br/>&#9500;&#9472;&#9472; js/<br/>&#9500;&#9472;&#9472; native/<br/>&#9492;&#9472;&#9472; shared/</pre><h4>BuckleScript</h4><p>At the root of the library we need a bsconfig.json file to drive<br/>bsb. The documentation is available at <a href="https://bucklescript.github.io/docs/en/build-configuration%5D(https://bucklescript.github.io/docs/en/build-configuration).">https://bucklescript.github.io/docs/en/build-configuration</a>.</p><p>The main part for us is sources. We will use it to tell bsb to look at the js and shared folders. We also want to set namespace to true, which will wrap all your project&rsquo;s files under a common module&nbsp;name.</p><pre> &quot;namespace&quot;: true,<br/> &quot;sources&quot;: [<br/> {<br/> &quot;dir&quot;: &quot;js&quot;,<br/> &quot;subdirs&quot;: true<br/> }, {<br/> &quot;dir&quot;: &quot;shared&quot;,<br/> &quot;subdirs&quot;: true<br/> }<br/> ],</pre><p>The rest of the file is as&nbsp;usual.</p><pre>{<br/> &quot;name&quot;: &quot;sharedlib&quot;,<br/> &quot;namespace&quot;: true,<br/> &quot;sources&quot;: [<br/> {<br/> &quot;dir&quot;: &quot;js&quot;,<br/> &quot;subdirs&quot;: true<br/> }, {<br/> &quot;dir&quot;: &quot;shared&quot;,<br/> &quot;subdirs&quot;: true<br/> }<br/> ],<br/> &quot;package-specs&quot;: {<br/> &quot;module&quot;: &quot;es6&quot;,<br/> &quot;in-source&quot;: true<br/> },<br/> &quot;refmt&quot;: 3,<br/> &quot;suffix&quot;: &quot;.bs.js&quot;,<br/> &quot;generate-merlin&quot;: true,<br/>}</pre><h4>Dune</h4><p>We must also add a dune file to the root of the library. For dune, we have different options&#8202;&mdash;&#8202;it is possible to ignore the js directory but read everything else. Or to check only shared and native. To make the configuration similar to BuckleScript, we will go with the second solution.</p><p>The dune directive to do that is dirs. By defaults it tells dune to explore every directory except the ones hidden (starting with a dot) or starting with an underscore. <a href="https://dune.readthedocs.io/en/stable/dune-files.html#dirs-since-1-6">More details in dune&rsquo;s documentation</a>. To make it do what we want, the configuration should&nbsp;be:</p><pre>(dirs shared native)</pre><p>We also use another option of dune to tell it to include the content of those two directories as if it was at the root of the project. Without this stanza, dune would only use the source files at the root of the project and ignore everything in the sub directories.</p><pre>(include_subdirs unqualified)</pre><p>Then we need the usual library stanza to give a name to our library, state the dependencies, compilation flags, etc. In our simple case, the only information needed is the name. We can explicitly set wrapped to true, but this is already the default behavior. The <a href="https://dune.readthedocs.io/en/stable/dune-files.html#library">documentation for the whole library stanza</a> describes how to specify more&nbsp;details.</p><p>The final dune file looks like&nbsp;this:</p><pre>(dirs shared native)<br/> (include_subdirs unqualified)<br/> (library<br/> (name sharedlib))</pre><p>We also want a basic dune-project. If we don&rsquo;t write it by hand, dune will generate it for us. I am using version 1.10 as an example. But it can be changed to whatever version suits your&nbsp;project.</p><pre>(lang dune 1.10)</pre><h3>Compilation</h3><p>With the setup described above, the compilation for BuckleScript and native is the same as in a setup with only one or the&nbsp;other.</p><ul><li>bsb -make-world for BuckleScript</li><li>dune build @all for&nbsp;dune</li></ul><p>The call to bsb is usally put in package.json in the scripts part, so that the usual yarn build can be used. For native, it depends if you rely on esy or&nbsp;opam.</p><h3>How to consume the&nbsp;library</h3><p>This is exactly the same setup that would be used in a pure BuckleScript or pure native&nbsp;library.</p><p>To use your library in BuckleScript:</p><ul><li>Add the name and version to package.json</li><li>Add the name to bsbconfig.json of consuming library/app</li></ul><p>To use your library in native OCaml, add the name of your library to the libraries part an executable or library stanza,&nbsp;e.g.</p><pre>(executable<br/> (name main)<br/> (libraries sharedlib))</pre><h3>Module naming</h3><p>If you want your module name to contain capital letters in the middle (e.g. TeenageMutantNinjaTurtles), then be aware that <a href="https://bucklescript.github.io/docs/en/build-configuration.html#name-namespace">name munging</a> works differently between bsbconfig.json and dune. For example, if you want to refer to your module as CoolSharedLib in your code, then the name in bsbconfig.json must be cool-shared-lib, and in dune it must be coolSharedLib.</p><h3>Platform specific&nbsp;code</h3><p>The whole library does not have to be exactly the same in the two platform. It is possible to add modules that are available only in one mode. Or to have modules with a different interface.</p><p>For example, by adding a file Foo.re in js but not in native, the library now has a module Foo available when compiled to javascript. But only when compiled to javascript.</p><h3>Downsides</h3><ul><li>Both bsb and dune generate&nbsp;.merlin files when they compile our library. They override each other. It might be troublesome if the version of ocaml used for native code is not 4.02.3. Simply recompile the library for your platform to solve the&nbsp;problem.</li><li>Out of the box, this approach doesn&rsquo;t really allow us to share interface files between both platforms: native and BuckleScript. One workaround for that, if we wanted to share some module Foo, is to:<br/>1. add Foo.mli or Foo.rei file in shared<br/>2. add include FooImplementation in Foo.ml<br/>3. add FooImplementation in both native and js&nbsp;folder</li><li>It&rsquo;s not possible to be platform specific for just a few lines of code (e.g. if IS_NATIVE foo else bar), the minimal per-platform unit is a file/module.</li></ul><h3>Example project</h3><p>We have set up a simple library to showcase what a repository looks like once the whole configuration is in place. It is <a href="https://github.com/ahrefs/hello-native-bucklescript">available on&nbsp;github</a>.</p><p>For now the repository contains only a library. But with this setup, it is actually possible to build an executable too. It is also possible to enrich it, for example by adding <a href="https://tech.ahrefs.com/getting-started-with-atdgen-and-bucklescript-1f3a14004081">atdgen to communicate between both sides of the&nbsp;library</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=22f45e5e946d" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/how-to-write-a-library-for-bucklescript-and-native-22f45e5e946d">How to write a library for BuckleScript and Native</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/how-to-write-a-library-for-bucklescript-and-native-22f45e5e946d?source=rss----303662d88bae--ocamlHow to write a library for BuckleScript and Native2019-10-22T10:09:09-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<p><a href="https://github.com/mjambon/atd">atdgen</a> is a project to create types and data structures that can be serialized to JSON. It is very convenient when communicating between multiple processes, creating a REST API or consuming JSON objects from other tools. It can be compared to <a href="https://json-schema.org/">JSON schema</a> or <a href="https://developers.google.com/protocol-buffers/">Protocol Buffers</a>, but with richer types and more features.</p><p>The idea is to write a list of types in a specification file, an&nbsp;.atd file. Then running atdgen, it is possible to generate OCaml or Java code to serialize/deserialize values of those types to/from corresponding json.</p><p>Until very recently, atdgen could generate code only for native OCaml. But <a href="https://github.com/mjambon/atd/pull/44">the support of bucklescript has been merged</a>! atdgen the cli tool is still a native OCaml binary. But it can output some OCaml code that can be compiled using <a href="https://bucklescript.github.io/">bucklescript</a>.</p><p>The work to implement this new feature of atdgen has been funded by <a href="https://ahrefs.com/">Ahrefs</a>. We highly appreciate open source tools. And as much as possible, we prefer to contribute to existing open source projects rather than to re-invent the wheel internally.</p><h3>Installation</h3><p>To install atdgen we first need to install <a href="https://opam.ocaml.org">opam</a> (OCaml package manager), as atdgen doesn&rsquo;t provide ready to use binaries and is only distributed as source package via opam. The procedure is simple and documented here: <a href="https://opam.ocaml.org/doc/2.0/Install.html">https://opam.ocaml.org/doc/2.0/Install.html</a></p><p>Then we need to initialize opam and create a switch. Any version of ocaml greater or equal to 4.03.0 should be&nbsp;fine.</p><pre>opam init -a<br/>opam switch create . 4.07.1 -y</pre><p>Once it is done, we have to install the development version of atdgen. The support of bucklescript is not officially released.</p><pre>opam pin add atd --dev-repo <br/>opam pin add atdgen --dev-repo</pre><p>Make sure that atdgen is available.</p><pre>$ which atdgen <br/>(current $PWD)/_opam/bin/atdgen</pre><p>Of course, we need bucklescript.</p><pre>yarn init <br/>yarn add bs-platform --dev</pre><p>We also need the bucklescript runtime for atdgen, as it is not currently provided by atdgen itself. So we have written and open-sourced our version of the runtime&nbsp;: <a href="https://github.com/ahrefs/bs-atdgen-codec-runtime">https://github.com/ahrefs/bs-atdgen-codec-runtime</a>.</p><p>This runtime is responsible for the conversion between JSON values and OCaml values. The JSON values are based on the standard <a href="https://bucklescript.github.io/bucklescript/api/Js.Json.html#TYPEt">Js.Json.t type</a> provided by bucklescript to be sure that it is easy to interoperate with the rest of the ecosystem.</p><p>It is published on npm for easy integration in bucklescript projects.</p><pre>yarn add @ahrefs/bs-atdgen-codec-runtime</pre><h3>Project configuration</h3><p>After the previous section, package.json should be almost ready. We can add a few scripts to make it more convenient to compile the project. Here is how it should look once completed.</p><pre>{<br/> &quot;name&quot;: &quot;demo-bs-atdgen&quot;,<br/> &quot;version&quot;: &quot;0.0.1&quot;,<br/> &quot;description&quot;: &quot;demo of atdgen with bucklescript&quot;,<br/> &quot;scripts&quot;: {<br/> &quot;clean&quot;: &quot;bsb -clean-world&quot;,<br/> &quot;build&quot;: &quot;bsb -make-world&quot;,<br/> &quot;watch&quot;: &quot;bsb -make-world -w&quot;,<br/> &quot;atdgen&quot;: &quot;atdgen -t meetup.atd &amp;&amp; atdgen -bs meetup.atd&quot;<br/> },<br/> &quot;devDependencies&quot;: {<br/> &quot;bs-platform&quot;: &quot;^4.0.5&quot;<br/> },<br/> &quot;peerDependencies&quot;: {<br/> &quot;bs-platform&quot;: &quot;^4.0.5&quot;<br/> },<br/> &quot;dependencies&quot;: {<br/> &quot;<a href="http://twitter.com/ahrefs/bs-atdgen-codec-runtime">@ahrefs/bs-atdgen-codec-runtime</a>&quot;: &quot;^1.0.4&quot;<br/> }<br/>}</pre><p>The bucklescript configuration is very simple. We use the basic configuration that can be found in any bucklescript project. Except that we need to add one dependency to bsconfig.json:</p><pre>{<br/> &quot;name&quot;: &quot;demo-bs-atdgen&quot;,<br/> &quot;version&quot;: &quot;0.0.1&quot;,<br/> &quot;sources&quot;: {<br/> &quot;dir&quot;: &quot;src&quot;,<br/> &quot;subdirs&quot;: true<br/> },<br/> &quot;package-specs&quot;: {<br/> &quot;module&quot;: &quot;commonjs&quot;,<br/> &quot;in-source&quot;: true<br/> },<br/> &quot;suffix&quot;: &quot;.bs.js&quot;,<br/> &quot;bs-dependencies&quot;: [<br/> &quot;<a href="http://twitter.com/ahrefs/bs-atdgen-codec-runtime">@ahrefs/bs-atdgen-codec-runtime</a>&quot;<br/> ],<br/> &quot;warnings&quot;: {<br/> &quot;error&quot;: &quot;+101&quot;<br/> },<br/> &quot;generate-merlin&quot;: true,<br/> &quot;namespace&quot;: true,<br/> &quot;refmt&quot;: 3<br/>}</pre><h3>First ATD definitions</h3><p>It is time to create a first&nbsp;.atd file, containing our types. This part is also documented on <a href="https://atd.readthedocs.io/en/latest/tutorial.html#getting-started">https://atd.readthedocs.io/en/latest/tutorial.html#getting-started</a></p><p>For this example, I decided to go with a meetup event. Put the type definitions in src/meetup.atd.</p><pre>(* This is a comment. Same syntax as in ocaml. *)</pre><pre>type access = [ Private | Public ]</pre><pre>(* the date will be a float in the json and a Js.Date.t in ocaml *)<br/>type date = float wrap &lt;ocaml module=&quot;Js.Date&quot; wrap=&quot;Js.Date.fromFloat&quot; unwrap=&quot;Js.Date.valueOf&quot;&gt;</pre><pre>(* Some people don't want to provide a phone number, make it optional *)<br/>type person = {<br/> name: string;<br/> email: string;<br/> ?phone: string nullable;<br/>}</pre><pre>type event = {<br/> access: access;<br/> name: string;<br/> host: person;<br/> date: date;<br/> guests: person list;<br/>}</pre><pre>type events = event list</pre><p>We use the atdgen binary (compiled previously) to generate the ocaml types and the code to serialize/deserialize those&nbsp;types.</p><pre>atdgen -t meetup.atd # generates an ocaml file containing the types<br/>atdgen -bs meetup.atd # generates the code to (de)serialize</pre><p>The generated files&nbsp;are:</p><ul><li>meetup_t.ml(i) which contain the ocaml types corresponding to our ATD definitions.</li><li>meetup_bs.ml(i) which contain the ocaml code to transform from and to json&nbsp;values.</li></ul><p>At this point we can compile our&nbsp;project.</p><pre>yarn build</pre><p>If everything worked properly, we now have two&nbsp;.bs.js files in the src directory.</p><pre>$ tree src<br/>src<br/>&#9500;&#9472;&#9472; meetup.atd<br/>&#9500;&#9472;&#9472; meetup_bs.bs.js<br/>&#9500;&#9472;&#9472; meetup_bs.ml<br/>&#9500;&#9472;&#9472; meetup_bs.mli<br/>&#9500;&#9472;&#9472; meetup_t.bs.js<br/>&#9500;&#9472;&#9472; meetup_t.ml<br/>&#9492;&#9472;&#9472; meetup_t.mli</pre><pre>0 directories, 7 files</pre><p>At this point, we can create new OCaml/Reason files in the src directory and use all the code atdgen generated for us. Two examples to illustrate that.</p><h3>Query a REST&nbsp;API</h3><p>A common usage of atdgen is to decode the JSON returned by a REST API. Here is a short example, using the reason syntax and bs-fetch.</p><pre>let get = (url, decode) =&gt;<br/> Js.Promise.(<br/> Fetch.fetchWithInit(<br/> url,<br/> Fetch.RequestInit.make(~method_=Get, ()),<br/> )<br/> |&gt; then_(Fetch.Response.json)<br/> |&gt; then_(json =&gt; json |&gt; decode |&gt; resolve)<br/> );</pre><pre>let v: Meetup_t.events =<br/> get(<br/> &quot;<a href="http://localhost:8000/events">http://localhost:8000/events</a>&quot;,<br/> Atdgen_codec_runtime.Decode.decode(Meetup_bs.read_events),<br/> );</pre><h3>Read and write a JSON&nbsp;file</h3><p>Atdgen for bucklescript doesn&rsquo;t take care of converting a string to a JSON object. Which allows us to use the performant json parser included in nodejs or the&nbsp;browser.</p><pre>let read_events filename =<br/> (* Read and parse the json file from disk, this doesn't involve atdgen. *)<br/> let json =<br/> Node_fs.readFileAsUtf8Sync filename<br/> |&gt; Js.Json.parseExn<br/> in<br/> (* Turn it into a proper record. The annotation is of course optional. *)<br/> let events: Meetup_t.events =<br/> Atdgen_codec_runtime.Decode.decode Meetup_bs.read_events json<br/> in<br/> events</pre><p>The reverse operation, converting a record to a JSON object and writing it in a file is also straightforward.</p><pre>let write_events filename events =<br/> Atdgen_codec_runtime.Encode.encode Meetup_bs.write_events events (* turn a list of records into json *)<br/> |. Js.Json.stringifyWithSpace 2 (* convert the json to a pretty string *)<br/> |&gt; Node_fs.writeFileAsUtf8Sync filename (* write the json in our file *)</pre><h3>Full example</h3><p>Now that we have our functions to read and write events, we can build a small cli to pretty print the list of events and add new&nbsp;events.</p><p>The source code of the full example is available <a href="https://github.com/ahrefs/bs-atdgen-codec-runtime/tree/master/example">on&nbsp;github</a>.</p><p>You can run it like&nbsp;this:</p><pre>$ echo &quot;[]&quot; &gt; events.json<br/>$ nodejs src/cli.bs.js add louis <a href="mailto:louis@nospam.com">louis@nospam.com</a><br/>$ nodejs src/cli.bs.js add bob <a href="mailto:bob@nospam.com">bob@nospam.com</a><br/>$ nodejs src/cli.bs.js print<br/>=== OCaml/Reason Meetup! summary ===<br/>date: Tue, 11 Sep 2018 15:04:16 GMT<br/>access: public<br/>host: bob &lt;<a href="mailto:bob@nospam.com">bob@nospam.com</a>&gt;<br/>guests: 1<br/>=== OCaml/Reason Meetup! summary ===<br/>date: Tue, 11 Sep 2018 15:04:13 GMT<br/>access: public<br/>host: louis &lt;<a href="mailto:louis@nospam.com">louis@nospam.com</a>&gt;<br/>guests: 1<br/>$ cat events.json<br/>[<br/> {<br/> &quot;guests&quot;: [<br/> {<br/> &quot;email&quot;: &quot;<a href="mailto:bob@nospam.com">bob@nospam.com</a>&quot;,<br/> &quot;name&quot;: &quot;bob&quot;<br/> }<br/> ],<br/> &quot;date&quot;: 1536678256177,<br/> &quot;host&quot;: {<br/> &quot;email&quot;: &quot;<a href="mailto:bob@nospam.com">bob@nospam.com</a>&quot;,<br/> &quot;name&quot;: &quot;bob&quot;<br/> },<br/> &quot;name&quot;: &quot;OCaml/Reason Meetup!&quot;,<br/> &quot;access&quot;: &quot;Public&quot;<br/> },<br/> {<br/> &quot;guests&quot;: [<br/> {<br/> &quot;email&quot;: &quot;<a href="mailto:louis@nospam.com">louis@nospam.com</a>&quot;,<br/> &quot;name&quot;: &quot;louis&quot;<br/> }<br/> ],<br/> &quot;date&quot;: 1536678253790,<br/> &quot;host&quot;: {<br/> &quot;email&quot;: &quot;<a href="mailto:louis@nospam.com">louis@nospam.com</a>&quot;,<br/> &quot;name&quot;: &quot;louis&quot;<br/> },<br/> &quot;name&quot;: &quot;OCaml/Reason Meetup!&quot;,<br/> &quot;access&quot;: &quot;Public&quot;<br/> }<br/>]</pre><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=1f3a14004081" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/getting-started-with-atdgen-and-bucklescript-1f3a14004081">Getting started with atdgen and bucklescript</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/getting-started-with-atdgen-and-bucklescript-1f3a14004081?source=rss----303662d88bae--ocamlGetting started with atdgen and bucklescript2018-09-12T02:53:58-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<blockquote>It was a dark and stormy night; the skylake CPU buzzed with excitement, and then, suddenly, the hyperthreads started to lock&nbsp;up..</blockquote><p>Or something like&nbsp;that.</p><p>This week a new erratum for the Intel Skylake and Kabylake processors families was brought to public attention on <a href="https://lists.debian.org/debian-devel/2017/06/msg00308.html">the Debian mailing list</a>, and then on <a href="https://news.ycombinator.com/item?id=14630183">various</a> <a href="https://www.reddit.com/r/programming/comments/6jfgfp/warning_intel_skylakekaby_lake_processors_broken/">social media</a> and <a href="http://www.theregister.co.uk/2017/06/25/intel_skylake_kaby_lake_hyperthreading/">news&nbsp;outlets</a>.</p><p>We have been investigating this issue since January with the core <a href="http://ocaml.org">OCaml</a> team, as we were struggling with a mysterious bug affecting our developers machines, and ultimately our production system, resulting in a corruption of important data in our databases.</p><p>At <a href="https://ahrefs.com">Ahrefs</a>, we operate a fleet of thousands of servers, running a wide variety of services (huge web crawler among others). At this scale, dealing with unexpected application behaviors is common. While we try to reduce the probability of the software not functioning as expected, bugs are sadly a real part of our everyday life. Even though we can assume the underlying hardware running any infrastructure can be thought of as more reliable and less prone to bugs than software components, issues can still arise in unexpected ways. When the number of servers increases, it is not unusual to observe faults in the hardware preventing the system from functioning as specified.</p><p>It is certainly not frequent to encounter such problems in CPUs but reading through <a href="https://www3.intel.com/content/dam/www/public/us/en/documents/specification-updates/desktop-6th-gen-core-family-spec-update.pdf">the list of errata published by any manufacturer,</a> each CPU model contains a fair amount of bugs. This story is about the bug in the microcode of Skylake processor leading to incorrect code execution under certain conditions. This is certainly scary at first sight: how can we trust our system if we cannot trust its main component&nbsp;? Yet, like software bugs, processor defects can be identified, contained, and we can take actions to prevent them from impacting the operation of the infrastructure.</p><p>We do not know the full implications of this particular bug, especially security implications in case of untrusted code execution. But we&rsquo;d like to tell the story of this erratum from our point of view, to provide some context, and show that dealing with it was not much different than dealing with any usual software flaw. While this post aims to cover our own perspective on this adventure, we would like to thank Mark Shinwell, Xavier Leroy, Fr&eacute;d&eacute;ric Bour, everyone involved in the <a href="https://caml.inria.fr/mantis/view.php?id=7452">Mantis issue</a> and the OCaml IRC channel for their help and time spent investigating with us. Update: Xavier Leroy told his own side of the story in another <a href="http://gallium.inria.fr/blog/intel-skylake-bug/">blog&nbsp;post.</a></p><h3>Setting the&nbsp;scene</h3><p>Our story starts in late 2016 after some of our backend developers received new laptops to work on. After a few days Enguerrand Decorne noticed unusual crashes during compilation of our OCaml codebase.</p><p>This issue, considered mildly annoying at first, seemed to affect only Enguerrand&rsquo;s machine. For a few days no other machine would exhibit the same behavior, so we figured this was a fault specific to his system configuration.</p><p>However, concerns were subsequently raised after witnessing the generation of invalid machine code and later on, after the deployment of a service on one of our new clusters composed of Skylake Xeon processors, leading to the insertion of corrupted data into our storage system. The priority raised from the annoying level, to potentially critical. Other developers started working together to obtain more information and assess the impact on our infrastructure. Soon after we were able to reproduce the issue on several machines.</p><p>The remainder of this post is a technical description of the steps taken to ensure that our systems were operating safely. It is intended to show that such low level CPU issues is not necessarily fatal&#8202;&mdash;&#8202;in less than two weeks, with the great help of core OCaml developers, we identified the conditions of the crash and set up a workaround.</p><h3>Tracking down crashes in&nbsp;OCaml</h3><p>Most of our backend code is written in <a href="https://ocaml.org">OCaml</a>, a high level and expressive language supporting functional programming style (among others), which allows us to develop robust systems with ease, thanks to its strong type system and mature&nbsp;legacy.</p><p>The compiler segfaults were definitely a surprise, since this shouldn&rsquo;t happen for any program written in OCaml, as type system and other features (such as automatic bounds-checking) usually guard us from such errors. However, stack overflows can be possible sources of segfault (when a non-optimal recursion is running too deep), so our first intuition was to increase the stack size when running the compiler. This didn&rsquo;t change anything, and the reported fault address wasn&rsquo;t anywhere near the stack address&nbsp;bound.</p><p>Before witnessing the crash on other machines, we suspected a failure in the virtualization software used by our two developers that were able to reproduce the crash, who use VMware as a part of their development workflow. We tried early on to switch to Virtualbox, but the migration proved itself fruitless as the crashes kept appearing. After a short while we began encountering the same issue on physical machines, so we ruled out a possible virtualization software&nbsp;bug.</p><p>The usual debugging process for crashing OCaml code didn&rsquo;t prove effective&#8202;&mdash;&#8202;we needed to narrow down our approach.</p><p>OCaml ships with <a href="https://realworldocaml.org/v1/en/html/the-compiler-backend-byte-code-and-native-code.html">two backend implementations</a>: a bytecode interpreter and a native compiler. We were able to reproduce the issue using both a native compiler and a compiler running on the bytecode interpreter. Consequently, this ruled out a miscompilation coming from the code <em>emitted</em> by the compiler, the OCaml runtime <em>itself</em> was misbehaving.</p><p>The runtime code is written in C, and implements low level functionalities, including the garbage collector used by both backends. After rebuilding the runtime with debug symbols, we were able to retrieve a proper stack trace and core dump. The stack trace pointed to the garbage collector&rsquo;s mark phase. OCaml&rsquo;s GC is a classic generational mark and sweep collector. The mark phase walks the heap starting from pointers on the stack and other registered root values, and marks every reachable block of&nbsp;memory.</p><p>Further inspection with <strong><em>gdb</em></strong> of the frame and address of crash revealed that the marking code encountered a corrupted block header with invalid size information, causing what looked like a buffer overrun error. Each memory block allocated in OCaml heap begins with a header word, storing metadata used by the GC, including a tag describing the kind of value present in this memory block. The header contains the size of the block, and the crash happened when the mark code was attempting to scan an array which was supposed to be more than 1TB&nbsp;large.</p><p>This was obviously not the cause of the problem but rather the consequence: something corrupted the header word after this block had been properly allocated, postponing the crash until the next GC cycle. It was the right time to escalate <a href="https://caml.inria.fr/mantis/view.php?id=7452">the issue to the OCaml bugtracker</a>, after isolating a proper test case to reproduce the&nbsp;issue.</p><h3>A set of strange&nbsp;leads</h3><p>Escalating the issue to Mantis made us to take a step back and gather our findings, and we quickly got great feedback from the OCaml core&nbsp;team.</p><p>At this point, what does the problem look&nbsp;like?</p><p>We only had sparse information, but <strong><em>dmesg</em></strong> gave us interesting data point. When a page fault occurs and the kernel detects an incorrect memory access, it logs a line in kernel log buffer containing the fault address, the instruction pointer and stack&nbsp;pointer.</p><p>[22985.879907] ocamlopt.opt[48221]: segfault at af8 ip 00005564455169bd sp 00007ffc9f36b130 error 4 in ocamlopt.opt[556445006000+613000]</p><p>Next to the 3 addresses, already available in the coredumps, an error code is reported. This number in decimal form is actually a bitset, and the flags are documented in the Linux kernel sources in <a href="https://github.com/torvalds/linux/blob/v4.11/arch/x86/mm/fault.c#L41">arch/x86/mm/fault.c</a>. Error 4 can thus be read as a read access page fault from user mode, trying to read memory which had not been previously mmap&rsquo;ed.</p><p>Error codes reported following our crashes involved protection faults or access to unmapped addresses, which corroborated our earlier buffer overrun hypothesis. More interestingly we witnessed a crash with the PF_RSVD flag enabled. This left us puzzled, none of us had ever seen such fault before. Apparently it indicates that the the page table was somehow corrupted, with some entries having non-zero bits reserved by the x86 architecture specification.</p><p>It was scary that the corruption would escape the process address space, and to our limited knowledge, it could only have been caused by kernel issue or potentially hardware issues, like memory errors. Yet we were able to reproduce this on several machines with different kernel version, and different hardware. We blamed virtual machines earlier but this theory was debunked already. We still have no explanation at this time, and pursuit on this front would require intimate knowledge of virtual memory implementations that we didn&rsquo;t&nbsp;have.</p><p>One developer wasn&rsquo;t able to reproduce the problem at all on his machine after hours of testing, but something was fishy: it didn&rsquo;t sound right that an OCaml runtime bug would be able to modify the page table. Maybe it was some corner case with reserved addresses, but this something was beyond our reach here. Out of ideas, it was time to get some assistance from tools intended to track memory corruptions, like <a href="https://github.com/google/sanitizers/wiki/AddressSanitizer">asan and&nbsp;ubsan</a>.</p><p>Running <strong><em>Asan</em></strong> didn&rsquo;t yield any meaningful results. <strong><em>Valgrind</em></strong> was later tried, following advises from the OCaml team, but every tools were preventing the crash. Quickly reproducing the bug for testing required running code in a loop, keeping the CPU and memory fully&nbsp;busy.</p><p>This was harder to do on developers machines, due to limited resources and other processes running, and Address Sanitizer would only increase the resources usage. Dedicating a powerful server would make further investigations more comfortable, and increase the likeliness of reproducing with instrumented code.</p><p>But with great surprise, it was not possible to reproduce the problem on a server machine, with and without instrumented code. This is when we realised that all the machines exhibiting the crashes were running a processor of the Intel Skylake processors family, while the server and other developer machines had CPUs from the Broadwell family.</p><h3>The hardware, an unusual&nbsp;suspect</h3><p>In the meantime several core OCaml developers had been closely investigating the issue and started auditing recent changes in the runtime, and identified a few suspicious changes and known&nbsp;bugs.</p><p>Certainly they were more qualified for this task, but it acted as an incentive to examine the history of this bug from our angle. At first, we had assumed that the bug was specific to the new laptop with virtual machines. This could not explain why the crash never manifested on older workstations equipped with Skylake processors. Several other developers had been using them for a few months, and only noticed the crash after awareness of the issue had been raised by Enguerrand.</p><p>What had changed, besides Skylake? Only a few week before, an internal migration from OCaml version 4.02.3 to 4.03.0 was rolled out in our codebase. Intrigued, we went ahead and tested OCaml 4.02.3 again, which showed no memory corruptions after several tests. It was time to browse the <a href="https://raw.githubusercontent.com/ocaml/ocaml/trunk/Changes">OCaml changelog</a> for runtime related entries. The search stopped quickly on a promising item in the list: the OCaml C runtime build optimisation level had been increased to -O2 from&nbsp;-O1.</p><p>Could the optimizations dig out an undefined behavior in C code, leading to bad assumptions in the GC code corrupting the heap&nbsp;? Rebuilding the runtime with -O1did not corrupt memory, so the source of the corruption was in the runtime <em>and</em> was triggered by some gcc specific optimization pass. This sounded like undefined behavior, although the information we had led us to some hardware&nbsp;bug.</p><p>The next day, Xavier Leroy commented on the bugreport reporting that the crash had been observed in the past. Another industrial OCaml user was affected, and they had discovered HyperThreading was part of the necessary conditions. After running the test case for several hours on several machines with HT disabled in the UEFI setup, it was clear we were facing a similar situation. This led to the hypothesis of a hardware&nbsp;bug:</p><blockquote><em>Is it crazy to imagine that gcc -O2 on the OCaml 4.03 runtime produces a specific instruction sequence that causes hardware issues in (some steppings of) Skylake processors with hyperthreading? Perhaps it is&nbsp;crazy.</em></blockquote><p>This possibility had struck us too, motivated by the HyperThreading, the page table corruption and the Skylake specific set of conditions.</p><p>This issue had certainly a strange profile. But nobody was ready to fully embrace the cpu bug hypothesis yet. We convinced ourselves that disabling HT could affect cache pressure and unfold some undefined behaviours.</p><p>HT could also explain the non-determinism, since cache pressure would depend on timings and scheduling. None of us had sufficient experience in this area to assess the strength of such hypothesis, and we did not quite buy it on a single threaded OCaml program. Our debugging motto claims that &ldquo;assumptions are not&nbsp;facts&rdquo;.</p><p>It was time to browse Intel errata list and attempt to update the CPU microcode. Although, the errata descriptions are formulated in vague terms, none of the issues disclosed at this time were looking similar to the situation under investigation. Unfortunately, CPUs microcode had no fix waiting for us either. OCaml developers investigated the errata list from their side but the lack of detailed information turned this into a fruitless and complex&nbsp;task.</p><p>In the absence of better alternative, we focused our work on pinpointing the exact source of the crash as if it was a software bug, in the hope of either finding a code issue or ruling out this hypothesis while getting more detailed data. We needed a way to identify the problematic code and find a workaround. From our side, it was not only a matter of finding whether or not there was a bug in OCaml code, but more crucially we needed a guarantee on the quality of our generated code running critical services in production.</p><h3>Identifying the offending code</h3><p>The other OCaml user affected by this issue reported that they had solved the problem by switching to another C compiler. Building the runtime with clang instead of GCC would prevent the GC from crashing. They also suggested to obtain a diff of the generated assembly. Indeed, once built with clang, the runtime would not crash. But clang generates widely different assembly from GCC and we did not have the resources to analyse several hundred thousand lines of&nbsp;changes.</p><p>If we could isolate the problematic C code, comparing the generated code would be easier. The problem had the form of a well known&nbsp;nail:</p><ul><li>Around 50 C files composing the OCaml&nbsp;runtime,</li><li>There is a good state (when built with gcc&nbsp;-O1)</li><li>And a bad state (when built with gcc&nbsp;-O2)</li></ul><p>This nail comes with a precious hammer: bisection.</p><p>The bisection approach had a downside in this occasion. Any state can be labeled bad with certainty as soon as the test crashes, but we would need to wait several hours to be confident enough to trust a non crashing test as good data-point. The reproducibility was not always consistent and a non-crashing state could be a false negative still waiting to trigger the conditions leading to the crash. A reduction of search space was necessary.</p><p>All the coredumps we had showed that the fault was caused by a corrupted heap block header, and our testcase involved the compiler. The OCaml compiler is not 100% deterministic, and IO/s primitives and unix environment in the runtime can affect timings and allocation patterns. But it sounded sensible to assume that the code corrupting a heap header block was also the code reading and writing those blocks: the major&nbsp;GC.</p><p>This hypothesis made bisecting fast: the first file we tried, <strong><em>major_gc.c</em></strong>, turned out to be the one. To make sure it was not a subtle issue in linker, reordering symbols or code blocks, we tried a few others files and confirmed changing the optimization level of some other files alone made no difference.</p><p>But the generated code difference was still way too large. Bringing this topic up on the <a href="http://webchat.freenode.net/?channels=#ocaml">OCaml IRC</a> discussion channel led to some useful inputs. We were taught that gcc supports an attribute to enable specific optimizations at the function level, using __attribute__((optimize(&quot;options,...&quot;))). Following the same strategy, it was easy to trace the source of the malfunctioning code to the <strong><em>sweep_slice</em></strong> function, which implements the sweeping phase of the classic mark and sweep garbage collector for the old generation.</p><p>Ignoring the subtle details of incremental GC, the <strong><em>sweep_slice</em></strong> function is the last pass of a normal major collection cycle. It is responsible for scanning all blocks in the major heap, and reclaiming unreachable blocks to the list of unallocated space.</p><p>The bulk of this function is a switch taking action for each block depending on its status&nbsp;:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cfbc19fddccc5f2c1a76fcc802fae049/href">https://medium.com/media/cfbc19fddccc5f2c1a76fcc802fae049/href</a></iframe><p>This finding felt consistent with the information at hand. When the block is reachable, the color (describing the reachability status of the block) is reset. If the block became unreachable (<em>while color</em>) - it is reclaimed. In both cases, the block header is modified.</p><p>Getting back to the assembly&nbsp;diff.</p><p>Nobody in the team knows a great deal about assembly and we only have a really basic understanding of most of the instructions used in both versions. It quickly became obvious that the noise level in this diff, with thousands of lines of changed, was still too high for us to spot anything related to the problem. This problem was getting far beyond the common knowledge of everyone in the&nbsp;team.</p><p>But this was still sounding like your day to day bug tracking process. The less you know, the more careful you need to be, tackling the problem step by step. We stuck to what approach had served us well until now: bisecting.</p><p>We went through the list of optimisation passes enabled by GCC at -O2. This is a fair amount of optimisation passes and it would have been too time consuming to try them one by one, given the time needed to trigger the crash. Yet we had a hint: a memory corruption was happening semi randomly in the garbage collector. We were also keeping the undefined behaviour bug as a potential explanation. It was likely a pass which would change the structure of the code, reordering blocks and changing conditions.</p><p>After reading the description of all switches in the detailed gcc manual, the -ftree-* pass family looked promising. This set of transformations works on the <a href="https://en.wikipedia.org/wiki/Static_single_assignment_form">SSA form</a> internal representation, a widespread intermediate language representation which has the benefit of being easy to read. They seem to make a huge impact on the generated assembly code, moving code blocks around and making assumptions on code invariants in order to move around, simplify or eliminate conditional checks altogether.</p><p>By looking at output of those passes on the related source code, we narrowed down the list of transformations to a couple of interesting passes, one of them being -ftree-vrp, which stands for Value Range Propagation. This pass computes bounds for each name binding and propagates proofs that a value must lie in a given&nbsp;range.</p><p>It turned out most of the other passes depended on it for further optimisations. Even though the issue ended up not being a bad assumptions in the range values, checking this pass proved to be worthwhile: enabling -ftree-vrp on <strong><em>sweep_slice</em></strong> function while every thing else was built with -O1 was enough to trigger a&nbsp;crash.</p><p>GCC provides very good diagnostics output, and after reading the manual we found the -fdump-tree-* switch to dump the SSA form before and after specific pass. The output is designed to be read by a human and provides meaningful naming, with source code locations, alongside the ranges propagated by the VRP pass. We spent some time studying the output and matched the difference in SSA tree between the crashing and not crashing&nbsp;code.</p><p>Examining the bounds and invariants derived by gcc, it was clear that no wrong hypothesis was&nbsp;stated.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a5a311d0b5a4f890f9541f0aed91e73e/href">https://medium.com/media/a5a311d0b5a4f890f9541f0aed91e73e/href</a></iframe><p>The only meaningful observable change involves the suppression of rechecking the loop condition in the else branch of the <strong><em>sweep_slice</em></strong> function, after Value Range Propagation proved that the condition was invariant in this&nbsp;branch.</p><p>Often, reading the code carefully is the fastest way to find a bug. But after spending hours staring at the major GC code, it was clear enough that this check removal should not cause any semantic&nbsp;changes.</p><p>In this process, we identified a suspicious bit of code, where a signed long variable was promoted to unsigned according to C standard rules, which was changing the bounds derived by gcc, assuming it was always positive. But after some thinking we realised it made no difference at assembly level and although wrong, this assumption was not used anywhere.</p><p>We were now ready to rule out the possibility of a bug in OCaml runtime. It was still possible that GCC backend had a bug and was miscompiling this particular shape of code. And we were back at the assembly level again. After writing some awk formatting script to cleanup assembly and minimise noise in the diff (by renaming labels, detecting spurious code move, etc), and preventing inlining, we found a minimal assembly patch causing the&nbsp;crash.</p><p>There were only cosmetic differences. The test removal was propagated down to assembly and caused gcc to reorganise the layout of each switch case&nbsp;block.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/532ab4896b11177a96203fd0c81eaa58/href">https://medium.com/media/532ab4896b11177a96203fd0c81eaa58/href</a></iframe><p>Among those minor differences and changes of layout, we noticed a particular change which impacted exactly the reachable block header updated which could have caused header corruption. In the unoptimised version, the updating code looked like&nbsp;this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/38ca30a1decf86233084721c3803b1c4/href">https://medium.com/media/38ca30a1decf86233084721c3803b1c4/href</a></iframe><p>For some reason, the block pointer was spilled to the&nbsp;stack.</p><p>Perhaps naively, and because we had earlier emitted the hypothesis of HT impacting cache pressure, we spent a few hours staring at this code and check if we were missing something subtle which could affect the control flow of the whole function and the stack location from which it was reloaded could be corrupted.</p><p>Despite our lack of assembly knowledge, after spending several hours reading this tiny change, we got convinced that it made strictly no semantic difference. Reading the x86 manual carefully didn&rsquo;t give any hint on any subtle behavior which would trigger. Executing any of those two sequence of instruction should give the exact same&nbsp;output.</p><h3>Mitigating the&nbsp;issue</h3><p>We were now quite certain it was a CPU&nbsp;bug.</p><p>The OCaml developers had reached the same conclusion, and were working on escalating the issue to Intel. After internal discussions we decided to keep this bug as low profile as possible since we were unsure about potential security implications, especially for JIT implementations.</p><p>Even if we had no confirmation at this point nor any explanations of the cause of this bug, which was beyond our reach, we could take&nbsp;actions.</p><p>The first step was to decide against getting any new Skylake based servers until further announcement. We were left with several Skylake machines but we refrained from deploying any OCaml code on them. OCaml comes with a great package manager, <a href="https://opam.ocaml.org/">opam</a>, which supports compiler switches. Switches allow to set up a clean and distinct environment with specific packages and compiler configuration.</p><p>We patched our internal opam repository to distribute unoptimised runtime to all developers and moved forward, waiting for further announcements.</p><p>This situation made us realise that microcode requires constant updates, just like any other software in the stack. We raised awareness on this topic in our devops team, and they took measure to ensure we could roll out updates to prod&nbsp;easily.</p><h3>Happy end</h3><p>In late May, devops team noticed a <a href="http://metadata.ftp-master.debian.org/changelogs/non-free/i/intel-microcode/intel-microcode_3.20170511.1_changelog">debian package update for intel-microcode</a> containing the following change:</p><pre>Likely fix nightmare-level Skylake erratum SKL150. Fortunately,<br/>either this erratum is very-low-hitting, or gcc/clang/icc/msvc<br/>won&rsquo;t usually issue the affected opcode pattern and it ends up<br/>being rare.<br/>SKL150 &mdash; Short loops using both the AH/BH/CH/DH registers and<br/>the corresponding wide register *may* result in unpredictable<br/>system behavior. Requires both logical processors of the same<br/>core (i.e. sibling hyperthreads) to be active to trigger, as<br/>well as a &ldquo;complex set of micro-architectural conditions&rdquo;</pre><p>The erratum description immediately rang a bell as it matched the diff in the assembly we had observed. We tested the microcode update and confirmed it fixed the corruption.</p><p>Finally, our Skylake CPUs were feeling safe and OCaml compiler was&nbsp;happy.</p><p><a href="https://ahrefs.com"><em>Ahrefs</em></a><em> runs an internet-scale bot that crawls the whole Web 24/7. Our backend system is powered by a custom petabyte-scale distributed key-value storage implemented in OCaml (and some C++ and Rust). We are a small team and strongly believe in better technology leading to better solutions for real-world problems. We worship functional languages and static typing, extensively employ code generation and meta-programming, value code clarity and predictability, and are constantly seeking to automate repetitive tasks and eliminate boilerplate. And we are&nbsp;</em><a href="https://ahrefs.com/jobs"><em>hiring</em></a><em>!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=ab1ad2beddcd" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/skylake-bug-a-detective-story-ab1ad2beddcd">Skylake bug: a detective story</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/skylake-bug-a-detective-story-ab1ad2beddcd?source=rss----303662d88bae--ocamlSkylake bug: a detective story2017-06-28T18:34:51-00:00ahrefs \ No newline at end of file +https://medium.com/feed/ahrefs/tagged/ocamlahrefs2023-07-14T05:47:24-00:00https://medium.com/feed/ahrefs/tagged/ocamlahrefs<iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fo2u9irv1tnE%3Fstart%3D9%26feature%3Doembed%26start%3D9&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Do2u9irv1tnE&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fo2u9irv1tnE%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/aef5aa9cb9b71aaafb0a07cb48cb312d/href">https://medium.com/media/aef5aa9cb9b71aaafb0a07cb48cb312d/href</a></iframe><h3>Transcript</h3><p><strong>David: [00:00:00]</strong> Hello, my name is David. I run <a href="https://emelle.tv/">EmelleTV</a>. It&rsquo;s a talk show about OCaml, ReScript, and Reason. I often bring guests from the community to talk about them and meet them and asking a lot of questions about the language or what they&rsquo;re working on, and of course having fun with Hindley&ndash;Milner type system. That&rsquo;s part of the show. I work for Ahrefs, it&rsquo;s actually this&nbsp;company.</p><p>Today I&rsquo;m interviewing a coworker, so it&rsquo;s going to be a little bit a branded stream. Hope you understand. It&rsquo;s a lovely company. Apply if you&rsquo;re looking for a job to work on OCaml or Reason. Aside from that, I maintain styled-ppx and implementation of React on server, but that&rsquo;s just enough about me, and I&rsquo;m going to introduce our guest, Louis. Hello, Louis. How are&nbsp;you?</p><p><strong>Louis: [00:00:59]</strong> Good, and&nbsp;you?</p><p><strong>David: [00:01:01]</strong> Good. Very good. You obviously work at Ahrefs. At what team do you&nbsp;work?</p><p><strong>Louis: [00:01:10]</strong> This is recently changing, but I have been in the back-end forever, since like seven years ago and I still have some of the projects that I had when I joined. This was stable. I&rsquo;m in this new team called middle-end. Ahrefs is not very good with naming. We say that it&rsquo;s the hardest thing in computer science. We have front-end that is actually full stack, then we have a back-end, which is more like data, and now we have middle-end, which is somewhere in the middle. I&rsquo;m supposed to lead this new middle-end team.</p><p><strong>David: [00:01:48]</strong> Nice.</p><p><strong>Louis: [00:01:49]</strong> We&rsquo;ll see how it&nbsp;goes.</p><p><strong>David: [00:01:49]</strong> Nice. Today I think we&rsquo;re going to answer a few questions about Ahrefs, I think has been a mysterious company, if you look at it from the outside. When I joined, I think you helped me understand a lot of things that I didn&rsquo;t know about Ahrefs. I might just fire the same questions that I did, just recorded so everybody can understand them. Aside from from Ahrefs, who are you and can you present a little about yourself?</p><p><strong>Louis: [00:02:21]</strong> This is a tough question. Who am I? I grew up in France. I&rsquo;m French, still I&rsquo;m French, but I&rsquo;ve been living in Singapore for seven years, with Ahrefs for seven years. I&rsquo;ve been working in OCaml my whole life basically because my first job was in OCaml, and Ahrefs which is my second job, is in OCaml too. I cannot say that it&rsquo;s better than the rest because I never tried the rest. I&rsquo;ve been involved with OCaml, like the OCaml meetup in Paris for some&nbsp;time.</p><p>I&rsquo;m on the online community. I&rsquo;m part of the OCaml Code of Conduct committee, which is an effort that was started last year, I think. So far we don&rsquo;t have a lot of work, so that&rsquo;s good. I&rsquo;m one of five doing this. Then outside of that, I&rsquo;m a pretty normal person. I&rsquo;m 31 years old, and that&rsquo;s about it, I would&nbsp;say.</p><p><strong>David: [00:03:35]</strong> That&rsquo;s the whole idea. You have been been writing OCaml for a long, long time. That&rsquo;s fair to&nbsp;say.</p><p><strong>Louis: [00:03:40]</strong> I&rsquo;ve been writing OCaml since I&rsquo;m 16 or 17 was when I wrote my first line, like 14 years ago, something like this. There was no Merlin at the&nbsp;time.</p><p><strong>David: [00:03:52]</strong> There was no LSP. The first question is, 15 years, this is a long time, but how do you see the evolution of entire language? Would you split it in chunks? How have you seen the progress of the language?</p><p><strong>Louis: [00:04:08]</strong> It&rsquo;s hard to say. When I joined the OCaml world, it was because of people who nowadays are fairly important like Gabriel Scherer, who&rsquo;s working in Inria, I think, but he&rsquo;s one of the main maintainer for OCaml. He was in this French forum, pushing very hard people to try OCaml and I got convinced. I started just writing a few lines here and there, and then I just stick to that for a long time. I&rsquo;ve been mostly a user like this. My usage has extended over time, but I&rsquo;ve never been called a contributor. My point of view is more as a&nbsp;user.</p><p>The biggest difference is the size of the community, I would say. It&rsquo;s much more dynamic than it used to be. We used to install packages like OCaml libraries, using Debian packages. It was apt install something. There was no opam, there was no Merlin, there was no vscode,&nbsp;right?</p><p><strong>David: [00:05:25]</strong> Right.</p><p><strong>Louis: [00:05:25]</strong> LSP didn&rsquo;t exist, so way less library. I think you can see today how it was in the past because you can see, we have 10 different libraries to do HTTP 1.1. We have 10 different standard libraries, and it&rsquo;s legacy of what OCaml was in the past. We used to have all those smart people, but they had no way to collaborate. There was no opam, there was no way to share your work. Everyone was smart enough to rewrite&nbsp;&mdash;</p><p><strong>David: [00:06:04]</strong> Build your own library for&nbsp;http.</p><p><strong>Louis: [00:06:05]</strong> Yes.</p><p><strong>David: [00:06:06]</strong> Right. That&rsquo;s always interesting for me, how OCaml got so many different things that are hard to create, like standard libraries. I think recently, Containers reached 10 years, so it&rsquo;s like what? [chuckles] It doesn&rsquo;t make much sense. If you look at now, it doesn&rsquo;t make much sense, but if you look at historically, it does make&nbsp;sense.</p><p><strong>Louis: [00:06:35]</strong> When you have no choice, you do it. You don&rsquo;t know that it&rsquo;s harder, you just see &ldquo;Oh, I can do it,&rdquo; and you do&nbsp;it.</p><p><strong>David: [00:06:42]</strong> Yes. You need to think it&rsquo;s easy. You need to start a standard library or http library saying, &ldquo;Oh, it&rsquo;s easy.&rdquo; Then, you start a little bit, and eventually, you create something. Last week&#8202;&mdash;&#8202;Oh, sorry, go&nbsp;on.</p><p><strong>Louis: [00:06:57]</strong> No, go&nbsp;ahead.</p><p><strong>David: [00:06:59]</strong> Last week, I tweeted that OCaml suffers a lot from the Python Paradox. The Python Paradox, I think somebody write it, I think it was, I don&rsquo;t remember the name of the guy, but somebody write it in 2004, that when you use Python for a company, and you get the smartest people that they want to innovate, and you have the pioneers of the language. Then, by default, you try to hire people that are in love with software, so eventually, they create good software or they are willing to suffer from getting out of the comfort zone and create software. I believe the combination is the same spot. Can you see, is that true? Do you&nbsp;agree?</p><p><strong>Louis: [00:07:49]</strong> I don&rsquo;t know if that&rsquo;s true. Partially, it&rsquo;s a strategy of Ahrefs, so I have to say it&rsquo;s&nbsp;true.</p><p><strong>David: [00:07:55]</strong> [laughs]</p><p><strong>Louis: [00:07:58]</strong> Yes, I think it&rsquo;s partially true, but it&rsquo;s not completely correct. For OCaml, at least it&rsquo;s a bit different from Python, because OCaml has this strong academic influence, so a lot of people are actually researcher. There is a big benefit that they have, not free time, but they manage their time, they manage what they work on, and they decide what is important. They got all this time to actually write this complicated code many times because actually, it&rsquo;s part of their job to just redo the same thing in better ways. It&rsquo;s normal you have to explore a&nbsp;subject.</p><p>It&rsquo;s okay to do it multiple times. It&rsquo;s a combination of those people are working in the right place, they have the right time, and they have the correct background. A lot of people were working on subjects that allowed them to do it. Some, it&rsquo;s because they were very strong in writing languages. Some, it&rsquo;s because they have this strong Unix background, I would&nbsp;say.</p><p><strong>David: [00:09:05]</strong> Right. It&rsquo;s very unixy. The start of OCaml is very unixy. That&rsquo;s&nbsp;true.</p><p><strong>Louis: [00:09:14]</strong> Xavier Leroy wrote LinuxThreads, I think that was used in Linux forever, so there is this background. Probably, it&rsquo;s a bit different in Python because it grew more in the industry rather than in an academic setup. For sure, if you try to target people who live in a niche, you find people with a different interest from the main programming community, I would say. At the same time, I think some of the best meetup or conference I&rsquo;ve been to were Java&nbsp;meetup.</p><p><strong>David: [00:09:59]</strong> All&nbsp;right.</p><p><strong>Louis: [00:10:00]</strong> They know that their language is boring. The language is the same since 20 years or 30 years. There are some changes but they don&rsquo;t really care about the language too much. It&rsquo;s a huge, huge community. Basically, everything already exists. There is no big bragging, everyone can do everything. There are 10 versions of everything, whatever. The benefit is that they are super open-minded.</p><p>Oh, something is new. Something is different. Okay. Let&rsquo;s see that. You go to that meetup and they will not talk only about all the fancy new feature in Java. It&rsquo;s like, &ldquo;Oh, I saw this new git tool. Oh, it&rsquo;s funny. Okay, let&rsquo;s try to use this.&rdquo; A new way to do web development. Okay, let&rsquo;s study the subject. It&rsquo;s not about Java itself because the language is not interesting enough. It&rsquo;s about other programming stuff. It&rsquo;s very fun to&nbsp;attend.</p><p><strong>David: [00:11:03]</strong> That&rsquo;s a good one. Actually, many people that now are starting to hear OCaml for the first time, after they leave or they got disappointed with the Rust policy drama. These people cannot get into OCaml because some influencer wanted to bash on Rust. They started exploring all the languages and of course Ocaml was one of those. Aside from Zed or whatever you compare it with, low level programming languages. Do you see those influencers move people to actually try the language and deploy it into users and doing serious stuff, or it&rsquo;s more like vain marketing?</p><p><strong>Louis: [00:11:56]</strong> I&rsquo;m not a big Twitch person. I don&rsquo;t know [crosstalk] modern influencers.</p><p><strong>David: [00:12:02]</strong> That&rsquo;s&nbsp;true.</p><p><strong>Louis: [00:12:03]</strong> I think it exists in two forms. In the past it existed in two forms. You had influencers, you had Rob Pike and- who&rsquo;s the other person? The two person who are behind Go. They do not make a good language but they are influencers. They were like, &ldquo;Oh, yes. We did UTF-8 and a Plan 9 in the past and we work at Google. Oh, it&rsquo;s going to be amazing.&rdquo; No, it&rsquo;s a crappy language, but they are influencers. They move&nbsp;people.</p><p><strong>David: [00:12:32]</strong> [laughs] Okay. Would you say that Go is&nbsp;crap?</p><p><strong>Louis: [00:12:38]</strong> Go is a language. I haven&rsquo;t used Go 2 extensively.</p><p><strong>David: [00:12:42]</strong> This is recorded. This is not a beer in Singapore. This is recorded. You can obviously bash go, that&rsquo;s part of the&nbsp;game.</p><p><strong>Louis: [00:12:50]</strong> Let&rsquo;s say Go is not the most modern language there&nbsp;is.</p><p><strong>David: [00:12:54]</strong> Right. Thank you. This is just for the headline. We don&rsquo;t want the headlines- because Ahrefs is going to be like&#8202;&mdash;&#8202;No, I&rsquo;m joking. [crosstalk] Yes, go on.&nbsp;Sorry.</p><p><strong>Louis: [00:13:10]</strong> On the same topic of influencer, we saw it with Reason. When the Reason comes, it&rsquo;s not just a random person creating Reason. It&rsquo;s Jordan and he comes with a React background, and he comes with followers. He is not doing videos online but it&rsquo;s the same idea. I think yes, it has definitely an influence and OCaml grew a lot when Reason&nbsp;started.</p><p><strong>David: [00:13:38]</strong> Yes, that&rsquo;s&nbsp;true.</p><p><strong>Louis: [00:13:39]</strong> I definitely think it has an influence.</p><p><strong>David: [00:13:43]</strong> That&rsquo;s true. From the community, how have you seen the Reason creation and adoption from your point of view? You can bash Reason if you&nbsp;want.</p><p><strong>[00:13:43]</strong> [crosstalk]</p><p><strong>Louis: [00:13:56]</strong> At that time I think the OCaml community was one IRC channel. It was a bit different from now. I think what I was not super convinced by when Reason to syntax arrived, I think the original claim by Jordan was he&rsquo;s making a better syntax. I was not super convinced that the syntax was better. It was developed independently from&nbsp;OCaml.</p><p>By experience I already knew at the time that if you start to fork or develop on your side and don&rsquo;t integrate fairly quickly with upstream it&rsquo;s actually never going to be integrated with upstream.</p><p><strong>David: [00:14:53]</strong> Right.</p><p><strong>Louis: [00:14:54]</strong> I don&rsquo;t know why exactly, but it has happened a few times. Then there is a question of bucklescript because if you write Reason it&rsquo;s two sides. There is a syntax which I only partially understood too because I was not a web developer, I&rsquo;m still not a web developer. I did not know about JSX. I did not know how powerful it was and I think React was not as big at the time too, but I think JSX is a nice idea and there are a lot of things in the syntax that are nice, like parentheses around arguments is a problem but it has some benefits, too.</p><p><strong>David: [00:15:42]</strong> Yes, I think some trade-offs from OCaml, or at least some edge cases from the syntax from OCaml got resolved in Reason just by adding more- like the parentheses or the braces or the semicolons. But yes, the others are, can remove some problems from the syntax. Not problems, but just the edge cases from the cleanness for&nbsp;OCaml.</p><p><strong>Louis: [00:16:10]</strong> Yes. Even sometimes it&rsquo;s not edge case but it&rsquo;s nice to see very clearly for example, when you apply a function, where are the arguments? Where it starts where it ends? There are benefits, obviously, like the OCaml syntax or Haskell syntax is lighter, we will say, have some benefits. The other one is nice,&nbsp;too.</p><p><strong>David: [00:16:36]</strong> Yes, definitely and you mentioned BuckleScript?</p><p><strong>Louis: [00:16:40]</strong> Yes. BuckleScript, they didn&rsquo;t have&nbsp;&mdash;</p><p><strong>David: [00:16:42]</strong> That was not so well received.</p><p><strong>Louis: [00:16:47]</strong> Yes, I think because there was Js_of_ocaml idea. There was js_of_ocaml and so again, it was like yes, I do something different and- I think Bob developed it fully inside Bloomberg at the time. Basically, he came out and he had, &ldquo;Oh, yes, I have a new project and it&rsquo;s working already.&rdquo; He didn&rsquo;t start to develop it in public. The community was much smaller, too so every time you split efforts like this, it&rsquo;s kind of costly. People will say, &ldquo;Yes, we will try to collaborate. We&rsquo;ll try to make the two projects work together,&rdquo; or whatever and it never works. Never works. I don&rsquo;t think I understood all the trade-off. I&rsquo;m happy that I invited Bob to the OCaml meetup in Paris which retrospectively, it was a good thing to&nbsp;do.</p><p><strong>David: [00:17:50]</strong> Yes, for the record, Louis was running the OCaml Paris Meetup, I think. Yes, go on with the&nbsp;story.</p><p><strong>Louis: [00:18:00]</strong> Yes, so when I moved to Singapore, I still organized one meetup, even though I was in Singapore and I invited Bob to present BuckleScript. At the time, it was a bit controversial, because many people were a bit unhappy with what he was doing, but I&rsquo;m happy that I did it. I didn&rsquo;t understood what I was doing exactly but at the end, I think it was the right thing to do. Even if the project died later on, you have to give such projects a&nbsp;chance.</p><p><strong>David: [00:18:35]</strong> Yes, I think I wouldn&rsquo;t say that BuckleScript died. It&rsquo;s more like BuckleScript has been working for seven years, I&nbsp;think.</p><p><strong>Louis: [00:18:42]</strong> Yes, no, even if it was a failure, which it was not, but maybe like six months later, it could have died and disappeared. Yes, I think when people have a drastically different approach, usually they have a reason. It&rsquo;s worth listening. A lot of what Bob defended, I&rsquo;m not sure I completely agree with it. He wants a very stable compiler, for example. He said, in Bloomberg, they are using GCC 3 or 4, I don&rsquo;t remember, since&nbsp;forever.</p><p>So they don&rsquo;t need to upgrade the compiler, the GCC compiler, for example. He thought the same idea can apply to OCaml, we don&rsquo;t need to follow the upstream compiler all the&nbsp;time.</p><p><strong>David: [00:19:27]</strong> Right.&nbsp;Yes.</p><p><strong>Louis: [00:19:29]</strong> Most companies actually they don&rsquo;t want to change compiler version. They want something stable. They want no surprise, which has some value, or the stability has some&nbsp;value.</p><p><strong>David: [00:19:40]</strong> Yes, that&rsquo;s true but I think when he mentioned about the compatibility with the compiler, I think it&rsquo;s mostly OCaml has been very stable since, what 6, 7 years ago, I think. I think there were some small changes or some addition features, but nothing really break, but mostly the syntax. Then he complained about the parsing, like the AST modifications, those were present, those were changing between versions. He wanted to not- because BuckleScript is a fork of the common compiler and embedded into ReScript&nbsp;now.</p><p>Yes, he was complaining about the AST transformations because every version changes a lot. There are migrations. You could write some logic to migrate from one to another. It&rsquo;s painful if you maintain a fork of this, you might suffer a lot from updating from one compiler to&nbsp;another.</p><p><strong>Louis: [00:20:41]</strong> Yes, and I think for him, even as an end user, the stability has some value. It&rsquo;s interesting for him to have a stable compiler and even for his target, the people he&rsquo;s targeting, the stability has some value&nbsp;too.</p><p><strong>David: [00:21:00]</strong> After you mentioned that people were installing or sharing libraries through Debian packages, which maybe- I&rsquo;m as old as you, but maybe I&rsquo;m too young to see how those package managers could work with apt get. What&rsquo;s the position of the tooling? Right now I think we are in a state where we have two bigger players such as opam and dune, as Package Manager and Build Infrastructure, we&rsquo;d call it, I don&rsquo;t know. Now dune is exploring installing packages. How do you see the tooling these recent&nbsp;years?</p><p><strong>Louis: [00:21:48]</strong> It&rsquo;s amazing. It&rsquo;s completely incredible. Then people will have different opinions on is opam perfect or whatever. If you compare to what it was before, it&rsquo;s incredible. I think even if you compare to other languages, it&rsquo;s a fairly solid experience now. Opam is working well. You just need to learn the UI, but it&rsquo;s working fairly well. Dune is relatively fast, easy to use. The LSP is pretty magical. Merlin is a very solid tool. It was one of the first, I think I would say, like a small language with a tool as powerful as&nbsp;Merlin.</p><p>It&rsquo;s not only powerful, it&rsquo;s avantgarde. It understood already that you had to be able to do error recovery and that you had to change the way you parse files to be able to work with something that is half&nbsp;broken.</p><p><strong>David: [00:22:57]</strong> Yes, that&rsquo;s&nbsp;true.</p><p><strong>Louis: [00:23:00]</strong> The people behind Merlin are super smart. In a way, it&rsquo;s not a surprise.</p><p><strong>David: [00:23:05]</strong> Right. You actually contributed to the LSP and dune, to both projects, I saw your contributions.</p><p><strong>Louis: [00:23:13]</strong> Yes, I have commits on many small- it&rsquo;s mostly small contributions, but I have commit on everything, I think at some&nbsp;point.</p><p><strong>David: [00:23:19]</strong> Right.</p><p><strong>Louis: [00:23:21]</strong> LSP, I participated in putting some ppx deriving stuff and I wrote a bunch of commands. I implemented some Merlin behavior inside LSP. If you hover multiple times on the same value, the type will be more and more verbose. I took this behavior back to LSP. Dune I have mostly bug fixes, probably small documentation, nothing&nbsp;big.</p><p><strong>David: [00:23:58]</strong> One of the things that you mentioned as well, I think we talked about this before. When OCaml was very young, all features that got added into the language were PhD projects, where it&rsquo;s a student that is very passionate or maybe just his guidance is OCaml fan, he just explored with a language in the theory on academia. Then he worked on a paper and eventually it gets released as part of the language. That was the times where maybe Jane Street not even started using OCaml seriously. Do you see that now? Do you see that those features or academic features got into language? Do you think it&rsquo;s a weird mix now or they compose well together? How do you see language after these contributions?</p><p><strong>Louis: [00:25:04]</strong> I was looking today at the OCaml change log because I was wondering when was the release of OCaml 4, and that was 11 years ago because OCaml 4 is- before to OCaml Multicore is the last time there was a big change which was GADT. In the meantime there was mostly small changes. I don&rsquo;t think the language changed much. If we look what were the big features we could say like the objects in OCaml, GADT, OCaml Multicore.</p><p>They all were developed by people in a research setup and somehow it seems to work. I&rsquo;m not a maintainer on OCaml. I think it works also because they don&rsquo;t have a lot of energy to integrate a lot of new features, they are very, very picky on what they actually accept in the compiler. Only the most solid implementations will get&nbsp;in.</p><p><strong>David: [00:26:36]</strong> Yes, that&rsquo;s true. I think the quality is something that everything core team members says all the time that all these things would be amazing to do but our quality bar is very high. Yes, you need to work on it much more to let us just even look at it. Yes, that&rsquo;s&nbsp;true.</p><p><strong>Louis: [00:26:54]</strong> Then there are things that do not compose super, super well. There are part of the module language and part of the object language that do not compose very well. You can make the compiler more or less blow up or the compilation time will become crazy. Actually, those are parts that I don&rsquo;t know very well. I very seldom combine first-class modules and&nbsp;objects.</p><p><strong>David: [00:27:21]</strong> Objects, yes. That&rsquo;s something I haven&rsquo;t done yet. I think the only experience with that combination might be ppxlib maybe, because you have the traversers. Yes, you use them. You instantiate the traverser. You don&rsquo;t do anything with internal states of anything. Good point. One thing that maybe it&rsquo;s worth saying is that right now you work at Ahrefs for seven&nbsp;years.</p><p>At the beginning when Ahrefs pick OCaml or Igor, our CTO came with OCaml in the back, there were not many companies working on- using it, using OCaml. Now we have Tezos, Tarides, Ahrefs of course, LexiFi, Bloomberg, BeSport. Many companies that have- even some of them have their own forks of OCaml that they are experimenting and deploying it or whatever. Seven years ago, do you think it&rsquo;s a risky decision? The second question is how can you convince your boss about using&nbsp;OCaml?</p><p><strong>Louis: [00:28:35]</strong> For sure, I think picking OCaml at the time was a risky choice because who do you hire? It&rsquo;s like there were five OCaml developers. In Paris, you can find people. In Paris, you can find students. You go to the OCaml meetup and socialize and you can more or less build a company, which is what the previous company I was in called Cryptosense was doing. This is how BeSport came to life. BeSport just picked a few people around Vincent Balat and then you meet people. You steal one or two person from the OCaml meetup and you tell them, &ldquo;Oh, join my company,&rdquo; and now you have enough people to push a project forward. How do you do this from another country? Even today, I think it&rsquo;s not an easy&nbsp;choice.</p><p><strong>David: [00:29:35]</strong> Somehow risky, yes. That&rsquo;s&nbsp;true.</p><p><strong>Louis: [00:29:38]</strong> Today, you can hire, but even if you have, I don&rsquo;t know, 2,000 packages on opam, the tooling is still- the libraries are not, there are not libraries for everything like you have in some other languages.</p><p><strong>David: [00:30:00]</strong> Right. It&rsquo;s big enough, but it&rsquo;s not populated with everything.</p><p><strong>Louis: [00:30:07]</strong> I don&rsquo;t know if we have full support of GRPC. I&rsquo;m not sure that we have complete support of http2 or 3. It&rsquo;s not that small, but many things like this. I would say, today I would say it&rsquo;s a risk. How would I convince my boss to move to OCaml? I would&nbsp;&mdash;</p><p><strong>David: [00:30:34]</strong> Would you do it? Maybe you would not do it. Maybe you say, &ldquo;It&rsquo;s fine, we can do with whatever,&rdquo; with Java you said that you enjoy the Java meetup, then you join your company writing Java. Would you be happy writing Java? Would you be fine? Or you would say &ldquo;Oh, OCaml here makes sense, let&rsquo;s try to change it.&rdquo; How would you do&nbsp;it?</p><p><strong>Louis: [00:30:57]</strong> I think if I was in a small company, it would definitely make sense to use OCaml. It&rsquo;s interesting because in a small company you could say all the Java tooling has more value than in a big company, but at the same time you have less hands. You need to be more productive per person and you have less time for maintenance, and those are two things for which OCaml is very strong. You can write few lines of code that do many things, so it&rsquo;s very expressive. At the same time, it&rsquo;s solid enough that when you write your code, you can launch it in prod and you can leave it there for some time and hopefully nothing&nbsp;breaks.</p><p>The language is stable, the compiler is stable, so there will be no big surprises. I think that&rsquo;s very valuable, and then you compare, what are the alternatives today? Rust is incredibly hard. It&rsquo;s very, very hard language to use. You can do fancy stuff, you have incredible community but it&rsquo;s a super hard language to use. You have what, Python, but then you are losing all the type safety. You have Go, which is a bit in between those. You have a fast Python I would say. Then you have Java. Java which has a huge community, and is a fast language.</p><p>In a way I think OCaml is closer to Java. It&rsquo;s one easy language to use, solid, no surprises. The feature set is not incredible but it&rsquo;s working well enough and you can do more or less what you want with it. You can do work in the back end, work in the front end, it&rsquo;s approachable. To me it&rsquo;s a replacement to Java. It&rsquo;s a light&nbsp;Java.</p><p><strong>David: [00:33:04]</strong> I&rsquo;m mostly front-end. Now I&rsquo;m doing some back-end stuff but I mostly am experienced from front-end. You are experienced from back-end of course and when I&rsquo;m talking to back-end persons from OCaml, every time I talk with a back-end person who only writes OCaml they mention then the runtime. From the front-end, it&rsquo;s a problem that I have never, ever thought. I know that the problem exists because I studied computer science and all these things, but it&rsquo;s something that in the front-end I never think about&nbsp;it.</p><p>How could you describe to me that- I know a little bit about the memory presentation and about the stack, the heap, how memory works, even the O(n) notation, O big notation. How can you describe the runtime of OCaml, from someone who doesn&rsquo;t know much about runtimes, so has nothing else to compare, rather than notes, for example. That&rsquo;s my experience.</p><p><strong>Louis: [00:34:08]</strong> Yes, I&rsquo;m not an expert either, but it&rsquo;s an interesting point, actually, because if you go on, for example, the real-world OCaml, there is a whole chapter on the runtime. I think it&rsquo;s important for the OCaml people because of their background. We have those unixy people, so they have experience with C before and because in C you need to know what is a representation in memory of everything you manipulate, they took that from C and bring it to OCaml. Those people, they like to know, when I have an integer, it&rsquo;s going to be nowadays, 64&nbsp;bits.</p><p><strong>David: [00:34:56]</strong> 63 right? That&rsquo;s the&nbsp;&mdash;</p><p><strong>Louis: [00:34:59]</strong> Yes, one bits for the right GC, and then we have 63 bits for the&nbsp;value.</p><p><strong>David: [00:35:05]</strong> Right. Yes, people love the runtime. I think it&rsquo;s like those things when&#8202;&mdash;&#8202;You guys started talking about the front-end. For me, I love CSS. I can talk all the time about CSS, but if you never have experience with a language or with designing the UI, CSS means nothing. You understand what they are saying because the thing makes sense, but semantically it doesn&rsquo;t. When you talk about the run time at the beginning, for me it felt like I have never, ever thought of&nbsp;this.</p><p><strong>Louis: [00:35:41]</strong> I guess it&rsquo;s two sides. There is the technical side, how it&rsquo;s actually implemented that when you allocate a value, where do you put it in memory? What is the representation of that value in memory? For example, we said that the int are 63 bits actually, that when you allocate the value, you allocate by words in OCaml. You have one word, for example, if you allocate the values that is on the heap, you have potentially two words. You have one word, which is a pointer to the actual value, and then the values, which is like a number of words afterwards.</p><p>You have the GC, so when is it triggered? Actually, the GC can be running every time you can allocate a value which means that you can write code that will not trigger the GC. It means you can write code that is very fast because there will be no interruption, and I think that&rsquo;s critical for companies like Jane Street. Then yes, the other side is the runtime from a user perspective. I see it two way. I see one way that it&rsquo;s like no one knows about the runtime because it&rsquo;s very, very simple in OCaml. You don&rsquo;t need to deal with the runtime very&nbsp;often.</p><p>You just know that you pass values by reference, so you don&rsquo;t make many copies, and then the GC is fairly fast and will not stop for too long. That&rsquo;s probably what 99% of the normal OCaml people know about the runtime. Then an interesting fact that comes with that is that the OCaml compiler is bad by modern standards, that it&rsquo;s not doing any kind of optimization or very little optimization, yet the native code is fairly fast. The native code that is generated for an OCaml program is fairly fast. I think if you look at the benchmark it&rsquo;s not too far away from C++, which is surprising, and it means that the language is pushing you to write code that by default is fairly efficient.</p><p><strong>David: [00:38:06]</strong> That&rsquo;s exactly my experience.</p><p><strong>Louis: [00:38:09]</strong> The types that are offered and the functions, the APIs that are offered, somehow allow you to write code that is not too, too bad. I think it&rsquo;s a miracle, but it&rsquo;s an interesting one.</p><p><strong>David: [00:38:23]</strong> Yes, that&rsquo;s exactly my experience. At Ahrefs, the formula of the Coca-Cola of Ahrefs is like the crawler, the thing that navigates the internet and saves data. After that, we have storage and all of these pieces that are complex. What can you explain about the secret sauce of Ahrefs? What are they from the outside? Many people would never, ever write a crawler or a very dummy one, but for one that indexes 9 billion pages, 1 trillion? I don&rsquo;t know the numbers but insane amount of numbers. What can you&nbsp;explain?</p><p><strong>Louis: [00:39:10]</strong> I guess the first question is what is a&nbsp;crawler?</p><p><strong>David: [00:39:13]</strong> Yes, yes, because you read the webpage, you scrap a webpage, that&rsquo;s fairly simple. You can do it in any language, but then what do you extract about this page, and more importantly, how you navigate to the next one. I think that these are the two main questions.</p><p><strong>Louis: [00:39:35]</strong> What you extract, depends. Ahrefs, we care about the links. What is Ahrefs building is more or less a map of the internet. The crawler is running all the time. It&rsquo;s downloading, I don&rsquo;t know, like 4 million pages per minute or something like this. There is a counter. Every minute we crawl 5 million pages. We have been talking for 40 minutes. You can count how many pages we have downloaded in a period of time. We download those pages and then we extract the links. That is the main information we care about. This is not the only information.</p><p>First is how do you parse HTML and how broken is HTML on the internet? This is horrible. The internet is broken. You have to extract all the links in a page and then you have to store all those links. When you store links, because&#8202;&mdash;&#8202;What is a crawler exactly? Where does it start and where does it end? Is it only the part that is downloading the html? Or is it actually the parsing too, and it&rsquo;s influencing how you are storing your data, because&#8202;&mdash;&#8202;Let&rsquo;s say you download a page and you have a 100 links in it, you do at least two things with those 100 links that you want to reuse them in your scheduler to decide what do I crawl&nbsp;next.</p><p>You also want to update counters, because you want to update your map of the internet. You downloaded a page, you know that there are links and you want to update the map. How do you update the map, because you have a 100 new links? What do you do? You update a 100 small counters, a 100 small integers. Then can you do it 5 million times per minute? Then can you do it in many direction, because it&rsquo;s a&nbsp;graph.</p><p><strong>David: [00:41:48]</strong> You would loop. If you don&rsquo;t do it properly, you would loop&nbsp;forever.</p><p><strong>Louis: [00:41:55]</strong> You have links between pages, but then you want to also count links between domains and you want to count the links inside the domain. Then how do you decide it&rsquo;s an interesting link or not? Then when you index a link, what do you index? You need to index the link itself, but you want to index the text that is attached to the link, maybe the paragraph that is around that specific link. You could look where it is in the page. Is it visible or not? You have&#8202;&mdash;&#8202;It&rsquo;s an open question.</p><p>That&rsquo;s an interesting question, because there is no one that can say, &ldquo;I&rsquo;m doing a crawler and this is the right way to do it.&rdquo; Even big companies like Google, they make tradeoffs. They decide, &ldquo;We do it in one way.&rdquo; Then they gather information they can gather. They cannot download every page on the internet all the time. They cannot download and process stuff fast enough. There is more content that is created than content that can be downloaded.</p><p><strong>David: [00:43:00]</strong> It&rsquo;s interesting, because if you think about fixing a bug on the crawler, it&rsquo;s usually when you have a database, you can run migrations or you can get out data. You can store data broken or whatever. You can fix it. If you have the history of internet, that&rsquo;s another source of data. It is life. I don&rsquo;t know the right metaphor, but it&rsquo;s&#8202;&mdash;&#8202;If you have to fix a bug on the crawler, that means that you stored information wrongly. That can affect the next version of your map, because it&rsquo;s not only a map, it&rsquo;s a map and a timeline. You can just look it up. It&rsquo;s an archive as well. I think internet archives, they don&rsquo;t have a crawler. I think they don&rsquo;t have a&nbsp;crawler.</p><p>It&rsquo;s the idea of&#8202;&mdash;&#8202;You can improve the crawler. Something that you didn&rsquo;t look before, now you are going to look it up now. I don&rsquo;t know, when&#8202;&mdash;&#8202;I think at some point we&#8202;&mdash;&#8202;At the beginning, either we started indexing, I think videos was&#8202;&mdash;&#8202;I don&rsquo;t remember. Some media, I don&rsquo;t know. That, of course, blowed up immensely, everything- they complicated everything.</p><p><strong>Louis: [00:44:14]</strong> Yes. That&rsquo;s an interesting question. Actually, Because, it is right that your database is very big so you cannot just migrate stuff. The big data page says we have 170 trillion rows in the database, so we cannot just push this to somewhere else.</p><p><strong>David: [00:44:35]</strong> First of all, what technology is that running&nbsp;on?</p><p><strong>Louis: [00:44:40]</strong> I think that&rsquo;s a combination of different technologies. That will be a ClickHouse and then some internal database. Custom&nbsp;stuff.</p><p><strong>David: [00:44:52]</strong> At Ahrefs, correct me if I&rsquo;m wrong, we like to build our own things mostly. When I have it in other companies, you would use Sentry for reporting, or you would use PagerDuty for live crashing, or you would use whatever tool that you- or a web server, like a framework that runs your server. I think we implemented all of this by ourselves. That sounds both crazy from the outside, but when you join Ahrefs, if you ever join the company, you understand perfectly why has it been done like that. Yes, we have our own database. It&rsquo;s&nbsp;scary.</p><p><strong>Louis: [00:45:41]</strong> It&rsquo;s not completely our own database, it&rsquo;s more like a wrapper around existing database. It&rsquo;s partially because we have no choice. The problem is large enough that you don&rsquo;t have a ready made solution. Google was like this for a very long time. They had MySQL, I think that they used very extensively MySQL and it&rsquo;s just that they used it in a way that was working for them. They don&rsquo;t have a giant MySQL database, but probably they just sharded the&nbsp;problem.</p><p>They have one small database per server and they have a smart way to send the tasks to the right server to retrieve the data they want. Because you have to build on top of something, we are a small company. The total number of employees, I don&rsquo;t know, it&rsquo;s 100 plus now, but the back-end team is still 15 people or something like this. We don&rsquo;t have too many&nbsp;hands.</p><p><strong>David: [00:46:43]</strong> Yes. That&rsquo;s&nbsp;insane.</p><p><strong>Louis: [00:46:47]</strong> You ask what you do when there is a bug in the crawler and it affects how you conceive the programs because you know that something will run forever. The strategy becomes, I don&rsquo;t want to fix bug by hands. It&rsquo;s, you have an auto healing index. You crawl a page for the first time, and let&rsquo;s say you make a mistake. The number of links you counted is off by one. You know it was like this for three days because you deployed, it was broken. Three days later, you notice it, and you cannot go back in time. It&rsquo;s already too&nbsp;late.</p><p>Instead, what you do is that you fix your crawler. The way you store the data, you make sure that the next time you crawl the page, it overrides the previous version with something that is correct now. You have to have those auto healing processes, and you cannot attend to every small detail by hand, and the full rebuild of the index will be the last resort. Only if you have absolutely &mdash;</p><p><strong>David: [00:48:01]</strong> Did that ever&nbsp;happen?</p><p><strong>Louis: [00:48:06]</strong> It partially happened. Not everything, but there are things that were rebuilt once in a while. We were storing two things because we download pages, we download the HTML that we store, and then we have two counters. We have the counters we extract from the page. Let&rsquo;s say you have one link that you see twice in a page. You have this link and the number two attached to it, and then you have diff. You store diff, let&rsquo;s say, because you downloaded that page that belongs to the domain ahrefs.com. Now you see that that specific URL, for example, has three links that were not present&nbsp;before.</p><p>You store somewhere plus three, and later on you will aggregate all those plus three, plus one, minus one together. There are two different things. You have the absolute numbers and then you have those diffs. Once in a while, we have a bug that we didn&rsquo;t compute the diff correctly. Then we will rebuild the diff from scratch. We will go back to those absolute numbers, process them altogether and then restore it. Then when it happens, it can take a month, but it hasn&rsquo;t been done in a long time. It&rsquo;s a long&nbsp;process.</p><p><strong>David: [00:49:28]</strong> Right. That&rsquo;s interesting.</p><p><strong>Louis: [00:49:32]</strong> This is where OCaml is shining, too, because it&rsquo;s very easy to have multiple versions of the same type, for example. If you store data, with a version number in the database, you have a&nbsp;variant.</p><p><strong>David: [00:49:48]</strong> Yes, you treat it differently or?</p><p><strong>Louis: [00:49:50]</strong> It&rsquo;s fairly automatic and-&nbsp;yes.</p><p><strong>David: [00:49:59]</strong> Yes, as well we have diffing on HTML. One of the big features that we did, I think that was last year, that we have diffing for the content of the page, or the diffing of links, we have as well diffing of content. That&rsquo;s very&nbsp;good.</p><p><strong>Louis: [00:50:18]</strong> We have a lot of small funny features. We are one of the first company after Google, obviously, to render pages at scale. We have hundreds of servers running chrome, and as much as possible, when we download the HTML of a page, which is the raw HTML, then we will put it in Chrome, let it run for a while and then get the rendered version of that. Which is incredibly expensive time-wise, because it&rsquo;s much harder work than just downloading the HTML. We couldn&rsquo;t do this if there was no project like Chrome that would be open source and usable for free. We are standing on the shoulders of giants for&nbsp;this.</p><p><strong>David: [00:51:08]</strong> Imagine trying to create a web engine just to see a page from the server. That&rsquo;s very good. What&rsquo;s the favorite part of working at&nbsp;Ahrefs?</p><p><strong>Louis: [00:51:26]</strong> To me, is the people. I&rsquo;m not a SEO expert, and I&rsquo;m not a SEO fan either. I didn&rsquo;t join Ahrefs because I love to study the internet, that was not my goal, and I&rsquo;m not a marketing person, so I don&rsquo;t have a big use for SEO by myself. At first when I joined, the technical challenge was fun, but nowadays to me, the value is more the people. You get to meet smart people who work on complicated projects. I spend a lot of time dealing with interns, for example, which is super gratifying, I feel. I try to spend a good amount of time sharing with other people, working on the tooling or stuff like this. I really like that part, you can see the influence you have on other people when you make their life&nbsp;easier.</p><p><strong>David: [00:52:32]</strong> That&rsquo;s good. What&rsquo;s your favorite part of&nbsp;OCaml?</p><p><strong>Louis: [00:52:37]</strong> Of&nbsp;OCaml?</p><p><strong>David: [00:52:38]</strong> Yes. You can say the&nbsp;people.</p><p><strong>Louis: [00:52:41]</strong> When it compiles, it works. That&rsquo;s the key point. Unlike Go, we have some&nbsp;types.</p><p><strong>[00:52:41]</strong> [laughter]</p><p><strong>Louis: [00:52:59]</strong> If we are a bit serious, maybe not the language itself, but the LSP is super, super good nowadays. It&rsquo;s definitely a very good experience. We have to thank Tarides for all the work they are doing on the tooling over the past three years now, because it&rsquo;s&nbsp;crazy.</p><p><strong>David: [00:53:21]</strong> I think Tarides is carrying most of the boring work. Not boring work, but work that is always hidden. That you don&rsquo;t get any fame, but you will only get the trash. When the toolings don&rsquo;t work, you complain, and when tooling works, you just don&rsquo;t celebrate it. Tarides is behind, for sure. You have been going to ICFP, ICFP is international conference for functional programming, for quite some time. One of the verticals, or one of the parts of ICFP is&nbsp;OCaml.</p><p>Last year we outgrow our neighbors, our language neighbors, I think it was Scala, maybe, Haskell. I think we outgrow them. What do you think about the conference?</p><p><strong>Louis: [00:54:20]</strong> Same thing, it&rsquo;s amazing to go there and meet the people actually, because ICFP, it has multiple parts. The main track is a bit more academic. Even though some people who work at Ahrefs, they published there, but they were students when they did it. It&rsquo;s a bit more academic. Then you have all the workshops that are a bit more approachable, at least for me, but you spend one week with smart people who are very excited by what they&rsquo;re doing. This is the amazing part. Once a year, everyone is super happy to meet each other. This is very much a good experience, but it&rsquo;s- about conferences, I think the ReasonML ones were very, very nice&nbsp;too.</p><p>Again, I&rsquo;m a back-end person, but it was super cool to attend a conference on a different topic where people have different interests, and it was the early days of the language for people who were super interesting, the people who attended were curious and wanted to see something new. They had different ideas. I think that was super&nbsp;good.</p><p><strong>David: [00:55:36]</strong> Yes, those conferences were very good. I haven&rsquo;t attended any, actually, but yes, I heard Javi saying amazing things about them. Almost everybody who attended said good things. Why there&rsquo;s no OCaml conference?</p><p><strong>Louis: [00:56:00]</strong> This is a multifold answer, because it&rsquo;s actually a question that was asked. There is this, how is it called, the OCaml Software Foundation, because if we can explain how OCaml, the management of OCaml is that&nbsp;&mdash;</p><p><strong>David: [00:56:23]</strong> Please do. As core contributor of the code of conduct, please&nbsp;do.</p><p><strong>Louis: [00:56:27]</strong> There is the core group of contributors for the language, and out of that before there was something called the OCaml Consortium, I think, where companies could pay few thousand USD a year and it will give them a license to use OCaml not as an open source project. You could get the compiler and do changes on it and you didn&rsquo;t have to publish the changes again. It was also a way to just sponsor the OCaml development. They took it to a different level. They created this OCaml Software Foundation that is pushing some efforts around&nbsp;OCaml.</p><p>One question was, do we want to have an OCaml conference or do we want to have OCaml- maybe not conference, but smaller events but that could happen more often. Where will we put those events in the world? You need people with time, you need people with money, and you need to find the right place for the right people to attend. I think no one has all those resources, including the mental space to build fancy ideas on what to put in a conference. I cannot provide a definitive answer because I&rsquo;m not the one deciding on all those things, but I think it&rsquo;s a combination of all those that makes the ICFP the place to&nbsp;be.</p><p><strong>David: [00:58:05]</strong> Right, because this year is on Seattle. Every year it changes the location.</p><p><strong>Louis: [00:58:13]</strong> Yes.</p><p><strong>David: [00:58:16]</strong> Last year we released we- I didn&rsquo;t but yes, OCaml released multicore and effects or handling effects. We chatted a bit, a lot at work about this, and I think you said multicore was not something that needs to happen, but you are not very excited. On the contrary, you said the effects are a big deal. Thinking about the person that doesn&rsquo;t know a bunch about what effects are, could you do a short summary and then explain why those are exciting?</p><p><strong>Louis: [00:59:01]</strong> I&rsquo;m not a specialist with effects either but to me, a parallel will be to talk about Rust. In Rust, you have those ways to, how is it called? Borrow checker. You have a way to know to who one value belongs. It heavily affects how you are writing code because then you need to architecture your code in a way that is safe. Do you know that, for example, that value can only be used by one bit of code at a&nbsp;time?</p><p><strong>David: [00:59:45]</strong> Right. Otherwise, you would have crazy bugs. Data corruption</p><p><strong>Louis: [00:59:56]</strong> That would be C. Rust came in and was provided this safety. That&rsquo;s a bit the same idea in OCaml. It&rsquo;s like you come with effects and I think it has many usages that I do not completely understand, but some of them allow us to change the way we do concurrent or parallel computations, and it makes it safe. Like the borrow checker makes the Rust code safe. This is definitely affecting the way you write code because now you have one more tool to express your ideas. I think this is definitely changing the way the language will be&nbsp;used.</p><p>While the multicore, it&rsquo;s just in the background, it is happening, but this is not the tool. This is just a mean, so it&rsquo;s like, how do we do fast computation? Do we need to split stuff on different cores and how do you do it? Either you fork or you do multicore. In a way, it could be completely hidden behind a magic API and I will not know if it&rsquo;s fork or multicore, and it&rsquo;ll be fine to me as a user. If you have something like the borrow checker in Rust, this is actually a language feature, and this is something I see day to day and it is affecting how I can think and what I can&nbsp;express.</p><p><strong>David: [01:01:36]</strong> Right. I see, I see. Yes, because right now one of the features that Jane Street, the famous company that does the Wall Street and whatnot and pushes OCaml for the next level, they have a team working on the OCaml compiler, and one of the big fears that they want to work on, I think, they call it locality or local, global variables. Would that express, I have no idea about those rather than watching Stephen Dolan at the presentation on last ICFP, but would that allow some of the users of OCaml that they do care about the memory layout or the owner of the variables to express those different changes regarding using multicore?</p><p><strong>Louis: [01:02:34]</strong> I don&rsquo;t know exactly&#8202;&mdash;&#8202;My own&#8202;&mdash;&#8202;I mean, I have a light understanding of that. To me, I think it would be interesting even if there was no multicore, the stuff they&rsquo;re doing local/global because we already had concurrency with lwt or stuff like this. It has benefits because you control your allocations too. You can decide what is allocated on the stack versus what is allocated on the heap. It can have big performance implication.</p><p>This is an exciting feature, but this is maybe where you see my C background that when I was in uni, the first year was just writing some C code and we had to rewrite Bash. We had our own version of Bash. We spent two months writing in Bash or stuff like this. We had to deal with many of the small like&#8202;&mdash;&#8202;You are launching a bunch of processes together and you have to manage your memory or whatever, or we had to rewrite malloc, so we&nbsp;&mdash;</p><p><strong>David: [01:03:53]</strong> Okay.</p><p><strong>Louis: [01:03:56]</strong> I know little bits about memory management and how to deal with pointers because I did those projects in the past. These local, global things seems appealing, but at the same time, it&rsquo;s probably not critical. It&rsquo;s not going to change the vast majority of the code that is written in general. All my small personal projects or even most of the code that is running at Ahrefs, performance is not key. I care more about the fact that the code is readable and stable rather than performance, I would&nbsp;say.</p><p><strong>David: [01:04:42]</strong> Yes. Only in somewhere else. Yes, I see your point. Usually, code, for example, just like a web API were way, way fast enough. There&rsquo;s no point to optimize the endpoints. Most of our endpoints I think we have 500 endpoints. That&rsquo;s optimizing one by one or optimizing 10% of them, they would not change absolutely anything.</p><p><strong>Louis: [01:05:10]</strong> We spend so much time doing queries to different databases or http query to gather whatever we need to gather before to answer a request. This is so expensive compared to what we do most of the&nbsp;time.</p><p><strong>David: [01:05:28]</strong> Right. That&rsquo;s true. That&rsquo;s true. Why do you think Ahrefs is such a different company? When I have experience with the&#8202;&mdash;&#8202;It&rsquo;s because of the culture maybe? Here we don&rsquo;t have real management, we don&rsquo;t have product owner. We don&rsquo;t have many things that when you come from working on the SaaS companies that are from the culture of US maybe, or some Europe companies. In Ahrefs we don&rsquo;t have anything like that. Can you say that it&rsquo;s good or bad and&nbsp;why?</p><p><strong>Louis: [01:06:07]</strong> It&rsquo;s good and bad. There are definitely some downsides. Why it&rsquo;s like this, is also because the company is young and small too. It&rsquo;s what? 10 years old so it takes time. Every time you want to make a change company-wide, it probably takes two years to actually make change&nbsp;happen.</p><p><strong>David: [01:06:33]</strong> Okay.</p><p><strong>Louis: [01:06:35]</strong> This is not the only company with a structure that is not well&nbsp;defined.</p><p><strong>David: [01:06:44]</strong> Right.</p><p><strong>Louis: [01:06:44]</strong> What happens is that there is a structure, it&rsquo;s just people don&rsquo;t have the title because actually when you have been in the company for a long time, you own some bits of codes and there are people who are expert on the subject. Then there are people that you trust for something and people that you trust for something else. Even though there is no direct management, there are people taking decisions, so who is taking the decision, right?</p><p><strong>David: [01:07:16]</strong> Right.</p><p><strong>Louis: [01:07:17]</strong> It&rsquo;s good to be flexible and it allows more or less anyone at some point to take a decision if they want to and if they dare to. The downside is that sometimes you don&rsquo;t know if you can take the decision or not, and you don&rsquo;t know who you should talk to and then there are some hidden politics because some products, some features there, they belong to someone. You don&rsquo;t want to offend that person so you can&rsquo;t go and touch this or stuff like&nbsp;this.</p><p><strong>David: [01:07:51]</strong> Well, I need to interrupt here. I think you have been way too long at Ahrefs to realize what politics&#8202;&mdash;&#8202;What it means because in Ahrefs there&rsquo;s literally zero politics or not politics, but battles or discussions for the sake of discussion, it&rsquo;s nearly zero. I think that&rsquo;s one of the things that at the beginning of like, are we not talking about this and somebody said no need to. It&rsquo;s the culture of getting very direct and very technical focus.</p><p>I think when you work in a company that you can be weeks without knowing what to do or just months working on so many processes that are close to useless from your point of view or maybe very beneficial from an individual contributor, you feel like you are losing your time. In Ahrefs I don&rsquo;t think I have been noticing a layer I thought I&rsquo;m losing time because of the company it&rsquo;s the other way around. Oh, my peer is asking me to implement something that needs to be done and I haven&rsquo;t finished yet. That&rsquo;s more the feeling of the work,&nbsp;right?</p><p><strong>Louis: [01:09:09]</strong> I guess it&rsquo;s not politics looking for power because there is no power to&nbsp;gain.</p><p><strong>David: [01:09:16]</strong> Exactly.</p><p><strong>Louis: [01:09:17]</strong> What do you want to own? There is nothing to own. You can try, but there is nothing to win at the&nbsp;end.</p><p><strong>David: [01:09:26]</strong> Getting to the last questions now, but have you been following a little what Javi and Antonio and a little bit of myself having worked in Melange. What&rsquo;s your opinion about&nbsp;Melange?</p><p><strong>Louis: [01:09:43]</strong> I know what Melange&nbsp;is.</p><p><strong>David: [01:09:46]</strong> Definitely.</p><p><strong>Louis: [01:09:47]</strong> Okay. What do I think about Melange? Again, it&rsquo;s a question that is hiding other questions. Let&rsquo;s say technically, for example, this is pretty impressive. What the four of you have been able to do in a few months is amazing. Because just to give some context, it&rsquo;s like moving&#8202;&mdash;&#8202;Okay, Melange was not super, super alive, six months ago. The project was moving but slowly. There was no Dune support, there was not much stuff happening. Then six months later, you have the whole Ahrefs front-end, which is like, hundreds of thousands of lines of code that are written by what? 30 people maybe&nbsp;now.</p><p>It&rsquo;s completely moved to Melange. This is amazing. I&rsquo;m able to compile all this code in one comment. I go in the repo, I do &ldquo;make dev&rdquo; and everything works.</p><p><strong>David: [01:10:56]</strong> These and many more advances, but yes, that&rsquo;s the part that it&rsquo;s&nbsp;funny.</p><p><strong>Louis: [01:11:04]</strong> Yes, it&rsquo;s amazing. It automatically works and it didn&rsquo;t break the experience of anyone so it&rsquo;s compatible with what was bucklescript or rescript beforehand. It&rsquo;s compatible with native code at the same time. It&rsquo;s amazing. What do I think about the project? Another side of the question will be, was it the right thing to do to fork rescript? Or, is it the right way to do it? Is it good to have a fork of the compiler inside of Melange to achieve that project? I don&rsquo;t have a strong opinion on&nbsp;it.</p><p>I don&rsquo;t have enough experience. After all those years of seeing Reason and Bucklescript evolving, I believe that the experience of the end user, so the developer that is using these tools, is more important than the technical implementation. Is it the best way to do it? I don&rsquo;t know. Does it give a good end user experience? Yes, then that was the right thing to&nbsp;do.</p><p><strong>David: [01:12:21]</strong> On those tools, you would always prioritize the developer experience, rather than technical merits? How would you choose&nbsp;&mdash;</p><p><strong>Louis: [01:12:33]</strong> As a user or as a developer of those&nbsp;tools?</p><p><strong>David: [01:12:36]</strong> As a developer of those&nbsp;tools.</p><p><strong>Louis: [01:12:39]</strong> As a developer of those tools, given the target, given what I see of how you build a community and it&rsquo;s like the early days of Melange, I would prioritize user experience. I think, for example, all the efforts that have been put into making Dune work, I think the target was the user experience at the end. Because we couldn&rsquo;t make it work another way. If we didn&rsquo;t have this, I&rsquo;m not sure that we would have moved to Melange, for&nbsp;example.</p><p><strong>David: [01:13:19]</strong> I&nbsp;see.</p><p><strong>Louis: [01:13:20]</strong> What&rsquo;s the downside was that for example, this is not the fastest implementation there is. I think there is some many different calls to this Melange compiler that are not the fastest way to do it, but the UI is good so we still use&nbsp;it.</p><p><strong>David: [01:13:44]</strong> What I would like to feature, knowing that at the start Bucklescript got born, even though they were like js_of_ocaml. Now, I think, eight or nine years past, Rescript got its own path, but then Melange is trying to again, be part of the OCaml to Javascript compilation, or Reason to Javascript compilation. How do you see the future? Because eventually, nobody wants to have two ways to Javascript.</p><p><strong>Louis: [01:14:16]</strong> I&rsquo;m not sure that&rsquo;s true. Why would people not want many ways to do the same thing? It&rsquo;s like if you look at other languages, actually, many of them have different ways to do the same thing. Why not OCaml? As long as the projects don&rsquo;t die, it&rsquo;s not like Melange is attacking jsoo or jsoo is attacking Melange. It&rsquo;s like, people don&rsquo;t hate each other. They are not fighting for users; I think the targets are a bit different.</p><p><strong>David: [01:14:53]</strong> You would want different ways of combining to Javascript? Because the sane competition? That&rsquo;s&nbsp;true-</p><p><strong>Louis: [01:15:03]</strong> To me it&rsquo;s not the sane competition. It&rsquo;s more that I think it targets different audience. It tries to do different things. One example will be during one of the Reason conferences, we wanted to do a workshop and we wanted to show atdgen which is a tool we&rsquo;re using a Ahrefs lots to parse and write JSON. It&rsquo;s protobuf but for&nbsp;JSON.</p><p><strong>David: [01:15:34]</strong> Yes, it would give us type safety from front end all the way down. Sorry, backend all the way&nbsp;down.</p><p><strong>Louis: [01:15:43]</strong> Yes.</p><p><strong>David: [01:15:43]</strong> Sorry, go&nbsp;on.</p><p><strong>Louis: [01:15:46]</strong> You have as with protobuf or with Graphql too you have a definition, you have a file with type definitions and from the definition you derive OCaml code or Python code or TypeScript code. It supports multiple languages. To do so you need an atdgen binary. In the Reason conference, you have people using Linux, Windows, Mac, different version, whatever so how do you give a binary that everyone can use? In two minutes, I just went into the atdgen repo and I enabled js_of_ocaml compilation inside Dune and now my binary is actually JS file that I can run in node&nbsp;JS.</p><p><strong>David: [01:16:34]</strong> Right.</p><p><strong>Louis: [01:16:35]</strong> I don&rsquo;t think that Melange aims to do that. Because then&nbsp;&mdash;</p><p><strong>David: [01:16:41]</strong> I think that&rsquo;s the magic. Yes, I&nbsp;agree.</p><p><strong>Louis: [01:16:44]</strong> In Melange you will have one file per module or something like this, which means I will need to run through webpack or something like this later&nbsp;on.</p><p><strong>David: [01:16:51]</strong> Yes, you could but you would face a few problems. Marshall for example, that it&rsquo;s the encoding/decoding on bytes, that doesn&rsquo;t work in&nbsp;Melange.</p><p><strong>Louis: [01:17:01]</strong> Well, it doesn&rsquo;t work in js_of_ocaml I think&nbsp;too.</p><p><strong>David: [01:17:05]</strong> Yes, but I think you can stub it, right? I think you can&nbsp;&mdash;</p><p><strong>Louis: [01:17:10]</strong> But I would say most of the time actually you don&rsquo;t care because it&rsquo;s corner cases, it&rsquo;s just that the UI they provide is good enough for OCaml people and Melange, it provides the nice, what? FFI, for example, to interact with the JavaScript code. The way it outputs code is closer to the JavaScript way too; I would say so it&rsquo;s easier to make webpack or other tools like this work&nbsp;together</p><p><strong>David: [01:17:39]</strong> Yes, I agree that those are different targets. It just my point of view was more like, okay, js_of_ocaml the crazy thing is that you have entire project in OCaml. You add one line say in Dune compile to node JS please and then you have a single file that is compiled to JavaScript. That&rsquo;s insane so if you have, for example, a compiler written in Menhir it&rsquo;s a language to write compilers in OCaml, you can compile it to JavaScript in one line or any library, even drivers, even anything that you can imagine. That&rsquo;s the valuable position or thing that gets people to try js_of_ocaml very fast. But on the contrary, the documentation is very&nbsp;bad.</p><p>It&rsquo;s the classic OCaml project that you need to understand 50% of the project to even start it so that&rsquo;s like&#8202;&mdash;&#8202;For people like me, I invest a lot of time trying js_of_ocaml and even try to write bindings to React and succeed but I did not succeed convincing people in Ahrefs, front end of Ahrefs to try js_of_ocaml. For me, that was the&#8202;&mdash;&#8202;That technology is not good enough for prime time or not good enough to convince my team, then yes, there&rsquo;s no way to convince any&nbsp;other.</p><p>On the opposite, Melange fits together the low barrier to try and good documentation and at some point, it gets complex but the ease of experience I think it&rsquo;s much better. But yes, you don&rsquo;t have a one line&#8202;&mdash;&#8202;You need to meddle it a bit on building the integration with your front end or your pipeline but yes, once it is done, it works. But yes, you would never do that with atd. The experience in atdgen that&rsquo;s not going to happen in&nbsp;Melange.</p><p><strong>Louis: [01:19:41]</strong> It&rsquo;s funny how you say it and it&rsquo;s true that it&rsquo;s easier. Many things in Melange are easier to experiment with and at the same time it&rsquo;s more complicated. For example, in js_of_ocaml you have a clear separation between OCaml types and JavaScript types. String that is an OCaml string is a different type from JavaScript string.</p><p><strong>David: [01:20:10]</strong> You have like a wrapper,&nbsp;right?</p><p><strong>Louis: [01:20:12]</strong> It&rsquo;s very explicit and it&rsquo;s good for the OCaml person because then you know when this is a part of the language you are comfortable with and then when it starts with JS, it&rsquo;s okay, be careful because you don&rsquo;t know what you are doing. This is easy and in js_of_ocaml. Because it&rsquo;s very easy. You see JS dot and then you know now I have a JavaScript value. In Melange it&rsquo;s your string is what? And you have to deal with the encoding. What is the actual encoding of a string in&nbsp;Ocaml?</p><p><strong>David: [01:20:57]</strong> Do you remember that I said that every time that I&rsquo;ll talk with a backend person, they always mention the runtime. Exactly that moment. You always think about the&nbsp;runtime.</p><p><strong>Louis: [01:21:06]</strong> Actually, I&rsquo;m not&nbsp;sure.</p><p><strong>David: [01:21:08]</strong> It&rsquo;s not the runtime itself, but the encoding. In Melange for example, of course, all the types not of course, but all the types that you have in language are the same representation as a JavaScript value. For example, a string is in a string, integration is a number, float is a number and so on and so forth. Variant is an object; a record is an object. Melange maps perfectly or as good as possible to JavaScript values. It&rsquo;s cool that you said that when every time that you work with js_of_ocaml, once you see JS dot, whatever this is the namespace and you know that you&rsquo;re treating with things that come from the&nbsp;client.</p><p>For example, that&rsquo;s a barrier for people that tried rescript or tried Melange in the first place because they don&rsquo;t understand why do I need a wrapper? Why do we need a generic for at type that already have? Because it&rsquo;s the mentality of why do I need to care about the&nbsp;runtime?</p><p><strong>Louis: [01:22:17]</strong> Yes, basically you pay a cost but at a different time, like in js_of_ocaml, you pay the cost very early because as soon as you write code you need to make the difference between the two words. In Melange you will only pay the cost if you write FFI and you need to care about the representation. It&rsquo;s if there is a string with something weird in it, you don&rsquo;t know the encoding of the string, for example, then you need to be&nbsp;careful.</p><p>The experience by default is much easier. It&rsquo;s just that when you are dealing with the boundaries then things can be a bit more implicit and probably you need to know the language better to do things the right way. It&rsquo;s easier and it&rsquo;s actually more complicated in some&nbsp;bits.</p><p><strong>David: [01:23:08]</strong> Yes, I think if you look now, js_of_ocaml and Melange are very drawn line. You can draw a line between the tradeoffs. One side is very clear, one side is very clear. Now, I would say that I&rsquo;m comfortable saying that both are balanced for the users, even rescript now. For me now, I have a feeling the three of projects are in the right column. You can classify them perfectly now. If you get into, &ldquo;Oh, I want to try this ML or like OCaml, whatever language as a whole,&rdquo; you can choose&#8202;&mdash;&#8202;Based on your team or your decision. You can choose clearly one&nbsp;another.</p><p><strong>Louis: [01:23:57]</strong> Yes. Actually, you said you couldn&rsquo;t sell js_of_ocaml to Ahrefs, but we can probably talk a bit about what was the discussion, what happened, because Javi and you, you actually tried to do something so that it could happen. You work on the React bindings and then you try to show that it could work. In a way, I think that js_of_ocaml, it could fit what we do because we don&rsquo;t depend on a lot of external code. One very interesting thing in Melange is that the FFI is very good. It&rsquo;s easy, convenient, to interface with other existing JavaScript libraries.</p><p>In Ahrefs, we have bindings to what, React, and then maybe one or two library to deal with the timestamps and charts. We don&rsquo;t have millions of bindings. We have maybe five big libraries we have bindings for, and then a bunch of smaller stuff. We don&rsquo;t bind to so many things and we don&rsquo;t need FFI that is amazing. It&rsquo;s not a priority. js_of_ocaml could have&nbsp;worked.</p><p><strong>David: [01:25:14]</strong> Could have worked. I&nbsp;agree.</p><p><strong>Louis: [01:25:16]</strong> The fact that even in this perfect setup for js_of_ocaml it fails is interesting. You find the right company with many OCaml people, many people who understand js_of_ocaml, and you don&rsquo;t need one of the best features of Melange and still, this is not actually the tool that won at the&nbsp;end.</p><p><strong>David: [01:25:42]</strong> Yes, that&rsquo;s true. The experience, I think that&rsquo;s exactly what you said, it could work, theoretically if you look at the direct from the outside or even if you look at far from the front end, it makes a lot of sense. Once we were working on this, I was working on this middle-end team, before it was not called middle-end. I was working on the middle-end, and most of my assumptions were like, &ldquo;It&rsquo;s going to work perfectly.&rdquo;</p><p>Because of what you said, right? Then when we try to&#8202;&mdash;&#8202;How can we write React, we are married to React. I think we like the model of components. We like the model of data; we like the composition. We&rsquo;re not going to change React. Let&rsquo;s bind it to React, so we create the same PPX and the same library to React. I think that was how Javi started and then we end up finishing.</p><p>did the emotion binding, so I know the CSS, everything worked and we felt like js_of_ocaml was very mature, but there were a few problems that you could not solve easily at the time. At the time js_of_ocaml didn&rsquo;t have Unicode support. Now they have some Unicode support or the parsing, I haven&rsquo;t followed that closely, but you would need another library to run to get the Unicode support that in Melange or Bucklescript at the time was natively. That was an issue. The other issue or biggest issue that you can&rsquo;t bypass is that js_of_ocaml, you compile it in one file, one gigantic&nbsp;file.</p><p>Incremental migrations were very hard or very difficult to iterate over time. You could migrate parts of the app, but then you would need to compile everything in both, have two duplicated apps. It was definitely not&#8202;&mdash;&#8202;The migration plan was impossible. We could try. I think we tried in one of the small apps, I think we could try wordcount, is one of the verticals we have at Ahrefs, with js_of_ocaml, and once we were trying those, we find the wrapper, it was very hard to&nbsp;sell.</p><p>The wrapper is like the Js.t that we call it in Recript, in js_of_ocaml I think it&rsquo;s JS.object. It&rsquo;s unsafe. You have JS.unsafe. There are many, yes, many constructions you can track with JavaScript differently from what we do with the bindings. That part was&#8202;&mdash;&#8202;With these three things that I said Rusty, which is one of let&rsquo;s say the only Tech Lead at Ahrefs, like the only person that&#8202;&mdash;&#8202;He&rsquo;s the CTO in the frontend, how I call&nbsp;it.</p><p>He was the person who we would need to convince to migrate to the frontend. He was definitely not on board with the idea. I think that&rsquo;s the main reason. He would chat with our people and people would say, &ldquo;Yes, fine, if Javi and David are happy, then we are all happy,&rdquo; but even though we migrate one small app, the experience was worse. The user experience of iterating over React components was worse or even the data was worse because you had this&nbsp;wrapper.</p><p><strong>Louis: [01:29:23]</strong> There were too honest in the way they named functions in the API. For example, all those unsafe functions, they exist in every FFI, it&rsquo;s just not called unsafe, but because it&rsquo;s called unsafe, people are like, &ldquo;They&rsquo;re not going to use this, you are not supposed to use it.&rdquo; Yes, you&rsquo;re supposed to use it. Just be careful when you do&nbsp;it.</p><p><strong>David: [01:29:47]</strong> I think you explain to me that anecdote, is that somebody asked Xavier Leroy the creator, the author of OCaml, they ask, &ldquo;What do you think about Objec.magic?&rdquo; Right? Object.magic is the method of OCaml that you can, like unsafe, coerce any variable, right? You can light the typechecker and say, &ldquo;Trust me, this is whatever, an array and it&rsquo;s a list or whatever&rdquo;. His answer was, it is like when you are working in the street, would you inject&#8202;&mdash;&#8202;How is that called? I don&rsquo;t remember the thing, but would you become a&nbsp;junkie?</p><p>You get a syringe, I don&rsquo;t know how to say in English, but would you inject some random thing on the street? That&rsquo;s not part of the language. I think you&rsquo;re explained me the anecdote, or maybe it&rsquo;s Javi, How do you see the purity of OCaml? Do you think that the OCaml is very pure or has some pragmatism on safety? Because of course it&rsquo;s type safe, of course, the compiler when it compiles it works, but you can bypass it from time to time. What&rsquo;s your&nbsp;opinion?</p><p><strong>Louis: [01:31:10]</strong> I don&rsquo;t think it&rsquo;s pure in any way, shape, or&nbsp;form.</p><p><strong>David: [01:31:17]</strong> You can write pure code,&nbsp;right?</p><p><strong>Louis: [01:31:20]</strong> Yes. You can write pure code. But for example, you have exceptions that are very pregnant, that are everywhere and you don&rsquo;t have any way to know if a function can raise an exception or&nbsp;not.</p><p><strong>David: [01:31:37]</strong> Right.</p><p><strong>Louis: [01:31:38]</strong> Okay, it depends what program you write, but basic things, you run your program, like a CLI that is running&#8202;&mdash;&#8202;I don&rsquo;t know, downloading something and you press control C like you want to stop your program. There is&#8202;&mdash;&#8202;It&rsquo;s a signal, and in OCaml it&rsquo;ll raise an exception that you need to&#8202;&mdash;&#8202;You can catch and you can do something with it, right? At any point in time, the user of your CLI can come and interrupt the program, right? Which means at any point in your program, you need to be able to deal with this interruption.</p><p><strong>David: [01:32:18]</strong> Right.</p><p><strong>Louis: [01:32:19]</strong> It&rsquo;s like as soon as you have these where is the purity, what is&#8202;&mdash;&#8202;You have no good way to protect yourself against all these issues. At the same time, I&rsquo;m probably biased because I have been using the language for long. It provides you what is good enough. There was some improvements because, I don&rsquo;t know if you remember, but at some point, the strings were mutable in&nbsp;OCaml.</p><p><strong>David: [01:32:51]</strong> Yes.</p><p><strong>Louis: [01:32:53]</strong> By defaults, the strings were actually what is called Bytes nowadays. It has been a big change. People had to fight to turn Bytes into string, because it was breaking code, obviously. There was more mutability. It was not as pure as it is nowadays, I would say that the balance is not too bad. Could it be more? Probably. There are some things that we can&rsquo;t really express in OCaml, like ownership of a&nbsp;value.</p><p>Like you open connection to a database, you have a handler or something like this that you want to use only at one point in time and you don&rsquo;t want to share. You have no way to express it. Then you can&rsquo;t really protect yourself against the steal. The code can take that value, put it in a global reference, and it can be suddenly reused elsewhere. This is where, for example, the local/global stuff&nbsp;&mdash;</p><p><strong>David: [01:34:06]</strong> Yes, solve exactly that&nbsp;issue.</p><p><strong>Louis: [01:34:09]</strong> Yes. This kind of issue. Is it a problem? Yes. Is it a problem that we face at work? Yes. For example, we see like&#8202;&mdash;&#8202;We have one problem where people can open the connection to a DB using one of those&#8202;&mdash;&#8202;A common pattern in the ocaml to do like &ldquo;with_db&rdquo; for example. Then you pass a continuation, you pass a function, and then this with_db function will create a DB handler and pass it to your function later&nbsp;on.</p><p>Inside your function, you can do one more with_db. This is something that you probably want to forbid because you don&rsquo;t want to open connections after connection after connection when there is already one available.</p><p><strong>David: [01:34:57]</strong> Right.</p><p><strong>Louis: [01:35:00]</strong> For now, how do you fix this? This is an actual problem and you have no good solution. But maybe you write different code than I do. You write code that is in the browser or just behind the browser so maybe you have different views. You have to deal with more mutability than I do, for example the whole DOM, before React. Yes, but before React no one assumed that anything was immutable in a browser. Everything could be changed at any point in&nbsp;time.</p><p><strong>David: [01:35:43]</strong> Yes. That&rsquo;s why in the browser many APIs were pushing for observables, right? You accept mutability into all your values and then you say any value can change in any time and you need to subscribe to&#8202;&mdash;&#8202;Listen to the changes or not and that&rsquo;s the trend of&#8202;&mdash;&#8202;I think that was one of the biggest inclusions of ES4 that didn&rsquo;t get published and they tried with ES5 and they didn&rsquo;t get to the language neither that are like these observables concept. I think they come from React JS and they come from reactive programming from, I don&rsquo;t know, 30 years ago where sometimes reactive is very useful. Before React, I would say that not many people did&#8202;&mdash;&#8202;The immutability was not part of their fashion of writing&nbsp;code.</p><p>We are very far from those problems. We do immutability in a few places, for example, we have a global theme, a CSS theme, right? You can have a dark or light theme. We interact with the browser directly. We opt out from React to do that because the performance is better. You can load that at the beginning, you can then allow React later. But the way it&rsquo;s just very self-contained, right? You will never want to write your data reactive.</p><p>Maybe you want, but for example, for Ahrefs it doesn&rsquo;t make any sense because our data is you have tabular data that never changes on your session, right? It&rsquo;s not live data. It&rsquo;s like you open a report and the report is the moment time that you request. There&rsquo;s no live thing. Nothing is very reactive in nature so yes, for us it&rsquo;s just like a perfect&nbsp;sense.</p><p><strong>Louis: [01:37:41]</strong> You would be happy with more&nbsp;purity?</p><p><strong>David: [01:37:45]</strong> Would we be happy with more purity? No, I think&nbsp;&mdash;</p><p><strong>Louis: [01:37:49]</strong> Would you wish to have a language that is closer to Haskell that is like&nbsp;&mdash;</p><p><strong>David: [01:37:54]</strong> No, I don&rsquo;t think so. I think no, because purity makes&#8202;&mdash;&#8202;Purity in some places makes your life so much better, right? But often you want the tools to be pure so like libraries that you create or you consume need to be pure but your application needs to do all sort of things, right? Your application or when you are a product engineer, you want to just ship fast and if something gets you in your way and you store it globally and deal with it later or store it globally and be safe and then forget about&nbsp;it.</p><p>You need to do things perfectly and draw the line and architect things that slows you down insanely. I think the line&#8202;&mdash;&#8202;OCaml is very well position where you can opt out, do your life easy and then move back and run fast. But yes, my tools to be pure or libraries that I&rsquo;m using or even&#8202;&mdash;&#8202;I know I&rsquo;m working on styled-ppx so making types safe, like your styles. I think that&rsquo;s something that I&rsquo;ve been pushing but yes, you want that tool to be type&nbsp;safe.</p><p>You don&rsquo;t want to do all your things on your app perfectly, to demand it perfectly mostly because on the web, everything is changing all the time. On the backend it&rsquo;s a little bit different but on the web, iterations are just much more common than in the&nbsp;backend</p><p><strong>Louis: [01:39:31]</strong> I find it interesting that everyone is pushing for immutable stuff. At least my impression is that in the front end React maybe didn&rsquo;t create this trend but made it popular. My understanding is that you deal with the DOM as an immutable object. You never manipulate the DOM directly anymore. You do it through React. You have an immutable object, more or less, which goes against many things that happened, historically in a browser, the way the DOM is implemented is completely not like this. It has some interesting benefits.</p><p>You can have any extension in your browser that are changing part of your page. I&rsquo;m using one daily. I&rsquo;m using Dashlane to store my passwords. It does stuff for&#8202;&mdash;&#8202;If there is an input field, it&rsquo;s creating a popup and I can click, input my password in that specific&nbsp;field.</p><p>To do this, it has to inject HTML in the page actually. But it breaks. Some apps are crashing because of this. Some apps, some websites, they&rsquo;re not crashing. They will just see that there is a change coming from my extension and they will just discard it and rerender without my&nbsp;stuff.</p><p><strong>I</strong>t goes against many things that happened for 20 years, more or less. You have to make both of those worlds still somehow work together.</p><p><strong>David: [01:41:18]</strong> I think React did&#8202;&mdash;&#8202;I think not even React, Meta did that all the time. They pushed for a solution that is way better in some areas but destroys previous effort insanely. For example, with GraphQL, I think it&rsquo;s happened the same. They say, &ldquo;You&rsquo;re going to have one endpoint. It&rsquo;s going to be through POST.&rdquo; You would call this endpoint all the time, which goes against completely about REST what we were doing&nbsp;before.</p><p>Of course, with all the tradeoffs, if you go 10 times&#8202;&mdash;&#8202;10 years back and you say to a person, &ldquo;No, we call all the time same endpoint.&rdquo; You will say, &ldquo;You guys are&nbsp;stupid.&rdquo;</p><p><strong>Louis: [01:41:58]</strong> RESTful was a&nbsp;trend.</p><p><strong>David: [01:42:00]</strong> Exactly. The RESTful, you will need to add the link to go to the next resource. Of course, all the people would scream at you. Similarly, it happens now with server components. I don&rsquo;t know if you are following the thing. Again, they are pushing for a new concept that they have mined in their business and works well. The rest of the people are like, &ldquo;No, that&rsquo;s just insanity.&rdquo; I think React, the first concept is you&#8202;&mdash;&#8202;The insert and update are the same operations.</p><p>There&rsquo;s no create the DOM and then update the DOM. It&rsquo;s always like, &ldquo;Do the thing.&rdquo; It&rsquo;s just rerender. Just because they push for that approach and they delay, of course, the first load is going to be slower. You don&rsquo;t have serialization. Then later updates are going to be&nbsp;faster.</p><p><strong>Louis: [01:42:58]</strong> Actually, even the later update are slower, because you need React to do this diff between the two version and to only update the relevant part of the DOM. React is doing what the browser was actually doing. You are duplicating the work and you are doing it in JavaScript, which is slow. The browser was doing it in a very optimized C++&nbsp;code</p><p><strong>David: [01:43:26]</strong> Fair point, but the DOM is fast enough. I think I read a lot of articles about anti-React that the DOM is fast enough. I think that&rsquo;s&#8202;&mdash;&#8202;These benchmarks are nonsense. Those benchmarks&#8202;&mdash;&#8202;Even the benchmarks that&#8202;&mdash;&#8202;I would call it micro-benchmarks. Even microbench like&#8202;&mdash;&#8202;I don&rsquo;t know, work faster, implement some charting library mutable to DOM and using whatever, Vanilla JavaScript or using React. Of course, you can outperform React but at what&nbsp;cost.</p><p>The cost of creating two charts, two components of a chart, the API nicely, blah blah blah blah rather than mutating the DOM all the time. That&rsquo;s super expensive. When you&rsquo;re working, for example, for Ahrefs, I think we have&#8202;&mdash;&#8202;I don&rsquo;t know, 2 million lines of code in reason. I don&rsquo;t know, 5,000 components. Some insane amount of number of components. If you do that in mutable or maybe not mutable but maybe just going to DOM and listening to DOM and hoping that everybody is a good citizen. It&rsquo;s just you would slow down development so hard that it doesn&rsquo;t make any&nbsp;sense.</p><p>I think React draw this line where virtual DOM is like if you know how to create the structures, know how to trigger the renders, I think can be as good as the DOM, of course. In general terms, I think it&rsquo;s good enough. I think the balance is very OCamly. [laughs] You know that Jordan was behind, when&#8202;&mdash;&#8202;Jordan is an OCamler that knows this balance, that&nbsp;&mdash;</p><p><strong>Louis: [01:45:23]</strong> It&rsquo;s funny, because you could say that for example Facebook has enough resources to make it work, right? They could have decided it is going to be a more troublesome for our developers, but we are going to offer a faster experience for the customers, the people actually visiting the website. But even them with their infinite resources, they decided to go in a different direction. Is it because it&rsquo;s a tech company? I feel that some big tech company, they run the way they do, because they are led by technical people, so they can make technical choices instead of business choices sometimes.</p><p><strong>David: [01:46:08]</strong> React is that, exactly that case. I think I saw the documentary about React, and it&rsquo;s more the idea just spreaded everywhere. I think they have that competing library; I don&rsquo;t know how, I think it&rsquo;s called Jacks or something. I don&rsquo;t the name, but they have a competing library that was written with PHP and XML, and the whole stack on meta back in the days. The idea of React spreads everywhere. The point that you made before of developer experience leads everything in the early days. I think that it just applied exponentially, because at some point they released publicly, everybody hated JSX. Then after one year it was the most famous library used. Then from now on, the monopoly went for, I don&rsquo;t know, six, four years, I don&rsquo;t know. So many years that now everybody has the component model, the hooks, the state. It spread the idea everywhere. It&rsquo;s interesting, but I think it&rsquo;s just like <strong>[unintelligible 01:47:11]</strong>&nbsp;,&nbsp;so.</p><p><strong>Louis: [01:47:13]</strong> How smart do you need to be to Jordan and be correct about React was the right thing to do, and to do it properly, and then Reason was the right thing to do, and to do it properly?</p><p><strong>David: [01:47:25]</strong> How smart need to do. I don&rsquo;t know. Uncountable, I would say. Hard to quantify smartness. It&rsquo;s hard to quantify smartness, but I think it&rsquo;s even harder when you look at what Jordan has been doing. I think Jordan is the kind of person when you speak with him, he talks, or he says things that doesn&rsquo;t make sense at the beginning. It&rsquo;s his way of thinking. He&rsquo;s thinking three, five years ahead, and when he explains the idea to you, you are like, &ldquo;I got the sense that I didn&rsquo;t understand anything.&rdquo; After a few months you start saying, &ldquo;Oh, right, it made sense.&rdquo; I think everybody on the React team only says how brilliant Jordan is. So,&nbsp;yes.</p><p><strong>Louis: [01:48:18]</strong> It&rsquo;s interesting that you interviewed Rudi, the author of Dune, and he said that even him, for example, originally when he saw the Reason syntax, he was like, &ldquo;meh,&rdquo; like, &ldquo;What is this thing?&rdquo; Like, &ldquo;Yet again?&rdquo; He say, &ldquo;Yes, at the end it was right to make it more approachable.&rdquo; This was from a user experience perspective. It&rsquo;s a clear&nbsp;benefit.</p><p><strong>David: [01:48:44]</strong> Yes. I love that interview, because Rudi said exactly that, like, &ldquo;Oh, at the beginning Reason felt like a toy, but then we were doing tooling for OCaml, and the language and a lot of work on the actual language. Reason was the thing that bring more people on OCaml, than we never, ever did. Even though it&rsquo;s not a competing language, even though the person that created has so much power into the frontend people, even that the number of people that got into OCaml community, it was bigger than any other effort that we made. [laughs] Which for me is super funny at the end of the day, because most of us came from the JavaScript and end up doing OCaml and mixing everything. That was the&nbsp;idea.</p><p><strong>Louis: [01:49:40]</strong> It&rsquo;s funny how you need a little bit of luck for all those things to work. You need, for example, Rudi to decide early on, &ldquo;Okay, I don&rsquo;t really trust this thing, but I still I&rsquo;m a good citizen, so I will add the support inside&nbsp;Dune&rdquo;</p><p><strong>David: [01:49:56]</strong> Yes. That&rsquo;s very&nbsp;noble.</p><p><strong>Louis: [01:49:58]</strong> It&rsquo;s like if you don&rsquo;t have those people who are able to compute this is maybe good or maybe bad, and are able to balance their opinion, versus the community thing. They have to do it early enough, at the right time. It&rsquo;s interesting that somehow&nbsp;&mdash;</p><p><strong>David: [01:50:24]</strong> Of course, not what everything Jordan says is correct, I think in the sense of, of course, he created stuff that was definitely not on shape or not on the area of success of React, of course. I think he created React and then React native. Of course, they both are insanely successful. Reason I would call it successful as well, but actually, push the idea of Esy. Esy is the package manager that is still somehow used, and some people love it. Even myself, I have a lot of respect for Esy, and use it from time to time. That you can consume JavaScript libraries, npm packages as well as OPAM packages.</p><p>This project has been suffering for long, that it&rsquo;s definitely not the right solution, or at least, it didn&rsquo;t create these ideas, this sudden idea to the rest of people to continue pushing for&nbsp;it.</p><p><strong>Louis: [01:51:27]</strong> This is one of those tools where I think the technical implementation was good, but the UI was not great. The output is just not nice, for example. You run it, and then it displays&nbsp;some-</p><p><strong>David: [01:51:44]</strong> You mean, the actual UI, the&nbsp;CLI?</p><p><strong>Louis: [01:51:46]</strong> Yes, because opam, which is not the most fancy tool ever, but still when you opam install, it has some colors. It doesn&rsquo;t display one line production. It&rsquo;s some kind of somehow clean output that Esy doesn&rsquo;t have. You had to learn this weird JSON syntax to put your package, and it outputs ugly text after that. The idea was very good, but the UI was not completely working.</p><p><strong>David: [01:52:24]</strong> I think Esy has some, people call it state-of-the-art ideas, the end goal of our package manager, what do you want to do, or we want to use. The efforts of maintaining the overrides or being on top of all the libraries or even compiles Esy, there&rsquo;s a lot of maintenance that needs to get done. At some point, we have a team of, I think, six, seven persons working on it, and that experience was very good, but from when Reason got a little bit lost, this team, those people&nbsp;&mdash;</p><p>Of course, when the blockchain companies started hiring all of them to work for Web3 and paying them insanely amount of money, then the project got a little bit carried over, got a little bit less maintenance then is likely in a stale mode that you can use, but you could get not as good as&nbsp;opam.</p><p><strong>Louis: [01:53:35]</strong> This exactly why there is no Rust code inside Ahrefs, because all the developers got stolen by the blockchain companies.</p><p><strong>David: [01:53:45]</strong> That&rsquo;s fair. That&rsquo;s fair. I think, Louis, we are running out of time. For me is daytime, I can do stuff, but for you is definitely night time. I can work, talk with you for hours and hours, but I think the show is reaching to a point to finish. It was a pleasure to have you, of&nbsp;course.</p><p><strong>Louis: [01:54:07]</strong> It&rsquo;s a pleasure.</p><p><strong>David: [01:54:09]</strong> If somebody attends to ICFP, please go to Louis, I think he&rsquo;s the party manager, and as well, a person very interesting to talk to. Please, bother him. I think he&rsquo;ll be in Seattle on September.</p><p><strong>Louis: [01:54:26]</strong> Yes, Seattle, September 4th to 9th, I think, something like that. It will be online too, this year. I think it will be online and for free. All the talks, at least all the ML, or maybe not ML, but the OCaml workshop will be online of free. There is no need to travel all the way to Seattle to see the talks, at least to see the OCaml workshop.</p><p><strong>David: [01:54:52]</strong> Makes sense. In this era of internet, I think that makes sense. Cool. Thanks everybody for being here. You&rsquo;re having a little bit late day, but that was perfect. Thanks, Louis, to spend time with&nbsp;us.</p><p><strong>Louis: [01:55:07]</strong> Thank for having me. That was&nbsp;fun.</p><p><strong>David: [01:55:10]</strong> See you&nbsp;guys.</p><p><strong>[01:55:13] [END OF&nbsp;AUDIO]</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=7767afbfbdb9" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/emelletv-talking-with-louis-roche%CC%81-about-ocaml-and-ahrefs-7767afbfbdb9">EmelleTV: Talking with Louis Roche&#769; about OCaml and Ahrefs</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/emelletv-talking-with-louis-roche%CC%81-about-ocaml-and-ahrefs-7767afbfbdb9?source=rss----303662d88bae--ocamlEmelleTV: Talking with Louis Roché about OCaml and Ahrefs2023-06-29T14:32:40-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<h3>OCaml, all the way&nbsp;down</h3><figure><img src="https://cdn-images-1.medium.com/max/1024/0*cGDQZKJ2bKMARpj9" alt=""/><figcaption>Photo by <a href="https://unsplash.com/ja/@lg17?utm_source=medium&amp;utm_medium=referral">Lance Grandahl</a> on&nbsp;<a href="https://unsplash.com?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><h4>Some history</h4><p>In 2021, we decided to evaluate <a href="https://github.com/melange-re/melange">Melange</a> as an alternative to <a href="http://rescript-lang.org/">ReScript</a> for compiling Ahrefs&rsquo; frontend codebase. We wrote about the reasons that led us there, as well as the limitations we encountered at the time, in <a href="https://tech.ahrefs.com/building-ahrefs-codebase-with-melange-9f881f6d022b">a previous&nbsp;article</a>.</p><p>After this experiment, discussions continued inside the team. Switching to a different compiler, which was in a very early stage, involved quite some risk. But so did the continued use of ReScript, which seemed to be diverging further and further away from&nbsp;OCaml.</p><p>Finally, in September 2022 (during <a href="https://icfp22.sigplan.org/">ICFP in Ljubljana</a>), we decided to bite the bullet and kicked off a project to deepen the integration between <a href="http://dune.build/">Dune</a> (OCaml&rsquo;s most used build system) and Melange. This better integration was the key to solve two of the three limitations we had encountered during our initial exploration of&nbsp;Melange:</p><ul><li>Build speed would increase due to less work needed to parse dune files, and more efficient rules planning and execution.</li><li>Developer ergonomics would get better, as Melange would become a first-class citizen in Dune, with concepts like Dune <a href="https://dune.readthedocs.io/en/stable/dune-files.html#library">libraries</a> and other stanzas becoming available to Melange&nbsp;users.</li></ul><p>Ahrefs&rsquo; leadership backed the project and agreed to financially support the development of this tighter integration. With this support, we set about building a team that included Rudi Grinberg, who maintains Dune as part of its development team, and Antonio Monteiro, who created Melange and is also part of the Dune development team.</p><h4>Heads down</h4><p>During the following months, we focused on two tasks, iterating over multiple cycles where the progress on one task would inform the next steps to take for the&nbsp;other:</p><ol><li>Evolve Dune to add stanzas, fields, and documentation to support Melange projects.</li><li>Migrate Ahrefs&rsquo; frontend codebase to use the Melange compiler and Dune, adapt third-party libraries and bindings to Melange, and polish the editor integration, build scripts, and other aspects of the development experience.</li></ol><p>We believe that tackling these two tasks in parallel led us to better results, compared to a more waterfall-based approach. As we applied the changes over Ahrefs&rsquo; large-ish frontend codebase&#8202;&mdash;&#8202;it will soon reach 5000 modules&#8202;&mdash;&#8202;we kept finding and fixing bugs, improving the ergonomics of the Dune and Melange integration, and in general making the solution more robust, real-world ready, and developer-friendly.</p><p>Another upside of the way the project was implemented is that we developed it initially in stealth mode, keeping it quite private. By working on it within a tight-knit team, before making a public release, we could make progress faster. We believe that this approach saved future Melange users a lot of churn and burn caused by the multiple changes in Dune stanza options, Melange flags, and other configurations we changed along the way, as we learned more about this integration.</p><h4>Migration strategies</h4><p>Initially, our plan was to progressively migrate Ahrefs&rsquo; code to Melange. As the frontend codebase is divided into different tools, each being self-contained, we thought we could introduce Melange to build one tool, then another tool, gradually migrating them one by&nbsp;one.</p><p>However, this approach turned out to be too complex because configuring a development environment that works on both Melange and ReScript is challenging. As developers could be working on multiple tools during the same week, or even within the same day, we realized that it was unfeasible to reconfigure the environment every time a developer switched from a tool built with Melange to a tool built with ReScript.</p><p>Therefore, we changed our minds and opted for a one-shot migration. We would ensure that CI, development, and staging environments were working with Melange and Dune. And we would do this on separate branches, while still using ReScript on our main branch CI and development scripts. Once we were confident everything was building and functioning correctly with Melange, we switched all CI and development scripts to use the Melange and Dune commands. We tried to keep the PR that applied this switch as small as possible, with just a few hundreds of lines of changes so that we could switch back to ReScript if needed. In fact, after a first attempt in March, we had to switch back to ReScript due to some issues on the developer experience side, related to build performance and ergonomics, which took a few more weeks to&nbsp;solve.</p><p>In terms of package management and third-party Melange dependencies, we followed a more gradual approach. Dune is quite flexible when it comes to <a href="https://dune.readthedocs.io/en/stable/dune-files.html#vendored-dirs">vendoring</a>, so in the initial phase, we downloaded Melange libraries with npm, and had Dune include them in the project as if they were local sources. Now we have started migrating some of these libraries so that we can consume them using opam, the OCaml package manager. This will involve first publishing them in our private opam mirror, but the plan is to have them published in the <a href="https://ocaml.org/packages">public opam repository</a> in the future so that other Melange developers can also use&nbsp;them.</p><h4>Timings</h4><p>You may be curious about the performance differences between the previous and current approaches. Measuring performance is tricky, but we attempted to measure a few different scenarios with both setups. The results can be seen&nbsp;below.</p><p>Keep in mind that Ahrefs frontend setup has specific characteristics, which affect the performance measurements:</p><ul><li>Before migration: Dune generated ml files from atd files, then ReScript build tool bsb built all hand-written source files plus the ones generated from atd&nbsp;files.</li><li>After migration: everything is built with Dune and&nbsp;Melange.</li></ul><p>All measurements were taken on a node with 2x AMD EPYC 7742 cpu @3.2 GHz (nproc=256), 1TB RAM, Debian 11 x86_64 GNU/Linux. The build target is always the entire Ahrefs frontend codebase.</p><p><strong>Cold build:</strong></p><ul><li>Before: real 0m28.232s, user 9m23.883s, sys 13m33.939s</li><li>After: real 1m14.208s, user 10m33.708s, sys 5m45.644s</li></ul><p><strong>Warm build</strong>, noop (no file is&nbsp;built):</p><ul><li>Before: real 0m14.687s, user 3m17.058s, sys 3m57.903s</li><li>After: real 0m21.895s, user 0m20.528s, sys&nbsp;0m1.372s</li></ul><p><strong>Watch mode, modifying an &ldquo;edge&rdquo; file</strong> with almost no reverse dependencies:</p><ul><li>Before: 1002ms</li><li>After: 1576ms</li></ul><p><strong>Watch mode, modifying an &ldquo;inner&rdquo; file</strong> belonging to a library, with many reverse dependencies:</p><ul><li>Before: 7032ms</li><li>After: 15394ms</li></ul><p>In general, Melange and Dune are slower than ReScript for cold builds in our setup. However, the differences are smaller for warm builds. For watch mode, the difference gets reduced when modifying edge&nbsp;files.</p><p>There is room for improvement in the way the Melange and Dune rules are arranged so that cold builds can get faster. For example, delaying some <a href="https://github.com/melange-re/melange/issues/464">optimizations in Melange</a> might allow to parallelize more&nbsp;work.</p><h4>Conclusions</h4><p>The results so far are quite encouraging. These are some of the things that are possible thanks to the deeper integration between Dune and Melange, and its application within the Ahrefs codebase:</p><ul><li>The same OCaml compiler is used on both frontend and backend codebases.</li><li>Access to all the bug fixes, error improvements, and new features that the OCaml compiler team added between versions 4.06 and 4.14 of the compiler.</li><li>A shared developer environment across teams, including editor extensions, OCaml LSP server, etc. No more need to maintain a different set of tooling for backend and frontend.</li><li>Removal of hand-written CI checks that were ensuring different tools in the frontend codebase would not access components from other tools. This is now solved by Dune libraries, and the OCaml compiler will complain if logical units try to reach outside their&nbsp;bounds.</li><li>Frontend and backend shared dependencies, such as <a href="https://github.com/anuragsoni/routes/">anuragsoni/routes</a>, can now be defined in a single place: an opam&nbsp;file.</li><li>Faster rebuilds and better watch mode, as Dune now controls all the build artifacts. Previously, Dune and ReScript were sharing responsibilities, which was leading to unnecessary rebuilds of some artifacts. Or alternatively, rebuilds were not starting when required due to the build system not tracking changes in some subsets of the&nbsp;sources.</li><li>Easier <a href="https://ocaml.org/docs/metaprogramming">PPX</a> maintenance, as there is no longer a need to publish pre-built versions of these&nbsp;tools.</li><li>Melange allows to run all ppxs <a href="https://github.com/melange-re/melange/pull/171">from a single executable file</a>, which has some nice performance benefits.</li><li>All the other advantages of using Dune: virtual libraries, watch mode, leverage integrations with tools like&nbsp;odoc&hellip;</li></ul><h4>What&rsquo;s next?</h4><p>We are excited about this project becoming a reality, and we believe that the deeper integration between OCaml and Melange through Dune, together with Melange&rsquo;s ergonomic integration with the JavaScript ecosystem through its bindings, can enable projects that were previously impossible to imagine. For example, full-stack React by hydrating components that are rendered <a href="https://github.com/ml-in-barcelona/server-reason-react/">server-side using native&nbsp;OCaml</a>.</p><p>Now, we have to make it easier for other people who are willing to try and use Melange and Dune. So our focus is shifting to documenting how Melange&nbsp;works.</p><p>There is a section for Melange in the Dune manual that will be included in the next stable release, and that can be consulted today in the latest branch: <a href="https://dune.readthedocs.io/en/latest/melange.html">https://dune.readthedocs.io/en/latest/melange.html</a>.</p><p>The next step will be to design and create a site where everyone can read and learn about what is needed to create and maintain a project using Melange and Dune. This site will include a playground, in the spirit of the <a href="https://reasonml.github.io/en/try">ReasonML one</a>, so that we can share snippets, see the resulting JavaScript compilation output, and iterate on ideas together.</p><p>Besides the above, we have plenty of other things we will be working on in the next months. We will share more information about the roadmap as soon as Dune 3.8 and its respective Melange version are published in the main public opam repository, which should happen in the next&nbsp;weeks.</p><h4>How to contribute?</h4><p>If you want to be a part of this, or you want to write or port your libraries to Melange, the best way to do so is by reaching out on the <a href="https://discord.gg/reasonml">ReasonML Discord</a>. There is a #melange dedicated channel where one can get help and advice on how to get&nbsp;started.</p><p>Otherwise, if you are missing features, find bugs, or run into confusing errors, please open an issue <a href="https://github.com/melange-re/melange">in the Melange public&nbsp;repo</a>.</p><p>We hope you share our excitement about this update. Our journey to integrate our frontend stack more naturally within the incredible language and ecosystem of OCaml will be well-documented. Stay tuned for further updates in the&nbsp;future!</p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=b14f5ec56df4" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/ahrefs-is-now-built-with-melange-b14f5ec56df4">Ahrefs is now built with Melange</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/ahrefs-is-now-built-with-melange-b14f5ec56df4?source=rss----303662d88bae--ocamlAhrefs is now built with Melange2023-05-03T19:06:58-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<h3>Intro</h3><p>There has never been a better time to learn OCaml, one of the premier statically-typed functional programming languages used in industry. We at Ahrefs have used it on our backend since the early days of the company, and <a href="https://tech.ahrefs.com/one-and-a-half-years-of-reasonml-in-production-2250cf5ba63b">since 2018 have even used it extensively for our frontend code</a>. Today we&rsquo;re very excited to share with you our favorite recommendations for getting started with&nbsp;OCaml!</p><h3>Best resources for learning&nbsp;OCaml</h3><p>If you have little functional programming experience or are even a beginner to programming, the place to start is <a href="https://ocaml-book.com/">OCaml from the Very Beginning</a>, a book that is now free thanks to generous funding from the <a href="https://ocaml-sf.org/">OCaml Software Foundation</a> (which Ahrefs is a sponsor of). The book can be viewed directly from its website and can also be downloaded as a PDF. While advertised as being approachable even to new programmers, this doesn&rsquo;t quite seem to be true, at least based on feedback we&rsquo;ve received. The text itself introduces concepts in a structured way, but the exercises require a little background in programming to complete. Such background info can be obtained by watching the opening videos in <a href="https://www.youtube.com/playlist?list=PLre5AT9JnKShBOPeuiD9b-I4XROIJhkIU">this series of lectures</a> from Cornell&rsquo;s OCaml programming course. Speaking of the Cornell course, their official online textbook <a href="https://cs3110.github.io/textbook/cover.html">OCaml Programming: Correct + Efficient + Beautiful</a> is an excellent resource for learners with some programming experience under their belt (specifically, you should have written some code using a mainstream imperative language like Python or&nbsp;Java).</p><h3>How to install&nbsp;OCaml</h3><p>The <a href="https://ocaml.org/docs/up-and-running">official installation instructions</a> are entirely adequate. It shows you how to install the compiler and some useful dev tools like dune (build system), utop (interactive read-eval-print loop), and ocaml-lsp-server (useful for editor integration).</p><p>Actually, if you are working through <a href="https://ocaml-book.com/">OCaml from the Very Beginning</a>, you do not need to install OCaml during the first several chapters, as you can execute code snippets directly on the <a href="https://try.ocamlpro.com/">Try OCaml</a> page, or create a notebook at <a href="https://sketch.sh/">Sketch.sh</a>, an interactive OCaml notebook site maintained by Ahrefs through our monthly Open Source Friday&nbsp;program.</p><h3>Editor support</h3><p>For most beginners to the language, we recommend the <a href="https://marketplace.visualstudio.com/items?itemName=ocamllabs.ocaml-platform">official OCaml Platform Visual Studio Code extension</a>. The official OCaml installation guide has a <a href="https://ocaml.org/docs/up-and-running#editor-support-for-ocaml">good section on setting it up</a>. There is also great support for users of <a href="https://github.com/ocaml/tuareg">emacs</a> and&nbsp;<a href="https://github.com/ocaml/vim-ocaml">vim</a>.</p><h3>Tips</h3><p>Even early on, it&rsquo;s a good idea to start saving your code into&nbsp;.ml files and learning how to run it. The easiest way to run a simple program is to start up utop and inside of it run #use &quot;name_of_your_program.ml&quot; as <a href="https://ocaml.org/docs/first-hour#running-ocaml-programs">described here</a>.</p><p>When creating a new notebook in <a href="https://sketch.sh/">Sketch.sh</a>, the default syntax is ReasonML (it&rsquo;s not a different language, just <a href="https://en.wikipedia.org/wiki/Reason_(programming_language)">an alternate syntax that more resembles JavaScript</a>). Click on ML in the top left corner to switch to the original OCaml&nbsp;syntax.</p><figure><img src="https://cdn-images-1.medium.com/max/1024/0*EgPCQlLR4C54N3Ge" alt=""/></figure><h3>Conclusion</h3><p>OCaml originated from French academia more than 25 years ago, and from there spread to elite universities and forward-thinking companies around the world. Now the OCaml community has produced high quality learning material that is both free and easy to access. So take the initiative and learn you some&nbsp;OCaml!</p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=2f22b578b984" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/how-to-get-started-with-ocaml-in-2022-2f22b578b984">How to get started with OCaml in 2022</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/how-to-get-started-with-ocaml-in-2022-2f22b578b984?source=rss----303662d88bae--ocamlHow to get started with OCaml in 20222022-10-31T16:13:10-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<h3>Monorobot: a notification bot for monorepos</h3><figure><img src="https://cdn-images-1.medium.com/max/1024/1*BQNCNLNPxGV3eXajYe6y2g.png" alt=""/><figcaption>Monorobot enables configurable directory tree notifications for your monorepo.</figcaption></figure><p>A few years ago, we decided to move most of our code into a monorepo. Many <a href="https://danluu.com/monorepo/">advocates</a> have highlighted its upsides, which include better cross-project coordination and simpler dependency management.</p><p>But one problem remained: <strong>none of the available GitHub integrations for Slack work nicely with monorepos</strong>. Slack is vital for day to day communication among Ahrefs&rsquo; globally distributed team, so a Slack integration was a must-have feature. We needed a service that could map activity from our various subprojects to their corresponding Slack channels&#8202;&mdash;&#8202;something existing solutions didn&rsquo;t&nbsp;offer.</p><p>That&rsquo;s why we built our own integration: <strong>Monorobot</strong>, a notification bot for monorepos. We&rsquo;ve improved it iteratively since the monorepo transition, incorporating real time feedback from our engineers over time. Today, Monorobot is an active member of Ahrefs&rsquo; Slack workspace, dutifully routing GitHub activity notifications to different channels based on the relevance of each activity.</p><p>And now we&rsquo;re <a href="https://github.com/ahrefs/monorobot">open-sourcing Monorobot</a>, for anybody to use in their monorepo setup! The package is available via&nbsp;<a href="https://opam.ocaml.org/packages/monorobot/">OPAM</a>:</p><pre>opam install monorobot</pre><p>Read on for more details about the motivation, an overview of the main features, and what&rsquo;s in the pipeline.</p><h3>Existing Slack integrations lack monorepo&nbsp;support</h3><p>Within a monorepo, multiple projects have their code located in separate, nested directories. Correspondingly, each project&rsquo;s Slack channel is only interested in activity from that part of the overall repository. The issue with most GitHub-to-Slack integrations is that once you subscribe a Slack channel to a GitHub repository, the channel receives <em>all</em> activity from that repository.</p><p>Suppose we operate various camel-related services, and we&rsquo;re planning to launch a new camel ride-sharing app called Camel Ride. The directory structure could look like&nbsp;this:</p><pre>monorepo/<br/>| frontend/<br/>| | camelride_ui/<br/>| | | mobile/<br/>| | | web/<br/>| | cameldance/<br/>| backend/<br/>| | camelride/<br/>| | | routing/<br/>| | | pricing/<br/>| | camelfood/</pre><p>As you can see, both the frontend/ and backend/ directories contain code for our fictitious ride-sharing service, along with code from other projects.</p><p>If we were to connect the <a href="https://slack.com/help/articles/232289568-GitHub-for-Slack">GitHub for Slack</a> integration to this repository, notifications for activity from all projects would be sent to the same channel. Even if I were only interested in activity from the Camel Ride project, I&rsquo;d need to sift through notifications from the other, unrelated projects. Imagine the volume of notifications this would create for a larger monorepo with dozens of projects. What a&nbsp;mess!</p><h3>Enter Monorobot</h3><figure><img src="https://cdn-images-1.medium.com/max/1024/1*ZHkBDdpNcMMw29BmHirM_A.png" alt=""/><figcaption>Monorobot, hard at&nbsp;work.</figcaption></figure><p>Monorobot enables more granular control over where notifications from the same repository get routed, depending on the type of activity. This routing behavior can be defined in a configuration file named&nbsp;.monorobot.json, which should be committed to the root of the monorepo. Once you create a <a href="https://docs.github.com/en/developers/webhooks-and-events/webhooks/about-webhooks">GitHub webhook</a> from the repository to a running instance of Monorobot, it will use the configuration file to route notifications to relevant channels based on the webhook event&nbsp;payload:</p><ul><li>For pushed commits, it checks the path prefixes of the files modified in the&nbsp;commits.</li><li>For activity related to PRs and issues, it checks their&nbsp;labels.</li><li>For status updates on pushed commits (e.g., CI builds), it uses the same path prefix logic as pushed&nbsp;commits.</li></ul><p>Additionally, Monorobot supports unfurling GitHub links shared in&nbsp;Slack.</p><h4>Path prefix routing for commit push notifications</h4><p>Continuing with our example, suppose we want to route all commit activity related to the Camel Ride project to a Slack channel called <em>#camelride</em>. Our configuration file might look like&nbsp;this:</p><pre>{<br/> ...,<br/> &quot;prefix_rules&quot;: {<br/> &quot;rules&quot;: [<br/> {<br/> &quot;match&quot;: [<br/> &quot;frontend/camelride_ui/&quot;,<br/> &quot;backend/camelride/&quot;<br/> ],<br/> &quot;ignore&quot;: [<br/> &quot;frontend/camelride_ui/images&quot;,<br/> ],<br/> &quot;channel&quot;: &quot;camelride&quot;<br/> }<br/> ]<br/> }<br/>}</pre><p>Each rule &ldquo;matches&rdquo; a file path to a channel. Whenever someone pushes a commit touching files with either of these prefixes, the <em>#camelride</em> channel will be notified. All other commits will be&nbsp;ignored.</p><p>If a file prefix appears in a rule&rsquo;s optional ignore field, the rule won't be matched even if the prefix is is also in the match field. In the above snippet, the Camel Ride frontend team has decided to silence notifications for activity in the images/ subdirectory.</p><p>Now, let&rsquo;s say the project&rsquo;s price optimization team is growing, and they&rsquo;ve decided to create their own separate Slack channel called <em>#camelride-pricing</em>. We can simply commit an update to the&nbsp;.monorobot.json file, and Monorobot will detect the configuration change:</p><pre>{<br/> ...,<br/> &quot;prefix_rules&quot;: {<br/> &quot;rules&quot;: [<br/> {<br/> &quot;match&quot;: [<br/> &quot;frontend/camelride_ui/&quot;,<br/> &quot;backend/camelride/&quot;<br/> ],<br/> &quot;ignore&quot;: [<br/> &quot;frontend/camelride_ui/images&quot;,<br/> ],<br/> &quot;channel&quot;: &quot;camelride&quot;<br/> },<br/> {<br/> &quot;match&quot;: [<br/> &quot;backend/camelride/pricing/&quot;<br/> ],<br/> &quot;channel&quot;: &quot;camelride-pricing&quot;<br/> }<br/> ]<br/> }<br/>}</pre><p>Since Monorobot will match the rule with the longest matched prefix, only commits related to the price optimization aspect of Camel Ride will notify <em>#camelride-pricing</em>, and all other general Camel Ride commits will notify <em>#camelride</em>.</p><p>There are additional configuration options for prefix rules (and for label rules discussed in the next section) that aren&rsquo;t mentioned here. Visit the <a href="https://github.com/ahrefs/monorobot">repository</a> for the full&nbsp;details.</p><h4>Label-based routing for PRs and issue notifications</h4><p>For activity related to pull requests and issues (opening, closing, merging, commenting, and reviewing), Monorobot uses labels to determine routing. The format is largely the same as for path prefix&nbsp;routing:</p><pre>{<br/> ...,<br/> &quot;label_rules&quot;: {<br/> &quot;default_channel&quot;: &quot;notifications&quot;,<br/> &quot;rules&quot;: [<br/> {<br/> &quot;match&quot;: [<br/> &quot;Camel Ride&quot;<br/> ],<br/> &quot;channel&quot;: &quot;camelride&quot;<br/> },<br/> {<br/> &quot;match&quot;: [<br/> &quot;Price Optimization&quot;<br/> ],<br/> &quot;channel&quot;: &quot;camelride-pricing&quot;<br/> }<br/> ]<br/> }<br/>}</pre><p>Here, all PRs and issues with the &ldquo;Camel Ride&rdquo; label will have activity sent to <em>#camelride</em>; those with the &ldquo;Price Optimization&rdquo; label to <em>#camelride-pricing</em>; and those with both labels to both channels.</p><p>The default_channel field provides an option to fall back on a channel if no rule is matched; this option is available for prefix rules as&nbsp;well.</p><h4>Status notifications</h4><p>Monorobot also supports build status notifications for CI pipelines. When it receives a status update for a pushed commit, it routes it to the relevant channel(s) by applying the prefix rules to the commit associated with the build. Further filtering based on status (e.g., ignoring canceled builds, and only notifying for a successful build when preceded by a failed one) is also possible.</p><h4>Link unfurling</h4><p>Finally, Monorobot can unfurl links to GitHub repositories shared on Slack (including private ones, if a personal access token is provided). This applies to commit, issue, and pull request&nbsp;URLs.</p><h3>What&rsquo;s next</h3><p>Monorobot is actively used at Ahrefs today, but there are lots of promising future directions it could take. Here, we list a&nbsp;few.</p><h4>Unifying GitHub and Slack identities</h4><p>It would be useful to allow GitHub user IDs to be mapped to Slack ones. This would enable more personalized features for Monorobot, such as direct messaging a user when their review is requested or when a CI build fails on a feature branch they authored.</p><h4>Consolidating notifications</h4><p>Sometimes, a collection of multiple GitHub webhook events makes sense to be grouped and delivered as a single Slack notification. For example, pull request reviews generate discrete webhook events for each review comment, but it would make more sense to pool them together, so as not to spam a channel with many notifications.</p><h4>Better status notifications</h4><p>A CI build failure can have multiple potential causes:</p><ol><li>A bad&nbsp;commit</li><li>A previous bad commit that has yet to be&nbsp;fixed</li><li>An issue with the pipeline itself (this is out of scope for Monorobot)</li></ol><p>It can be quite tricky to discern between the first two causes from the GitHub webhook event alone. Cause 1 is handled well by our current approach of using path prefix routing on the commit associated with the build. But with cause 2, that same approach doesn&rsquo;t always send the build failure notification to the channel where it is actually relevant. In that case, the originator of the initial bad commit won&rsquo;t be nagged about all subsequent failures, and Slack channels with no relevance to the cause of failure will get polluted with unnecessary notifications.</p><p>How can we best determine whether a status notification is &ldquo;relevant&rdquo; to a Slack channel? This is still an open question, but one possible direction is to track build state per <em>build step</em> rather than per <em>status</em>, and route notifications based on that. For example, if an overall build fails due to a backend build step failure, then it could be sent to a channel where the frontend team won&rsquo;t be notified.</p><h3>Wrapping up</h3><p>The overall goal of Monorobot is to make Slack notifications more <em>relevant</em> for all teams in a large <em>monorepo environment</em>, using the information available from GitHub webhook events. We&rsquo;ve had fairly positive results with our own internal usage, and now we hope others find it useful as&nbsp;well.</p><p>Monorobot is written in OCaml. <a href="https://github.com/ahrefs/monorobot">We welcome your feedback and contributions on&nbsp;GitHub!</a></p><p>P.S. If anyone does make an actual ride sharing service for camels, do let us&nbsp;know&hellip;</p><p><em>Thanks to Feihong, Igor, and Louis for feedback on this&nbsp;post.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=374260e2ca43" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/monorobot-a-slack-bot-for-monorepos-374260e2ca43">Monorobot: a Slack bot for monorepos</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/monorobot-a-slack-bot-for-monorepos-374260e2ca43?source=rss----303662d88bae--ocamlMonorobot: a Slack bot for monorepos2021-12-09T15:19:04-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<figure><img src="https://cdn-images-1.medium.com/max/1024/1*tYLUO4FDmJ6bzlsPp14LdQ.jpeg" alt=""/><figcaption>Photo by <a href="https://unsplash.com/@madebyjens?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Jens Lelie</a> on&nbsp;<a href="https://unsplash.com/s/photos/fork-road?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></figcaption></figure><p>At Ahrefs, we have been using BuckleScript and ReasonML in production <a href="https://tech.ahrefs.com/one-and-a-half-years-of-reasonml-in-production-2250cf5ba63b">for more than two years</a>. We already have a codebase of tens of thousands of lines of code, with several web applications that are data intensive and communicate with backend services written in <a href="http://ocaml.org/">OCaml</a>, using tools like&nbsp;<a href="https://github.com/ahrefs/atd">atd</a>.</p><p>Given our investment in these technologies, we have been following closely the recent changes in <a href="https://rescript-lang.org/">ReScript</a>, with its rebrand and renaming, and the split with the ReasonML project, explained in the project <a href="https://rescript-lang.org/blog/bucklescript-is-rebranding">blog&nbsp;post</a>.</p><h3>ReScript: becoming its own&nbsp;language</h3><p>We are excited about the way ReScript is unifying the experience and making it easier for developers who are getting started to find documentation in a single place, as well as continuing its strong focus on performance and readable JavaScript output.</p><p>On the other hand, we are trying to figure out the implications of this change in the mid- and long-term, especially regarding the integration with the OCaml ecosystem. And more importantly, what this evolution will mean for production users like us who rely on this integration.</p><p>ReScript integration with OCaml has historically been seamless, as BuckleScript started originally as a <a href="https://www.reddit.com/r/ocaml/comments/4enok3/bloombergbucklescript_a_back_end_for_the_ocaml/">new backend for the OCaml compiler</a>. However, in recent months, there have been several hints that ReScript wants to evolve towards becoming its own language:</p><ul><li>It has now <a href="https://github.com/rescript-lang/syntax">its own parser</a>, incompatible with OCaml native applications</li><li>Official repository guidelines for technical writing mentions explicitly that <a href="https://github.com/rescript-association/rescript-lang.org/blob/master/CONTRIBUTING.md#technical-writing-documentation">no reference to OCaml</a> should appear in&nbsp;docs</li><li>Upgrades to the latest version of OCaml compiler, which <a href="https://web.archive.org/web/20210208054855if_/https://github.com/rescript-lang/rescript-compiler/wiki">used to be part of the roadmap</a>, have been <a href="https://forum.rescript-lang.org/t/some-thoughts-on-community-building/1474">deprioritized</a> recently.</li></ul><p>So, even if officially ReScript has not announced that they will break backwards compatibility with OCaml, just the fact that it is sticking with an old version of the OCaml compiler poses some challenges for us in terms of tooling. The uncertainty about the future and the pace of changes add some risk to the high-level goals we have for our teams and codebase: we would like to share <em>more</em> code between frontend and backend, not&nbsp;less.</p><h3>Melange: a fork of ReScript, focused on OCaml compatibility</h3><p>When Ant&oacute;nio Monteiro <a href="https://anmonteiro.com/2021/03/on-ocaml-and-the-js-platform/">announced Melange</a>, a fork of ReScript but with a strong focus on keeping compatibility with OCaml, we decided to try it out and see how it could work for&nbsp;us.</p><p>Ultimately, the experiment was successful. We managed to build all our frontend applications with Melange, while keeping the existing bundling setup, which currently uses&nbsp;Webpack.</p><p>Throughout this process, we had to modify some parts of the code. We will now go through the most relevant parts of the&nbsp;process:</p><ul><li>Upgrade to OCaml 4.12: the most relevant part was the deprecation of Pervasives module to use&nbsp;Stdlib.</li><li>Use ppxlib in our ppxs: we had to upgrade the two ppxs that we use in the frontend codebase to the latest compiler version, <a href="https://github.com/ahrefs/bs-emotion/compare/master...jchavarri:ocaml4.12-ppxlib">bs-emotion-ppx</a> and an in-house <a href="https://github.com/ahrefs/bs-react-intl-ppx">ppx for internationalization</a>.</li><li>Configure esy: we were already using esy to bring the editor tooling into scope of the developer environment, so we just had to make sure melange would also be included in the json configuration.</li><li>Upgrade to Reason 3.7.0: a quite simple change too, as the whole process is automated by using refmt. As a side note, we ran into <a href="https://github.com/reasonml/reason/issues/2636">a small bug</a> with some type annotations, that we were able to work&nbsp;around.</li><li>&ldquo;Lift&rdquo; dune workspace to the root of our monorepo: this is probably the most intrusive change. Because we have shared code between backend and frontend, and Dune needs to have access to all sources under its workspace, we had to &ldquo;lift&rdquo; the Dune workspace from the backend directory to the root of monorepo.</li></ul><h3>The good</h3><p>This experiment allowed us to experience what a project like Melange could offer for our use case. Here are some of the things we might be able to leverage in a codebase built with&nbsp;Melange:</p><ul><li>Recent version of the OCaml compiler: at some point, we could pin compiler version between backend and frontend teams, making upgrades more straightforward as they would happen atomically.</li><li>Shared editor tooling: the official OCaml <a href="https://github.com/ocamllabs/vscode-ocaml-platform">vscode extension</a> works great with Melange, as well as any other OCaml editor integration. Having backend and frontend teams use similar editor setup removes a lot of maintenance work for&nbsp;us.</li><li>Consuming ppxs from source: Melange allows to consume ppxs from source, which also removes issues with pre-compiled ppxs (like this issue with the recent <a href="https://github.com/ahrefs/bs-emotion/issues/53">M1&nbsp;Macs</a>).</li><li>Melange allows to run all ppxs <a href="https://github.com/melange-re/melange/pull/171">from a single executable file</a>, which has some nice performance benefits.</li><li>Use Dune for atd files generators: ReScript &ldquo;generators&rdquo; are unfortunately <a href="https://web.archive.org/web/20200710044513if_/https://reasonml.org/docs/reason-compiler/latest/build-advanced">not documented anymore</a>, but we use them extensively for atd file generation. Being able to share Dune rules in backend and frontend would make our build setup&nbsp;easier.</li><li>Access to OCaml documentation tooling: Melange allows to leverage existing tooling for generating documentation, like&nbsp;<a href="https://github.com/ocaml/odoc/">odoc</a>.</li><li>Async syntax: the latest Reason version <a href="https://github.com/reasonml/reason/pull/2487">supports &ldquo;let op&rdquo; syntax</a>, which is handy for client-side code.</li></ul><h3>The bad</h3><p>While there are many things that are exciting about Melange, there are some other parts that can be improved.</p><ul><li>Build performance: We already knew that performance would be far worse than ReScript, as Melange uses Dune in a way that it was not designed for. In our tests, builds with Melange are roughly 1 order of magnitude slower than ReScript&nbsp;ones.</li><li>First-class Dune support: if there was a deeper integration between Dune and Melange, we could explore features like shared libraries or shared rules between backend and frontend. As of today, Dune has no knowledge about Melange environment, so it can perform basic rules execution, but there is no access to high level stanzas like library in&nbsp;Melange.</li><li>Two-headed goal: finally, we see a more strategic risk in Melange proposition. Right now it has two goals: keep compatibility with both ReScript and OCaml. But we don&rsquo;t know how long these goals will be feasible. If at some point ReScript decides to move away from the OCaml compiler fully, then Melange users would not be able to consume any updates to the ReScript ecosystem anymore.</li></ul><h3>Alright, but are you migrating to Melange or ReScript?</h3><p>With all the information available, the answer is: we don&rsquo;t know yet. &#128516; We want to keep exploring all the available options and have as much information as possible before committing further. So for now, we are upgrading the codebase to recent versions of ReScript, but we are holding up on features that only work one way. For example, we have not migrated our codebase to the ReScript syntax yet, as <a href="https://github.com/rescript-lang/syntax/issues/405">there is no way to translate back to Reason&nbsp;syntax</a>.</p><p>In the meantime, we will keep exploring how far the limitations of Melange can be mitigated. To be continued! &#128640;</p><p><em>Thanks to Igor and Feihong for reviewing and improving earlier versions of this&nbsp;post.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=9f881f6d022b" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/building-ahrefs-codebase-with-melange-9f881f6d022b">Building Ahrefs codebase with Melange</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/building-ahrefs-codebase-with-melange-9f881f6d022b?source=rss----303662d88bae--ocamlBuilding Ahrefs codebase with Melange2021-05-18T15:24:20-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<figure><img src="https://cdn-images-1.medium.com/max/1024/1*Nl5vYk_k-mC4j32XEjryHQ.jpeg" alt=""/><figcaption>Photo by <a href="https://unsplash.com/@willianjusten">https://unsplash.com/@willianjusten</a></figcaption></figure><p>The first <a href="https://reasonml.org/">Reason</a> application at <a href="https://ahrefs.com">Ahrefs</a> went online on January 31, 2019. Since then, many more applications have been either rewritten in Reason, are being slowly migrated from React to ReasonReact, or are conceived from the start as Reason projects. It is safe to say that the bet placed on Reason paid off big time. We will never go back to doing pure JavaScript again, with the possible exception of simple backend&nbsp;scripts.</p><p>In the past few years, it&rsquo;s come to light that there are a number of other <a href="https://www.messenger.com/">large</a> <a href="https://www.onegraph.com/">Reason</a>/<a href="https://darklang.com/">BuckleScript</a> <a href="https://onivim.io/">codebases</a> in the wild, but there still isn&rsquo;t a ton of information out there about what it&rsquo;s really like to work with Reason in production. To help remedy that, we thought it would be instructive to ask each of our frontend team members what their Reason journey has been like so&nbsp;far.</p><p>We gave them the following questions as starting points (but they were free to talk about anything they&nbsp;wanted):</p><ul><li>How does Reason compare to other languages you&rsquo;ve used in the&nbsp;past?</li><li>What&rsquo;s your favorite thing about&nbsp;Reason?</li><li>What&rsquo;s your least favorite thing about&nbsp;Reason?</li><li>How does ReasonReact compare to other frameworks you&rsquo;ve&nbsp;used?</li><li>Was it easy to pick up Reason? Why or why&nbsp;not?</li></ul><h4>Javi</h4><ul><li>How does Reason compare to other languages you&rsquo;ve used in the&nbsp;past?</li></ul><p>In the past I worked with languages like Java, C, or less known like Pascal or Prolog. But the languages I&rsquo;ve spent more time with are Objective-C and JavaScript. The main difference between all those languages and Reason is the exhaustiveness that you get from OCaml type checker. This is maybe awkward, but it feels like you stop coding alone and suddenly you have a sidekick always sitting next to you, that is helping you notice the things you forgot about, or found new code that is not consistent with code you or someone else wrote&nbsp;before.</p><p>In a world that is moving towards remote work, where many of us spend hours every day coding physically far from our colleagues, it makes the experience much more delightful. Plus, it allows for teams working on different time zones to keep a healthier work-life balance, because there is less need to have synchronous communication than with more dynamic languages, as more assumptions and design decisions are &ldquo;embedded&rdquo; into the&nbsp;code.</p><ul><li>What&rsquo;s your favorite thing about&nbsp;Reason?</li></ul><p>Can I pick two things? It&rsquo;s hard to choose only&nbsp;one.</p><p>The first one is the exhaustiveness and quality of the type checker, as mentioned above. Sometimes it takes a bit longer to build a feature than what it would in other languages, until the types are figured out. But this is largely compensated by the confidence one has when shipping code to production, or diving into large refactors.</p><p>The second one is the speed of the BuckleScript build system, which is built on top of <a href="https://ninja-build.org/">ninja</a>. I had never worked with such fast build system. As an example, we have recently started to use remote machines to develop at Ahrefs. In one of these machines that has 72 cores, BuckleScript takes roughly 3 seconds to clean build <em>all</em> our Reason code: application, libs, decoders&hellip; everything. Many tens of thousand lines of code! We thought there were something wrong, but we realized the compiler is just So Blazing&nbsp;Fast&trade;&#65039;.</p><ul><li>What&rsquo;s your least favorite thing about&nbsp;Reason?</li></ul><p>I guess we&rsquo;re going through a necessary stage until things stabilize in the future, but there is a lot of fragmentation at the moment between &ldquo;Reason native&rdquo;, which tries to stay closer to OCaml, and &ldquo;Reason web&rdquo;, which has a goal to become friendlier for JavaScript developers.</p><p>I am excited to see what <a href="https://reasonml.org/blog/bucklescript-8-1-new-syntax">BuckleScript new syntax</a> will lead to, but I would also love to see a &ldquo;universal&rdquo; solution that works for the main use cases out of the box, becoming sort of Rails for Ocaml or Reason. <a href="https://github.com/oxidizing/sihl/">sihl</a> is a project that seems to go in that direction and looks very promising.</p><ul><li>How does ReasonReact compare to other frameworks you&rsquo;ve&nbsp;used?</li></ul><p>I consider ReasonReact mostly like React + types on top, because the bindings layer is very thin. The thing that I like most about React is that it follows the Unix philosophy: it does one thing and it does it really well. Maybe we have forgotten already today, but having to maintain and mutate UI based on data updates was one of the main sources of bugs in the past. The other nice thing is that there is so much good content about it: blog posts, documentation, etc.</p><ul><li>Was it easy to pick up Reason? Why or why&nbsp;not?</li></ul><p>It took some time, as with any other language. We have things like syntax or semantics much more ingrained into our brains than we think, so there is always some &ldquo;rewiring&rdquo; time that is needed to learn a new language, even if Reason makes an effort to stay close to JavaScript syntax. The most challenging part was probably the bindings one, because coming from JavaScript, there are no previous knowledge that one can use as foundation to build upon, it&rsquo;s all &ldquo;new knowledge&rdquo;. glennsl <a href="https://github.com/glennsl/bucklescript-ffi-cheatsheet">BuckleScript ffi cheatsheet</a> was a huge help for&nbsp;me.</p><h4>Ze</h4><p>I really like working with Reason, and have wanted to do so for a while. I was quite happy to see that working with it matched my expectations.</p><p>You get so much support from the type system, and still have a lot of flexibility to represent your domain model. Coming from other languages or paradigms, you don&rsquo;t feel limited at all in what you can&nbsp;achieve.</p><p>The language has such a strong type system that you feel much more comfortable with your&nbsp;coding.</p><p>The OCaml type system is there to make sure you code with assurance. This is especially true when refactoring code. You can be sure that everything will work fine after it compiles. If it compiles, it works&nbsp;:)</p><p>It&rsquo;s also very helpful when working on a monorepo. You don&rsquo;t have to keep reading the source code of everything you use to make sure you don&rsquo;t have types mistakes. Changes in code in one lib reflect immediately in all the others. This makes the feedback loop much shorter and&nbsp;safer.</p><p>The editors integrations with the type system are quite good and help a lot to write code better and&nbsp;faster.</p><p>Also, compilation times are super&nbsp;fast.</p><p>Last, but not least, ReasonReact is, for me, the hidden gem of ReasonML. The newcomers that have some difficulty with the language should start with it. IMHO, ReasonReact is simpler and has a better developer experience than React itself. It should be the gateway drug frontend developers need to get started with Reason/OCaml &#128516;</p><h4>Liubomyr</h4><p>To me, all those language features boil down to one essential thing, and it&rsquo;s the easiness of refactoring. New business requirements popups all the time, and often your initial code assumptions are no longer correct. It was such a pain to modify code in a large JS codebase, as you never know how many things you potentially break in the process. With Reason, it has never been easier. If you need to change your data shape or some component API, you just do it, and from there, the compiler will guide you through all the places you broke, and help to fix&nbsp;those.</p><p>Coming from the JS world, it feels like the initial development is slower, because of the learning curve, missing bindings, less StackOverflow answers, but in the end, you are getting a stable software which is way easier to maintain and add features&nbsp;to.</p><h4>Egor</h4><p>I switched to Reason when I joined Ahrefs team about a year ago, before that I worked mostly with Ruby language.</p><p>The first thing that impressed me in ReasonML was code refactoring. Refactoring in language with a strong type system, like ReasonML and OCaml, is much easier than what I am used to. If your program compiles after your refactoring&#8202;&mdash;&#8202;most likely you did everything right, if it doesn&rsquo;t compile&#8202;&mdash;&#8202;you can immediately see what you forgot to change. This can be achieved in languages with a dynamic type system only with a huge amount of code tests (supporting big test suite is a time consuming process as well as code support).</p><p>The other thing that I really like about ReasonML codebase&#8202;&mdash;&#8202;how readable it is. When you just enter into ReasonML world&#8202;&mdash;&#8202;some things can be unfriendly from the first sight, for example, immutable let bindings, but in the end, you realize that these language decisions help you to write cleaner and simpler&nbsp;code.</p><h4>Seif</h4><p>The programming language I used the most in the past is JavaScript. I switched to Reason when I joined Ahrefs a few months ago. From the start, I worked mainly on the code shared by the majority of the tools and I don&rsquo;t think I would have had the same confidence making changes if I was doing it with JavaScript. I love JavaScript&rsquo;s developer experience and accessibility. Reason provided me predictability without hurting these very same things I like about JavaScript.</p><h4>Bryan</h4><p>Reason (and OCaml) is, by far, one of the easiest languages to work with. Easy in the sense that the compiler helps eliminate an entire class of errors so you don&rsquo;t have to worry about them. Additionally, in most other web-centric languages, it&rsquo;s a pain to add features to existing code that you&rsquo;ve not touched for a long time. With strong static typing, I can usually add the feature I want in either the backend or frontend, and then let the compiler tell me what needs to be&nbsp;updated.</p><p>Pattern-matching is one of my favourite features in Reason. To me, it makes more sense to be able to explicitly specify conditions that I&rsquo;m interested in a clear and concise manner, and let the compiler tell me if I missed out a particular condition. Records go hand-in-hand with this. As software programs are made up of data and instructions, records are the perfect data containers. They are quick to define and query, focusing on data rather than behaviour (think classes and instance methods).</p><p>It definitely took a while to pick up Reason mainly because it takes time to become familiar with idiomatic OCaml. But once I crested that learning curve, everything just made sense and all the features of the language that made Reason seemingly difficult to learn&#8202;&mdash;&#8202;strong typing, the functional paradigm, etc, became assistants that helped me to write better&nbsp;code.</p><h4>Feihong</h4><p><a href="https://reasonml.github.io/reason-react/en/">ReasonReact</a> is a great library for making complex UIs in a large codebase because you get the familiarity of React coupled with the type safety of OCaml. Having two well-established technologies in its foundation is a big advantage that ReasonReact has over other functional UI libraries/frameworks in the transpile-to-JS universe. I didn&rsquo;t have any professional OCaml experience before joining, yet the ramp up was made much easier by my existing knowledge of React and the (somewhat superficial) similarity of the Reason syntax to JS. Oftentimes it was possible to correctly guess the intent of existing Reason code without knowing all the syntax, because most React concepts carry over pretty directly. And even though the documentation is incomplete and not perfect, it&rsquo;s quite usable already and among conceptually-similar frameworks is second only to the Elm documentation.</p><p>The compiler errors were difficult to get used to at first. The compiler is fairly good at pointing out the location of the error, but not necessarily as good at explaining the nature or cause of the error. As such, having a REPL would be extremely useful. Actually, OCaml does have its own REPL, but BuckleScript (the compiler used by Reason to translate OCaml to JS) does not at the moment. Nonetheless, the <a href="https://reasonml.github.io/en/try">Try Reason</a> page is a really good tool to try out small snippets of code and is extremely useful while learning the language (we will still occasionally post Try Reason links in our slack channel).</p><h3>Summary</h3><p>The reality is that Ahrefs has always been an OCaml shop, but in the past OCaml was only used to build the backend. Now that we are also using it on the frontend, we get the benefits that our backend colleagues have enjoyed for many years: the expressiveness afforded by pattern matching, the ease of refactoring in large codebases, the stability of a mature programming language, and the confidence of &ldquo;if it compiles, it works&rdquo;. To make a shoddy nautical analogy, it is as if we had built a wooden ship powered by a turbo engine. But now the wooden parts are being replaced with steel and plastic, bringing the exterior of the ship up to modern standards as well. As a result, the ship runs faster and more reliably, making the passengers (our users) more satisfied. Also, pirates (bugs) have a harder time hijacking the ship because it&rsquo;s sturdier and defended by well-disciplined camels. Because the ship keeps getting more and more passengers who want to experience a delightful ride and take pictures with enigmatic camels, we require a constant influx of willing and able boat engineers (who aren&rsquo;t allergic to camels) to extend and maintain the ship. (Yes, that means that <a href="https://ahrefs.com/jobs">we are hiring</a>&#65039;.)</p><p><em>Thanks to Raman and Louis for fact checking this&nbsp;post.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=2250cf5ba63b" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/one-and-a-half-years-of-reasonml-in-production-2250cf5ba63b">One and a half years of ReasonML in production</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/one-and-a-half-years-of-reasonml-in-production-2250cf5ba63b?source=rss----303662d88bae--ocamlOne and a half years of ReasonML in production2020-07-26T15:19:31-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<p><em>Written with </em><a href="https://twitter.com/javierwchavarri"><em>Javier Ch&aacute;varri</em></a><em> and </em><a href="https://github.com/feihong/"><em>Feihong&nbsp;Hsu</em></a><em>.</em></p><p>The first <a href="https://www.reason-conf.us/">Reason Conf US</a> just ended. Many talks mentioned native compilation. Sharing code between BuckleScript and native artifacts is a use case which is more and more common. This blog post is an introduction on how to set up a library available for both worlds, sharing as much code as possible.</p><h3>The goal</h3><p>What we try to produce is a library with an identical interface for BuckleScript and native. But without duplicating code. It should also be possible to have some parts of the library that are a different implementation depending on the target, as we want to be able to leverage existing libraries that are working only in one of the&nbsp;worlds.</p><h3>The build&nbsp;systems</h3><p>For BuckleScript, there is only one build system: bsb. It is driven by a bsconfig.json file. And is installed as part of the bs-platform.</p><p>On the native side, there are a lot of different build systems that are available. But recently one of them became a de facto standard: dune. It works with a very minimal amount of configuration. And it supports the reason syntax by&nbsp;default.</p><p>These two tools are working in a way which is pretty similar. They share a lot of concepts. And it is easy to set them up so that both are working in the same codebase.</p><p>The main similarities that interest us&nbsp;are:</p><ul><li>The ability to work on specific source directories</li><li>Namespacing in bsb and wrapping in dune are both putting all the<br/>files of the library under a single module&nbsp;name</li></ul><h3>The source code file&nbsp;tree</h3><p>The code of the library is split into 3 directories.</p><pre>&#9500;&#9472;&#9472; js/<br/>&#9500;&#9472;&#9472; native/<br/>&#9492;&#9472;&#9472; shared/</pre><ul><li>shared is meant to host most of the code and all the code in this directory will be compiled in both&nbsp;modes.</li><li>js contains the parts that are specific to BuckleScript.</li><li>native contains the parts that are specific to native&nbsp;OCaml.</li></ul><h3>Set up the build&nbsp;systems</h3><p>Once we have our basic skeleton for the library, it is time to set up the build systems. We want to have two configurations as similar as possible to make them easier to understand. Once we are done, the tree will look like&nbsp;this:</p><pre>&#9500;&#9472;&#9472; bsconfig.json<br/>&#9500;&#9472;&#9472; dune<br/>&#9500;&#9472;&#9472; dune-project<br/>&#9500;&#9472;&#9472; js/<br/>&#9500;&#9472;&#9472; native/<br/>&#9492;&#9472;&#9472; shared/</pre><h4>BuckleScript</h4><p>At the root of the library we need a bsconfig.json file to drive<br/>bsb. The documentation is available at <a href="https://bucklescript.github.io/docs/en/build-configuration%5D(https://bucklescript.github.io/docs/en/build-configuration).">https://bucklescript.github.io/docs/en/build-configuration</a>.</p><p>The main part for us is sources. We will use it to tell bsb to look at the js and shared folders. We also want to set namespace to true, which will wrap all your project&rsquo;s files under a common module&nbsp;name.</p><pre> &quot;namespace&quot;: true,<br/> &quot;sources&quot;: [<br/> {<br/> &quot;dir&quot;: &quot;js&quot;,<br/> &quot;subdirs&quot;: true<br/> }, {<br/> &quot;dir&quot;: &quot;shared&quot;,<br/> &quot;subdirs&quot;: true<br/> }<br/> ],</pre><p>The rest of the file is as&nbsp;usual.</p><pre>{<br/> &quot;name&quot;: &quot;sharedlib&quot;,<br/> &quot;namespace&quot;: true,<br/> &quot;sources&quot;: [<br/> {<br/> &quot;dir&quot;: &quot;js&quot;,<br/> &quot;subdirs&quot;: true<br/> }, {<br/> &quot;dir&quot;: &quot;shared&quot;,<br/> &quot;subdirs&quot;: true<br/> }<br/> ],<br/> &quot;package-specs&quot;: {<br/> &quot;module&quot;: &quot;es6&quot;,<br/> &quot;in-source&quot;: true<br/> },<br/> &quot;refmt&quot;: 3,<br/> &quot;suffix&quot;: &quot;.bs.js&quot;,<br/> &quot;generate-merlin&quot;: true,<br/>}</pre><h4>Dune</h4><p>We must also add a dune file to the root of the library. For dune, we have different options&#8202;&mdash;&#8202;it is possible to ignore the js directory but read everything else. Or to check only shared and native. To make the configuration similar to BuckleScript, we will go with the second solution.</p><p>The dune directive to do that is dirs. By defaults it tells dune to explore every directory except the ones hidden (starting with a dot) or starting with an underscore. <a href="https://dune.readthedocs.io/en/stable/dune-files.html#dirs-since-1-6">More details in dune&rsquo;s documentation</a>. To make it do what we want, the configuration should&nbsp;be:</p><pre>(dirs shared native)</pre><p>We also use another option of dune to tell it to include the content of those two directories as if it was at the root of the project. Without this stanza, dune would only use the source files at the root of the project and ignore everything in the sub directories.</p><pre>(include_subdirs unqualified)</pre><p>Then we need the usual library stanza to give a name to our library, state the dependencies, compilation flags, etc. In our simple case, the only information needed is the name. We can explicitly set wrapped to true, but this is already the default behavior. The <a href="https://dune.readthedocs.io/en/stable/dune-files.html#library">documentation for the whole library stanza</a> describes how to specify more&nbsp;details.</p><p>The final dune file looks like&nbsp;this:</p><pre>(dirs shared native)<br/> (include_subdirs unqualified)<br/> (library<br/> (name sharedlib))</pre><p>We also want a basic dune-project. If we don&rsquo;t write it by hand, dune will generate it for us. I am using version 1.10 as an example. But it can be changed to whatever version suits your&nbsp;project.</p><pre>(lang dune 1.10)</pre><h3>Compilation</h3><p>With the setup described above, the compilation for BuckleScript and native is the same as in a setup with only one or the&nbsp;other.</p><ul><li>bsb -make-world for BuckleScript</li><li>dune build @all for&nbsp;dune</li></ul><p>The call to bsb is usally put in package.json in the scripts part, so that the usual yarn build can be used. For native, it depends if you rely on esy or&nbsp;opam.</p><h3>How to consume the&nbsp;library</h3><p>This is exactly the same setup that would be used in a pure BuckleScript or pure native&nbsp;library.</p><p>To use your library in BuckleScript:</p><ul><li>Add the name and version to package.json</li><li>Add the name to bsbconfig.json of consuming library/app</li></ul><p>To use your library in native OCaml, add the name of your library to the libraries part an executable or library stanza,&nbsp;e.g.</p><pre>(executable<br/> (name main)<br/> (libraries sharedlib))</pre><h3>Module naming</h3><p>If you want your module name to contain capital letters in the middle (e.g. TeenageMutantNinjaTurtles), then be aware that <a href="https://bucklescript.github.io/docs/en/build-configuration.html#name-namespace">name munging</a> works differently between bsbconfig.json and dune. For example, if you want to refer to your module as CoolSharedLib in your code, then the name in bsbconfig.json must be cool-shared-lib, and in dune it must be coolSharedLib.</p><h3>Platform specific&nbsp;code</h3><p>The whole library does not have to be exactly the same in the two platform. It is possible to add modules that are available only in one mode. Or to have modules with a different interface.</p><p>For example, by adding a file Foo.re in js but not in native, the library now has a module Foo available when compiled to javascript. But only when compiled to javascript.</p><h3>Downsides</h3><ul><li>Both bsb and dune generate&nbsp;.merlin files when they compile our library. They override each other. It might be troublesome if the version of ocaml used for native code is not 4.02.3. Simply recompile the library for your platform to solve the&nbsp;problem.</li><li>Out of the box, this approach doesn&rsquo;t really allow us to share interface files between both platforms: native and BuckleScript. One workaround for that, if we wanted to share some module Foo, is to:<br/>1. add Foo.mli or Foo.rei file in shared<br/>2. add include FooImplementation in Foo.ml<br/>3. add FooImplementation in both native and js&nbsp;folder</li><li>It&rsquo;s not possible to be platform specific for just a few lines of code (e.g. if IS_NATIVE foo else bar), the minimal per-platform unit is a file/module.</li></ul><h3>Example project</h3><p>We have set up a simple library to showcase what a repository looks like once the whole configuration is in place. It is <a href="https://github.com/ahrefs/hello-native-bucklescript">available on&nbsp;github</a>.</p><p>For now the repository contains only a library. But with this setup, it is actually possible to build an executable too. It is also possible to enrich it, for example by adding <a href="https://tech.ahrefs.com/getting-started-with-atdgen-and-bucklescript-1f3a14004081">atdgen to communicate between both sides of the&nbsp;library</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=22f45e5e946d" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/how-to-write-a-library-for-bucklescript-and-native-22f45e5e946d">How to write a library for BuckleScript and Native</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/how-to-write-a-library-for-bucklescript-and-native-22f45e5e946d?source=rss----303662d88bae--ocamlHow to write a library for BuckleScript and Native2019-10-22T10:09:09-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<p><a href="https://github.com/mjambon/atd">atdgen</a> is a project to create types and data structures that can be serialized to JSON. It is very convenient when communicating between multiple processes, creating a REST API or consuming JSON objects from other tools. It can be compared to <a href="https://json-schema.org/">JSON schema</a> or <a href="https://developers.google.com/protocol-buffers/">Protocol Buffers</a>, but with richer types and more features.</p><p>The idea is to write a list of types in a specification file, an&nbsp;.atd file. Then running atdgen, it is possible to generate OCaml or Java code to serialize/deserialize values of those types to/from corresponding json.</p><p>Until very recently, atdgen could generate code only for native OCaml. But <a href="https://github.com/mjambon/atd/pull/44">the support of bucklescript has been merged</a>! atdgen the cli tool is still a native OCaml binary. But it can output some OCaml code that can be compiled using <a href="https://bucklescript.github.io/">bucklescript</a>.</p><p>The work to implement this new feature of atdgen has been funded by <a href="https://ahrefs.com/">Ahrefs</a>. We highly appreciate open source tools. And as much as possible, we prefer to contribute to existing open source projects rather than to re-invent the wheel internally.</p><h3>Installation</h3><p>To install atdgen we first need to install <a href="https://opam.ocaml.org">opam</a> (OCaml package manager), as atdgen doesn&rsquo;t provide ready to use binaries and is only distributed as source package via opam. The procedure is simple and documented here: <a href="https://opam.ocaml.org/doc/2.0/Install.html">https://opam.ocaml.org/doc/2.0/Install.html</a></p><p>Then we need to initialize opam and create a switch. Any version of ocaml greater or equal to 4.03.0 should be&nbsp;fine.</p><pre>opam init -a<br/>opam switch create . 4.07.1 -y</pre><p>Once it is done, we have to install the development version of atdgen. The support of bucklescript is not officially released.</p><pre>opam pin add atd --dev-repo <br/>opam pin add atdgen --dev-repo</pre><p>Make sure that atdgen is available.</p><pre>$ which atdgen <br/>(current $PWD)/_opam/bin/atdgen</pre><p>Of course, we need bucklescript.</p><pre>yarn init <br/>yarn add bs-platform --dev</pre><p>We also need the bucklescript runtime for atdgen, as it is not currently provided by atdgen itself. So we have written and open-sourced our version of the runtime&nbsp;: <a href="https://github.com/ahrefs/bs-atdgen-codec-runtime">https://github.com/ahrefs/bs-atdgen-codec-runtime</a>.</p><p>This runtime is responsible for the conversion between JSON values and OCaml values. The JSON values are based on the standard <a href="https://bucklescript.github.io/bucklescript/api/Js.Json.html#TYPEt">Js.Json.t type</a> provided by bucklescript to be sure that it is easy to interoperate with the rest of the ecosystem.</p><p>It is published on npm for easy integration in bucklescript projects.</p><pre>yarn add @ahrefs/bs-atdgen-codec-runtime</pre><h3>Project configuration</h3><p>After the previous section, package.json should be almost ready. We can add a few scripts to make it more convenient to compile the project. Here is how it should look once completed.</p><pre>{<br/> &quot;name&quot;: &quot;demo-bs-atdgen&quot;,<br/> &quot;version&quot;: &quot;0.0.1&quot;,<br/> &quot;description&quot;: &quot;demo of atdgen with bucklescript&quot;,<br/> &quot;scripts&quot;: {<br/> &quot;clean&quot;: &quot;bsb -clean-world&quot;,<br/> &quot;build&quot;: &quot;bsb -make-world&quot;,<br/> &quot;watch&quot;: &quot;bsb -make-world -w&quot;,<br/> &quot;atdgen&quot;: &quot;atdgen -t meetup.atd &amp;&amp; atdgen -bs meetup.atd&quot;<br/> },<br/> &quot;devDependencies&quot;: {<br/> &quot;bs-platform&quot;: &quot;^4.0.5&quot;<br/> },<br/> &quot;peerDependencies&quot;: {<br/> &quot;bs-platform&quot;: &quot;^4.0.5&quot;<br/> },<br/> &quot;dependencies&quot;: {<br/> &quot;<a href="http://twitter.com/ahrefs/bs-atdgen-codec-runtime">@ahrefs/bs-atdgen-codec-runtime</a>&quot;: &quot;^1.0.4&quot;<br/> }<br/>}</pre><p>The bucklescript configuration is very simple. We use the basic configuration that can be found in any bucklescript project. Except that we need to add one dependency to bsconfig.json:</p><pre>{<br/> &quot;name&quot;: &quot;demo-bs-atdgen&quot;,<br/> &quot;version&quot;: &quot;0.0.1&quot;,<br/> &quot;sources&quot;: {<br/> &quot;dir&quot;: &quot;src&quot;,<br/> &quot;subdirs&quot;: true<br/> },<br/> &quot;package-specs&quot;: {<br/> &quot;module&quot;: &quot;commonjs&quot;,<br/> &quot;in-source&quot;: true<br/> },<br/> &quot;suffix&quot;: &quot;.bs.js&quot;,<br/> &quot;bs-dependencies&quot;: [<br/> &quot;<a href="http://twitter.com/ahrefs/bs-atdgen-codec-runtime">@ahrefs/bs-atdgen-codec-runtime</a>&quot;<br/> ],<br/> &quot;warnings&quot;: {<br/> &quot;error&quot;: &quot;+101&quot;<br/> },<br/> &quot;generate-merlin&quot;: true,<br/> &quot;namespace&quot;: true,<br/> &quot;refmt&quot;: 3<br/>}</pre><h3>First ATD definitions</h3><p>It is time to create a first&nbsp;.atd file, containing our types. This part is also documented on <a href="https://atd.readthedocs.io/en/latest/tutorial.html#getting-started">https://atd.readthedocs.io/en/latest/tutorial.html#getting-started</a></p><p>For this example, I decided to go with a meetup event. Put the type definitions in src/meetup.atd.</p><pre>(* This is a comment. Same syntax as in ocaml. *)</pre><pre>type access = [ Private | Public ]</pre><pre>(* the date will be a float in the json and a Js.Date.t in ocaml *)<br/>type date = float wrap &lt;ocaml module=&quot;Js.Date&quot; wrap=&quot;Js.Date.fromFloat&quot; unwrap=&quot;Js.Date.valueOf&quot;&gt;</pre><pre>(* Some people don't want to provide a phone number, make it optional *)<br/>type person = {<br/> name: string;<br/> email: string;<br/> ?phone: string nullable;<br/>}</pre><pre>type event = {<br/> access: access;<br/> name: string;<br/> host: person;<br/> date: date;<br/> guests: person list;<br/>}</pre><pre>type events = event list</pre><p>We use the atdgen binary (compiled previously) to generate the ocaml types and the code to serialize/deserialize those&nbsp;types.</p><pre>atdgen -t meetup.atd # generates an ocaml file containing the types<br/>atdgen -bs meetup.atd # generates the code to (de)serialize</pre><p>The generated files&nbsp;are:</p><ul><li>meetup_t.ml(i) which contain the ocaml types corresponding to our ATD definitions.</li><li>meetup_bs.ml(i) which contain the ocaml code to transform from and to json&nbsp;values.</li></ul><p>At this point we can compile our&nbsp;project.</p><pre>yarn build</pre><p>If everything worked properly, we now have two&nbsp;.bs.js files in the src directory.</p><pre>$ tree src<br/>src<br/>&#9500;&#9472;&#9472; meetup.atd<br/>&#9500;&#9472;&#9472; meetup_bs.bs.js<br/>&#9500;&#9472;&#9472; meetup_bs.ml<br/>&#9500;&#9472;&#9472; meetup_bs.mli<br/>&#9500;&#9472;&#9472; meetup_t.bs.js<br/>&#9500;&#9472;&#9472; meetup_t.ml<br/>&#9492;&#9472;&#9472; meetup_t.mli</pre><pre>0 directories, 7 files</pre><p>At this point, we can create new OCaml/Reason files in the src directory and use all the code atdgen generated for us. Two examples to illustrate that.</p><h3>Query a REST&nbsp;API</h3><p>A common usage of atdgen is to decode the JSON returned by a REST API. Here is a short example, using the reason syntax and bs-fetch.</p><pre>let get = (url, decode) =&gt;<br/> Js.Promise.(<br/> Fetch.fetchWithInit(<br/> url,<br/> Fetch.RequestInit.make(~method_=Get, ()),<br/> )<br/> |&gt; then_(Fetch.Response.json)<br/> |&gt; then_(json =&gt; json |&gt; decode |&gt; resolve)<br/> );</pre><pre>let v: Meetup_t.events =<br/> get(<br/> &quot;<a href="http://localhost:8000/events">http://localhost:8000/events</a>&quot;,<br/> Atdgen_codec_runtime.Decode.decode(Meetup_bs.read_events),<br/> );</pre><h3>Read and write a JSON&nbsp;file</h3><p>Atdgen for bucklescript doesn&rsquo;t take care of converting a string to a JSON object. Which allows us to use the performant json parser included in nodejs or the&nbsp;browser.</p><pre>let read_events filename =<br/> (* Read and parse the json file from disk, this doesn't involve atdgen. *)<br/> let json =<br/> Node_fs.readFileAsUtf8Sync filename<br/> |&gt; Js.Json.parseExn<br/> in<br/> (* Turn it into a proper record. The annotation is of course optional. *)<br/> let events: Meetup_t.events =<br/> Atdgen_codec_runtime.Decode.decode Meetup_bs.read_events json<br/> in<br/> events</pre><p>The reverse operation, converting a record to a JSON object and writing it in a file is also straightforward.</p><pre>let write_events filename events =<br/> Atdgen_codec_runtime.Encode.encode Meetup_bs.write_events events (* turn a list of records into json *)<br/> |. Js.Json.stringifyWithSpace 2 (* convert the json to a pretty string *)<br/> |&gt; Node_fs.writeFileAsUtf8Sync filename (* write the json in our file *)</pre><h3>Full example</h3><p>Now that we have our functions to read and write events, we can build a small cli to pretty print the list of events and add new&nbsp;events.</p><p>The source code of the full example is available <a href="https://github.com/ahrefs/bs-atdgen-codec-runtime/tree/master/example">on&nbsp;github</a>.</p><p>You can run it like&nbsp;this:</p><pre>$ echo &quot;[]&quot; &gt; events.json<br/>$ nodejs src/cli.bs.js add louis <a href="mailto:louis@nospam.com">louis@nospam.com</a><br/>$ nodejs src/cli.bs.js add bob <a href="mailto:bob@nospam.com">bob@nospam.com</a><br/>$ nodejs src/cli.bs.js print<br/>=== OCaml/Reason Meetup! summary ===<br/>date: Tue, 11 Sep 2018 15:04:16 GMT<br/>access: public<br/>host: bob &lt;<a href="mailto:bob@nospam.com">bob@nospam.com</a>&gt;<br/>guests: 1<br/>=== OCaml/Reason Meetup! summary ===<br/>date: Tue, 11 Sep 2018 15:04:13 GMT<br/>access: public<br/>host: louis &lt;<a href="mailto:louis@nospam.com">louis@nospam.com</a>&gt;<br/>guests: 1<br/>$ cat events.json<br/>[<br/> {<br/> &quot;guests&quot;: [<br/> {<br/> &quot;email&quot;: &quot;<a href="mailto:bob@nospam.com">bob@nospam.com</a>&quot;,<br/> &quot;name&quot;: &quot;bob&quot;<br/> }<br/> ],<br/> &quot;date&quot;: 1536678256177,<br/> &quot;host&quot;: {<br/> &quot;email&quot;: &quot;<a href="mailto:bob@nospam.com">bob@nospam.com</a>&quot;,<br/> &quot;name&quot;: &quot;bob&quot;<br/> },<br/> &quot;name&quot;: &quot;OCaml/Reason Meetup!&quot;,<br/> &quot;access&quot;: &quot;Public&quot;<br/> },<br/> {<br/> &quot;guests&quot;: [<br/> {<br/> &quot;email&quot;: &quot;<a href="mailto:louis@nospam.com">louis@nospam.com</a>&quot;,<br/> &quot;name&quot;: &quot;louis&quot;<br/> }<br/> ],<br/> &quot;date&quot;: 1536678253790,<br/> &quot;host&quot;: {<br/> &quot;email&quot;: &quot;<a href="mailto:louis@nospam.com">louis@nospam.com</a>&quot;,<br/> &quot;name&quot;: &quot;louis&quot;<br/> },<br/> &quot;name&quot;: &quot;OCaml/Reason Meetup!&quot;,<br/> &quot;access&quot;: &quot;Public&quot;<br/> }<br/>]</pre><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=1f3a14004081" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/getting-started-with-atdgen-and-bucklescript-1f3a14004081">Getting started with atdgen and bucklescript</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/getting-started-with-atdgen-and-bucklescript-1f3a14004081?source=rss----303662d88bae--ocamlGetting started with atdgen and bucklescript2018-09-12T02:53:58-00:00ahrefshttps://medium.com/feed/ahrefs/tagged/ocamlahrefs<blockquote>It was a dark and stormy night; the skylake CPU buzzed with excitement, and then, suddenly, the hyperthreads started to lock&nbsp;up..</blockquote><p>Or something like&nbsp;that.</p><p>This week a new erratum for the Intel Skylake and Kabylake processors families was brought to public attention on <a href="https://lists.debian.org/debian-devel/2017/06/msg00308.html">the Debian mailing list</a>, and then on <a href="https://news.ycombinator.com/item?id=14630183">various</a> <a href="https://www.reddit.com/r/programming/comments/6jfgfp/warning_intel_skylakekaby_lake_processors_broken/">social media</a> and <a href="http://www.theregister.co.uk/2017/06/25/intel_skylake_kaby_lake_hyperthreading/">news&nbsp;outlets</a>.</p><p>We have been investigating this issue since January with the core <a href="http://ocaml.org">OCaml</a> team, as we were struggling with a mysterious bug affecting our developers machines, and ultimately our production system, resulting in a corruption of important data in our databases.</p><p>At <a href="https://ahrefs.com">Ahrefs</a>, we operate a fleet of thousands of servers, running a wide variety of services (huge web crawler among others). At this scale, dealing with unexpected application behaviors is common. While we try to reduce the probability of the software not functioning as expected, bugs are sadly a real part of our everyday life. Even though we can assume the underlying hardware running any infrastructure can be thought of as more reliable and less prone to bugs than software components, issues can still arise in unexpected ways. When the number of servers increases, it is not unusual to observe faults in the hardware preventing the system from functioning as specified.</p><p>It is certainly not frequent to encounter such problems in CPUs but reading through <a href="https://www3.intel.com/content/dam/www/public/us/en/documents/specification-updates/desktop-6th-gen-core-family-spec-update.pdf">the list of errata published by any manufacturer,</a> each CPU model contains a fair amount of bugs. This story is about the bug in the microcode of Skylake processor leading to incorrect code execution under certain conditions. This is certainly scary at first sight: how can we trust our system if we cannot trust its main component&nbsp;? Yet, like software bugs, processor defects can be identified, contained, and we can take actions to prevent them from impacting the operation of the infrastructure.</p><p>We do not know the full implications of this particular bug, especially security implications in case of untrusted code execution. But we&rsquo;d like to tell the story of this erratum from our point of view, to provide some context, and show that dealing with it was not much different than dealing with any usual software flaw. While this post aims to cover our own perspective on this adventure, we would like to thank Mark Shinwell, Xavier Leroy, Fr&eacute;d&eacute;ric Bour, everyone involved in the <a href="https://caml.inria.fr/mantis/view.php?id=7452">Mantis issue</a> and the OCaml IRC channel for their help and time spent investigating with us. Update: Xavier Leroy told his own side of the story in another <a href="http://gallium.inria.fr/blog/intel-skylake-bug/">blog&nbsp;post.</a></p><h3>Setting the&nbsp;scene</h3><p>Our story starts in late 2016 after some of our backend developers received new laptops to work on. After a few days Enguerrand Decorne noticed unusual crashes during compilation of our OCaml codebase.</p><p>This issue, considered mildly annoying at first, seemed to affect only Enguerrand&rsquo;s machine. For a few days no other machine would exhibit the same behavior, so we figured this was a fault specific to his system configuration.</p><p>However, concerns were subsequently raised after witnessing the generation of invalid machine code and later on, after the deployment of a service on one of our new clusters composed of Skylake Xeon processors, leading to the insertion of corrupted data into our storage system. The priority raised from the annoying level, to potentially critical. Other developers started working together to obtain more information and assess the impact on our infrastructure. Soon after we were able to reproduce the issue on several machines.</p><p>The remainder of this post is a technical description of the steps taken to ensure that our systems were operating safely. It is intended to show that such low level CPU issues is not necessarily fatal&#8202;&mdash;&#8202;in less than two weeks, with the great help of core OCaml developers, we identified the conditions of the crash and set up a workaround.</p><h3>Tracking down crashes in&nbsp;OCaml</h3><p>Most of our backend code is written in <a href="https://ocaml.org">OCaml</a>, a high level and expressive language supporting functional programming style (among others), which allows us to develop robust systems with ease, thanks to its strong type system and mature&nbsp;legacy.</p><p>The compiler segfaults were definitely a surprise, since this shouldn&rsquo;t happen for any program written in OCaml, as type system and other features (such as automatic bounds-checking) usually guard us from such errors. However, stack overflows can be possible sources of segfault (when a non-optimal recursion is running too deep), so our first intuition was to increase the stack size when running the compiler. This didn&rsquo;t change anything, and the reported fault address wasn&rsquo;t anywhere near the stack address&nbsp;bound.</p><p>Before witnessing the crash on other machines, we suspected a failure in the virtualization software used by our two developers that were able to reproduce the crash, who use VMware as a part of their development workflow. We tried early on to switch to Virtualbox, but the migration proved itself fruitless as the crashes kept appearing. After a short while we began encountering the same issue on physical machines, so we ruled out a possible virtualization software&nbsp;bug.</p><p>The usual debugging process for crashing OCaml code didn&rsquo;t prove effective&#8202;&mdash;&#8202;we needed to narrow down our approach.</p><p>OCaml ships with <a href="https://realworldocaml.org/v1/en/html/the-compiler-backend-byte-code-and-native-code.html">two backend implementations</a>: a bytecode interpreter and a native compiler. We were able to reproduce the issue using both a native compiler and a compiler running on the bytecode interpreter. Consequently, this ruled out a miscompilation coming from the code <em>emitted</em> by the compiler, the OCaml runtime <em>itself</em> was misbehaving.</p><p>The runtime code is written in C, and implements low level functionalities, including the garbage collector used by both backends. After rebuilding the runtime with debug symbols, we were able to retrieve a proper stack trace and core dump. The stack trace pointed to the garbage collector&rsquo;s mark phase. OCaml&rsquo;s GC is a classic generational mark and sweep collector. The mark phase walks the heap starting from pointers on the stack and other registered root values, and marks every reachable block of&nbsp;memory.</p><p>Further inspection with <strong><em>gdb</em></strong> of the frame and address of crash revealed that the marking code encountered a corrupted block header with invalid size information, causing what looked like a buffer overrun error. Each memory block allocated in OCaml heap begins with a header word, storing metadata used by the GC, including a tag describing the kind of value present in this memory block. The header contains the size of the block, and the crash happened when the mark code was attempting to scan an array which was supposed to be more than 1TB&nbsp;large.</p><p>This was obviously not the cause of the problem but rather the consequence: something corrupted the header word after this block had been properly allocated, postponing the crash until the next GC cycle. It was the right time to escalate <a href="https://caml.inria.fr/mantis/view.php?id=7452">the issue to the OCaml bugtracker</a>, after isolating a proper test case to reproduce the&nbsp;issue.</p><h3>A set of strange&nbsp;leads</h3><p>Escalating the issue to Mantis made us to take a step back and gather our findings, and we quickly got great feedback from the OCaml core&nbsp;team.</p><p>At this point, what does the problem look&nbsp;like?</p><p>We only had sparse information, but <strong><em>dmesg</em></strong> gave us interesting data point. When a page fault occurs and the kernel detects an incorrect memory access, it logs a line in kernel log buffer containing the fault address, the instruction pointer and stack&nbsp;pointer.</p><p>[22985.879907] ocamlopt.opt[48221]: segfault at af8 ip 00005564455169bd sp 00007ffc9f36b130 error 4 in ocamlopt.opt[556445006000+613000]</p><p>Next to the 3 addresses, already available in the coredumps, an error code is reported. This number in decimal form is actually a bitset, and the flags are documented in the Linux kernel sources in <a href="https://github.com/torvalds/linux/blob/v4.11/arch/x86/mm/fault.c#L41">arch/x86/mm/fault.c</a>. Error 4 can thus be read as a read access page fault from user mode, trying to read memory which had not been previously mmap&rsquo;ed.</p><p>Error codes reported following our crashes involved protection faults or access to unmapped addresses, which corroborated our earlier buffer overrun hypothesis. More interestingly we witnessed a crash with the PF_RSVD flag enabled. This left us puzzled, none of us had ever seen such fault before. Apparently it indicates that the the page table was somehow corrupted, with some entries having non-zero bits reserved by the x86 architecture specification.</p><p>It was scary that the corruption would escape the process address space, and to our limited knowledge, it could only have been caused by kernel issue or potentially hardware issues, like memory errors. Yet we were able to reproduce this on several machines with different kernel version, and different hardware. We blamed virtual machines earlier but this theory was debunked already. We still have no explanation at this time, and pursuit on this front would require intimate knowledge of virtual memory implementations that we didn&rsquo;t&nbsp;have.</p><p>One developer wasn&rsquo;t able to reproduce the problem at all on his machine after hours of testing, but something was fishy: it didn&rsquo;t sound right that an OCaml runtime bug would be able to modify the page table. Maybe it was some corner case with reserved addresses, but this something was beyond our reach here. Out of ideas, it was time to get some assistance from tools intended to track memory corruptions, like <a href="https://github.com/google/sanitizers/wiki/AddressSanitizer">asan and&nbsp;ubsan</a>.</p><p>Running <strong><em>Asan</em></strong> didn&rsquo;t yield any meaningful results. <strong><em>Valgrind</em></strong> was later tried, following advises from the OCaml team, but every tools were preventing the crash. Quickly reproducing the bug for testing required running code in a loop, keeping the CPU and memory fully&nbsp;busy.</p><p>This was harder to do on developers machines, due to limited resources and other processes running, and Address Sanitizer would only increase the resources usage. Dedicating a powerful server would make further investigations more comfortable, and increase the likeliness of reproducing with instrumented code.</p><p>But with great surprise, it was not possible to reproduce the problem on a server machine, with and without instrumented code. This is when we realised that all the machines exhibiting the crashes were running a processor of the Intel Skylake processors family, while the server and other developer machines had CPUs from the Broadwell family.</p><h3>The hardware, an unusual&nbsp;suspect</h3><p>In the meantime several core OCaml developers had been closely investigating the issue and started auditing recent changes in the runtime, and identified a few suspicious changes and known&nbsp;bugs.</p><p>Certainly they were more qualified for this task, but it acted as an incentive to examine the history of this bug from our angle. At first, we had assumed that the bug was specific to the new laptop with virtual machines. This could not explain why the crash never manifested on older workstations equipped with Skylake processors. Several other developers had been using them for a few months, and only noticed the crash after awareness of the issue had been raised by Enguerrand.</p><p>What had changed, besides Skylake? Only a few week before, an internal migration from OCaml version 4.02.3 to 4.03.0 was rolled out in our codebase. Intrigued, we went ahead and tested OCaml 4.02.3 again, which showed no memory corruptions after several tests. It was time to browse the <a href="https://raw.githubusercontent.com/ocaml/ocaml/trunk/Changes">OCaml changelog</a> for runtime related entries. The search stopped quickly on a promising item in the list: the OCaml C runtime build optimisation level had been increased to -O2 from&nbsp;-O1.</p><p>Could the optimizations dig out an undefined behavior in C code, leading to bad assumptions in the GC code corrupting the heap&nbsp;? Rebuilding the runtime with -O1did not corrupt memory, so the source of the corruption was in the runtime <em>and</em> was triggered by some gcc specific optimization pass. This sounded like undefined behavior, although the information we had led us to some hardware&nbsp;bug.</p><p>The next day, Xavier Leroy commented on the bugreport reporting that the crash had been observed in the past. Another industrial OCaml user was affected, and they had discovered HyperThreading was part of the necessary conditions. After running the test case for several hours on several machines with HT disabled in the UEFI setup, it was clear we were facing a similar situation. This led to the hypothesis of a hardware&nbsp;bug:</p><blockquote><em>Is it crazy to imagine that gcc -O2 on the OCaml 4.03 runtime produces a specific instruction sequence that causes hardware issues in (some steppings of) Skylake processors with hyperthreading? Perhaps it is&nbsp;crazy.</em></blockquote><p>This possibility had struck us too, motivated by the HyperThreading, the page table corruption and the Skylake specific set of conditions.</p><p>This issue had certainly a strange profile. But nobody was ready to fully embrace the cpu bug hypothesis yet. We convinced ourselves that disabling HT could affect cache pressure and unfold some undefined behaviours.</p><p>HT could also explain the non-determinism, since cache pressure would depend on timings and scheduling. None of us had sufficient experience in this area to assess the strength of such hypothesis, and we did not quite buy it on a single threaded OCaml program. Our debugging motto claims that &ldquo;assumptions are not&nbsp;facts&rdquo;.</p><p>It was time to browse Intel errata list and attempt to update the CPU microcode. Although, the errata descriptions are formulated in vague terms, none of the issues disclosed at this time were looking similar to the situation under investigation. Unfortunately, CPUs microcode had no fix waiting for us either. OCaml developers investigated the errata list from their side but the lack of detailed information turned this into a fruitless and complex&nbsp;task.</p><p>In the absence of better alternative, we focused our work on pinpointing the exact source of the crash as if it was a software bug, in the hope of either finding a code issue or ruling out this hypothesis while getting more detailed data. We needed a way to identify the problematic code and find a workaround. From our side, it was not only a matter of finding whether or not there was a bug in OCaml code, but more crucially we needed a guarantee on the quality of our generated code running critical services in production.</p><h3>Identifying the offending code</h3><p>The other OCaml user affected by this issue reported that they had solved the problem by switching to another C compiler. Building the runtime with clang instead of GCC would prevent the GC from crashing. They also suggested to obtain a diff of the generated assembly. Indeed, once built with clang, the runtime would not crash. But clang generates widely different assembly from GCC and we did not have the resources to analyse several hundred thousand lines of&nbsp;changes.</p><p>If we could isolate the problematic C code, comparing the generated code would be easier. The problem had the form of a well known&nbsp;nail:</p><ul><li>Around 50 C files composing the OCaml&nbsp;runtime,</li><li>There is a good state (when built with gcc&nbsp;-O1)</li><li>And a bad state (when built with gcc&nbsp;-O2)</li></ul><p>This nail comes with a precious hammer: bisection.</p><p>The bisection approach had a downside in this occasion. Any state can be labeled bad with certainty as soon as the test crashes, but we would need to wait several hours to be confident enough to trust a non crashing test as good data-point. The reproducibility was not always consistent and a non-crashing state could be a false negative still waiting to trigger the conditions leading to the crash. A reduction of search space was necessary.</p><p>All the coredumps we had showed that the fault was caused by a corrupted heap block header, and our testcase involved the compiler. The OCaml compiler is not 100% deterministic, and IO/s primitives and unix environment in the runtime can affect timings and allocation patterns. But it sounded sensible to assume that the code corrupting a heap header block was also the code reading and writing those blocks: the major&nbsp;GC.</p><p>This hypothesis made bisecting fast: the first file we tried, <strong><em>major_gc.c</em></strong>, turned out to be the one. To make sure it was not a subtle issue in linker, reordering symbols or code blocks, we tried a few others files and confirmed changing the optimization level of some other files alone made no difference.</p><p>But the generated code difference was still way too large. Bringing this topic up on the <a href="http://webchat.freenode.net/?channels=#ocaml">OCaml IRC</a> discussion channel led to some useful inputs. We were taught that gcc supports an attribute to enable specific optimizations at the function level, using __attribute__((optimize(&quot;options,...&quot;))). Following the same strategy, it was easy to trace the source of the malfunctioning code to the <strong><em>sweep_slice</em></strong> function, which implements the sweeping phase of the classic mark and sweep garbage collector for the old generation.</p><p>Ignoring the subtle details of incremental GC, the <strong><em>sweep_slice</em></strong> function is the last pass of a normal major collection cycle. It is responsible for scanning all blocks in the major heap, and reclaiming unreachable blocks to the list of unallocated space.</p><p>The bulk of this function is a switch taking action for each block depending on its status&nbsp;:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/cfbc19fddccc5f2c1a76fcc802fae049/href">https://medium.com/media/cfbc19fddccc5f2c1a76fcc802fae049/href</a></iframe><p>This finding felt consistent with the information at hand. When the block is reachable, the color (describing the reachability status of the block) is reset. If the block became unreachable (<em>while color</em>) - it is reclaimed. In both cases, the block header is modified.</p><p>Getting back to the assembly&nbsp;diff.</p><p>Nobody in the team knows a great deal about assembly and we only have a really basic understanding of most of the instructions used in both versions. It quickly became obvious that the noise level in this diff, with thousands of lines of changed, was still too high for us to spot anything related to the problem. This problem was getting far beyond the common knowledge of everyone in the&nbsp;team.</p><p>But this was still sounding like your day to day bug tracking process. The less you know, the more careful you need to be, tackling the problem step by step. We stuck to what approach had served us well until now: bisecting.</p><p>We went through the list of optimisation passes enabled by GCC at -O2. This is a fair amount of optimisation passes and it would have been too time consuming to try them one by one, given the time needed to trigger the crash. Yet we had a hint: a memory corruption was happening semi randomly in the garbage collector. We were also keeping the undefined behaviour bug as a potential explanation. It was likely a pass which would change the structure of the code, reordering blocks and changing conditions.</p><p>After reading the description of all switches in the detailed gcc manual, the -ftree-* pass family looked promising. This set of transformations works on the <a href="https://en.wikipedia.org/wiki/Static_single_assignment_form">SSA form</a> internal representation, a widespread intermediate language representation which has the benefit of being easy to read. They seem to make a huge impact on the generated assembly code, moving code blocks around and making assumptions on code invariants in order to move around, simplify or eliminate conditional checks altogether.</p><p>By looking at output of those passes on the related source code, we narrowed down the list of transformations to a couple of interesting passes, one of them being -ftree-vrp, which stands for Value Range Propagation. This pass computes bounds for each name binding and propagates proofs that a value must lie in a given&nbsp;range.</p><p>It turned out most of the other passes depended on it for further optimisations. Even though the issue ended up not being a bad assumptions in the range values, checking this pass proved to be worthwhile: enabling -ftree-vrp on <strong><em>sweep_slice</em></strong> function while every thing else was built with -O1 was enough to trigger a&nbsp;crash.</p><p>GCC provides very good diagnostics output, and after reading the manual we found the -fdump-tree-* switch to dump the SSA form before and after specific pass. The output is designed to be read by a human and provides meaningful naming, with source code locations, alongside the ranges propagated by the VRP pass. We spent some time studying the output and matched the difference in SSA tree between the crashing and not crashing&nbsp;code.</p><p>Examining the bounds and invariants derived by gcc, it was clear that no wrong hypothesis was&nbsp;stated.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a5a311d0b5a4f890f9541f0aed91e73e/href">https://medium.com/media/a5a311d0b5a4f890f9541f0aed91e73e/href</a></iframe><p>The only meaningful observable change involves the suppression of rechecking the loop condition in the else branch of the <strong><em>sweep_slice</em></strong> function, after Value Range Propagation proved that the condition was invariant in this&nbsp;branch.</p><p>Often, reading the code carefully is the fastest way to find a bug. But after spending hours staring at the major GC code, it was clear enough that this check removal should not cause any semantic&nbsp;changes.</p><p>In this process, we identified a suspicious bit of code, where a signed long variable was promoted to unsigned according to C standard rules, which was changing the bounds derived by gcc, assuming it was always positive. But after some thinking we realised it made no difference at assembly level and although wrong, this assumption was not used anywhere.</p><p>We were now ready to rule out the possibility of a bug in OCaml runtime. It was still possible that GCC backend had a bug and was miscompiling this particular shape of code. And we were back at the assembly level again. After writing some awk formatting script to cleanup assembly and minimise noise in the diff (by renaming labels, detecting spurious code move, etc), and preventing inlining, we found a minimal assembly patch causing the&nbsp;crash.</p><p>There were only cosmetic differences. The test removal was propagated down to assembly and caused gcc to reorganise the layout of each switch case&nbsp;block.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/532ab4896b11177a96203fd0c81eaa58/href">https://medium.com/media/532ab4896b11177a96203fd0c81eaa58/href</a></iframe><p>Among those minor differences and changes of layout, we noticed a particular change which impacted exactly the reachable block header updated which could have caused header corruption. In the unoptimised version, the updating code looked like&nbsp;this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/38ca30a1decf86233084721c3803b1c4/href">https://medium.com/media/38ca30a1decf86233084721c3803b1c4/href</a></iframe><p>For some reason, the block pointer was spilled to the&nbsp;stack.</p><p>Perhaps naively, and because we had earlier emitted the hypothesis of HT impacting cache pressure, we spent a few hours staring at this code and check if we were missing something subtle which could affect the control flow of the whole function and the stack location from which it was reloaded could be corrupted.</p><p>Despite our lack of assembly knowledge, after spending several hours reading this tiny change, we got convinced that it made strictly no semantic difference. Reading the x86 manual carefully didn&rsquo;t give any hint on any subtle behavior which would trigger. Executing any of those two sequence of instruction should give the exact same&nbsp;output.</p><h3>Mitigating the&nbsp;issue</h3><p>We were now quite certain it was a CPU&nbsp;bug.</p><p>The OCaml developers had reached the same conclusion, and were working on escalating the issue to Intel. After internal discussions we decided to keep this bug as low profile as possible since we were unsure about potential security implications, especially for JIT implementations.</p><p>Even if we had no confirmation at this point nor any explanations of the cause of this bug, which was beyond our reach, we could take&nbsp;actions.</p><p>The first step was to decide against getting any new Skylake based servers until further announcement. We were left with several Skylake machines but we refrained from deploying any OCaml code on them. OCaml comes with a great package manager, <a href="https://opam.ocaml.org/">opam</a>, which supports compiler switches. Switches allow to set up a clean and distinct environment with specific packages and compiler configuration.</p><p>We patched our internal opam repository to distribute unoptimised runtime to all developers and moved forward, waiting for further announcements.</p><p>This situation made us realise that microcode requires constant updates, just like any other software in the stack. We raised awareness on this topic in our devops team, and they took measure to ensure we could roll out updates to prod&nbsp;easily.</p><h3>Happy end</h3><p>In late May, devops team noticed a <a href="http://metadata.ftp-master.debian.org/changelogs/non-free/i/intel-microcode/intel-microcode_3.20170511.1_changelog">debian package update for intel-microcode</a> containing the following change:</p><pre>Likely fix nightmare-level Skylake erratum SKL150. Fortunately,<br/>either this erratum is very-low-hitting, or gcc/clang/icc/msvc<br/>won&rsquo;t usually issue the affected opcode pattern and it ends up<br/>being rare.<br/>SKL150 &mdash; Short loops using both the AH/BH/CH/DH registers and<br/>the corresponding wide register *may* result in unpredictable<br/>system behavior. Requires both logical processors of the same<br/>core (i.e. sibling hyperthreads) to be active to trigger, as<br/>well as a &ldquo;complex set of micro-architectural conditions&rdquo;</pre><p>The erratum description immediately rang a bell as it matched the diff in the assembly we had observed. We tested the microcode update and confirmed it fixed the corruption.</p><p>Finally, our Skylake CPUs were feeling safe and OCaml compiler was&nbsp;happy.</p><p><a href="https://ahrefs.com"><em>Ahrefs</em></a><em> runs an internet-scale bot that crawls the whole Web 24/7. Our backend system is powered by a custom petabyte-scale distributed key-value storage implemented in OCaml (and some C++ and Rust). We are a small team and strongly believe in better technology leading to better solutions for real-world problems. We worship functional languages and static typing, extensively employ code generation and meta-programming, value code clarity and predictability, and are constantly seeking to automate repetitive tasks and eliminate boilerplate. And we are&nbsp;</em><a href="https://ahrefs.com/jobs"><em>hiring</em></a><em>!</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=ab1ad2beddcd" width="1" height="1" alt=""/><hr/><p><a href="https://tech.ahrefs.com/skylake-bug-a-detective-story-ab1ad2beddcd">Skylake bug: a detective story</a> was originally published in <a href="https://tech.ahrefs.com">Ahrefs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>https://tech.ahrefs.com/skylake-bug-a-detective-story-ab1ad2beddcd?source=rss----303662d88bae--ocamlSkylake bug: a detective story2017-06-28T18:34:51-00:00ahrefs \ No newline at end of file diff --git a/data/planet/ambassadortothecomputers.xml b/data/planet/ambassadortothecomputers.xml index 4190b9aa82..0d6edf9d81 100644 --- a/data/planet/ambassadortothecomputers.xml +++ b/data/planet/ambassadortothecomputers.xml @@ -1,5 +1,5 @@ -http://ambassadortothecomputers.blogspot.com/feeds/posts/default?alt=rssambassadortothecomputers2023-07-13T05:47:28-00:00http://ambassadortothecomputers.blogspot.com/feeds/posts/default?alt=rssambassadortothecomputers<p>In this post I want to build on the backtracking logic monad we covered <a href="http://ambassadortothecomputers.blogspot.com/2011/04/logic-programming-in-scala-part-2.html">last time</a> by adding <em>unification</em>, yielding an embedded DSL for Prolog-style logic programming.</p> +http://ambassadortothecomputers.blogspot.com/feeds/posts/default?alt=rssambassadortothecomputers2023-07-14T05:47:25-00:00http://ambassadortothecomputers.blogspot.com/feeds/posts/default?alt=rssambassadortothecomputers<p>In this post I want to build on the backtracking logic monad we covered <a href="http://ambassadortothecomputers.blogspot.com/2011/04/logic-programming-in-scala-part-2.html">last time</a> by adding <em>unification</em>, yielding an embedded DSL for Prolog-style logic programming.</p> <b>Prolog</b> <p>Here is a small Prolog example, the rough equivalent of <code>List.contains</code> in Scala:</p> <div class="highlight"><pre><code class="prolog"> <span class="nf">member</span><span class="p">(</span><span class="nv">X</span><span class="p">,</span> <span class="p">[</span><span class="nv">X</span><span class="p">|</span><span class="nv">T</span><span class="p">]).</span> diff --git a/data/planet/andrej.xml b/data/planet/andrej.xml index fcbd2411ec..59a8b8c95d 100644 --- a/data/planet/andrej.xml +++ b/data/planet/andrej.xml @@ -1,5 +1,5 @@ -http://math.andrej.com/feed.xmlandrej2023-07-13T05:47:27-00:00http://math.andrej.com/feed.xmlandrej<p>I am at the <a href="http://www.ipam.ucla.edu/programs/workshops/machine-assisted-proofs/">Machine assisted proofs</a> workshop at the <a href="http://www.ipam.ucla.edu">UCLA Institute for Pure and Applied Mathematics</a>, where I am about to give a talk on &ldquo;Formalizing invisible mathematics&rdquo;.</p> +http://math.andrej.com/feed.xmlandrej2023-07-14T05:47:24-00:00http://math.andrej.com/feed.xmlandrej<p>I am at the <a href="http://www.ipam.ucla.edu/programs/workshops/machine-assisted-proofs/">Machine assisted proofs</a> workshop at the <a href="http://www.ipam.ucla.edu">UCLA Institute for Pure and Applied Mathematics</a>, where I am about to give a talk on &ldquo;Formalizing invisible mathematics&rdquo;.</p> <p>Here are the <a href="http://math.andrej.com/asset/data/formalizing-invisible-mathematics.pdf">slides with speaker notes</a> and the <a href="https://youtu.be/wZSvuCJBaFU">video recording of the talk</a>.</p> diff --git a/data/planet/ashishagarwal.xml b/data/planet/ashishagarwal.xml index d8301fbf76..adb8f11c8b 100644 --- a/data/planet/ashishagarwal.xml +++ b/data/planet/ashishagarwal.xml @@ -1,5 +1,5 @@ -http://ashishagarwal.org/tag/ocaml/feed/ashishagarwal2023-07-13T05:47:27-00:00http://ashishagarwal.org/tag/ocaml/feed/ashishagarwal<p><strong>Abstract</strong><br/> +http://ashishagarwal.org/tag/ocaml/feed/ashishagarwal2023-07-14T05:47:24-00:00http://ashishagarwal.org/tag/ocaml/feed/ashishagarwal<p><strong>Abstract</strong><br/> High-throughput genomic sequencing is characterized by large diverse datasets and numerous analysis methods. It is normal for an individual bioinformatician to work with thousands of data files and employ hundreds of distinct computations during the course of a single project. This problem is magnified in &ldquo;core facilities&rdquo;, which support multiple researchers working on diverse projects. Most investigators use ad hoc methods to manage this complexity with dire consequences: analyses frequently fail to meet the scientific mandate of reproducibility; improved analysis methods are often not considered because recomputing all downstream steps would be overwhelming; hard drives and CPUs are used sub-optimally; and, in some cases, raw data is lost.</p> <p>We describe HITSCORE, an OCaml software stack that operates all computational aspects of the Genomics Core Facility at New York University&rsquo;s Center for Genomics and Systems Biology. HITSCORE has been in production use for one year, and was implemented quickly by less than two programmers following design advice from several biologists. A simple domain specific language (DSL) enables generating type safe database bindings and GUI components, and greatly eases updates and migration of our data model. We found a multi-lingual stack too burdensome in a small team setting, and credit OCaml for fulfilling the needs of our full application stack. It has good database bindings, excels at encoding complex domain logic, and now allows construction of rich websites due to the Ocsigen web programming framework. Higher level libraries for distributed computing would be a welcome improvement.</p> <p>The opportunity to build this system did not stem directly from any strength of functional programming or OCaml. It was necessary for a person with credibility amongst biologists to champion its development, and this credibility took several years to build. Rapid development appears to be the single most important factor in allaying doubts about using a lesser known language, and we will briefly describe our experiences in bringing OCaml to several high profile projects.</p> diff --git a/data/planet/bap.xml b/data/planet/bap.xml index 35ba898957..fe8f95c9db 100644 --- a/data/planet/bap.xml +++ b/data/planet/bap.xml @@ -1,5 +1,5 @@ -https://binaryanalysisplatform.github.io/feed.xmlbap2023-07-13T05:47:28-00:00https://binaryanalysisplatform.github.io/feed.xmlbap<h1>Defining instructions semantics using Primus Lisp (Tutorial)</h1> +https://binaryanalysisplatform.github.io/feed.xmlbap2023-07-14T05:47:25-00:00https://binaryanalysisplatform.github.io/feed.xmlbap<h1>Defining instructions semantics using Primus Lisp (Tutorial)</h1> <h2>Introduction</h2> diff --git a/data/planet/baturin.xml b/data/planet/baturin.xml index 99c1f19f38..b29ff508be 100644 --- a/data/planet/baturin.xml +++ b/data/planet/baturin.xml @@ -1,5 +1,5 @@ -https://baturin.org/blog/atom-ocaml.xmlbaturin2023-07-05T05:48:06-00:00https://baturin.org/blog/atom-ocaml.xmlbaturin +https://baturin.org/blog/atom-ocaml.xmlbaturin2023-07-14T05:47:25-00:00https://baturin.org/blog/atom-ocaml.xmlbaturin One thing I find odd about many interpreter projects is that they are designed as standalone and can't be used as embedded scripting languages. Lua-ML is completely different in that regard: it's designed as an extension language first and offers some unique features for that use case, including a reconfigurable runtime library. You can remove modules from its standard library or replace diff --git a/data/planet/cameleon.xml b/data/planet/cameleon.xml index f39d113fac..cdbfc9b4e4 100644 --- a/data/planet/cameleon.xml +++ b/data/planet/cameleon.xml @@ -1,2 +1,2 @@ -http://www.blogger.com/feeds/7617521785419311079/posts/defaultcameleon2023-07-13T05:47:27-00:00http://www.blogger.com/feeds/7617521785419311079/posts/defaultcameleonNew commands are available in the OCaml mode of Chamo. They use the <span style="color: rgb(51, 102, 102);font-family:courier new;">.annot</span> files generated by ocamlc. Here is a list of these commands. Default key bindings are shown between parenthesis.<br/><br/><span style="color: rgb(51, 102, 255); font-weight: bold;font-family:courier new;">ocaml_display_type_annot (A-t)</span> already existed to display the type of the expression under the cursor. Now <span style="font-weight: bold; color: rgb(51, 102, 255);font-family:courier new;">ocaml_copy_type_annot (CA-t)</span> does the same but also copies the type in the clipboard so that it can be easily pasted somewhere else, for example in a <span style="color: rgb(51, 102, 102);font-family:courier new;">.mli</span> file. This prevents from having to launch a <span style="color: rgb(51, 102, 102);font-family:courier new;">ocamlc -i</span> command to get the type.<br/><br/><span style="color: rgb(51, 102, 255); font-weight: bold;font-family:courier new;">ocaml_display_ident_annot (A-i)</span><span style="font-family:courier new;"></span> displays the &quot;ident&quot; information, that is whether the identifier is local to the file or its fully qualified name if it is defined elsewhere. <span style="font-weight: bold; color: rgb(51, 102, 255);font-family:courier new;">ocaml_jump_to_local_def (A-j)</span> does the same but if the ident is defined in the file, the cursor is positioned on the identifier definition.<br/><br/><br/><span style="font-weight: bold; color: rgb(51, 102, 255);font-family:courier new;">ocaml_display_call_annot (A-c)</span> displays the &quot;call&quot; information, that is whether a function call is &quot;tail&quot; or &quot;stack&quot;. <span style="font-weight: bold; color: rgb(51, 102, 255);font-family:courier new;">ocaml_show_stack_calls (CA-c)</span> highlights (or not) all the calls using the stack. This can be useful to check whether a function is tail-recursive. The screenshot below shows the result on the <span style="color: rgb(51, 153, 153);font-family:courier new;">List</span> module.<br/><a href="http://3.bp.blogspot.com/_RT8DPiBmxGY/S1hxkWOPSlI/AAAAAAAAAA8/ZuZjsQWDkJA/s1600-h/stack_calls.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img src="http://3.bp.blogspot.com/_RT8DPiBmxGY/S1hxkWOPSlI/AAAAAAAAAA8/ZuZjsQWDkJA/s200/stack_calls.png" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 200px; height: 174px;" alt="" border="0"/></a><br/>At last, <span style="font-weight: bold; color: rgb(51, 102, 255);font-family:courier new;">ocaml_expand_ext_idents (CA-x)</span> prompts the user to replace each external identifier by its fully qualified identifier (except for idents from <span style="font-family:courier new;">Pervasives</span>). I personnally use the <span style="color: rgb(51, 102, 102);font-family:courier new;">open</span> directive only not to prefix record fields and constructors, but always use fully qualified identifiers. This command is useful when working on a code not written by me and full of <span style="color: rgb(51, 102, 102);font-family:courier new;">open</span>'s at the beginning of a file.<br/><br/>All these commands are available from revision 745 of the repository and in the nightly snapshot.https://ocameleon.blogspot.com/2010/01/playing-with-annot-files.htmlPlaying with .annot files2010-01-21T14:58:00-00:00Zoggyhttp://www.blogger.com/feeds/7617521785419311079/posts/defaultcameleonA R mode is now available for Chamo, as a <a href="http://home.gna.org/cameleon/snippets.en.html">separate snippet</a>. By now, this mode has only one key binding, to call the &quot;r_eval&quot; command. This command sends the contents of the active view to a background R process. The output of this process is displayed in the &quot;outputs&quot; window. Other commands can easily be defined the same way to interact with other programs (see <a href="http://home.gna.org/cameleon/snippets/code_R_mode.html">the details</a>).<br/><br/>If some text is selected in the view, then only this text is sent to the R process. Closing the R output tab in the &quot;outputs&quot; window closes the R process. When the &quot;r_eval&quot; command is executed again, a new process is created. If the command is executed and the R process is still running, then it is used and no other process is launched.<br/><br/><a href="http://3.bp.blogspot.com/_RT8DPiBmxGY/SCBvaxuVAVI/AAAAAAAAAAo/LOXoepGGYx8/s1600-h/r_mode.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img src="http://3.bp.blogspot.com/_RT8DPiBmxGY/SCBvaxuVAVI/AAAAAAAAAAo/LOXoepGGYx8/s320/r_mode.png" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" alt="" border="0"/></a>https://ocameleon.blogspot.com/2008/05/r-mode-in-chamo.htmlR mode in Chamo2008-05-06T14:37:00-00:00Zoggyhttp://www.blogger.com/feeds/7617521785419311079/posts/defaultcameleonThe Chamo editor now includes some ocamlbuild support through the internal command &quot;ocaml_build&quot;: An ocamlbuild command is proposed to the user who can edit it and run it.<br/><br/><a href="http://2.bp.blogspot.com/_RT8DPiBmxGY/SBiIKhuVATI/AAAAAAAAAAM/WBh5pChCVHw/s1600-h/ocamlbuild_asks.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img src="http://2.bp.blogspot.com/_RT8DPiBmxGY/SBiIKhuVATI/AAAAAAAAAAM/WBh5pChCVHw/s320/ocamlbuild_asks.png" style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" alt="" border="0"/></a><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>The output of the command is displayed in a new &quot;outputs&quot; window, and is analyzed. In case of error (or warning considered as error), the editor displays, in the active view, the file where the error was found, and highlights the corresponding characters.<br/><br/><div style="text-align: center;"><a href="http://3.bp.blogspot.com/_RT8DPiBmxGY/SBiIcxuVAUI/AAAAAAAAAAU/Y6lbWsiazv4/s1600-h/ocamlbuild_error.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img src="http://3.bp.blogspot.com/_RT8DPiBmxGY/SBiIcxuVAUI/AAAAAAAAAAU/Y6lbWsiazv4/s320/ocamlbuild_error.png" style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" alt="" border="0"/></a><br/></div><br/><br/><br/><br/><br/><br/><br/><br/>The command used to compile is kept associated to the file, so that it is proposed the next time the internal command &quot;ocaml_build&quot; is launch on the file. These associations are even stored on disk to be kept between two sessions of Chamo launched in the same directory.https://ocameleon.blogspot.com/2008/04/ocamlbuild-support-in-chamo.htmlOCamlbuild support in Chamo2008-04-30T14:33:00-00:00Zoggy \ No newline at end of file +http://www.blogger.com/feeds/7617521785419311079/posts/defaultcameleon2023-07-14T05:47:24-00:00http://www.blogger.com/feeds/7617521785419311079/posts/defaultcameleonNew commands are available in the OCaml mode of Chamo. They use the <span style="color: rgb(51, 102, 102);font-family:courier new;">.annot</span> files generated by ocamlc. Here is a list of these commands. Default key bindings are shown between parenthesis.<br/><br/><span style="color: rgb(51, 102, 255); font-weight: bold;font-family:courier new;">ocaml_display_type_annot (A-t)</span> already existed to display the type of the expression under the cursor. Now <span style="font-weight: bold; color: rgb(51, 102, 255);font-family:courier new;">ocaml_copy_type_annot (CA-t)</span> does the same but also copies the type in the clipboard so that it can be easily pasted somewhere else, for example in a <span style="color: rgb(51, 102, 102);font-family:courier new;">.mli</span> file. This prevents from having to launch a <span style="color: rgb(51, 102, 102);font-family:courier new;">ocamlc -i</span> command to get the type.<br/><br/><span style="color: rgb(51, 102, 255); font-weight: bold;font-family:courier new;">ocaml_display_ident_annot (A-i)</span><span style="font-family:courier new;"></span> displays the &quot;ident&quot; information, that is whether the identifier is local to the file or its fully qualified name if it is defined elsewhere. <span style="font-weight: bold; color: rgb(51, 102, 255);font-family:courier new;">ocaml_jump_to_local_def (A-j)</span> does the same but if the ident is defined in the file, the cursor is positioned on the identifier definition.<br/><br/><br/><span style="font-weight: bold; color: rgb(51, 102, 255);font-family:courier new;">ocaml_display_call_annot (A-c)</span> displays the &quot;call&quot; information, that is whether a function call is &quot;tail&quot; or &quot;stack&quot;. <span style="font-weight: bold; color: rgb(51, 102, 255);font-family:courier new;">ocaml_show_stack_calls (CA-c)</span> highlights (or not) all the calls using the stack. This can be useful to check whether a function is tail-recursive. The screenshot below shows the result on the <span style="color: rgb(51, 153, 153);font-family:courier new;">List</span> module.<br/><a href="http://3.bp.blogspot.com/_RT8DPiBmxGY/S1hxkWOPSlI/AAAAAAAAAA8/ZuZjsQWDkJA/s1600-h/stack_calls.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img src="http://3.bp.blogspot.com/_RT8DPiBmxGY/S1hxkWOPSlI/AAAAAAAAAA8/ZuZjsQWDkJA/s200/stack_calls.png" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 200px; height: 174px;" alt="" border="0"/></a><br/>At last, <span style="font-weight: bold; color: rgb(51, 102, 255);font-family:courier new;">ocaml_expand_ext_idents (CA-x)</span> prompts the user to replace each external identifier by its fully qualified identifier (except for idents from <span style="font-family:courier new;">Pervasives</span>). I personnally use the <span style="color: rgb(51, 102, 102);font-family:courier new;">open</span> directive only not to prefix record fields and constructors, but always use fully qualified identifiers. This command is useful when working on a code not written by me and full of <span style="color: rgb(51, 102, 102);font-family:courier new;">open</span>'s at the beginning of a file.<br/><br/>All these commands are available from revision 745 of the repository and in the nightly snapshot.https://ocameleon.blogspot.com/2010/01/playing-with-annot-files.htmlPlaying with .annot files2010-01-21T14:58:00-00:00Zoggyhttp://www.blogger.com/feeds/7617521785419311079/posts/defaultcameleonA R mode is now available for Chamo, as a <a href="http://home.gna.org/cameleon/snippets.en.html">separate snippet</a>. By now, this mode has only one key binding, to call the &quot;r_eval&quot; command. This command sends the contents of the active view to a background R process. The output of this process is displayed in the &quot;outputs&quot; window. Other commands can easily be defined the same way to interact with other programs (see <a href="http://home.gna.org/cameleon/snippets/code_R_mode.html">the details</a>).<br/><br/>If some text is selected in the view, then only this text is sent to the R process. Closing the R output tab in the &quot;outputs&quot; window closes the R process. When the &quot;r_eval&quot; command is executed again, a new process is created. If the command is executed and the R process is still running, then it is used and no other process is launched.<br/><br/><a href="http://3.bp.blogspot.com/_RT8DPiBmxGY/SCBvaxuVAVI/AAAAAAAAAAo/LOXoepGGYx8/s1600-h/r_mode.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img src="http://3.bp.blogspot.com/_RT8DPiBmxGY/SCBvaxuVAVI/AAAAAAAAAAo/LOXoepGGYx8/s320/r_mode.png" style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" alt="" border="0"/></a>https://ocameleon.blogspot.com/2008/05/r-mode-in-chamo.htmlR mode in Chamo2008-05-06T14:37:00-00:00Zoggyhttp://www.blogger.com/feeds/7617521785419311079/posts/defaultcameleonThe Chamo editor now includes some ocamlbuild support through the internal command &quot;ocaml_build&quot;: An ocamlbuild command is proposed to the user who can edit it and run it.<br/><br/><a href="http://2.bp.blogspot.com/_RT8DPiBmxGY/SBiIKhuVATI/AAAAAAAAAAM/WBh5pChCVHw/s1600-h/ocamlbuild_asks.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img src="http://2.bp.blogspot.com/_RT8DPiBmxGY/SBiIKhuVATI/AAAAAAAAAAM/WBh5pChCVHw/s320/ocamlbuild_asks.png" style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" alt="" border="0"/></a><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/>The output of the command is displayed in a new &quot;outputs&quot; window, and is analyzed. In case of error (or warning considered as error), the editor displays, in the active view, the file where the error was found, and highlights the corresponding characters.<br/><br/><div style="text-align: center;"><a href="http://3.bp.blogspot.com/_RT8DPiBmxGY/SBiIcxuVAUI/AAAAAAAAAAU/Y6lbWsiazv4/s1600-h/ocamlbuild_error.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img src="http://3.bp.blogspot.com/_RT8DPiBmxGY/SBiIcxuVAUI/AAAAAAAAAAU/Y6lbWsiazv4/s320/ocamlbuild_error.png" style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" alt="" border="0"/></a><br/></div><br/><br/><br/><br/><br/><br/><br/><br/>The command used to compile is kept associated to the file, so that it is proposed the next time the internal command &quot;ocaml_build&quot; is launch on the file. These associations are even stored on disk to be kept between two sessions of Chamo launched in the same directory.https://ocameleon.blogspot.com/2008/04/ocamlbuild-support-in-chamo.htmlOCamlbuild support in Chamo2008-04-30T14:33:00-00:00Zoggy \ No newline at end of file diff --git a/data/planet/cburnout.xml b/data/planet/cburnout.xml index 462b65f33b..8ef2c0eaea 100644 --- a/data/planet/cburnout.xml +++ b/data/planet/cburnout.xml @@ -1,5 +1,5 @@ -http://www.blogger.com/feeds/9108979482982930820/posts/default/-/OCamlcburnout2023-07-13T05:47:27-00:00http://www.blogger.com/feeds/9108979482982930820/posts/default/-/OCamlcburnout<div dir="ltr" style="text-align: left;" trbidi="on"> +http://www.blogger.com/feeds/9108979482982930820/posts/default/-/OCamlcburnout2023-07-14T05:47:24-00:00http://www.blogger.com/feeds/9108979482982930820/posts/default/-/OCamlcburnout<div dir="ltr" style="text-align: left;" trbidi="on"> <br/> A journey toward a state-machine without mutable state, but enough flexibility to express GUI behaviors. This is nothing new in it's parts, but maybe as a whole. In scouring GUI lore there is very little in a functional style.<br/> <br/> diff --git a/data/planet/coherentpdf.xml b/data/planet/coherentpdf.xml index fcbe736eef..ba4feaa93c 100644 --- a/data/planet/coherentpdf.xml +++ b/data/planet/coherentpdf.xml @@ -1,5 +1,5 @@ -https://coherentpdf.com/blog/?tag=ocaml&feed=rss2coherentpdf2023-07-13T05:47:27-00:00https://coherentpdf.com/blog/?tag=ocaml&feed=rss2coherentpdf<p>The&nbsp;<code>cpdf</code>&nbsp;tool has been available commercially since 2007, and is widely used in industry and government. The same technology is used in the&nbsp;<a href="http://www.coherentpdf.com/proview.html">Proview PDF Editor</a>&nbsp;for the mac.</p> +https://coherentpdf.com/blog/?tag=ocaml&feed=rss2coherentpdf2023-07-14T05:47:24-00:00https://coherentpdf.com/blog/?tag=ocaml&feed=rss2coherentpdf<p>The&nbsp;<code>cpdf</code>&nbsp;tool has been available commercially since 2007, and is widely used in industry and government. The same technology is used in the&nbsp;<a href="http://www.coherentpdf.com/proview.html">Proview PDF Editor</a>&nbsp;for the mac.</p> <p>Now we&rsquo;re releasing it for free, under a&nbsp;special not-for-commercial-use license.</p> <p>Binaries for Windows, Mac and Linux, OCaml source code, and full documentation are all available <a href="http://community.coherentpdf.com/">here</a>.</p> <p>The Coherent PDF Command Line Tools allow you to manipulate existing PDF files in a variety of ways. For example:</p> diff --git a/data/planet/coq.xml b/data/planet/coq.xml index 705360fbfe..97e19eaa2a 100644 --- a/data/planet/coq.xml +++ b/data/planet/coq.xml @@ -1,5 +1,5 @@ -https://coq.inria.fr/rss.xmlcoq2023-07-13T05:47:27-00:00https://coq.inria.fr/rss.xmlcoq +https://coq.inria.fr/rss.xmlcoq2023-07-14T05:47:24-00:00https://coq.inria.fr/rss.xmlcoq <p> The Coq development team is proud to announce the immediate availability of diff --git a/data/planet/cufp.xml b/data/planet/cufp.xml index 9c5b4e7f49..39c8d7b12d 100644 --- a/data/planet/cufp.xml +++ b/data/planet/cufp.xml @@ -1,5 +1,5 @@ -http://cufp.org/blog/all.rss.xmlcufp2023-07-13T05:47:27-00:00http://cufp.org/blog/all.rss.xmlcufp +http://cufp.org/blog/all.rss.xmlcufp2023-07-14T05:47:24-00:00http://cufp.org/blog/all.rss.xmlcufp <p>CUFP 2015 will be held in Vancouver, Canada. It is co-located with <a href="http://icfpconference.org/icfp2015/">ICFP 2015</a>.</p> <p>The call for presentations is available <a href="http://cufp.org/2015/call-for-presentations.html">here</a>. Submissions are due by June 14.</p> diff --git a/data/planet/cwn.xml b/data/planet/cwn.xml index ab80e519c8..7d5fb8631d 100644 --- a/data/planet/cwn.xml +++ b/data/planet/cwn.xml @@ -1,2 +1,2 @@ -https://alan.petitepomme.net/cwn/cwn.rsscwn2023-07-13T05:47:26-00:00https://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#1">opam 2.2.0~alpha release!</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#2">Initial Emissions Monitoring of the OCaml.org Infrastructure</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#3">Autofonce, a modern runner for GNU Autotests suites</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#4">First beta release of OCaml 5.1.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#5">Dream-html - DSL to build HTML, integrated with Dream</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#6">ppx_subliner 0.2.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#7">happy-eyeballs, dns, http-{lwt,mirage}-client ++ writeup of happy-eyeballs issue and fix</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#8">Getting started with ReasonReact and Melange</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#9">Making OCaml 5 Succeed for Developers and Organisations</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#10">Llama, an OCaml library for declaratively building software-defined modular synthesizers</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#11">dune 3.9.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#12">Depending on non-OCaml languages from the opam repository</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#13">Status of DkML Windows</a></li></ol>https://alan.petitepomme.net/cwn/2023.07.11.htmlOCaml Weekly News, 11 Jul 20232023-07-11T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#1">New release of CAISAR, a platform for characterizing AI safety and robustness</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#2">stdlib-random release 1.1.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#3">dune 3.8.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#4">plotly release 1.0.0, a wrapper for Plotly open source graphing library</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#5">Help us Make the New Learn Area on OCaml.org Awesome</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#6">Sedlex 3.2</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#7">dune 3.9.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#8">Other OCaml News</a></li></ol>https://alan.petitepomme.net/cwn/2023.07.04.htmlOCaml Weekly News, 04 Jul 20232023-07-04T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#1">dune 3.8.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#2">moonpool 0.2</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#3">aeroon, wrapper to Aeron</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#4">Representing OCaml on Lemmy</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#5">awa-ssh release 0.3</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#6">Ppxlib dev meetings</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#7">User-friendly continuations over OCaml 5 effects?</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#8">Raising the minimum tested version of OCaml to 4.05 or 4.11 (from 4.02)</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#9">guroobi, wrapper to Gurobi</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#10">euler, an arithmetic library for native integers</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#11">CFP - JFLA 2024 - Journ&eacute;es Francophones des Langages Applicatifs</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#12">OCaml.org Newsletter: May 2023</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#13">Other OCaml News</a></li></ol>https://alan.petitepomme.net/cwn/2023.06.27.htmlOCaml Weekly News, 27 Jun 20232023-06-27T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#1">Packaging an executable for homebrew install for non-OCaml users</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#2">v0.16 release of Jane Street packages</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#3">New release of Menhir (20230608)</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#4">Dream-html - DSL to build HTML, integrated with Dream</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#5">release of minisat 0.5</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#6">Which filters would you like to see on the OCaml blog at OCaml.org?</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#7">OCaml Platform Newsletter, May 2023</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#8">Congratulation to the OCaml team for the 2023 SIGPLAN programming languages software award! &#127942;</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#9">Other OCaml News</a></li></ol>https://alan.petitepomme.net/cwn/2023.06.20.htmlOCaml Weekly News, 20 Jun 20232023-06-20T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#1">release of minisat 0.5</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#2">containers 3.12</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#3">Recent tar releases (2.5.0, 2.4.0, ...)</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#4">mpp.0.3.6, which adds compatibility with OCaml 5, is now in opam</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#5">trace 0.1, tracy-client 0.1</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#6">A short review of fmlib_browser (web frontend library)</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#7">moonpool 0.1</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#8">Other OCaml News</a></li></ol>https://alan.petitepomme.net/cwn/2023.06.13.htmlOCaml Weekly News, 13 Jun 20232023-06-13T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#1">Meetup group in New York City</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#2">Creating a tutorial on sequences</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#3">new release: Merlin 4.9</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#4">Taking Inventory of the OCaml Ecosystem on OCaml.org</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#5">New release: DocuLib 1.3.5</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#6">opam 2.1.5 release!</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#7">dune 3.8.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#8">Second alpha release of OCaml 5.1.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#9">ML'23: ACM SIGPLAN ML Family Workshop &mdash; Call for presentations</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#10">qcheck-lin and qcheck-stm 0.2</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#11">Melange 1.0 &ndash; compile OCaml / ReasonML to JavaScript</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#12">Debugging Native Code in &quot;Second OCaml&quot; YouTube Video</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#13">Sandmark nightly now supports latency profiling</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#14">Update on Eio (effects-based direct-style IO for OCaml 5)</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#15">Initial Emissions Monitoring of the OCaml.org Infrastructure</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#16">Other OCaml News</a></li></ol>https://alan.petitepomme.net/cwn/2023.06.06.htmlOCaml Weekly News, 06 Jun 20232023-06-06T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.05.30.html#1">ML'23: ACM SIGPLAN ML Family Workshop &mdash; Call for presentations</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.30.html#2">OCaml Workshop 2023 -- presentation deadline on June 1st, online attendance option</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.30.html#3">A Roadmap for the OCaml Platform - Seeking Your Feedback</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.30.html#4">new release: tiny_httpd 0.13</a></li></ol>https://alan.petitepomme.net/cwn/2023.05.30.htmlOCaml Weekly News, 30 May 20232023-05-30T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#1">Looking for example tsdl games</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#2">OCaml.org Newsletter: April 2023</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#3">A bestiary of GADT examples?</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#4">2023 StackOverflow Developer Survey</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#5">Release 0.5.4 of ~Fmlib_browser~</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#6">OCaml Platform Newsletter: April 2023</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#7">Eio Developer Meetings</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#8">New major release of Parany (v14.0.0)</a></li></ol>https://alan.petitepomme.net/cwn/2023.05.23.htmlOCaml Weekly News, 23 May 20232023-05-23T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#1">Rendering React in OCaml</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#2">Ahrefs is Hiring</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#3">tmx: Import 2D game maps with ease</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#4">Brr 0.0.5, the WebGPU edition</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#5">A bestiary of GADT examples?</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#6">Open-source tool to make a static blog in OCaml?</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#7">BER MetaOCaml N114, for OCaml 4.14.1</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#8">Building iOS apps with OCaml?</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#9">A Minimal Prototype of In-Package Search is on staging.ocaml.org</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#10">New release of Fix (20230505)</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#11">QCheck 0.21</a></li></ol>https://alan.petitepomme.net/cwn/2023.05.16.htmlOCaml Weekly News, 16 May 20232023-05-16T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#1">Overview of libraries for showing OCaml values</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#2">kcas and kcas_data 0.3.0: Software Transactional Memory</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#3">OCaml.org Newsletter: March 2023</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#4">Creating a tutorial on sequences</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#5">You started to learn OCaml less than 12 months ago? Please help us with our user survey on the OCaml.org Learning Area</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#6">Explorations on Package Management in Dune</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#7">Functional web applications running in the browser</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#8">Ahrefs is now built with Melange</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#9">Other OCaml News</a></li></ol>https://alan.petitepomme.net/cwn/2023.05.09.htmlOCaml Weekly News, 09 May 20232023-05-09T12:00:00-00:00cwn \ No newline at end of file +https://alan.petitepomme.net/cwn/cwn.rsscwn2023-07-14T05:47:24-00:00https://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#1">opam 2.2.0~alpha release!</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#2">Initial Emissions Monitoring of the OCaml.org Infrastructure</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#3">Autofonce, a modern runner for GNU Autotests suites</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#4">First beta release of OCaml 5.1.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#5">Dream-html - DSL to build HTML, integrated with Dream</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#6">ppx_subliner 0.2.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#7">happy-eyeballs, dns, http-{lwt,mirage}-client ++ writeup of happy-eyeballs issue and fix</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#8">Getting started with ReasonReact and Melange</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#9">Making OCaml 5 Succeed for Developers and Organisations</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#10">Llama, an OCaml library for declaratively building software-defined modular synthesizers</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#11">dune 3.9.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#12">Depending on non-OCaml languages from the opam repository</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.11.html#13">Status of DkML Windows</a></li></ol>https://alan.petitepomme.net/cwn/2023.07.11.htmlOCaml Weekly News, 11 Jul 20232023-07-11T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#1">New release of CAISAR, a platform for characterizing AI safety and robustness</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#2">stdlib-random release 1.1.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#3">dune 3.8.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#4">plotly release 1.0.0, a wrapper for Plotly open source graphing library</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#5">Help us Make the New Learn Area on OCaml.org Awesome</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#6">Sedlex 3.2</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#7">dune 3.9.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.07.04.html#8">Other OCaml News</a></li></ol>https://alan.petitepomme.net/cwn/2023.07.04.htmlOCaml Weekly News, 04 Jul 20232023-07-04T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#1">dune 3.8.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#2">moonpool 0.2</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#3">aeroon, wrapper to Aeron</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#4">Representing OCaml on Lemmy</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#5">awa-ssh release 0.3</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#6">Ppxlib dev meetings</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#7">User-friendly continuations over OCaml 5 effects?</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#8">Raising the minimum tested version of OCaml to 4.05 or 4.11 (from 4.02)</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#9">guroobi, wrapper to Gurobi</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#10">euler, an arithmetic library for native integers</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#11">CFP - JFLA 2024 - Journ&eacute;es Francophones des Langages Applicatifs</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#12">OCaml.org Newsletter: May 2023</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.27.html#13">Other OCaml News</a></li></ol>https://alan.petitepomme.net/cwn/2023.06.27.htmlOCaml Weekly News, 27 Jun 20232023-06-27T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#1">Packaging an executable for homebrew install for non-OCaml users</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#2">v0.16 release of Jane Street packages</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#3">New release of Menhir (20230608)</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#4">Dream-html - DSL to build HTML, integrated with Dream</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#5">release of minisat 0.5</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#6">Which filters would you like to see on the OCaml blog at OCaml.org?</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#7">OCaml Platform Newsletter, May 2023</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#8">Congratulation to the OCaml team for the 2023 SIGPLAN programming languages software award! &#127942;</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.20.html#9">Other OCaml News</a></li></ol>https://alan.petitepomme.net/cwn/2023.06.20.htmlOCaml Weekly News, 20 Jun 20232023-06-20T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#1">release of minisat 0.5</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#2">containers 3.12</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#3">Recent tar releases (2.5.0, 2.4.0, ...)</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#4">mpp.0.3.6, which adds compatibility with OCaml 5, is now in opam</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#5">trace 0.1, tracy-client 0.1</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#6">A short review of fmlib_browser (web frontend library)</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#7">moonpool 0.1</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.13.html#8">Other OCaml News</a></li></ol>https://alan.petitepomme.net/cwn/2023.06.13.htmlOCaml Weekly News, 13 Jun 20232023-06-13T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#1">Meetup group in New York City</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#2">Creating a tutorial on sequences</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#3">new release: Merlin 4.9</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#4">Taking Inventory of the OCaml Ecosystem on OCaml.org</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#5">New release: DocuLib 1.3.5</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#6">opam 2.1.5 release!</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#7">dune 3.8.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#8">Second alpha release of OCaml 5.1.0</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#9">ML'23: ACM SIGPLAN ML Family Workshop &mdash; Call for presentations</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#10">qcheck-lin and qcheck-stm 0.2</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#11">Melange 1.0 &ndash; compile OCaml / ReasonML to JavaScript</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#12">Debugging Native Code in &quot;Second OCaml&quot; YouTube Video</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#13">Sandmark nightly now supports latency profiling</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#14">Update on Eio (effects-based direct-style IO for OCaml 5)</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#15">Initial Emissions Monitoring of the OCaml.org Infrastructure</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.06.06.html#16">Other OCaml News</a></li></ol>https://alan.petitepomme.net/cwn/2023.06.06.htmlOCaml Weekly News, 06 Jun 20232023-06-06T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.05.30.html#1">ML'23: ACM SIGPLAN ML Family Workshop &mdash; Call for presentations</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.30.html#2">OCaml Workshop 2023 -- presentation deadline on June 1st, online attendance option</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.30.html#3">A Roadmap for the OCaml Platform - Seeking Your Feedback</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.30.html#4">new release: tiny_httpd 0.13</a></li></ol>https://alan.petitepomme.net/cwn/2023.05.30.htmlOCaml Weekly News, 30 May 20232023-05-30T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#1">Looking for example tsdl games</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#2">OCaml.org Newsletter: April 2023</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#3">A bestiary of GADT examples?</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#4">2023 StackOverflow Developer Survey</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#5">Release 0.5.4 of ~Fmlib_browser~</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#6">OCaml Platform Newsletter: April 2023</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#7">Eio Developer Meetings</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.23.html#8">New major release of Parany (v14.0.0)</a></li></ol>https://alan.petitepomme.net/cwn/2023.05.23.htmlOCaml Weekly News, 23 May 20232023-05-23T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#1">Rendering React in OCaml</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#2">Ahrefs is Hiring</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#3">tmx: Import 2D game maps with ease</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#4">Brr 0.0.5, the WebGPU edition</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#5">A bestiary of GADT examples?</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#6">Open-source tool to make a static blog in OCaml?</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#7">BER MetaOCaml N114, for OCaml 4.14.1</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#8">Building iOS apps with OCaml?</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#9">A Minimal Prototype of In-Package Search is on staging.ocaml.org</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#10">New release of Fix (20230505)</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.16.html#11">QCheck 0.21</a></li></ol>https://alan.petitepomme.net/cwn/2023.05.16.htmlOCaml Weekly News, 16 May 20232023-05-16T12:00:00-00:00cwnhttps://alan.petitepomme.net/cwn/cwn.rsscwn<ol><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#1">Overview of libraries for showing OCaml values</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#2">kcas and kcas_data 0.3.0: Software Transactional Memory</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#3">OCaml.org Newsletter: March 2023</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#4">Creating a tutorial on sequences</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#5">You started to learn OCaml less than 12 months ago? Please help us with our user survey on the OCaml.org Learning Area</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#6">Explorations on Package Management in Dune</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#7">Functional web applications running in the browser</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#8">Ahrefs is now built with Melange</a></li><li><a href="https://alan.petitepomme.net/cwn/2023.05.09.html#9">Other OCaml News</a></li></ol>https://alan.petitepomme.net/cwn/2023.05.09.htmlOCaml Weekly News, 09 May 20232023-05-09T12:00:00-00:00cwn \ No newline at end of file diff --git a/data/planet/dbaelde.xml b/data/planet/dbaelde.xml index 7f58d03d4b..1a88af787c 100644 --- a/data/planet/dbaelde.xml +++ b/data/planet/dbaelde.xml @@ -1,5 +1,5 @@ -http://www.blogger.com/feeds/17133288/posts/default/-/ocamldbaelde2023-07-13T05:47:27-00:00http://www.blogger.com/feeds/17133288/posts/default/-/ocamldbaeldeMaintenant que je travaille un peu dans le domaine de la s&eacute;curit&eacute;, je pense notamment aux g&eacute;n&eacute;rateurs de nombres al&eacute;atoires. Apr&egrave;s quelques lectures <a href="http://en.wikipedia.org/wiki/Pseudorandom_number_generator">sur</a> <a href="http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator">le sujet</a>, je me suis demand&eacute; comment fonctionnait le module <code>Random</code> de Caml.<br/> +http://www.blogger.com/feeds/17133288/posts/default/-/ocamldbaelde2023-07-14T05:47:24-00:00http://www.blogger.com/feeds/17133288/posts/default/-/ocamldbaeldeMaintenant que je travaille un peu dans le domaine de la s&eacute;curit&eacute;, je pense notamment aux g&eacute;n&eacute;rateurs de nombres al&eacute;atoires. Apr&egrave;s quelques lectures <a href="http://en.wikipedia.org/wiki/Pseudorandom_number_generator">sur</a> <a href="http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator">le sujet</a>, je me suis demand&eacute; comment fonctionnait le module <code>Random</code> de Caml.<br/> <br/> Il y a s&ucirc;rement beaucoup de choses &agrave; dire, mais mon attention a &eacute;t&eacute; retenue par un truc simple: <code>self_init</code> initialise le g&eacute;n&eacute;rateur de fa&ccedil;on tr&egrave;s simple, &agrave; partir de l'heure et de l'identifiant du processus, donn&eacute;es pour le moins al&eacute;atoires. Il faut donc vraiment se m&eacute;fier de cela si on souhaite utiliser le module <code>Random</code> &agrave; des fins cryptographiques. En pratique, le petit bout de code suivant devine assez rapidement la graine g&eacute;n&eacute;r&eacute;e, en supposant connu l'identifiant du processus (ce n'est pas bien dur &agrave; deviner sinon) et en supposant approximativement connue l'heure de l'initialisation:<br/> <br/> diff --git a/data/planet/drup.xml b/data/planet/drup.xml index b81aa7fd69..1a5c28a583 100644 --- a/data/planet/drup.xml +++ b/data/planet/drup.xml @@ -1,5 +1,5 @@ -http://drup.github.io/feed-ocaml.xmldrup2023-07-13T05:47:28-00:00http://drup.github.io/feed-ocaml.xmldrup +http://drup.github.io/feed-ocaml.xmldrup2023-07-14T05:47:25-00:00http://drup.github.io/feed-ocaml.xmldrup diff --git a/data/planet/dutherenverseauborddelatable.xml b/data/planet/dutherenverseauborddelatable.xml index 86f6cc98d9..f497f74b35 100644 --- a/data/planet/dutherenverseauborddelatable.xml +++ b/data/planet/dutherenverseauborddelatable.xml @@ -1,5 +1,5 @@ -https://dutherenverseauborddelatable.wordpress.com/category/ocaml/feed/dutherenverseauborddelatable2023-07-13T05:47:27-00:00https://dutherenverseauborddelatable.wordpress.com/category/ocaml/feed/dutherenverseauborddelatable<h2 style="text-align:justify;">tl;dr</h2> +https://dutherenverseauborddelatable.wordpress.com/category/ocaml/feed/dutherenverseauborddelatable2023-07-14T05:47:24-00:00https://dutherenverseauborddelatable.wordpress.com/category/ocaml/feed/dutherenverseauborddelatable<h2 style="text-align:justify;">tl;dr</h2> <p style="text-align:justify;">JavaScript is a dynamic language. However, by borrowing a few pages from static languages &ndash; and a few existing tools &ndash; we can considerable improve reliability and maintainability.</p> <h2 style="text-align:justify;">&laquo; Writing one million lines of code of JavaScript is simply impossible &raquo;</h2> <p style="text-align:right;">(source: speaker in a recent open-source conference)</p> diff --git a/data/planet/emelle-tv.xml b/data/planet/emelle-tv.xml index 818118acb5..83fc562c94 100644 --- a/data/planet/emelle-tv.xml +++ b/data/planet/emelle-tv.xml @@ -1,5 +1,5 @@ -https://watch.ocaml.org/feeds/videos.xml?videoChannelId=23emelle-tv2023-07-13T05:47:26-00:00https://watch.ocaml.org/feeds/videos.xml?videoChannelId=23emelle-tvhttps://watch.ocaml.org/w/u95Usnr46V4JCcdSdrBYimTalking with Gabriel Nordeborn ReScript, Relay and everything else!2023-03-17T21:20:37-00:00emelle-tvhttps://watch.ocaml.org/feeds/videos.xml?videoChannelId=23emelle-tv<p>If you would like to sponsor the show contact <a href="https://twitter.com/davesnx" target="_blank" rel="noopener noreferrer">https://twitter.com/davesnx</a></p> +https://watch.ocaml.org/feeds/videos.xml?videoChannelId=23emelle-tv2023-07-14T05:47:24-00:00https://watch.ocaml.org/feeds/videos.xml?videoChannelId=23emelle-tvhttps://watch.ocaml.org/w/u95Usnr46V4JCcdSdrBYimTalking with Gabriel Nordeborn ReScript, Relay and everything else!2023-03-17T21:20:37-00:00emelle-tvhttps://watch.ocaml.org/feeds/videos.xml?videoChannelId=23emelle-tv<p>If you would like to sponsor the show contact <a href="https://twitter.com/davesnx" target="_blank" rel="noopener noreferrer">https://twitter.com/davesnx</a></p> <p>Consider sponsoring Ant&oacute;nio's work: <a href="https://github.com/sponsors/anmonteiro" target="_blank" rel="noopener noreferrer">https://github.com/sponsors/anmonteiro</a></p> https://watch.ocaml.org/w/aEabwHEfXTKGxTNi6Xhy2aTalking with António Monteiro about Melange, Esy, Reason, OCaml and more2023-03-17T21:10:48-00:00emelle-tvhttps://watch.ocaml.org/feeds/videos.xml?videoChannelId=23emelle-tv<p>Craig Ferguson is a software developer at Tarides. Join us in this episode to talk more about OCaml, MirageOS, Irmin and much more!</p> <p>We are looking for sponsors! If you'd like to support more content for Ocaml, Reason and ReScript just send us a message at <a target="_blank" rel="noopener noreferrer">emelletvshow@gmail.com</a> -- Watch live at <a href="https://www.twitch.tv/emelletv" target="_blank" rel="noopener noreferrer">https://www.twitch.tv/emelletv</a></p> diff --git a/data/planet/emillon.xml b/data/planet/emillon.xml index 2296fb165d..728f1890d6 100644 --- a/data/planet/emillon.xml +++ b/data/planet/emillon.xml @@ -1,5 +1,5 @@ -http://blog.emillon.org/feeds/ocaml.xmlemillon2023-07-13T05:47:27-00:00http://blog.emillon.org/feeds/ocaml.xmlemillon<p>Hello! It&rsquo;s 2016, it&rsquo;s November, and apparently it rhymes with <a href="http://nabomamo.botally.net/">#NaBoMaMo</a> 2016, +http://blog.emillon.org/feeds/ocaml.xmlemillon2023-07-14T05:47:24-00:00http://blog.emillon.org/feeds/ocaml.xmlemillon<p>Hello! It&rsquo;s 2016, it&rsquo;s November, and apparently it rhymes with <a href="http://nabomamo.botally.net/">#NaBoMaMo</a> 2016, the National Bot Making Month. <a href="https://github.com/emillon/rain-bot">I made a bot!</a>.</p> <p><em>Full disclosure:</em> it&rsquo;s actually 2017, but I started writing this in 2016 so it&rsquo;s OK. Also I&rsquo;m not actually from the US, but I&rsquo;ll relax the definition a bit diff --git a/data/planet/erratique.xml b/data/planet/erratique.xml index fac285ca9a..1361c0dae2 100644 --- a/data/planet/erratique.xml +++ b/data/planet/erratique.xml @@ -1,2 +1,2 @@ -https://erratique.ch/feeds/news.atomerratique2023-07-13T05:47:27-00:00https://erratique.ch/feeds/news.atomerratiqueNeologisms for the current computing era.https://erratique.ch/writings/anti-personnel-computingAnti-personnel computing2023-06-11T14:13:42-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueFirst release of <a href="https://erratique.ch/software/qrc">Qrc</a>, a <abbr>QR</abbr> code encoder for OCaml.https://erratique.ch/software/qrcQrc2020-10-22T23:50:55-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueFirst release of <a href="https://erratique.ch/software/brr">Brr</a>, a toolkit for programming browsers in OCaml.https://erratique.ch/software/brrBrr2020-10-14T08:00:55-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueFirst release of <a href="https://erratique.ch/software/down">Down</a>, an unintrusive OCaml toplevel experience upgrade.https://erratique.ch/software/downDown2019-07-23T21:15:55-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueUucd, Uucp, Uunf and Uuseg were refreshed for Unicode 10.0.0. Find the details via the <a href="https://erratique.ch/software">software page</a>.https://erratique.ch/softwareUnicode 10.0.0 refresh2017-06-21T00:15:00-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueTen years ago I published a <a href="http://alan.petitepomme.net/cwn/2007.02.27.html#3">first bit</a> of free software. Over the <a href="https://erratique.ch/tags/OCaml">years</a>, this has now expanded to 28 OCaml packages, without counting random informally published elucubrations. Thanks to <a href="http://ocamllabs.io">OCaml Labs</a>' support, there will be more.https://erratique.ch/contact.en102017-02-27T19:15:55-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueUucd, Uucp, Uunf, Uuseg and Uutf were all refreshed for Unicode 9.0.0. They also support the new Uchar.t type introduced in OCaml 4.03 and compile with safe string. Find about them on the <a href="https://erratique.ch/software">software page</a>.https://erratique.ch/softwareUnicode 9.0.0 refresh2016-11-23T17:00:49-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueA few other new releases that went unannounced on this feed. Find about them on the <a href="https://erratique.ch/software">software page</a>.https://erratique.ch/softwareAsetmap, Bos, Hmap and Webbrowser2016-09-29T21:40:49-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>It seems the Topkg rewrite went unannounced on this feed. If you are in need of a no-nonsense release workflow to package and publish your packages on OPAM, simply topkg them.</p>https://erratique.ch/software/topkgTopkg2016-09-29T21:40:48-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Odig. If you can't keep track of the documentation of the OCaml packages you use, just odig them locally.</p>https://erratique.ch/software/odigOdig 0.0.12016-09-29T20:53:49-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueA few new releases that went unannounced on this feed. Find about them on the <a href="https://erratique.ch/software">software page</a>.https://erratique.ch/softwareAstring, Fmt, Logs, Ptime, Mtime, Rresult2015-12-24T22:55:00-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueRelease of Uucd, Uucp, Uunf and Uuseg to support Unicode 8.0.0.https://erratique.ch/softwareRelease of Uucd 3.0.0, Uucp 1.0.0, Uunf 1.0.0 and Uuseg 0.9.02015-06-17T23:55:50-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>I eventually read through John Whitington's latest book &laquo;&nbsp;More OCaml.&nbsp;&raquo; It's again a very good one, I made a small review <a href="http://www.amazon.com/review/R7DMDHZMOKS8X">here</a>.</p>http://www.amazon.com/review/R7DMDHZMOKS8XOn the book « More OCaml »2015-05-23T15:17:21-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Uuseg, Unicode text segmentation for OCaml.</p>https://erratique.ch/software/uusegUuseg 0.8.02014-12-23T21:07:47-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Cmdliner 0.9.6, consult the release notes for details.</p>https://erratique.ch/software/cmdlinerCmdliner 0.9.62014-11-18T14:23:09-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Uucp, access to Unicode character properties for OCaml. Thanks to <a href="http://ocamllabs.io">OCaml Labs</a> for sponsoring this work.</p>https://erratique.ch/software/uucpUucp 0.9.02014-06-28T21:53:49-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Uucd and Uunf to support Unicode 7.0.0.</p>https://erratique.ch/softwareUucd 2.0.0 and Uunf 0.9.32014-06-16T23:41:53-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Tsdl, thin bindings to SDL for OCaml.</p>https://erratique.ch/software/tsdlTsdl 0.8.02014-05-18T23:57:31-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Tgls, thin bindings to OpenGL {3,4} and OpenGL ES {2,3} for OCaml.</p>https://erratique.ch/software/tglsTgls 0.8.02014-05-18T17:05:49-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Opening a <a href="https://erratique.ch/log">log</a> for publishing erratic snapshots of ongoing work.</p>http://erratique.ch/logLog erratique2014-05-18T14:00:32-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p><a href="http://ocamllabs.io">OCaml Labs</a> kindly invited me to spend a second summer in Cambridge for working on OCaml free software graphical libraries. I'm looking forward to reconnect with the regular lab members and meet the other <a href="http://openmirage.org/blog/welcome-to-our-summer-hackers">interesting guests</a>.</p>https://erratique.ch/software/reactNew Cambridgian summer2014-05-09T09:13:30-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of React 1.0.0, consult the release notes for details.</p>https://erratique.ch/software/reactReact 1.0.02014-04-02T16:05:26-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Cmdliner 0.9.4, consult the release notes for details.</p>https://erratique.ch/software/cmdlinerCmdliner 0.9.42014-02-09T21:38:16-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Uucd and Uunf to support Unicode 6.3.0. Consult the individual release notes for details.</p>https://erratique.ch/softwareUucd 1.0.0 and Uunf 0.9.22013-10-01T12:54:03-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Gg and Vg. Thanks to <a href="http://www.xenproject.org/developers/teams/xapi.html">Citrix Systems R&amp;D</a> and <a href="http://ocamllabs.io">OCaml Labs</a> for sponsoring this work.</p>https://erratique.ch/softwareGg 0.8.0 and Vg 0.8.02013-09-24T22:29:33-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Uutf 0.9.3 and Xmlm 1.2.0. Consult the individual release notes for details.</p>https://erratique.ch/softwareUutf 0.9.3 and Xmlm 1.2.02013-09-06T16:55:54-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Cambridge overflows with OCaml programmers. I got to meet John Whitington of <a href="http://www.coherentpdf.com/ocaml-libraries.html">camlpdf</a> fame. He kindly offered me a copy of his book &laquo;&nbsp;<a href="http://ocaml-book.com">OCaml from the very beginning</a>. &raquo; I read it and made a small review <a href="http://www.amazon.co.uk/review/R28WYJ13WA94YL/ref=cm_cr_rdp_perm?ie=UTF8&amp;ASIN=0957671105&amp;linkCode=&amp;nodeID=&amp;tag=">here</a>.</p>http://www.amazon.co.uk/review/R28WYJ13WA94YL/ref=cm_cr_rdp_perm?ie=UTF8&ASIN=0957671105&linkCode=&nodeID=&tag=On the book « OCaml from the very beginning »2013-07-04T22:43:32-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p><a href="http://gaspardbuma.org/en">Gaspard Buma</a>'s show <em>Boats to nowhere</em> is now playing at the <a href="http://www.arsenic.ch">Arsenic</a>. I helped with the show's visuals and along the way prototyped <a href="https://erratique.ch/software/four">Four</a> a lightweight modern OpenGL rendering engine for Lua.</p>https://erratique.ch/software/fourFour2013-02-14T21:29:49-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Cmdliner 0.9.3, Uutf 0.9.2, Uunf 0.9.1 and Uucd 0.9.2. Consult the individual release notes for details.</p>https://erratique.ch/softwareWinter distribution2013-01-05T17:18:05-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Uunf, an OCaml module for Unicode text normalization.</p>https://erratique.ch/software/uunfUunf 0.9.02012-09-07T16:47:59-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Uucd, an Unicode character database decoder for OCaml.</p>https://erratique.ch/software/uucdUucd 0.9.02012-09-07T16:47:58-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Jsonm, a non-blocking streaming JSON codec for OCaml.</p>https://erratique.ch/software/jsonmJsonm 0.9.02012-05-05T14:18:37-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Uutf, a non-blocking streaming Unicode codec for OCaml.</p>https://erratique.ch/software/uutfUutf 0.9.02012-05-05T14:16:08-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Cmdliner 0.9.1, React 0.9.3, Rtime 0.9.2, Uuidm 0.9.4, and Xmlm 1.1.0. Consult the individual release notes for details. All modules now support <a href="http://oasis.ocamlcore.org"><abbr>OASIS</abbr></a>.</p>https://erratique.ch/softwareSpring release2012-03-17T11:42:26-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Cmdliner, an OCaml module for the declarative definition of command line interfaces.</p>https://erratique.ch/software/cmdlinerCmdliner 0.9.02011-05-27T14:49:02-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Fixes a bug in the weak heap implementation. Thanks to <a href="http://jaked.org">Jake Donham</a> for reporting and discussing the fix.</p>https://erratique.ch/software/reactReact 0.9.22010-04-25T20:41:26-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Minor release of React and Rtime.</p>https://erratique.ch/software/reactReact 0.9.1 and Rtime 0.9.12010-04-15T17:05:26-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Rtime, an OCaml module implementing timelines for React.</p>https://erratique.ch/software/rtimeRtime 0.9.02009-01-20T03:00:20-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of React, an OCaml module for functional reactive programming (<abbr>FRP</abbr>).</p>https://erratique.ch/software/reactReact 0.9.02009-01-20T02:57:19-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Uuidm, an OCaml module for universally unique identifiers (<abbr>UUID</abbr>s).</p>https://erratique.ch/software/uuidmUuidm 0.9.02008-06-11T18:10:19-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>New release of Xmlm. Changes are detailed in the release notes of the distribution.</p>https://erratique.ch/software/xmlmXmlm 1.0.02008-03-17T21:59:00-00:00Daniel Bünzli \ No newline at end of file +https://erratique.ch/feeds/news.atomerratique2023-07-14T05:47:24-00:00https://erratique.ch/feeds/news.atomerratiqueNeologisms for the current computing era.https://erratique.ch/writings/anti-personnel-computingAnti-personnel computing2023-06-11T14:13:42-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueFirst release of <a href="https://erratique.ch/software/qrc">Qrc</a>, a <abbr>QR</abbr> code encoder for OCaml.https://erratique.ch/software/qrcQrc2020-10-22T23:50:55-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueFirst release of <a href="https://erratique.ch/software/brr">Brr</a>, a toolkit for programming browsers in OCaml.https://erratique.ch/software/brrBrr2020-10-14T08:00:55-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueFirst release of <a href="https://erratique.ch/software/down">Down</a>, an unintrusive OCaml toplevel experience upgrade.https://erratique.ch/software/downDown2019-07-23T21:15:55-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueUucd, Uucp, Uunf and Uuseg were refreshed for Unicode 10.0.0. Find the details via the <a href="https://erratique.ch/software">software page</a>.https://erratique.ch/softwareUnicode 10.0.0 refresh2017-06-21T00:15:00-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueTen years ago I published a <a href="http://alan.petitepomme.net/cwn/2007.02.27.html#3">first bit</a> of free software. Over the <a href="https://erratique.ch/tags/OCaml">years</a>, this has now expanded to 28 OCaml packages, without counting random informally published elucubrations. Thanks to <a href="http://ocamllabs.io">OCaml Labs</a>' support, there will be more.https://erratique.ch/contact.en102017-02-27T19:15:55-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueUucd, Uucp, Uunf, Uuseg and Uutf were all refreshed for Unicode 9.0.0. They also support the new Uchar.t type introduced in OCaml 4.03 and compile with safe string. Find about them on the <a href="https://erratique.ch/software">software page</a>.https://erratique.ch/softwareUnicode 9.0.0 refresh2016-11-23T17:00:49-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueA few other new releases that went unannounced on this feed. Find about them on the <a href="https://erratique.ch/software">software page</a>.https://erratique.ch/softwareAsetmap, Bos, Hmap and Webbrowser2016-09-29T21:40:49-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>It seems the Topkg rewrite went unannounced on this feed. If you are in need of a no-nonsense release workflow to package and publish your packages on OPAM, simply topkg them.</p>https://erratique.ch/software/topkgTopkg2016-09-29T21:40:48-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Odig. If you can't keep track of the documentation of the OCaml packages you use, just odig them locally.</p>https://erratique.ch/software/odigOdig 0.0.12016-09-29T20:53:49-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueA few new releases that went unannounced on this feed. Find about them on the <a href="https://erratique.ch/software">software page</a>.https://erratique.ch/softwareAstring, Fmt, Logs, Ptime, Mtime, Rresult2015-12-24T22:55:00-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratiqueRelease of Uucd, Uucp, Uunf and Uuseg to support Unicode 8.0.0.https://erratique.ch/softwareRelease of Uucd 3.0.0, Uucp 1.0.0, Uunf 1.0.0 and Uuseg 0.9.02015-06-17T23:55:50-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>I eventually read through John Whitington's latest book &laquo;&nbsp;More OCaml.&nbsp;&raquo; It's again a very good one, I made a small review <a href="http://www.amazon.com/review/R7DMDHZMOKS8X">here</a>.</p>http://www.amazon.com/review/R7DMDHZMOKS8XOn the book « More OCaml »2015-05-23T15:17:21-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Uuseg, Unicode text segmentation for OCaml.</p>https://erratique.ch/software/uusegUuseg 0.8.02014-12-23T21:07:47-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Cmdliner 0.9.6, consult the release notes for details.</p>https://erratique.ch/software/cmdlinerCmdliner 0.9.62014-11-18T14:23:09-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Uucp, access to Unicode character properties for OCaml. Thanks to <a href="http://ocamllabs.io">OCaml Labs</a> for sponsoring this work.</p>https://erratique.ch/software/uucpUucp 0.9.02014-06-28T21:53:49-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Uucd and Uunf to support Unicode 7.0.0.</p>https://erratique.ch/softwareUucd 2.0.0 and Uunf 0.9.32014-06-16T23:41:53-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Tsdl, thin bindings to SDL for OCaml.</p>https://erratique.ch/software/tsdlTsdl 0.8.02014-05-18T23:57:31-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Tgls, thin bindings to OpenGL {3,4} and OpenGL ES {2,3} for OCaml.</p>https://erratique.ch/software/tglsTgls 0.8.02014-05-18T17:05:49-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Opening a <a href="https://erratique.ch/log">log</a> for publishing erratic snapshots of ongoing work.</p>http://erratique.ch/logLog erratique2014-05-18T14:00:32-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p><a href="http://ocamllabs.io">OCaml Labs</a> kindly invited me to spend a second summer in Cambridge for working on OCaml free software graphical libraries. I'm looking forward to reconnect with the regular lab members and meet the other <a href="http://openmirage.org/blog/welcome-to-our-summer-hackers">interesting guests</a>.</p>https://erratique.ch/software/reactNew Cambridgian summer2014-05-09T09:13:30-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of React 1.0.0, consult the release notes for details.</p>https://erratique.ch/software/reactReact 1.0.02014-04-02T16:05:26-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Cmdliner 0.9.4, consult the release notes for details.</p>https://erratique.ch/software/cmdlinerCmdliner 0.9.42014-02-09T21:38:16-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Uucd and Uunf to support Unicode 6.3.0. Consult the individual release notes for details.</p>https://erratique.ch/softwareUucd 1.0.0 and Uunf 0.9.22013-10-01T12:54:03-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Gg and Vg. Thanks to <a href="http://www.xenproject.org/developers/teams/xapi.html">Citrix Systems R&amp;D</a> and <a href="http://ocamllabs.io">OCaml Labs</a> for sponsoring this work.</p>https://erratique.ch/softwareGg 0.8.0 and Vg 0.8.02013-09-24T22:29:33-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Uutf 0.9.3 and Xmlm 1.2.0. Consult the individual release notes for details.</p>https://erratique.ch/softwareUutf 0.9.3 and Xmlm 1.2.02013-09-06T16:55:54-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Cambridge overflows with OCaml programmers. I got to meet John Whitington of <a href="http://www.coherentpdf.com/ocaml-libraries.html">camlpdf</a> fame. He kindly offered me a copy of his book &laquo;&nbsp;<a href="http://ocaml-book.com">OCaml from the very beginning</a>. &raquo; I read it and made a small review <a href="http://www.amazon.co.uk/review/R28WYJ13WA94YL/ref=cm_cr_rdp_perm?ie=UTF8&amp;ASIN=0957671105&amp;linkCode=&amp;nodeID=&amp;tag=">here</a>.</p>http://www.amazon.co.uk/review/R28WYJ13WA94YL/ref=cm_cr_rdp_perm?ie=UTF8&ASIN=0957671105&linkCode=&nodeID=&tag=On the book « OCaml from the very beginning »2013-07-04T22:43:32-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p><a href="http://gaspardbuma.org/en">Gaspard Buma</a>'s show <em>Boats to nowhere</em> is now playing at the <a href="http://www.arsenic.ch">Arsenic</a>. I helped with the show's visuals and along the way prototyped <a href="https://erratique.ch/software/four">Four</a> a lightweight modern OpenGL rendering engine for Lua.</p>https://erratique.ch/software/fourFour2013-02-14T21:29:49-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Cmdliner 0.9.3, Uutf 0.9.2, Uunf 0.9.1 and Uucd 0.9.2. Consult the individual release notes for details.</p>https://erratique.ch/softwareWinter distribution2013-01-05T17:18:05-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Uunf, an OCaml module for Unicode text normalization.</p>https://erratique.ch/software/uunfUunf 0.9.02012-09-07T16:47:59-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Uucd, an Unicode character database decoder for OCaml.</p>https://erratique.ch/software/uucdUucd 0.9.02012-09-07T16:47:58-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Jsonm, a non-blocking streaming JSON codec for OCaml.</p>https://erratique.ch/software/jsonmJsonm 0.9.02012-05-05T14:18:37-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Uutf, a non-blocking streaming Unicode codec for OCaml.</p>https://erratique.ch/software/uutfUutf 0.9.02012-05-05T14:16:08-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Release of Cmdliner 0.9.1, React 0.9.3, Rtime 0.9.2, Uuidm 0.9.4, and Xmlm 1.1.0. Consult the individual release notes for details. All modules now support <a href="http://oasis.ocamlcore.org"><abbr>OASIS</abbr></a>.</p>https://erratique.ch/softwareSpring release2012-03-17T11:42:26-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Cmdliner, an OCaml module for the declarative definition of command line interfaces.</p>https://erratique.ch/software/cmdlinerCmdliner 0.9.02011-05-27T14:49:02-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Fixes a bug in the weak heap implementation. Thanks to <a href="http://jaked.org">Jake Donham</a> for reporting and discussing the fix.</p>https://erratique.ch/software/reactReact 0.9.22010-04-25T20:41:26-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>Minor release of React and Rtime.</p>https://erratique.ch/software/reactReact 0.9.1 and Rtime 0.9.12010-04-15T17:05:26-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Rtime, an OCaml module implementing timelines for React.</p>https://erratique.ch/software/rtimeRtime 0.9.02009-01-20T03:00:20-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of React, an OCaml module for functional reactive programming (<abbr>FRP</abbr>).</p>https://erratique.ch/software/reactReact 0.9.02009-01-20T02:57:19-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>First release of Uuidm, an OCaml module for universally unique identifiers (<abbr>UUID</abbr>s).</p>https://erratique.ch/software/uuidmUuidm 0.9.02008-06-11T18:10:19-00:00Daniel Bünzlihttps://erratique.ch/feeds/news.atomerratique<p>New release of Xmlm. Changes are detailed in the release notes of the distribution.</p>https://erratique.ch/software/xmlmXmlm 1.0.02008-03-17T21:59:00-00:00Daniel Bünzli \ No newline at end of file diff --git a/data/planet/frama-c.xml b/data/planet/frama-c.xml index 83b46b0ddf..c5953da9b8 100644 --- a/data/planet/frama-c.xml +++ b/data/planet/frama-c.xml @@ -1,2 +1,2 @@ -http://frama-c.com/rss.xmlframa-c2023-07-13T05:47:27-00:00http://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/cobalt.html%20Release of Frama-C 27.0 (Cobalt)2023-06-15T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/cobalt.html%20Beta release of Frama-C 27.0~beta (Cobalt)2023-05-16T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/events/2023-04-28-cyberhackathon.html%20Cyberhackathon Frama-C + Binsec2023-04-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2023-02-28-fixed-term-use-case.html%203-year Engineer Position at CEA LIST - LSL2023-02-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2023-02-28-fixed-term-kernel.html%203-year Computer Scientist Position at CEA LIST - LSL2023-02-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2023-02-28-fixed-term-ivette.html%203-year Engineer Position at CEA LIST - LSL2023-02-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2023-02-28-fixed-term-analysis.html%203-year Computer Scientist Position at CEA LIST - LSL2023-02-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/iron.html%20Release of Frama-C 26.1 (Iron)2023-02-15T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/metacsl.html%20MetAcsl for Frama-C 26.0 Iron2022-12-09T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/iron.html%20Release of Frama-C 26.0 (Iron)2022-11-23T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2022-11-04-internship-ml4eva.html%20Internship Position at CEA LIST - LSL2022-11-04T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/iron.html%20Beta release of Frama-C 26.0~beta (Iron)2022-10-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2022-10-21-internships-eva.html%20Internship Position at CEA LIST - LSL2022-10-21T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.132022-10-06T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/manganese.html%20Release of Frama-C 25.0 (Manganese)2022-06-21T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/manganese.html%20Beta release of Frama-C 25.0~beta (Manganese)2022-05-11T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.122022-04-12T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/ltest.html%20Release of LTest 0.12022-04-08T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2022-03-28-machine-learning-for-improving-formal-verification-of-code.html%20PhD Position at CEA LIST - LSL2022-03-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2022-02-01-permanent-computer-scientist-cyber-security-verification.html%20Permanent Computer Scientist Position at CEA LIST - LSL2022-02-01T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/chromium.html%20Release of Frama-C 24.0 (Chromium)2021-11-30T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/chromium.html%20Beta release of Frama-C 24.0-beta (Chromium)2021-11-04T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2021-08-05-outline-runtime-assertion-checking.html%20PhD Position at CEA List - LSL2021-08-05T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2021-08-05-designing-compilation-techniques-for-improving-efficiency-of-e-acsl.html%20Postdoc Position at CEA List - LSL2021-08-05T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2021-08-05-control-flow-integrity-for-remote-attestation.html%20Postdoc Position at CEA List - LSL2021-08-05T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/vanadium.html%20Release of Frama-C 23.1 (Vanadium)2021-07-21T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.112021-07-13T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/vanadium.html%20Release of Frama-C 23.0 (Vanadium)2021-07-06T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/vanadium.html%20Beta release of Frama-C 23.0~rc1 (Vanadium)2021-05-20T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.102021-03-08T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/metacsl.html%20First release of MetAcsl plugin2020-12-09T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/titanium.html%20Release of Frama-C 22.0 (Titanium)2020-11-20T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/titanium.html%20Beta release of Frama-C 22.0-beta (Titanium)2020-10-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.92020-07-15T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/scandium.html%20Release of Frama-C 21.1 (Scandium)2020-06-25T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/sandium.html%20Release of Frama-C 21.0 (Scandium)2020-06-12T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.82020-03-10T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/calcium.html%20Release of Frama-C 20.0 (Calcium)2019-12-04T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/potassium.html%20Release of Frama-C 19.1 (Potassium)2019-09-17T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.72019-09-13T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/potassium.html%20Release of Frama-C 19.0 (Potassium)2019-06-21T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/events/fc-day-2019.html%20Frama-C and SPARK Day 20192019-05-18T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/argon.html%20Release of Frama-C 18.0 (Argon)2018-10-29T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.62018-07-23T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/chlorine.html%20Release of Frama-C 17.0 (Chlorine)2018-05-31T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.52018-02-19T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.42017-12-21T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/sulfur.html%20Release of Frama-C 16.0 (Sulfur)2017-11-29T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.32017-08-02T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/phosphorus.html%20Release of Frama-C 15.0 (Phosphorus)2017-05-31T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.22017-05-05T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/events/eacsl-0.8.html%20Release of E-ACSL 0.0.82017-01-17T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/silicon.html%20Release of Frama-C 14.0 (Silicon)2016-12-01T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.12016-07-04T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/aluminium.html%20Release of Frama-C 13.0 (Aluminium)2016-05-31T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/magnesium.html%20Release of Frama-C 12.0 (Magnesium)2016-01-15T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/sodium.html%20Release of Frama-C 11.0 (Sodium)2015-03-06T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/neon.html%20Release of Frama-C 10.0 (Neon)2014-03-07T00:00:00-00:00frama-c \ No newline at end of file +http://frama-c.com/rss.xmlframa-c2023-07-14T05:47:24-00:00http://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/cobalt.html%20Release of Frama-C 27.0 (Cobalt)2023-06-15T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/cobalt.html%20Beta release of Frama-C 27.0~beta (Cobalt)2023-05-16T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/events/2023-04-28-cyberhackathon.html%20Cyberhackathon Frama-C + Binsec2023-04-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2023-02-28-fixed-term-use-case.html%203-year Engineer Position at CEA LIST - LSL2023-02-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2023-02-28-fixed-term-kernel.html%203-year Computer Scientist Position at CEA LIST - LSL2023-02-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2023-02-28-fixed-term-ivette.html%203-year Engineer Position at CEA LIST - LSL2023-02-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2023-02-28-fixed-term-analysis.html%203-year Computer Scientist Position at CEA LIST - LSL2023-02-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/iron.html%20Release of Frama-C 26.1 (Iron)2023-02-15T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/metacsl.html%20MetAcsl for Frama-C 26.0 Iron2022-12-09T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/iron.html%20Release of Frama-C 26.0 (Iron)2022-11-23T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2022-11-04-internship-ml4eva.html%20Internship Position at CEA LIST - LSL2022-11-04T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/iron.html%20Beta release of Frama-C 26.0~beta (Iron)2022-10-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2022-10-21-internships-eva.html%20Internship Position at CEA LIST - LSL2022-10-21T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.132022-10-06T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/manganese.html%20Release of Frama-C 25.0 (Manganese)2022-06-21T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/manganese.html%20Beta release of Frama-C 25.0~beta (Manganese)2022-05-11T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.122022-04-12T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/ltest.html%20Release of LTest 0.12022-04-08T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2022-03-28-machine-learning-for-improving-formal-verification-of-code.html%20PhD Position at CEA LIST - LSL2022-03-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2022-02-01-permanent-computer-scientist-cyber-security-verification.html%20Permanent Computer Scientist Position at CEA LIST - LSL2022-02-01T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/chromium.html%20Release of Frama-C 24.0 (Chromium)2021-11-30T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/chromium.html%20Beta release of Frama-C 24.0-beta (Chromium)2021-11-04T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2021-08-05-outline-runtime-assertion-checking.html%20PhD Position at CEA List - LSL2021-08-05T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2021-08-05-designing-compilation-techniques-for-improving-efficiency-of-e-acsl.html%20Postdoc Position at CEA List - LSL2021-08-05T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/jobs/2021-08-05-control-flow-integrity-for-remote-attestation.html%20Postdoc Position at CEA List - LSL2021-08-05T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/vanadium.html%20Release of Frama-C 23.1 (Vanadium)2021-07-21T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.112021-07-13T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/vanadium.html%20Release of Frama-C 23.0 (Vanadium)2021-07-06T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/vanadium.html%20Beta release of Frama-C 23.0~rc1 (Vanadium)2021-05-20T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.102021-03-08T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/metacsl.html%20First release of MetAcsl plugin2020-12-09T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/titanium.html%20Release of Frama-C 22.0 (Titanium)2020-11-20T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/titanium.html%20Beta release of Frama-C 22.0-beta (Titanium)2020-10-28T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.92020-07-15T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/scandium.html%20Release of Frama-C 21.1 (Scandium)2020-06-25T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/sandium.html%20Release of Frama-C 21.0 (Scandium)2020-06-12T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.82020-03-10T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/calcium.html%20Release of Frama-C 20.0 (Calcium)2019-12-04T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/potassium.html%20Release of Frama-C 19.1 (Potassium)2019-09-17T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.72019-09-13T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/potassium.html%20Release of Frama-C 19.0 (Potassium)2019-06-21T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/events/fc-day-2019.html%20Frama-C and SPARK Day 20192019-05-18T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/argon.html%20Release of Frama-C 18.0 (Argon)2018-10-29T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.62018-07-23T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/chlorine.html%20Release of Frama-C 17.0 (Chlorine)2018-05-31T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.52018-02-19T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.42017-12-21T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/sulfur.html%20Release of Frama-C 16.0 (Sulfur)2017-11-29T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.32017-08-02T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/phosphorus.html%20Release of Frama-C 15.0 (Phosphorus)2017-05-31T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.22017-05-05T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-chttp://frama-c.com/%20/events/eacsl-0.8.html%20Release of E-ACSL 0.0.82017-01-17T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/silicon.html%20Release of Frama-C 14.0 (Silicon)2016-12-01T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-plugins/frama-clang.html%20Release of Frama-Clang 0.0.12016-07-04T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/aluminium.html%20Release of Frama-C 13.0 (Aluminium)2016-05-31T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/magnesium.html%20Release of Frama-C 12.0 (Magnesium)2016-01-15T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/sodium.html%20Release of Frama-C 11.0 (Sodium)2015-03-06T00:00:00-00:00frama-chttp://frama-c.com/rss.xmlframa-c%20https://frama-c.com/fc-versions/neon.html%20Release of Frama-C 10.0 (Neon)2014-03-07T00:00:00-00:00frama-c \ No newline at end of file diff --git a/data/planet/gaius.xml b/data/planet/gaius.xml index 6c5beab816..aa3838b162 100644 --- a/data/planet/gaius.xml +++ b/data/planet/gaius.xml @@ -1,5 +1,5 @@ -https://gaius.tech/category/ocaml/feed/gaius2023-07-13T05:47:27-00:00https://gaius.tech/category/ocaml/feed/gaius<p>Generally, every program I write, regardless of what useful thing it actually does, and regardless of what programming language it is written in, has to do certain things, which usually includes</p> +https://gaius.tech/category/ocaml/feed/gaius2023-07-14T05:47:24-00:00https://gaius.tech/category/ocaml/feed/gaius<p>Generally, every program I write, regardless of what useful thing it actually does, and regardless of what programming language it is written in, has to do certain things, which usually includes</p> <ul> <li><b>Importing a library</b> and calling functions contained within that library</li> <li><b>Handling datatypes</b> such as converting between strings and integers, and knowing when this is implicit or explicit, how dates and times work, and so on</li> diff --git a/data/planet/gallium.xml b/data/planet/gallium.xml index e4cccf5ccf..eefd5b9b0e 100644 --- a/data/planet/gallium.xml +++ b/data/planet/gallium.xml @@ -1,5 +1,5 @@ -http://gallium.inria.fr/blog/index.rssgallium2023-07-13T05:47:27-00:00http://gallium.inria.fr/blog/index.rssgallium +http://gallium.inria.fr/blog/index.rssgallium2023-07-14T05:47:24-00:00http://gallium.inria.fr/blog/index.rssgallium <p>This series of blog posts aims to give a short weekly glimpse into my diff --git a/data/planet/hannes.xml b/data/planet/hannes.xml index d76b2f2dc4..baf8a0d9a8 100644 --- a/data/planet/hannes.xml +++ b/data/planet/hannes.xml @@ -1,5 +1,5 @@ -https://hannes.robur.coop/atomhannes2023-07-13T05:47:26-00:00https://hannes.robur.coop/atomhannes<p>EDIT (2023-05-16): Updated with albatross release version 2.0.0.</p> +https://hannes.robur.coop/atomhannes2023-07-14T05:47:24-00:00https://hannes.robur.coop/atomhannes<p>EDIT (2023-05-16): Updated with albatross release version 2.0.0.</p> <h2>Deploying MirageOS unikernels</h2> <p>More than five years ago, I posted <a href="https://hannes.robur.coop/Posts/VMM">how to deploy MirageOS unikernels</a>. My motivation to work on this topic is that I'm convinced of reduced complexity, improved security, and more sustainable resource footprint of MirageOS unikernels, and want to ease deployment thereof. More than one year ago, I described <a href="https://hannes.robur.coop/Posts/Deploy">how to deploy reproducible unikernels</a>.</p> <h2>Albatross</h2> diff --git a/data/planet/hongboz.xml b/data/planet/hongboz.xml index a2413db438..765e4b847b 100644 --- a/data/planet/hongboz.xml +++ b/data/planet/hongboz.xml @@ -1,5 +1,5 @@ -https://hongboz.wordpress.com/feed/hongboz2023-07-13T05:47:28-00:00https://hongboz.wordpress.com/feed/hongboz<div> +https://hongboz.wordpress.com/feed/hongboz2023-07-14T05:47:24-00:00https://hongboz.wordpress.com/feed/hongboz<div> <p> Fan is a metaprogramming tool for OCaml. I believe it would be an<br/> invaluable tool for the community when it&rsquo;s production ready. diff --git a/data/planet/inria.xml b/data/planet/inria.xml index de2430852b..8e02eb7d3e 100644 --- a/data/planet/inria.xml +++ b/data/planet/inria.xml @@ -1,5 +1,5 @@ -http://caml.inria.fr/news.en.rssinria2023-07-13T05:47:27-00:00http://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.07/OCaml 4.07.0 released2018-07-10T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.06/OCaml 4.06.1 released2018-02-16T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.06/OCaml 4.06.0 released2017-11-03T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.05/OCaml 4.05.0 released2017-07-13T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.04/OCaml 4.04.2 released2017-06-23T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.04/OCaml 4.04.1 released2017-04-14T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinria92425dad29862b8353b58cbdb1189358Docker joins the Caml Consortium2017-01-17T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.04/OCaml 4.04.0 released2016-11-04T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinria2bae422fe363a5c4772d7945795649a0Kernelyze LLC joins the Caml Consortium2016-08-09T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinria1d9fcede0a3dceb538f0fd352d7e1b40Ahrefs joins the Caml Consortium2016-05-12T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.03/OCaml 4.03.0 released2016-04-25T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinria2c046c0e75c9ae593db7a3ff95086969Facebook joins the Caml Consortium2016-04-15T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.02/OCaml 4.02.3 released2015-07-27T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.02/OCaml 4.02.2 released2015-06-17T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinria21663c2b16d2f7e3a1c2f87deccb459eAesthetic Integration joins the Caml Consortium2015-06-03T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriae2d6bc2c4eea94d6f615b1dca68a68d5Bloomberg joins the Caml Consortium2014-11-06T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.02/OCaml 4.02.1 released2014-10-14T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://programmer-avec-ocaml.lri.fr/New book: Apprendre à programmer avec OCaml: +<feed xmlns="http://www.w3.org/2005/Atom"><id>http://caml.inria.fr/news.en.rss</id><title type="text">inria2023-07-14T05:47:24-00:00http://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.07/OCaml 4.07.0 released2018-07-10T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.06/OCaml 4.06.1 released2018-02-16T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.06/OCaml 4.06.0 released2017-11-03T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.05/OCaml 4.05.0 released2017-07-13T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.04/OCaml 4.04.2 released2017-06-23T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.04/OCaml 4.04.1 released2017-04-14T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinria92425dad29862b8353b58cbdb1189358Docker joins the Caml Consortium2017-01-17T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.04/OCaml 4.04.0 released2016-11-04T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinria2bae422fe363a5c4772d7945795649a0Kernelyze LLC joins the Caml Consortium2016-08-09T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinria1d9fcede0a3dceb538f0fd352d7e1b40Ahrefs joins the Caml Consortium2016-05-12T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.03/OCaml 4.03.0 released2016-04-25T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinria2c046c0e75c9ae593db7a3ff95086969Facebook joins the Caml Consortium2016-04-15T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.02/OCaml 4.02.3 released2015-07-27T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.02/OCaml 4.02.2 released2015-06-17T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinria21663c2b16d2f7e3a1c2f87deccb459eAesthetic Integration joins the Caml Consortium2015-06-03T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriae2d6bc2c4eea94d6f615b1dca68a68d5Bloomberg joins the Caml Consortium2014-11-06T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.02/OCaml 4.02.1 released2014-10-14T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://programmer-avec-ocaml.lri.fr/New book: Apprendre à programmer avec OCaml: Algorithmes et structures de données, by Sylvain Conchon and Jean-Christophe Filliâtre2014-09-11T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.02/OCaml 4.02.0 released2014-08-29T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttps://realworldocaml.org/New book: Real World OCaml, by Yaron Minsky, Anil Madhavepeddy, and Jason Hickey2013-11-17T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.01/OCaml 4.01.0 released2013-09-12T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://ocaml-book.com/New book: OCaml from the very beginning, by John Whitington2013-06-20T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.00/OCaml 4.00.1 released2012-10-05T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-4.00/OCaml 4.00.0 released2012-07-26T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://queue.acm.org/detail.cfm?id=2038036"OCaml for the Masses", a paper by Yaron Minsky, published in ACM Queue2011-11-05T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/ocaml/name.en.htmlObjective Caml renamed to OCaml2011-07-29T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.12/OCaml 3.12.1 released2011-07-04T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/consortium/OCamlPro becomes member of the Caml Consortium2011-05-10T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/consortium/Esterel Technologies becomes member of the Caml Consortium2011-04-20T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/consortium/Mylife.com becomes member of the Caml Consortium2010-09-21T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.12/Objective Caml 3.12.0 released2010-08-02T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.12/Objective Caml 3.12.0+beta1 released2010-06-16T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.11/Objective Caml 3.11.2 released2010-01-20T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/consortium/MLstate becomes member of the Caml Consortium2010-01-04T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.11/Objective Caml 3.11.1 released2009-06-12T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/consortium/SimCorp becomes member of the Caml Consortium2009-02-13T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://cocan.org/events/europe/ocamlmeetinggrenoble2009OCaml users' meeting in Grenoble2009-02-04T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.11/Objective Caml 3.11.0 released2008-12-04T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/consortium/OCamlCore becomes member of the Caml Consortium2008-09-19T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/consortium/CEA becomes member of the Caml Consortium2008-06-03T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.10/Objective Caml 3.10.2 released2008-02-29T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.10/Objective Caml 3.10.1 released2008-01-11T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/consortium/Jane Street Capital becomes member of the Caml Consortium2007-11-20T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/consortium/XenSource becomes member of the Caml Consortium2007-09-01T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/consortium/Intel becomes member of the Caml Consortium2007-06-15T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.10/Objective Caml 3.10 released2007-05-17T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.09/Objective Caml 3.09.3 released (bug-fix)2006-09-15T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.09/Objective Caml 3.09.2 released (bug-fix)2006-04-14T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.09/Objective Caml 3.09.1 released (bug-fix)2006-01-04T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/mantisNew bug tracker for OCaml2005-11-18T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.09/Objective Caml 3.09 released2005-10-27T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.08/Objective Caml 3.08.4 released (bug-fix)2005-08-16T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.08/Objective Caml 3.08.3 released (bug-fix)2005-03-17T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinria30297e33079d9c616e3fdf285ec1410aNew web site2005-03-14T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.08/Objective Caml 3.08.2 released (bug-fix)2004-11-01T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://www.cis.upenn.edu/proj/plclub/contest/results.phpAn Objective Caml program wins the judge's prize at the ICFP 2004 programming contest.2004-09-20T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.08/Objective Caml 3.08.1 released (bug-fix)2004-08-01T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://caml.inria.fr/pub/distrib/ocaml-3.08/Objective Caml 3.08 released2004-07-01T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriaf9b0e03d73ff565987cca9783e597276Objective Caml 3.07 released2003-10-01T00:00:00-00:00inriahttp://caml.inria.fr/news.en.rssinriahttp://www.dtek.chalmers.se/groups/icfpcontest/An Objective Caml program wins the "lightning division" at the diff --git a/data/planet/janestreet.xml b/data/planet/janestreet.xml index 2040a8db44..3c2048d189 100644 --- a/data/planet/janestreet.xml +++ b/data/planet/janestreet.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<feed xmlns="http://www.w3.org/2005/Atom"><id>https://blog.janestreet.com/feed.xml</id><title type="text">janestreet2023-07-13T05:47:26-00:00https://blog.janestreet.com/feed.xmljanestreet<p>Jane Street is excited to announce our sponsorship of +https://blog.janestreet.com/feed.xmljanestreet2023-07-14T05:47:24-00:00https://blog.janestreet.com/feed.xmljanestreet<p>Jane Street is excited to announce our sponsorship of <a href="https://some.3b1b.co/">SoME3</a>, Grant Sanderson and James Schloss&rsquo;s third Summer of Math Exposition. SoME is a contest that Grant and James created to encourage the development of fun and interesting diff --git a/data/planet/kcsrk.xml b/data/planet/kcsrk.xml index 06b8119254..fbad7f3bdf 100644 --- a/data/planet/kcsrk.xml +++ b/data/planet/kcsrk.xml @@ -1,5 +1,5 @@ -https://kcsrk.info/atom-ocaml.xmlkcsrk2023-07-13T05:47:28-00:00https://kcsrk.info/atom-ocaml.xmlkcsrk<p>It has been 3 months since I joined <a href="https://www.iitm.ac.in/">IIT Madras</a> and it +https://kcsrk.info/atom-ocaml.xmlkcsrk2023-07-14T05:47:25-00:00https://kcsrk.info/atom-ocaml.xmlkcsrk<p>It has been 3 months since I joined <a href="https://www.iitm.ac.in/">IIT Madras</a> and it has been good fun so far. Along with the members of the <a href="http://rise.cse.iitm.ac.in/">RISE group</a>, we&rsquo;ve initiated a project to build secure applications on top of secure extensions of the open-source diff --git a/data/planet/lpw25.xml b/data/planet/lpw25.xml index bf95504dd0..c9f90ad668 100644 --- a/data/planet/lpw25.xml +++ b/data/planet/lpw25.xml @@ -1,5 +1,5 @@ -http://lpw25.net/rss.xmllpw252023-07-13T05:47:28-00:00http://lpw25.net/rss.xmllpw25<div class="well well-small"> +http://lpw25.net/rss.xmllpw252023-07-14T05:47:25-00:00http://lpw25.net/rss.xmllpw25<div class="well well-small"> <h4> Contents </h4> diff --git a/data/planet/mcclurmc.xml b/data/planet/mcclurmc.xml index 0cf535beee..3a4c5d0432 100644 --- a/data/planet/mcclurmc.xml +++ b/data/planet/mcclurmc.xml @@ -1,5 +1,5 @@ -https://mcclurmc.wordpress.com/feed/mcclurmc2023-07-13T05:47:28-00:00https://mcclurmc.wordpress.com/feed/mcclurmc<p>I&rsquo;ve recently stumbled upon a useful OCaml design pattern for functorizing an existing module, without changing the way existing clients of that module use it. This is really useful for stubbing out dependencies when you&rsquo;re refactoring code for unit tests. Here&rsquo;s a simplified example from a bit of code that I refactored today.</p> +https://mcclurmc.wordpress.com/feed/mcclurmc2023-07-14T05:47:25-00:00https://mcclurmc.wordpress.com/feed/mcclurmc<p>I&rsquo;ve recently stumbled upon a useful OCaml design pattern for functorizing an existing module, without changing the way existing clients of that module use it. This is really useful for stubbing out dependencies when you&rsquo;re refactoring code for unit tests. Here&rsquo;s a simplified example from a bit of code that I refactored today.</p> <pre class="brush: plain; title: ; notranslate"> module Ovs = struct diff --git a/data/planet/mega-nerd.xml b/data/planet/mega-nerd.xml index d7d4033b16..ed16862fb4 100644 --- a/data/planet/mega-nerd.xml +++ b/data/planet/mega-nerd.xml @@ -1,5 +1,5 @@ -http://www.mega-nerd.com/erikd/Blog/index.rss20mega-nerd2023-07-13T05:47:27-00:00http://www.mega-nerd.com/erikd/Blog/index.rss20mega-nerd +http://www.mega-nerd.com/erikd/Blog/index.rss20mega-nerd2023-07-14T05:47:24-00:00http://www.mega-nerd.com/erikd/Blog/index.rss20mega-nerd <p> Disclaimer: I work at Ambiata (our diff --git a/data/planet/mgiovannini.xml b/data/planet/mgiovannini.xml index ffce826126..4426c100a9 100644 --- a/data/planet/mgiovannini.xml +++ b/data/planet/mgiovannini.xml @@ -1,5 +1,5 @@ -http://www.blogger.com/feeds/5888658295182480819/posts/defaultmgiovannini2023-07-13T05:47:28-00:00http://www.blogger.com/feeds/5888658295182480819/posts/defaultmgiovanniniThis post might seem to be in apparent contradiction: Ocamlnet is a large, very opinionated framework for network programming that solves most, if not all, those infrastructure issues that need to be taken care of when writing a networked, distributed, fault-tolerant server, from process management to string decoding and including protocol parsing and building. The fact is that Ocamlnet is not https://alaska-kamtchatka.blogspot.com/2012/10/how-to-write-simple-web-application.htmlHow to Write a Simple Web Application Using Ocamlnet2012-10-25T14:58:00-00:00Matías Giovanninihttp://www.blogger.com/feeds/5888658295182480819/posts/defaultmgiovanniniThe so-called master-transaction update is one of the, if not the defining algorithms of the discipline formerly known as &quot;data processing&quot;. Given two sorted files of records with increasing keys, the process applies each record in the transaction file to each record of the the master file and outputs the result, if any, to the updated master file in one pass over each input. The same algorithm https://alaska-kamtchatka.blogspot.com/2012/08/merge-right.htmlMerge Right2012-08-07T00:15:00-00:00Matías Giovanninihttp://www.blogger.com/feeds/5888658295182480819/posts/defaultmgiovanniniYou don't have to be writing an interpreter or some other kind of abstract code to profit from some phantom types. Suppose you have two or more functions that work by &quot;cooking&quot; a simple value (a float, say) with a lengthy computation before proceeding: +http://www.blogger.com/feeds/5888658295182480819/posts/defaultmgiovannini2023-07-14T05:47:25-00:00http://www.blogger.com/feeds/5888658295182480819/posts/defaultmgiovanniniThis post might seem to be in apparent contradiction: Ocamlnet is a large, very opinionated framework for network programming that solves most, if not all, those infrastructure issues that need to be taken care of when writing a networked, distributed, fault-tolerant server, from process management to string decoding and including protocol parsing and building. The fact is that Ocamlnet is not https://alaska-kamtchatka.blogspot.com/2012/10/how-to-write-simple-web-application.htmlHow to Write a Simple Web Application Using Ocamlnet2012-10-25T14:58:00-00:00Matías Giovanninihttp://www.blogger.com/feeds/5888658295182480819/posts/defaultmgiovanniniThe so-called master-transaction update is one of the, if not the defining algorithms of the discipline formerly known as &quot;data processing&quot;. Given two sorted files of records with increasing keys, the process applies each record in the transaction file to each record of the the master file and outputs the result, if any, to the updated master file in one pass over each input. The same algorithm https://alaska-kamtchatka.blogspot.com/2012/08/merge-right.htmlMerge Right2012-08-07T00:15:00-00:00Matías Giovanninihttp://www.blogger.com/feeds/5888658295182480819/posts/defaultmgiovanniniYou don't have to be writing an interpreter or some other kind of abstract code to profit from some phantom types. Suppose you have two or more functions that work by &quot;cooking&quot; a simple value (a float, say) with a lengthy computation before proceeding: let sun_geometric_longitude j = diff --git a/data/planet/mlin.xml b/data/planet/mlin.xml index 4aab3e0ba6..5615bb321f 100644 --- a/data/planet/mlin.xml +++ b/data/planet/mlin.xml @@ -1,5 +1,5 @@ -http://www.blogger.com/feeds/3693082774051755513/posts/default/-/OCamlmlin2023-07-13T05:47:28-00:00http://www.blogger.com/feeds/3693082774051755513/posts/default/-/OCamlmlin<b>Update (Oct 2013):</b> Anil &nbsp;Madhavapeddy has <a href="http://anil.recoil.org/2013/09/30/travis-and-ocaml.html">fleshed this out further</a>.<br/><br/> +http://www.blogger.com/feeds/3693082774051755513/posts/default/-/OCamlmlin2023-07-14T05:47:25-00:00http://www.blogger.com/feeds/3693082774051755513/posts/default/-/OCamlmlin<b>Update (Oct 2013):</b> Anil &nbsp;Madhavapeddy has <a href="http://anil.recoil.org/2013/09/30/travis-and-ocaml.html">fleshed this out further</a>.<br/><br/> This evening I spent some time getting unit tests for my OCaml projects to run on <a href="https://travis-ci.org/">Travis CI</a>, a free service for continuous integration on public GitHub projects. Although Travis has no built-in OCaml environment, it's straightforward to hijack its C environment to install OCaml and <a href="http://opam.ocamlpro.com/">OPAM</a>, then build an OCaml project and run its tests.<br/> <br/> <b>1.</b> Perform the <a href="http://about.travis-ci.org/docs/user/getting-started/">initial setup</a> to get Travis CI watching your GitHub repo (up to and including step two of that guide).<br/> diff --git a/data/planet/ocaml-book.xml b/data/planet/ocaml-book.xml index e4411cdd16..8c5cde4fd7 100644 --- a/data/planet/ocaml-book.xml +++ b/data/planet/ocaml-book.xml @@ -1,2 +1,2 @@ -http://ocaml-book.com/blog?format=rssocaml-book2023-07-13T05:47:28-00:00http://ocaml-book.com/blog?format=rssocaml-book<p class="">Thanks to a grant from the OCaml Software Foundation (<a href="http://ocaml-sf.org/">ocaml-sf.org</a>), I am able to release my 2013 book OCaml from the Very Beginning free-of-charge in the existing PDF format, and in a new HTML format:<br/><br/><a href="https://johnwhitington.net/ocamlfromtheverybeginning/">https://johnwhitington.net/ocamlfromtheverybeginning/</a><br/><br/>The book continues to be available in paperback and Kindle formats from Amazon.<br/><br/>The book has been updated for OCaml 4.14 in all formats.</p>http://ocaml-book.com/blog/2022/2/18/ocaml-from-the-very-beginning-now-free-in-html-and-pdf-formatsOCaml from the Very Beginning now free in HTML and PDF formats2022-02-18T16:49:32-00:00ocaml-bookhttp://ocaml-book.com/blog?format=rssocaml-book<p>OCaml 4.06 has, by default, immutable strings. This necessitates some changes to &quot;More OCaml&quot; (&quot;OCaml from the Very Beginning&quot; is unaffected).</p><p>The paper and kindle books (on Amazon), as well as the PDF e-book here, have been updated, together with the online resources.&nbsp;The new code works on any version of OCaml starting from 4.02.0.</p><p>If you are an existing customer, and have not received an update email, please contact the author using the form on this website.</p>http://ocaml-book.com/blog/2017/10/14/more-ocaml-updated-to-support-ocaml-406-immutable-strings"More OCaml" updated to support OCaml 4.06 immutable strings2017-10-14T16:17:10-00:00ocaml-bookhttp://ocaml-book.com/blog?format=rssocaml-book<p class="">More OCaml: Algorithms, Methods &amp; Diversions is now available on <a href="http://www.amazon.com/More-OCaml-Algorithms-Methods-Diversions/dp/0957671113/">Amazon</a> at $39.99 or less, or as a DRM-free PDF eBook for $19.99 at <a href="http://ocaml-book.com/more-ocaml-algorithms-methods-diversions/">ocaml-book.com</a>, where you will also find sample chapters, and the exercises and examples to download.</p><p class="">Here's the blurb:</p><p class="">&nbsp;</p><p class="">In&nbsp;<em>More OCaml</em>&nbsp;John Whitington takes a meandering tour of functional programming with OCaml, introducing various language features and describing some classic algorithms. The book ends with a large worked example dealing with the production of PDF files. There are questions for each chapter together with worked answers and hints.</p><p class=""><em>More OCaml</em>&nbsp;will appeal both to existing OCaml programmers who wish to brush up their skills, and to experienced programmers eager to explore functional languages such as OCaml. It is hoped that each reader will find something new, or see an old thing in a new light. For the more casual reader, or those who are used to a different functional language, a summary of basic OCaml is provided at the front of the book.</p><p class="">&nbsp;</p><p class="">If you buy the book, please do consider leaving a review on Amazon, which you can do even if you buy just the PDF eBook.</p><p class="">&nbsp;</p>http://ocaml-book.com/blog/2014/8/27/more-ocaml-algorithms-methods-diversionsMore OCaml: Algorithms, Methods & Diversions2014-08-27T12:00:32-00:00ocaml-bookhttp://ocaml-book.com/blog?format=rssocaml-book<p>Owing to the print-on-demand process we're using, it's simple to update the book to fix the few errata which have been pointed out by kind readers since publication. The new text is now live on <a href="http://www.amazon.com/OCaml-Very-Beginning-John-Whitington/dp/0957671105">Amazon</a>, the <a href="http://www.amazon.com/OCaml-Very-Beginning-ebook/dp/B00DJF1ZBQ/ref=tmm_kin_swatch_0?_encoding=UTF8&amp;sr=&amp;qid=">Kindle Store</a>, and <a href="http://www.ocaml-book.com/">our website</a>.&nbsp;</p><p>To update the Kindle copy, go to &quot;Manage My Kindle&quot; on Amazon (there is no automatic update process).&nbsp;</p><p>If you have purchased a PDF e-book, just email us for an updated PDF (it is possible to notify customers of an updated version by email, but since none of the errata are serious, we've opted not to do so).&nbsp;</p><p>If you have a physical book, you can fix the errata yourself from the <a href="http://ocaml-book.com/errata/">errata page</a> on the website. In addition, if you have purchased the physical book, and would like a copy of the new PDF, please forward your amazon receipt to <a href="mailto:contact@coherentgraphics.co.uk">contact@coherentgraphics.co.uk</a>&nbsp;</p><p>And finally, if you have found mistakes in the book (or have any suggestions for the next edition), please do tell us, using the <a href="http://ocaml-book.com/contact/">contact form</a> on the website.&nbsp;</p><p>&nbsp;</p>http://ocaml-book.com/blog/2013/10/15/reprinting-of-ocaml-from-the-very-beginningReprinting of "OCaml from the Very Beginning"2013-10-15T14:31:28-00:00ocaml-bookhttp://ocaml-book.com/blog?format=rssocaml-book<p>I've made a few little tutorial videos to go with the book. Just seven for now, covering the first four chapters, but more to come:</p><ol><li>Evaluating an expression</li><li>True and false</li><li>Making decisions</li><li>Names and functions</li><li>Patterns</li><li>Lists</li><li>Take and drop</li><li>Appending two lists</li></ol><p>They're not really a substitute for the book but, when learning, it's always helpful to go over things twice, particularly using a different medium.</p><p>The videos are available <a href="http://ocaml-book.com/videos/">here</a>.&nbsp;</p><p>&nbsp;</p>http://ocaml-book.com/blog/2013/9/27/ocaml-tutorial-videos-now-availableOCaml tutorial videos now available2013-09-27T14:04:48-00:00ocaml-bookhttp://ocaml-book.com/blog?format=rssocaml-book<p class="">OCaml from the Very Beginning (204pp, paperback) is now available <a href="http://www.amazon.com/OCaml-Very-Beginning-John-Whitington/dp/0957671105%3FSubscriptionId=0ENGV10E9K9QDNSJ5C82&amp;tag=coherentpdfco-21&amp;linkCode=xm2&amp;camp=2025&amp;creative=165953&amp;creativeASIN=0957671105">on Amazon</a> for $39.99 / &euro;29.99 / &pound;24.99, as well as an e-book from <a href="http://www.ocaml-book.com/">ocaml-book.com</a> for $19.99.&nbsp;Here are <a href="http://www.ocaml-book.com/">preview chapters</a> and <a href="http://ocaml-book.com/s/ocaml-from-the-very-beginning-examples-and-exercises.zip">a .zip of the examples and exercises</a>.&nbsp;</p><p class="">Here's the blurb:&nbsp;<br/></p><blockquote><p class="">In <em>OCaml from the Very Beginning</em> John Whitington takes a no-prerequisites approach to teaching a modern general-purpose programming language. Each small, self-contained chapter introduces a new topic, building until the reader can write quite substantial programs. There are plenty of questions and, crucially, worked answers and hints.</p></blockquote><blockquote><p class=""><em>OCaml from the Very Beginning</em> will appeal both to new programmers, and experienced programmers eager to explore functional languages such as OCaml. It is suitable both for formal use within an undergraduate or graduate curriculum, and for the interested amateur.</p></blockquote><p data-rte-preserve-empty="true" class=""></p><p class="">Please do review the book on Amazon if you have the chance.</p><p class="">&nbsp;</p>http://ocaml-book.com/blog/2013/6/6/now-available-on-amazonNow available on Amazon2013-06-07T14:21:23-00:00ocaml-book \ No newline at end of file +http://ocaml-book.com/blog?format=rssocaml-book2023-07-14T05:47:25-00:00http://ocaml-book.com/blog?format=rssocaml-book<p class="">Thanks to a grant from the OCaml Software Foundation (<a href="http://ocaml-sf.org/">ocaml-sf.org</a>), I am able to release my 2013 book OCaml from the Very Beginning free-of-charge in the existing PDF format, and in a new HTML format:<br/><br/><a href="https://johnwhitington.net/ocamlfromtheverybeginning/">https://johnwhitington.net/ocamlfromtheverybeginning/</a><br/><br/>The book continues to be available in paperback and Kindle formats from Amazon.<br/><br/>The book has been updated for OCaml 4.14 in all formats.</p>http://ocaml-book.com/blog/2022/2/18/ocaml-from-the-very-beginning-now-free-in-html-and-pdf-formatsOCaml from the Very Beginning now free in HTML and PDF formats2022-02-18T16:49:32-00:00ocaml-bookhttp://ocaml-book.com/blog?format=rssocaml-book<p>OCaml 4.06 has, by default, immutable strings. This necessitates some changes to &quot;More OCaml&quot; (&quot;OCaml from the Very Beginning&quot; is unaffected).</p><p>The paper and kindle books (on Amazon), as well as the PDF e-book here, have been updated, together with the online resources.&nbsp;The new code works on any version of OCaml starting from 4.02.0.</p><p>If you are an existing customer, and have not received an update email, please contact the author using the form on this website.</p>http://ocaml-book.com/blog/2017/10/14/more-ocaml-updated-to-support-ocaml-406-immutable-strings"More OCaml" updated to support OCaml 4.06 immutable strings2017-10-14T16:17:10-00:00ocaml-bookhttp://ocaml-book.com/blog?format=rssocaml-book<p class="">More OCaml: Algorithms, Methods &amp; Diversions is now available on <a href="http://www.amazon.com/More-OCaml-Algorithms-Methods-Diversions/dp/0957671113/">Amazon</a> at $39.99 or less, or as a DRM-free PDF eBook for $19.99 at <a href="http://ocaml-book.com/more-ocaml-algorithms-methods-diversions/">ocaml-book.com</a>, where you will also find sample chapters, and the exercises and examples to download.</p><p class="">Here's the blurb:</p><p class="">&nbsp;</p><p class="">In&nbsp;<em>More OCaml</em>&nbsp;John Whitington takes a meandering tour of functional programming with OCaml, introducing various language features and describing some classic algorithms. The book ends with a large worked example dealing with the production of PDF files. There are questions for each chapter together with worked answers and hints.</p><p class=""><em>More OCaml</em>&nbsp;will appeal both to existing OCaml programmers who wish to brush up their skills, and to experienced programmers eager to explore functional languages such as OCaml. It is hoped that each reader will find something new, or see an old thing in a new light. For the more casual reader, or those who are used to a different functional language, a summary of basic OCaml is provided at the front of the book.</p><p class="">&nbsp;</p><p class="">If you buy the book, please do consider leaving a review on Amazon, which you can do even if you buy just the PDF eBook.</p><p class="">&nbsp;</p>http://ocaml-book.com/blog/2014/8/27/more-ocaml-algorithms-methods-diversionsMore OCaml: Algorithms, Methods & Diversions2014-08-27T12:00:32-00:00ocaml-bookhttp://ocaml-book.com/blog?format=rssocaml-book<p>Owing to the print-on-demand process we're using, it's simple to update the book to fix the few errata which have been pointed out by kind readers since publication. The new text is now live on <a href="http://www.amazon.com/OCaml-Very-Beginning-John-Whitington/dp/0957671105">Amazon</a>, the <a href="http://www.amazon.com/OCaml-Very-Beginning-ebook/dp/B00DJF1ZBQ/ref=tmm_kin_swatch_0?_encoding=UTF8&amp;sr=&amp;qid=">Kindle Store</a>, and <a href="http://www.ocaml-book.com/">our website</a>.&nbsp;</p><p>To update the Kindle copy, go to &quot;Manage My Kindle&quot; on Amazon (there is no automatic update process).&nbsp;</p><p>If you have purchased a PDF e-book, just email us for an updated PDF (it is possible to notify customers of an updated version by email, but since none of the errata are serious, we've opted not to do so).&nbsp;</p><p>If you have a physical book, you can fix the errata yourself from the <a href="http://ocaml-book.com/errata/">errata page</a> on the website. In addition, if you have purchased the physical book, and would like a copy of the new PDF, please forward your amazon receipt to <a href="mailto:contact@coherentgraphics.co.uk">contact@coherentgraphics.co.uk</a>&nbsp;</p><p>And finally, if you have found mistakes in the book (or have any suggestions for the next edition), please do tell us, using the <a href="http://ocaml-book.com/contact/">contact form</a> on the website.&nbsp;</p><p>&nbsp;</p>http://ocaml-book.com/blog/2013/10/15/reprinting-of-ocaml-from-the-very-beginningReprinting of "OCaml from the Very Beginning"2013-10-15T14:31:28-00:00ocaml-bookhttp://ocaml-book.com/blog?format=rssocaml-book<p>I've made a few little tutorial videos to go with the book. Just seven for now, covering the first four chapters, but more to come:</p><ol><li>Evaluating an expression</li><li>True and false</li><li>Making decisions</li><li>Names and functions</li><li>Patterns</li><li>Lists</li><li>Take and drop</li><li>Appending two lists</li></ol><p>They're not really a substitute for the book but, when learning, it's always helpful to go over things twice, particularly using a different medium.</p><p>The videos are available <a href="http://ocaml-book.com/videos/">here</a>.&nbsp;</p><p>&nbsp;</p>http://ocaml-book.com/blog/2013/9/27/ocaml-tutorial-videos-now-availableOCaml tutorial videos now available2013-09-27T14:04:48-00:00ocaml-bookhttp://ocaml-book.com/blog?format=rssocaml-book<p class="">OCaml from the Very Beginning (204pp, paperback) is now available <a href="http://www.amazon.com/OCaml-Very-Beginning-John-Whitington/dp/0957671105%3FSubscriptionId=0ENGV10E9K9QDNSJ5C82&amp;tag=coherentpdfco-21&amp;linkCode=xm2&amp;camp=2025&amp;creative=165953&amp;creativeASIN=0957671105">on Amazon</a> for $39.99 / &euro;29.99 / &pound;24.99, as well as an e-book from <a href="http://www.ocaml-book.com/">ocaml-book.com</a> for $19.99.&nbsp;Here are <a href="http://www.ocaml-book.com/">preview chapters</a> and <a href="http://ocaml-book.com/s/ocaml-from-the-very-beginning-examples-and-exercises.zip">a .zip of the examples and exercises</a>.&nbsp;</p><p class="">Here's the blurb:&nbsp;<br/></p><blockquote><p class="">In <em>OCaml from the Very Beginning</em> John Whitington takes a no-prerequisites approach to teaching a modern general-purpose programming language. Each small, self-contained chapter introduces a new topic, building until the reader can write quite substantial programs. There are plenty of questions and, crucially, worked answers and hints.</p></blockquote><blockquote><p class=""><em>OCaml from the Very Beginning</em> will appeal both to new programmers, and experienced programmers eager to explore functional languages such as OCaml. It is suitable both for formal use within an undergraduate or graduate curriculum, and for the interested amateur.</p></blockquote><p data-rte-preserve-empty="true" class=""></p><p class="">Please do review the book on Amazon if you have the chance.</p><p class="">&nbsp;</p>http://ocaml-book.com/blog/2013/6/6/now-available-on-amazonNow available on Amazon2013-06-07T14:21:23-00:00ocaml-book \ No newline at end of file diff --git a/data/planet/ocamlcore.xml b/data/planet/ocamlcore.xml index cfe44cae09..2e93478224 100644 --- a/data/planet/ocamlcore.xml +++ b/data/planet/ocamlcore.xml @@ -1,5 +1,5 @@ -http://www.ocamlcore.com/wp/feed/?amp%3Blanguage=en&language=enocamlcore2023-07-13T05:47:28-00:00http://www.ocamlcore.com/wp/feed/?amp%3Blanguage=en&language=enocamlcore<p>As I have announced <a href="http://forge.ocamlcore.org/forum/forum.php?forum_id=811">2 years ago</a>, I decided to move to a new company and to take new challenges. The website, www.ocamlcore.com, will soon be converted to a static website. As announced, this change will <strong>not</strong> affect at all the community services offered through ocamlcore.org (especially forge.ocamlcore.org), except that we will migrate to .ocaml.org DNS (soon) but we will keep the old DNS as well with some redirect.</p> +http://www.ocamlcore.com/wp/feed/?amp%3Blanguage=en&language=enocamlcore2023-07-14T05:47:25-00:00http://www.ocamlcore.com/wp/feed/?amp%3Blanguage=en&language=enocamlcore<p>As I have announced <a href="http://forge.ocamlcore.org/forum/forum.php?forum_id=811">2 years ago</a>, I decided to move to a new company and to take new challenges. The website, www.ocamlcore.com, will soon be converted to a static website. As announced, this change will <strong>not</strong> affect at all the community services offered through ocamlcore.org (especially forge.ocamlcore.org), except that we will migrate to .ocaml.org DNS (soon) but we will keep the old DNS as well with some redirect.</p> <p>I am very happy to have been able to run this company for 4 years. This was great and helps me to tackle various challenge in OCaml.</p> <p>Thanks to all the <a href="http://www.ocamlcore.com/wp/company/clients/">companies</a> that supported me during this journey.</p> http://www.ocamlcore.com/wp/2013/10/ocamlcore-sarl-is-now-officially-closed/OCamlCore SARL is now officially closed.2013-10-17T22:30:21-00:00ocamlcorehttp://www.ocamlcore.com/wp/feed/?amp%3Blanguage=en&language=enocamlcore<p>4 weeks ago, on Friday April 15th, the annual OCaml Meeting took place at Telecom Paris. OCamlCore (the company), organized this meeting for the fourth time. The event was quite a successful day. There were 65 attendees and 12 talks.</p> diff --git a/data/planet/ocamljava.xml b/data/planet/ocamljava.xml index c6939f818c..e468576fdb 100644 --- a/data/planet/ocamljava.xml +++ b/data/planet/ocamljava.xml @@ -1,5 +1,5 @@ -http://www.ocamljava.org/feed.xmlocamljava2023-07-13T05:47:28-00:00http://www.ocamljava.org/feed.xmlocamljava<p>The third alpha version is finally available, fixing several bugs, and enhancing the Java library.</p> +http://www.ocamljava.org/feed.xmlocamljava2023-07-14T05:47:25-00:00http://www.ocamljava.org/feed.xmlocamljava<p>The third alpha version is finally available, fixing several bugs, and enhancing the Java library.</p> http://www.ocamljava.org/news/index.html#alpha3Third alpha version2015-06-08T22:00:00-00:00Xavier Clerchttp://www.ocamljava.org/feed.xmlocamljava<p>The new release, namely <em>2.0-alpha2</em>, is mainly a bugfix relase, fixing the following issues:</p> http://www.ocamljava.org/2014/09/22/alpha2/Alpha22014-09-22T21:00:00-00:00Xavier Clerchttp://www.ocamljava.org/feed.xmlocamljava<p>A new alpha version has been released, fixing several blocking / annoying bugs.</p> http://www.ocamljava.org/news/index.html#alpha2New alpha version2014-09-22T21:00:00-00:00Xavier Clerchttp://www.ocamljava.org/feed.xmlocamljava<p>The project is finally <em>re</em>-open-sourced. Well, at least partially: the code for the compiler and associated tools, as well as libraries is available. The code for the runtime support library is not yet, but will follow once cleaned. Put otherwise, the part of the project written in OCaml is fully available, while the part written in Java remains <em>closed</em>. As it is nevertheless quite a big step forward, the version has changed from <em>early-access</em> to <em>alpha</em>.</p> diff --git a/data/planet/ocamllabs.xml b/data/planet/ocamllabs.xml index e835e88643..d27fbedbae 100644 --- a/data/planet/ocamllabs.xml +++ b/data/planet/ocamllabs.xml @@ -1,5 +1,5 @@ -http://ocamllabs.io/compiler-hacking/rss.xmlocamllabs2023-07-13T05:47:28-00:00http://ocamllabs.io/compiler-hacking/rss.xmlocamllabs<p>Our next OCaml Compiler Hacking event will be on Thursday 7th December in The Thomas Gray Room at Pembroke College, Cambridge.</p> +http://ocamllabs.io/compiler-hacking/rss.xmlocamllabs2023-07-14T05:47:25-00:00http://ocamllabs.io/compiler-hacking/rss.xmlocamllabs<p>Our next OCaml Compiler Hacking event will be on Thursday 7th December in The Thomas Gray Room at Pembroke College, Cambridge.</p> <p>If you're planning to come along, it'd be helpful if you could <a href="https://doodle.com/poll/khqk6i49r4828apu">indicate interest via Doodle</a> and <a href="http://lists.ocaml.org/admin/cam-compiler-hacking">sign up to the mailing list</a> to receive updates.</p> diff --git a/data/planet/ocsigen.xml b/data/planet/ocsigen.xml index 674108cf1f..9dffd34a9b 100644 --- a/data/planet/ocsigen.xml +++ b/data/planet/ocsigen.xml @@ -1,5 +1,5 @@ -https://ocsigen.org/feed.xmlocsigen2023-07-13T05:47:28-00:00https://ocsigen.org/feed.xmlocsigen<p>New release: Ocsigen Start 2.18</p> +https://ocsigen.org/feed.xmlocsigen2023-07-14T05:47:25-00:00https://ocsigen.org/feed.xmlocsigen<p>New release: Ocsigen Start 2.18</p> <p><a href="https://ocsigen.org/ocsigen-start/">Ocsigen Start</a> is a template for client-server Web and/or mobile app in OCaml or ReasonML. It contains many standard features like user management, notifications, and many code examples. diff --git a/data/planet/opa.xml b/data/planet/opa.xml index f57d9c5d8d..313b879a4d 100644 --- a/data/planet/opa.xml +++ b/data/planet/opa.xml @@ -1,5 +1,5 @@ -http://www.blogger.com/feeds/2073503406800427577/posts/defaultopa2023-07-13T05:47:28-00:00http://www.blogger.com/feeds/2073503406800427577/posts/defaultopaAs many of you know, the main source to learn Opa is the O'Reilly book: <a href="http://shop.oreilly.com/product/0636920025436.do">Opa, Up and Running</a>*.<br/> +http://www.blogger.com/feeds/2073503406800427577/posts/defaultopa2023-07-14T05:47:25-00:00http://www.blogger.com/feeds/2073503406800427577/posts/defaultopaAs many of you know, the main source to learn Opa is the O'Reilly book: <a href="http://shop.oreilly.com/product/0636920025436.do">Opa, Up and Running</a>*.<br/> <br/> One of the highlight of the book is a walk-through the development of Birdy, a micro-blogging platform, aka. mini-Twitter.<br/> <br/> diff --git a/data/planet/orbitz.xml b/data/planet/orbitz.xml index 6b762c7a85..a4a36cfc6e 100644 --- a/data/planet/orbitz.xml +++ b/data/planet/orbitz.xml @@ -1,5 +1,5 @@ -http://functional-orbitz.blogspot.com/feeds/posts/default/-/planetocaml?alt=rssorbitz2023-07-13T05:47:28-00:00http://functional-orbitz.blogspot.com/feeds/posts/default/-/planetocaml?alt=rssorbitz<p> +http://functional-orbitz.blogspot.com/feeds/posts/default/-/planetocaml?alt=rssorbitz2023-07-14T05:47:25-00:00http://functional-orbitz.blogspot.com/feeds/posts/default/-/planetocaml?alt=rssorbitz<p> <i>Note, this post is written against the 2.0.1 version of <code>gen_server</code></i> </p> diff --git a/data/planet/pdonadeo.xml b/data/planet/pdonadeo.xml index 034bd3ba37..d420e31db0 100644 --- a/data/planet/pdonadeo.xml +++ b/data/planet/pdonadeo.xml @@ -1,5 +1,5 @@ -http://www.donadeo.net/facets/programming-languages/objective-caml/feed/pdonadeo2023-07-13T05:47:28-00:00http://www.donadeo.net/facets/programming-languages/objective-caml/feed/pdonadeo<div> +http://www.donadeo.net/facets/programming-languages/objective-caml/feed/pdonadeo2023-07-14T05:47:25-00:00http://www.donadeo.net/facets/programming-languages/objective-caml/feed/pdonadeo<div> <p class="noindent">I'm in this situation: I need to compile an OCaml program on a CentOS 6.5 server. This is actually quite problematic, because CentOS 6.5 provide out of the box a very old OCaml 3.11.2, released by INRIA in January 2010, more than four years ago.</p> <p class="noindent">No problem, <a href="https://opam.ocaml.org/" title="OPAM - Home">OPAM</a> come to the rescue! No. The OPAM team doesn't provide a binary executable compatible with the (actually very old) system libraries present in CentOS. diff --git a/data/planet/psellos.xml b/data/planet/psellos.xml index d095a09f78..a9beb27853 100644 --- a/data/planet/psellos.xml +++ b/data/planet/psellos.xml @@ -1,5 +1,5 @@ -http://psellos.com/atom.xmlpsellos2023-07-13T05:47:28-00:00http://psellos.com/atom.xmlpsellos<div class="date">August 26, 2020</div> +http://psellos.com/atom.xmlpsellos2023-07-14T05:47:25-00:00http://psellos.com/atom.xmlpsellos<div class="date">August 26, 2020</div> <p>Since last year I&rsquo;ve been using BuckleScript to build web apps in OCaml and have been enjoying it very much. However, when I went to the diff --git a/data/planet/reynard.xml b/data/planet/reynard.xml index 2df0c816a3..bdd159cd21 100644 --- a/data/planet/reynard.xml +++ b/data/planet/reynard.xml @@ -1,5 +1,5 @@ -http://reynard.io/feed.xmlreynard2023-07-13T05:47:28-00:00http://reynard.io/feed.xmlreynard<p>Thanks to everyone who joined us for OCaml Compiler Hacking in the (incredibly warm!) Old Library at Pembroke College this week.</p> +http://reynard.io/feed.xmlreynard2023-07-14T05:47:24-00:00http://reynard.io/feed.xmlreynard<p>Thanks to everyone who joined us for OCaml Compiler Hacking in the (incredibly warm!) Old Library at Pembroke College this week.</p> <p>Prior to the event, we attempted a temporary update of the <a href="https://github.com/ocamllabs/compiler-hacking/wiki/Things-to-work-on">&ldquo;Things to Work On&rdquo;</a> wiki page, and added some projects needing attention (thank you to Mark Shinwell, David Allsopp and Anil Madhavapeddy). We will go through the list in more detail this month and update the remaining items. If you have any suggestions for compiler projects, please join the discussion on the <a href="http://lists.ocaml.org/listinfo/cam-compiler-hacking">mailing list</a>, or in the <a href="https://discuss.ocaml.org/t/ocaml-compiler-hacking-event/140">OCaml Discourse Forum</a>.</p> diff --git a/data/planet/rgrinberg.xml b/data/planet/rgrinberg.xml index 42b55f5c86..dbd608fcf8 100644 --- a/data/planet/rgrinberg.xml +++ b/data/planet/rgrinberg.xml @@ -1,5 +1,5 @@ -http://rgrinberg.com/blog/atom.xmlrgrinberg2023-07-13T05:47:28-00:00http://rgrinberg.com/blog/atom.xmlrgrinberg<p>There&rsquo;s been some recent grumbling about the usability of ppx in OCaml, and +http://rgrinberg.com/blog/atom.xmlrgrinberg2023-07-14T05:47:25-00:00http://rgrinberg.com/blog/atom.xmlrgrinberg<p>There&rsquo;s been some recent grumbling about the usability of ppx in OCaml, and instead of just letting it slide again, I&rsquo;ve decided to do something constructive about this and write a little tutorial on how to write a <code class="docutils literal notranslate"><span class="pre">deriving</span></code> plugin.</p> diff --git a/data/planet/rjones.xml b/data/planet/rjones.xml index cfa8f9d720..acc2219dac 100644 --- a/data/planet/rjones.xml +++ b/data/planet/rjones.xml @@ -1,5 +1,5 @@ -https://rwmj.wordpress.com/tag/ocaml/feed/rjones2023-07-13T05:47:28-00:00https://rwmj.wordpress.com/tag/ocaml/feed/rjones<p><a href="https://github.com/ocaml/ocaml/commit/8f3833c4d0ef656c826359f4137c1eb3d46ea0ef">https://github.com/ocaml/ocaml/commit/8f3833c4d0ef656c826359f4137c1eb3d46ea0ef</a></p> +https://rwmj.wordpress.com/tag/ocaml/feed/rjones2023-07-14T05:47:25-00:00https://rwmj.wordpress.com/tag/ocaml/feed/rjones<p><a href="https://github.com/ocaml/ocaml/commit/8f3833c4d0ef656c826359f4137c1eb3d46ea0ef">https://github.com/ocaml/ocaml/commit/8f3833c4d0ef656c826359f4137c1eb3d46ea0ef</a></p> <p>We&rsquo;ve been <a href="https://rwmj.wordpress.com/2016/11/19/ocaml-4-04-risc-v-s390-power-and-more/">using this patch in Fedora since Nov 2016</a>.</p> https://rwmj.wordpress.com/2020/04/24/ocaml-risc-v-port-is-now-upstream/OCaml RISC-V port is now upstream!2020-04-24T14:34:36-00:00rjoneshttps://rwmj.wordpress.com/tag/ocaml/feed/rjones<p><a href="http://libguestfs.org/">libguestfs</a> is a C library for creating and editing disk images. In the most common (but not the only) configuration, it uses KVM to sandbox access to disk images. The C library talks to a separate daemon running inside a KVM appliance, as in this Unicode-art diagram taken from the <a href="http://libguestfs.org/guestfs-internals.1.html#architecture">fine manual</a>:</p> <pre> diff --git a/data/planet/sfletcher.xml b/data/planet/sfletcher.xml index f4504209f4..31695acd65 100644 --- a/data/planet/sfletcher.xml +++ b/data/planet/sfletcher.xml @@ -1,5 +1,5 @@ -http://blog.shaynefletcher.org/feeds/posts/default/-/OCamlsfletcher2023-07-13T05:47:28-00:00http://blog.shaynefletcher.org/feeds/posts/default/-/OCamlsfletcher<html><head> +http://blog.shaynefletcher.org/feeds/posts/default/-/OCamlsfletcher2023-07-14T05:47:25-00:00http://blog.shaynefletcher.org/feeds/posts/default/-/OCamlsfletcher<html><head> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/> <title>Bucket Sort</title> diff --git a/data/planet/signalsandthreads.xml b/data/planet/signalsandthreads.xml index 576ebd4ff6..31771ba8b3 100644 --- a/data/planet/signalsandthreads.xml +++ b/data/planet/signalsandthreads.xml @@ -1,5 +1,5 @@ -https://feeds.simplecast.com/L9810DOasignalsandthreads2023-07-13T05:47:28-00:00https://feeds.simplecast.com/L9810DOasignalsandthreads<p>Richard Eisenberg is one of the core maintainers of Haskell. He recently joined Jane Street&rsquo;s Tools and Compilers team, where he hacks on the OCaml compiler. He and Ron discuss the powerful language feature that got him into PL design in the first place&mdash;dependent types&mdash;and its role in a world where AIs can (somewhat) competently write your code for you. They also discuss the differences between Haskell and OCaml; the perils of trying to make a language that works for everybody; and how best a company like Jane Street can collaborate with the open source community.</p><p>You can find the transcript for this episode &nbsp;on our <a href="https://signalsandthreads.com/future-of-programming" target="_blank">website.</a></p><p>Some links to topics that came up in the discussion:</p><ul><li><a href="https://wiki.haskell.org/Dependent_type">Dependent types</a></li><li><a href="https://www.haskell.org/ghc/">GHC</a></li><li><a href="https://www.janestreet.com/tech-talks/unboxed-types-for-ocaml/">Unboxed types in OCaml</a></li><li><a href="https://typeclasses.com/extensions-intro">Language extensions in Haskell</a></li></ul> +https://feeds.simplecast.com/L9810DOasignalsandthreads2023-07-14T05:47:25-00:00https://feeds.simplecast.com/L9810DOasignalsandthreads<p>Richard Eisenberg is one of the core maintainers of Haskell. He recently joined Jane Street&rsquo;s Tools and Compilers team, where he hacks on the OCaml compiler. He and Ron discuss the powerful language feature that got him into PL design in the first place&mdash;dependent types&mdash;and its role in a world where AIs can (somewhat) competently write your code for you. They also discuss the differences between Haskell and OCaml; the perils of trying to make a language that works for everybody; and how best a company like Jane Street can collaborate with the open source community.</p><p>You can find the transcript for this episode &nbsp;on our <a href="https://signalsandthreads.com/future-of-programming" target="_blank">website.</a></p><p>Some links to topics that came up in the discussion:</p><ul><li><a href="https://wiki.haskell.org/Dependent_type">Dependent types</a></li><li><a href="https://www.haskell.org/ghc/">GHC</a></li><li><a href="https://www.janestreet.com/tech-talks/unboxed-types-for-ocaml/">Unboxed types in OCaml</a></li><li><a href="https://typeclasses.com/extensions-intro">Language extensions in Haskell</a></li></ul> https://signals-threads.simplecast.com/episodes/the-future-of-programming-with-richard-eisenberg-pOktpZ_eThe Future of Programming with Richard Eisenberg2023-05-18T15:15:49-00:00signals-and-threads@janestreet.com (Jane Street)signalsandthreadshttps://feeds.simplecast.com/L9810DOasignalsandthreads<p>Ella Ehrlich has been a developer at Jane Street for close to a decade. During much of that time, she&rsquo;s worked on Gord, one of Jane Street&rsquo;s oldest and most critical systems, which is responsible for normalizing and distributing the firm&rsquo;s trading data. Ella and Ron talk about how to grow and modernize a legacy system without compromising uptime, why game developers are the &ldquo;musicians of software,&rdquo; and some of the work Jane Street has done to try to hire a more diverse set of software engineers.</p><p>You can find the transcript for this episode &nbsp;on our <a href="https://signalsandthreads.com/swapping-the-engine-out-of-a-moving-race-car" target="_blank">website.</a></p><p>Some links to topics that came up in the discussion:</p><ul><li><a href="https://lol.fandom.com/wiki/Evil_Geniuses.NA">EG</a>, The League of Legends team that Ella is a huge fan of.</li><li><a href="https://kafka.apache.org/">Apache Kafka</a>, the message bus that Gord migrated to.</li><li>Some of the <a href="https://www.openfigi.com/">various</a> <a href="https://en.wikipedia.org/wiki/Reuters_Instrument_Code">sources</a> <a href="https://www.cmegroup.com/tools-information/vendorSymbol.html">of</a> <a href="https://www.isin.org/">symbology</a> you have to deal with when normalizing trading data. (Really, there are too many sources to list here!)</li><li>A list of Jane Street&rsquo;s recruiting <a href="https://www.janestreet.com/join-jane-street/programs-and-events/">Programs and Events</a>, including <a href="https://www.janestreet.com/join-jane-street/programs-and-events/insight/">INSIGHT</a>, which focuses on women, and <a href="https://www.janestreet.com/join-jane-street/programs-and-events/in-focus/">IN FOCUS</a>, which focuses on historically underrepresented ethnic or racial minorities.</li></ul> https://signals-threads.simplecast.com/episodes/swapping-the-engine-out-of-a-moving-race-car-with-ella-ehrlich-WWjYmqQISwapping the Engine Out of a Moving Race Car with Ella Ehrlich2022-09-12T20:46:54-00:00signals-and-threads@janestreet.com (Jane Street)signalsandthreadshttps://feeds.simplecast.com/L9810DOasignalsandthreads<p>Doug Patti is a developer in Jane Street&rsquo;s Client-Facing Tech team, where he works on a system called Concord that undergirds Jane Street&rsquo;s client offerings. In this episode, Doug and Ron discuss how Concord, which has state-machine replication as its core abstraction, helps Jane Street achieve the reliability, scalability, and speed that the client business demands. They&rsquo;ll also discuss Doug&rsquo;s involvement in building a successor system called Aria, which is designed to deliver those same benefits to a much wider audience.</p><p>You can find the transcript for this episode &nbsp;on our <a href="https://signalsandthreads.com/state-machine-replication-and-why-you-should-care" target="_blank">website</a>.</p><p>Some links to topics that came up in the discussion:</p><ul><li>Jane Street&rsquo;s <a href="https://www.janestreet.com/institutional-services/electronic-trading-platforms/">client-facing trading platforms</a></li><li>A Signals and Threads episode on <a href="https://signalsandthreads.com/multicast-and-the-markets/">market data and multicast</a> which discusses some of the history of state-machine replication in the markets.</li><li>The <a href="https://www.investopedia.com/terms/f/financial-information-exchange.asp">FIX protocol</a></li><li><a href="https://en.wikipedia.org/wiki/Multicast">UDP multicast</a></li><li><a href="https://en.wikipedia.org/wiki/Reliable_multicast#:~:text=A%20reliable%20multicast%20is%20any,as%20multi-receiver%20file%20transfer.">Reliable multicast</a></li><li><a href="https://kafka.apache.org/intro">Kafka</a></li></ul> https://signals-threads.simplecast.com/episodes/state-machine-replication-and-why-you-should-care-with-doug-patti-ddqeDcTwState Machine Replication, and Why You Should Care with Doug Patti2022-04-20T16:00:00-00:00signals-and-threads@janestreet.com (Jane Street)signalsandthreadshttps://feeds.simplecast.com/L9810DOasignalsandthreads<p>Stephen Dolan works on Jane Street&rsquo;s Tools and Compilers team where he focuses on the OCaml compiler. In this episode, Stephen and Ron take a trip down memory lane, discussing how to manage computer memory efficiently and safely. They consider trade-offs between reference counting and garbage collection, the surprising gains achieved by prefetching, and how new language features like local allocation and unboxed types could give OCaml users more control over their memory.</p><p>You can find the transcript for this episode &nbsp;on our <a href="https://signalsandthreads.com/memory-management" target="_blank">website</a>.</p><p>Some links to topics that came up in the discussion:</p><ul><li>Stephen&rsquo;s command-line JSON processor, <a href="https://github.com/stedolan/jq">jq</a></li><li>Stephen&rsquo;s Cambridge dissertation, <a href="https://www.cs.tufts.edu/~nr/cs257/archive/stephen-dolan/thesis.pdf">&ldquo;Algebraic Subtyping&rdquo;</a>, and a <a href="https://github.com/stedolan/mlsub">protoype implementation of mlsub</a>, a language based on those ideas.</li><li>A <a href="https://blog.janestreet.com/memory-allocator-showdown/">post from Stephen</a> on how to benchmark different memory allocators.</li><li>A Jane Street tech talk on <a href="https://www.janestreet.com/tech-talks/unboxed-types-for-ocaml/">&ldquo;Unboxed Types for OCaml&rdquo;</a>, and an <a href="https://github.com/ocaml/RFCs/blob/881b220adc1f358ab15f7743d5cd764222ab7d30/rfcs/unboxed-types.md">RFC</a> in the OCaml RFC repo.</li><li>A paper from Stephen and <a href="https://kcsrk.info/">KC Sivaramakrishnan</a> called <a href="https://kcsrk.info/papers/pldi18-memory.pdf">&ldquo;Bounding Data Races in Space and Time&rdquo;</a>, which is all about a new and better memory model for Multicore OCaml.</li><li>Another <a href="https://arxiv.org/pdf/2004.11663.pdf">paper</a> describing the design of OCaml&rsquo;s multicore GC.</li><li>The Rust RFC for <a href="https://rust-lang.github.io/rfcs/0387-higher-ranked-trait-bounds.html">Higher-ranked trait bounds</a>.</li></ul> diff --git a/data/planet/skjegstad.xml b/data/planet/skjegstad.xml index 67917c4e61..ae29e74f00 100644 --- a/data/planet/skjegstad.xml +++ b/data/planet/skjegstad.xml @@ -1,5 +1,5 @@ -http://www.skjegstad.com/feeds/ocaml.tag.atom.xmlskjegstad2023-07-13T05:47:28-00:00http://www.skjegstad.com/feeds/ocaml.tag.atom.xmlskjegstad<p><a href="https://github.com/mirage/jitsu.git">Jitsu</a> - or Just-in-Time Summoning of Unikernels - is a prototype DNS server that can boot virtual machines on demand. When Jitsu receives a DNS query, a virtual machine is booted automatically before the query response is sent back to the client. If the virtual machine is a <a href="http://queue.acm.org/detail.cfm?id=2566628">unikernel</a>, it can boot in milliseconds and be available as soon as the client receives the response. To the client it will look like it was on the whole time. </p> +http://www.skjegstad.com/feeds/ocaml.tag.atom.xmlskjegstad2023-07-14T05:47:25-00:00http://www.skjegstad.com/feeds/ocaml.tag.atom.xmlskjegstad<p><a href="https://github.com/mirage/jitsu.git">Jitsu</a> - or Just-in-Time Summoning of Unikernels - is a prototype DNS server that can boot virtual machines on demand. When Jitsu receives a DNS query, a virtual machine is booted automatically before the query response is sent back to the client. If the virtual machine is a <a href="http://queue.acm.org/detail.cfm?id=2566628">unikernel</a>, it can boot in milliseconds and be available as soon as the client receives the response. To the client it will look like it was on the whole time. </p> <p>Jitsu can be used to run microservices that only exist after they have been resolved in DNS - and perhaps in the future can facilitate <a href="http://amirchaudhry.com/heroku-for-unikernels-pt2/">demand-driven clouds</a> or extreme scaling with <a href="http://www.skjegstad.com/blog/2015/03/25/mirageos-vm-per-url-experiment/">a unikernel per URL</a>. Jitsu has also been used to boot unikernels in milliseconds on <a href="https://www.usenix.org/system/files/conference/nsdi15/nsdi15-paper-madhavapeddy.pdf">ARM devices</a>.</p> <p>A new version of Jitsu was just released and I'll summarize some of the old and new features here. This is the first version that supports both <a href="https://mirage.io">MirageOS</a> and <a href="https://github.com/rumpkernel/rumprun">Rumprun</a> unikernels and uses the distributed <a href="https://github.com/mirage/irmin">Irmin</a> database to store state. A full list of changes is available <a href="https://github.com/mirage/jitsu/blob/master/CHANGES.md">here</a>.</p> diff --git a/data/planet/smondet.xml b/data/planet/smondet.xml index d055e03919..27ccdab19e 100644 --- a/data/planet/smondet.xml +++ b/data/planet/smondet.xml @@ -1,5 +1,5 @@ -https://seb.mondet.org/b/OCaml.rsssmondet2023-07-13T05:47:28-00:00https://seb.mondet.org/b/OCaml.rsssmondet +https://seb.mondet.org/b/OCaml.rsssmondet2023-07-14T05:47:25-00:00https://seb.mondet.org/b/OCaml.rsssmondet TZComet and CleanNFT Metadata: a generic token-viewer &#9732; Also new domain tzcomet.io &#127776; https://seb.mondet.org/b/0012-tzcomet-token-viewer.htmlTZComet's New Token Viewer2021-03-25T13:00:42-00:00smondethttps://seb.mondet.org/b/OCaml.rsssmondet diff --git a/data/planet/syntaxexclamation.xml b/data/planet/syntaxexclamation.xml index 1acf132a65..288a98d379 100644 --- a/data/planet/syntaxexclamation.xml +++ b/data/planet/syntaxexclamation.xml @@ -1,5 +1,5 @@ -https://syntaxexclamation.wordpress.com/tag/ocaml/feed/syntaxexclamation2023-07-13T05:47:28-00:00https://syntaxexclamation.wordpress.com/tag/ocaml/feed/syntaxexclamation<p>One of the first choice to make when starting the development of a compiler, or any program manipulating syntax&nbsp;with binders (e.g. programs with functions and variables), is how to&nbsp;represent these terms. Some specialized programming languages, like <a href="http://complogic.cs.mcgill.ca/beluga/" title="Beluga">Beluga</a>, have built-in facilities for this. But if you choose a general-purpose one, like OCaml, then you have plenty of choices: Named terms, De Bruijn indices, Locally nameless, Higher-order abstract syntax (HOAS)&hellip; each with their idiosyncrasies, inconvenients etc. This issue is pervasive in PL research and almost formed a subfield of itself. If you are interested, there is a wealth of literature on the topic; a documented discussion happened on LtU <a href="http://lambda-the-ultimate.org/node/3627" title="A Type-theoretic Foundation for Programming with Higher-order Abstract Syntax and First-class Substitutions">some years back</a> (already), which is probably a good starting point, although of course some has&nbsp;happened since then.</p> +https://syntaxexclamation.wordpress.com/tag/ocaml/feed/syntaxexclamation2023-07-14T05:47:25-00:00https://syntaxexclamation.wordpress.com/tag/ocaml/feed/syntaxexclamation<p>One of the first choice to make when starting the development of a compiler, or any program manipulating syntax&nbsp;with binders (e.g. programs with functions and variables), is how to&nbsp;represent these terms. Some specialized programming languages, like <a href="http://complogic.cs.mcgill.ca/beluga/" title="Beluga">Beluga</a>, have built-in facilities for this. But if you choose a general-purpose one, like OCaml, then you have plenty of choices: Named terms, De Bruijn indices, Locally nameless, Higher-order abstract syntax (HOAS)&hellip; each with their idiosyncrasies, inconvenients etc. This issue is pervasive in PL research and almost formed a subfield of itself. If you are interested, there is a wealth of literature on the topic; a documented discussion happened on LtU <a href="http://lambda-the-ultimate.org/node/3627" title="A Type-theoretic Foundation for Programming with Higher-order Abstract Syntax and First-class Substitutions">some years back</a> (already), which is probably a good starting point, although of course some has&nbsp;happened since then.</p> <p>Today I will be looking at implementing&nbsp;in OCaml one of the most recent and praised ones: Parametric HOAS (PHOAS). For some reason that I detail hereafter, the traditional way of implementing PHOAS can be cumbersome, and I propose an alternative here, which happens to be one of my very first uses of first-class modules.</p> <p><span></span></p> <h4>Parametric HOAS, the traditional way</h4> diff --git a/data/planet/szacchiroli.xml b/data/planet/szacchiroli.xml index db39cd8d74..19742f4b9d 100644 --- a/data/planet/szacchiroli.xml +++ b/data/planet/szacchiroli.xml @@ -1,5 +1,5 @@ -https://upsilon.cc/~zack/tags/ocaml/index.rssszacchiroli2023-07-13T05:47:28-00:00https://upsilon.cc/~zack/tags/ocaml/index.rssszacchiroli<h1>OCaml HTTP is now on the OCaml forge</h1> +https://upsilon.cc/~zack/tags/ocaml/index.rssszacchiroli2023-07-14T05:47:25-00:00https://upsilon.cc/~zack/tags/ocaml/index.rssszacchiroli<h1>OCaml HTTP is now on the OCaml forge</h1> <p>It's been a <a href="http://upsilon.cc/~zack/blog/posts/2009/03/ocaml-http_is_looking_for_a_new_maintainer/"> long time</a>. But finally OCaml HTTP has a <a href="http://ocaml-http.forge.ocamlcore.org/">new home</a> and a new maintainer.</p> diff --git a/data/planet/talex5.xml b/data/planet/talex5.xml index 2fb1a570d6..5262a3c122 100644 --- a/data/planet/talex5.xml +++ b/data/planet/talex5.xml @@ -1,5 +1,5 @@ -http://roscidus.com/blog/blog/categories/ocaml/atom.xmltalex52023-07-13T05:47:28-00:00http://roscidus.com/blog/blog/categories/ocaml/atom.xmltalex5<p>&quot;Is this software safe?&quot; is a question software engineers should be able to answer, +http://roscidus.com/blog/blog/categories/ocaml/atom.xmltalex52023-07-14T05:47:25-00:00http://roscidus.com/blog/blog/categories/ocaml/atom.xmltalex5<p>&quot;Is this software safe?&quot; is a question software engineers should be able to answer, but doing so can be difficult. Capabilities offer an elegant solution, but seem to be little known among functional programmers. This post is an introduction to capabilities in the context of ordinary programming diff --git a/data/planet/tarides.xml b/data/planet/tarides.xml index 61bad64b16..07a48ede42 100644 --- a/data/planet/tarides.xml +++ b/data/planet/tarides.xml @@ -1,5 +1,5 @@ -https://tarides.com/feed.xmltarides2023-07-13T05:47:25-00:00https://tarides.com/feed.xmltarides<p>OCaml-CI started with the goal of making a better continuous build system for OCaml projects. When we began in 2019, the goals were clear: it should provide a zero-configuration experience for OCaml projects using opam and Dune, and it should use an incremental architecture to avoid expensive recomputation of builds. We're delighted to announce that we achieved these goals, and OCaml-CI is currently tracking over five hundred repositories and processing over a hundred thousand jobs daily. This is inspiring news to those already using OCaml-CI or developers looking for a CI solution for their OCaml project.</p> +https://tarides.com/feed.xmltarides2023-07-14T05:47:24-00:00https://tarides.com/feed.xmltarides<p>OCaml-CI started with the goal of making a better continuous build system for OCaml projects. When we began in 2019, the goals were clear: it should provide a zero-configuration experience for OCaml projects using opam and Dune, and it should use an incremental architecture to avoid expensive recomputation of builds. We're delighted to announce that we achieved these goals, and OCaml-CI is currently tracking over five hundred repositories and processing over a hundred thousand jobs daily. This is inspiring news to those already using OCaml-CI or developers looking for a CI solution for their OCaml project.</p> <p>Throughout 2022, the Tarides CI team worked on rennovating OCaml-CI, focusing on improving the usability of the website, adding build history for branches, supporting new platforms, and launching experimental build support. We will cover all of those things in this blog post and hope you find them useful.</p> <p>There is also a <a href="https://discuss.ocaml.org/t/best-practices-for-continuous-integration-ci-in-2023/12380">Discuss thread on CI Best Practices</a>.</p> <h2 style="position:relative;"><a href="https://tarides.com/feed.xml#what-is-ocaml-ci" aria-label="what is ocaml ci permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>What is OCaml-CI?</h2> diff --git a/data/planet/tvaroquaux.xml b/data/planet/tvaroquaux.xml index 91d5c0c4a4..c2c01dacf8 100644 --- a/data/planet/tvaroquaux.xml +++ b/data/planet/tvaroquaux.xml @@ -1,5 +1,5 @@ -http://www.blogger.com/feeds/6115529230232389198/posts/defaulttvaroquaux2023-07-13T05:47:28-00:00http://www.blogger.com/feeds/6115529230232389198/posts/defaulttvaroquaux<div dir="ltr" style="text-align: left;" trbidi="on">Last month my <a href="http://gael-varoquaux.info/blog/">brother</a> came to visit and we did what every normal family would do: have beer and talk comp-scy. When he asked me how we debugged programs I had to sheepishly admit that I use printf... Part of the issue is that ocaml doesn't have good support for elf debugging annotation (the patch in <a href="http://caml.inria.fr/mantis/view.php?id=4888">PR#4888</a> hopes to address some of that) but it also comes from the fact that I am just not really up to speed on my debugging tools... Printf debugging has nearly no learning curve but it is slow and painful. Tools like gdb,strace,gprof,valgrind come with a steeper learning curve (especially for higher level languages because they require you to peer under the abstraction) but are the way to go in the long run.<br/> +http://www.blogger.com/feeds/6115529230232389198/posts/defaulttvaroquaux2023-07-14T05:47:25-00:00http://www.blogger.com/feeds/6115529230232389198/posts/defaulttvaroquaux<div dir="ltr" style="text-align: left;" trbidi="on">Last month my <a href="http://gael-varoquaux.info/blog/">brother</a> came to visit and we did what every normal family would do: have beer and talk comp-scy. When he asked me how we debugged programs I had to sheepishly admit that I use printf... Part of the issue is that ocaml doesn't have good support for elf debugging annotation (the patch in <a href="http://caml.inria.fr/mantis/view.php?id=4888">PR#4888</a> hopes to address some of that) but it also comes from the fact that I am just not really up to speed on my debugging tools... Printf debugging has nearly no learning curve but it is slow and painful. Tools like gdb,strace,gprof,valgrind come with a steeper learning curve (especially for higher level languages because they require you to peer under the abstraction) but are the way to go in the long run.<br/> <br/> So this month is going to be the <b>no printf debugging month</b> which means that I will only start modifying the source code of a programmer to debug it only as a last resort.<br/> <br/> diff --git a/data/planet/typeocaml.xml b/data/planet/typeocaml.xml index 85232fd059..3a0e40b143 100644 --- a/data/planet/typeocaml.xml +++ b/data/planet/typeocaml.xml @@ -1,5 +1,5 @@ -http://typeocaml.com/rss/typeocaml2023-07-13T05:47:28-00:00http://typeocaml.com/rss/typeocaml<p><img src="http://typeocaml.com/content/images/2017/10/cube-2-1.jpg#hero" alt="hero"/></p> +http://typeocaml.com/rss/typeocaml2023-07-14T05:47:25-00:00http://typeocaml.com/rss/typeocaml<p><img src="http://typeocaml.com/content/images/2017/10/cube-2-1.jpg#hero" alt="hero"/></p> <p>Here is the Pearl No.4:</p> diff --git a/data/planet/ujamjar.xml b/data/planet/ujamjar.xml index 76a93e69c6..5978781849 100644 --- a/data/planet/ujamjar.xml +++ b/data/planet/ujamjar.xml @@ -1,5 +1,5 @@ -http://www.ujamjar.com/ocaml.xmlujamjar2023-07-13T05:47:27-00:00http://www.ujamjar.com/ocaml.xmlujamjar<p><a href="https://github.com/ujamjar/hardcaml-examples">hardcaml-examples</a> +http://www.ujamjar.com/ocaml.xmlujamjar2023-07-14T05:47:24-00:00http://www.ujamjar.com/ocaml.xmlujamjar<p><a href="https://github.com/ujamjar/hardcaml-examples">hardcaml-examples</a> provides a small framework for creating <a href="https://github.com/ujamjar/hardcaml">HardCaml</a> based cores and six example designs. The framework code provides the general plumbing required to create a console based application with features including code generation, diff --git a/data/planet/yansnotes.xml b/data/planet/yansnotes.xml index 154b15344b..f4c30f5447 100644 --- a/data/planet/yansnotes.xml +++ b/data/planet/yansnotes.xml @@ -1,5 +1,5 @@ -http://yansnotes.blogspot.com/feeds/posts/default/-/ocamlyansnotes2023-07-13T05:47:28-00:00http://yansnotes.blogspot.com/feeds/posts/default/-/ocamlyansnotes<div dir="ltr" style="text-align: left;" trbidi="on"> +http://yansnotes.blogspot.com/feeds/posts/default/-/ocamlyansnotes2023-07-14T05:47:25-00:00http://yansnotes.blogspot.com/feeds/posts/default/-/ocamlyansnotes<div dir="ltr" style="text-align: left;" trbidi="on"> After successfully installing OCaml and Ocaide plugin for Eclipse on a &nbsp;Mac, I now think it's straightforward, however, before I completely forget the pain involved in figuring out what goes where. I wanted to put down some pointers for noobies like me, in hope that it will save people some valuable time.<br/> <br/> In general, <a href="http://ocaml.org/">ocaml.org</a> is a great spot for finding any information related to OCaml. Installing OCaml is no different, you can read all about it <a href="https://ocaml.org/docs/install.html#MacOSX" target="_blank">here</a>. There is tons of very useful and detailed information that I highly recommend anyone who is interested in OCaml to check out. In this post I just summarize the steps it took me to get from zero to OCaml installed (hero!).<br/>