Did you implement formulas from scratch, or used a third-party lib?
HN user
dmitry-vsl
Creator of Leporello.js - online JavaScript/TypeScript playground and debugger
https://leporello.tech/
dmitry.vasil@gmail.com
Probably better to use partitioned table and drop old partitions.
We had createScheduledPosts.ts that would run every 15 minutes, scan our table of scheduled posts and create any that needed to be published.
Why not set the publication_date when you create a post and have a function getPublishedPosts that fetches a list of posts, filtering out those with a publication_date earlier than the current date? With this approach, you don't need cron jobs at all.
Is it possible to use batch mode with fine-tuned models?
I think this is a fabrication by the journalist. Overall, it seems to me that there was an ideological agenda behind this story. In the USSR, no topic could cause a stir in major media outlets without an ideological directive.
Does it implement JS standard library, for example Map, Set etc?
So, it's impossible to transfer a value from one machine to another if there's no network connection between them? How did this extremely trivial observation become a well-known theorem?
I am developing an online IDE capable of visualizing a program's call tree. Within this IDE, users can select a node in the call tree to observe detailed information, including function arguments, return values, local variables, and intermediate expressions. Additionally, the IDE features a time-travel engine that displays the values of mutable objects at the specific moment when a particular function and statement were executed.
You can try it online here: https://app.leporello.tech/?example=fibonacci
I am building an IDE for functional JS. It can visualise a call tree of a program, helping to understand execution of recursive functions
> you can use print statements and step debugging, together, at any point in time in the recording
I am working on something similar. I am building an IDE that allows to jump from the line printed by a console.log call to a corresponding code location, and observe variables and intermediate expressions.
It also displays a dynamic calltree of a program, allowing to navigate it in a time-travel manner.
Currently it only supports pure functional subset of JavaScript, but I am working on support for imperative programming (mutating data in place).
There was a similar tool developed by Oracle called mod_plsql, which served as an Apache web server module. As far as I remember, it allowed you to configure a mapping from a URL to a stored procedure. These stored procedures could receive HTTP request parameters and return HTML content.
I've always felt that this approach is the right way to build applications. Application servers seemed like an unnecessary layer to me, essentially serving as intermediaries that merely passed data from the database to the browser. In the past, they played a more critical role in generating HTML, but nowadays, application servers are primarily used for handling APIs. Consequently, they often lack meaningful tasks to justify their existence.
Having your code closely integrated with the data also has the benefit of improving performance.
Leporello.js: https://leporello.tech/
Leporello.js is an interactive functional programming environment designed for pure functional subset of JavaScript. It executes code instantly as you type and displays results next to it. Leporello.js also features an omnipresent debugger. Just position your cursor on any line or select any expression, and immediately see its value. Leporello.js visualizes a dynamic call tree of your program. Thanks to the data immutability in functional programming, it allows you to navigate the call tree both forward and backward, offering a time-travel-like experience.
Shameless plug: I have always been fascinated by edit-and-continue and I build a JavaScript IDE centered around it.
> How does it deal with patterns from popular frameworks or libraries that are borderline frameworks. React, Vue, Express, NestJS etc.
React is a great fit for Leporello.js. There is an example of React TODO app that you can write and debug in Leporello. It is showcased in the video. You can play with it yourself if follow the link https://app.leporello.tech/?example=todos-preact
Speaking about backend frameworks, basically you code is a function Request -> Response. How do you organize your code is up to you. You can code it in a functional manner. What is great about Leporello, is that it remembers all the calls your app made to databases, other microservices and external APIs and allows to debug them in a time-travel manner, seeing requests and responses. You can run your code once, and then debug and navigate it forward and backward, seeing runtime values that were generated when your code was executed. It a huge time saving, especially when external resources are slow and may require complex setup or teardown before or after being called.
> It feels like leporello has to store a lot of possible branch-outs of the state
Could you please clarify, what do you mean by branch-outs of the state?
> That is, how leporello handles a codebase that's partially written in freestyle JS and not the subset that leporello specify handles?
Leporello is based on the idea that you can have much more powerful dev experience (time-travel debugging, better debugger UX) if you adhere to functional code. Look at the recent news from Jetbrains [0]. They presented predictive debugger for their .NET IDE. They called it "a game changing look into the future" and it is actually a huge improvement of ergonomics. But with FP, you get predictive debugger for free. It is just a trivial consequence of not having data mutations. So inside the function, each name is binded to single immutable value.
If you have freestyle JS, then Leporello is not a good fit for you. It requires some buy-in from a developer. The good thing is that you still write plain vanilla javascript, without non-standart extensions that require some kind of transpilation.
I would be delighted to turn it into a business, but I may not be able to do it without securing funding.
I don't have any experience with Jsonnet, but from what I can gather, it appears to be a Turing-complete functional programming language. Leporello.js, on the other hand, is a UX concept that can be applied to any functional programming language, including Jsonnet.
In fact, I believe it's possible to write code in TypeScript that would be very similar to Jsonnet. TypeScript provides the capability to create compiler plugins, which can restrict the allowed language subset, effectively making it more limited and suitable for configuration
Currently, Leporello.js relies on my custom JavaScript parser, which, while functional, is not yet complete and exhibits some quirks. My plan is to replace it with a TypeScript parser, thereby providing full support for both JavaScript and TypeScript within Leporello.js. Additionally, I'm going to develop a VSCode extension, which will offer you all the features available in ts-server.
Thank you for your feedback! I believe it has some value in teaching programming in the spirit of "Structure and Interpretation of Computer Programs." There is a JavaScript edition of the SICP book. I believe Leporello.js would be a nice environment for students to solve problems from this book.
Thank you for the suggestion! I am using the Ace editor. I will consider adding a configuration option, but my main goal is to build a VSCode plugin, so all the configuration will be left to the user.
Leporello.js follows a pragmatic functional approach. You can use IO functions and throw exceptions as you typically would, without the need for an IO monad or an Option monad. However, there is one critical limitation – you cannot mutate your data structures. Mutations are not allowed because they would make time-travel debugging impossible. For instance, the following code is forbidden:
const point = {x: 1, y: 2}
point.x = 2
And instead you should use this: const point = {x: 1, y: 2}
const another_point = {...point, x : 2}
In Leporello.js, it's vital to avoid mutating data structures; instead, you create new ones. You can watch Rich Hickey's insightful talk [0], where he discusses the advantages of immutability in functional programming.In many ways, Leporello.js bears a resemblance to Clojure. Clojure served as a source of inspiration for Leporello.js, to the extent that I even contemplated building Leporello.js for Clojure first.
I agree that enforcing strict purity in Leporello.js might limit its adoption among developers who prefer a more flexible approach. However, this initial focus on a pure functional subset allowed me to concentrate on the core idea – reimagining developer tools for functional programming from the ground up.
Exploring the development of a two-mode debugger that can seamlessly switch between traditional imperative debugging and Leporello.js-style debugging for pure functions in modern multiparadigm languages is indeed an intriguing research avenue.
It is an AI voice generator https://genny.lovo.ai/
I plan to blog about Leporello.js internals, but now I will try to give you a short answer.
When navigating a call tree, Leporello.js evaluates your functions with tracing enabled, collecting execution information and materializing parts of the call tree in memory. This evaluation is lazy, but if a function invokes an IO operation, the corresponding call tree node is saved eagerly to ensure the function is called only once, avoiding duplicate IO operations.
Handling state mutations is more complex. Leporello.js doesn't inherently know if a function, possibly from a third-party library, will mutate its arguments. Therefore, when using such functions, there's a risk of displaying incorrect data when you navigate and debug your code.
Ideally, a language would color functions based on their purity, allowing smart IDEs to deep clone arguments before invoking impure functions, enabling time-travel debugging. Maybe I will add comment pragmas to Leporello.js. They would allow to have state-mutating functions as first-class citizens in Leporello.js. Syntactically, they can be just ordinary comments:
// leporello: mutation
function sort(arr) {
arr.sort() // in javascript, sort mutates array in-place
}
Currently, this responsibility falls on the programmer. If you use argument-mutating functions, consider wrapping them in a pure functional interface. The viable approach is structuring your program with a 'functional core, imperative shell' architecture. This approach, as seen in Leporello.js itself, involves a main codebase that is pure functional, operating on a single immutable data structure describing Leporello.js's state, while the 'shell' part invokes pure functions and applies effects.The notable example of such architecture is Redux. Redux architecture fits perfectly for apps build with Leporello.js, as you can see in TODO app example https://app.leporello.tech/?example=todos-preact
Bret Victor's talks, particularly 'Learnable Programming' and especially 'Inventing On Principle' [0] served as the inspiration behind my creation of an IDE called Leporello.js [1]. You can find my interpretation of his example from 'Learnable Programming' here: https://vimeo.com/870708017
To experiment with this example yourself, please follow the link: https://app.leporello.tech/?share_id=ece060b7c63121741be30fd...
As a shameless plug, earlier today I featured Leporello.js on Show HN [2]. If you have any questions, please feel free to ask.
My both mother and father developed software running on IBM mainframes for large USSR enterprises. It's interesting that USSR could not purchase mainframes legally so USSR worked around this restriction and finally was able to buy software with the help of KGB agents in Romania who introduced themselves to IBM sales as Romanian citizens. You can read more about it here [1] After crash of soviet economy my parents became unemployed and never worked as programmers again. My father teached me some C in TurboC IDE. Currently I am full stack web dev. [1] http://www.csd.uwo.ca/~magi/personal/humour/Computer_Folklor...