HN user

h3rald

139 karma
Posts17
Comments38
View on HN

min creator here :)

min does not have a C FLI essentially because it has a "Nim FLI". It is really easy to add new symbols to the language using a Nim API (which is also used internally to define all symbols of the language).

See https://min-lang.org/learn-extending/ for more info. Maybe I should generate some Nim docs for the public API though... but it's really easy to use, and you can check the lib folder of the repo for examples: https://github.com/h3rald/min/tree/master/minpkg/lib

Wow! Your web site changed a bit since last time I saw it, congratulations Yanis! It's great to see a programming language implemented in Nim to look so polished!

Nice project! It looks pretty similar to my own LiteStore: https://h3rald.com/litestore/

The feature set is pretty similar, but I focused mainly on the free form/nosql-ish aspect of it, and although I added support for server-side JavaScript middleware I didn't include authentication OOTB (although it could be implemented or you can integrate with an OAuth2 system - it can validate JWT tokens).

And yes, LiteStore's web app hasn't been updated in years and overall your project looks much more polished than mine.

Good job! Bookmarking ;)

I am "eating my own dog food" in the sense that I am currently using two projects that I developed specifically for that:

- HastyScribe[1] -- an opinionated markdown compiler that supports advanced features for technical writing like macros, fields and transclusion. - HastySite[2] -- a highly customizable static site generator based on HastyScribe and min[3], another project of mine (and a pretty deep rabbit hole to go into, if you like unusual programming languages)

Examples can be found in the docs listed for most of my with my projects, here:

https://h3rald.com/projects

The only thing missing from those is search, but I could plug in LiteStore[4] and be done with it. OK, I think that's enough self-promotion for one comment, but you did ask...

[1] https://h3rald.com/hastyscribe/

[2] https://h3rald.com/hastysite/

[3] https://h3rald.com/min/

[4] https://h3rald.com/litestore/

Uhm... expensive?! ;)

The municipality of Triora, a beautiful historical town now nearly abandoned, very close to the Ligurian coast in Italy, is selling houses as low as 1 (one!) euro, in an attempt to re-populate the area and get someone to invest in restoring the historical landmarks...

https://1eurohouses.com/triora-imperia-liguria/

Honestly, this is a real bargain considering what this place is like and its historical significance.

Granted, you have to commit to restoring the place, but still!

Here's most of the stuff that I built myself (and that I still use on a regular basis):

- fae [https://h3rald.com/fae] · a minuscule find and edit utility

- h3 [https://h3.js.org] · an extremely simple javascript microframework

- hastyscribe [https://h3rald.com/hastyscribe] · a professional markdown compiler

- hastysite [https://hastysite.h3rald.com] · a high-performance static site generator

- herald [https://h3rald.com/herald-vim-color-scheme] · a well-balanced vim color scheme

- litestore [https://h3rald.com/litestore] · a minimalist nosql document store

- min [https://min-lang.org] · a small but practical concatenative programming language

- mn [https://h3rald.com/mn] · a truly minimal concatenative programming language

- nifty [https://h3rald.com/nifty] · a tiny (pseudo) package manager and script runner

- nimhttpd [https://h3rald.com/nimhttpd] · a static file web server

Interesting project! I recently created something similar[1] because I wanted a simple, easy to use, bloat-free micro framework to create single page applications. I also wanted it to be somewhat "battery-included" and provide things like routing and state management out of the box.

I think skruv comes with even bigger batteries (SVG support, Shadow Dom integration and additional vdom related apis), and I am curious to see how they all play together. The one thing that does seem a bit weird is the html helper functions... like Mithril, I went straight for hyperscript: I think it is very underrated right now but it is actually a good way to write a dom tree -- and you also get JSX support (nearly) for free.

Anyhow, keep up the good work, I think the world needs more micro frameworks like these: powerful but simple enough to be understood and extended easily if needed.

[1] https://h3.js.org

For my personal projects I find particularly satisfying using my own stack:

- https://h3rald.com/litestore if I need a RESTful searchable data store and some relatively simple middleware logic.

- https://h3.js.org if I need to write a single-page application and I just want to get things done fast.

- https://hastysite.h3rald.com if I need a static site generator.

- https://min-lang.org for more complex things. It took a bit to get used to it, but I managed to get quite productive with it in the end.

I do occasionally try out more traditional things or the latest stuff but... using my own code feels a lot more gratifying. If I needed something different, I found myself building it from scratch exactly like I wanted it.

Joy was the inspiration for min :)

min is actually mainly an interpreted language, BUT it can actually as of recently be transpiled to Nim (which in turns generates C code which can be compiled), so you can actually create executable files from min, which is pretty cool.

Adding this form of compilation was actually really easy because in a stack-based language there's essentially one instruction: push an item on the stack... the only things I had to add was wrapping external files in functions to delay their evaluation to when they are required.

Combinators like linrec etc are no different from ordinary operators, they are pushed on the stack and they rearrange it...

Consider the following program that takes an integer as input and prints its factorial:

  args
  (compiled?)
    (0)
    (1)
  if get int
  (dup 0 ==) (1 +) 
  (dup 1 -) (*) linrec
  puts
Note how I am getting the first or second argument from the command line depending if I am running the program through the interpreter (min factorial.min 5) or as a stand-alone executable (./factorial 5).

When running the min "compiler":

  min -c factorial.min
...the following Nim code gets generated. As you can see, it's mostly just pushing items on the stack :)
  import min
  MINCOMPILED = true
  var i = newMinInterpreter("factorial.min")
  i.stdLib()
  ### factorial.min (main)
  i.push MinValue(kind: minSymbol, symVal: "args", column: 4, line: 1, filename: "factorial.min")
  var q1 = newSeq[MinValue](0)
  q1.add MinValue(kind: minSymbol, symVal: "compiled?", column: 10, line: 2, filename: "factorial.min")
  i.push MinValue(kind: minQuotation, qVal: q1)
  var q2 = newSeq[MinValue](0)
  q2.add MinValue(kind: minInt, intVal: 0)
  i.push MinValue(kind: minQuotation, qVal: q2)
  var q3 = newSeq[MinValue](0)
  q3.add MinValue(kind: minInt, intVal: 1)
  i.push MinValue(kind: minQuotation, qVal: q3)
  i.push MinValue(kind: minSymbol, symVal: "if", column: 2, line: 5, filename: "factorial.min")
  i.push MinValue(kind: minSymbol, symVal: "get", column: 6, line: 5, filename: "factorial.min")
  i.push MinValue(kind: minSymbol, symVal: "int", column: 10, line: 5, filename: "factorial.min")
  var q4 = newSeq[MinValue](0)
  q4.add MinValue(kind: minSymbol, symVal: "dup", column: 4, line: 6, filename: "factorial.min")
  q4.add MinValue(kind: minInt, intVal: 0)
  q4.add MinValue(kind: minSymbol, symVal: "==", column: 9, line: 6, filename: "factorial.min")
  i.push MinValue(kind: minQuotation, qVal: q4)
  var q5 = newSeq[MinValue](0)
  q5.add MinValue(kind: minInt, intVal: 1)
  q5.add MinValue(kind: minSymbol, symVal: "+", column: 15, line: 6, filename: "factorial.min")
  i.push MinValue(kind: minQuotation, qVal: q5)
  var q6 = newSeq[MinValue](0)
  q6.add MinValue(kind: minSymbol, symVal: "dup", column: 4, line: 7, filename: "factorial.min")
  q6.add MinValue(kind: minInt, intVal: 1)
  q6.add MinValue(kind: minSymbol, symVal: "-", column: 8, line: 7, filename: "factorial.min")
  i.push MinValue(kind: minQuotation%, qVal: q6)
  var q7 = newSeq[MinValue](0)
  q7.add MinValue(kind: minSymbol, symVal: "*", column: 12, line: 7, filename: "factorial.min")
  i.push MinValue(kind: minQuotation, qVal: q7)
  i.push MinValue(kind: minSymbol, symVal: "linrec", column: 20, line: 7, filename: "factorial.min")
  i.push MinValue(kind: minSymbol, symVal: "puts", column: 4, line: 8, filename: "factorial.min")

I have been using Mithril.js for a while and never ran into problems, but admittedly I only used it for small, personal project.

What I liked about Mithril was its simplicity: a clean API with a handful of methods but batteries-included at the same time, and very easy to learn, too!

Eventually I decided to write my own micro framework which borrows heavily from Mithril in terms of api design and approach (https://h3.js.org) -- basically, like Mithril, it comes with its own Virtual DOM implementation, hyperscript syntax (imho the best way to write a view, once you get used to it), a minimal router but also more obvious ways to manage local and global state.

Yeah, I am not even thinking about competing with React or other frameworks, as long as it works for me. I have learnt more building a micro framework from scratch about how single page application work than from using React or Angular and constantly checking stack overflow and other docs to make sure I was doing stuff "in the right way".

I would however be curious at what are the limits of such frameworks. Real-time dom updates... depends how complex I guess, and how fast. It would be nice to have a way to benchmark this properly...

These days I keep tinkering with min (https://min-lang.org). It is a small but fairly batteries-included concatenative programming language I've been working on for years.

Not many people use it of course, and it's not going to ever become mainstream, but I am using it everyday to perform small tasks and also more recently even to build small APIs for other personal projects. Plus I find that working on your own programming language is a very rewarding experience, and it stimulates creative thinking.

I actually go through phases... I have a few open source projects I keep coming back to every few months to fix issues, add small (or big) features, tweaks etc. the most notable ones are listed on my personal page (https://cevasco.org) -- it almost feels like I have my own very quirky and opinionated software ecosystem :)

That's the spirit! It doesn't really matter whether this will become the next (p)React, as ling as you learnt something from building it and you are enjoying using it.

And yes, I did create something like this but I wanted to include also a router (like Mithril) and a standardized way to handle state, both global and local... and I ended up with https://h3.js.org -- yep, probably not many people use it but I have been using it for months for personal projects and I keep tinkering to improve a little bit whenever I find I need to polish some rough edges or support additional use cases.

Like others said, I wonder how long it will take for bloat to creep in. For now though yes, I agree that you really don't need much code to build a fully functional SPA. And creating your own micro framework really helps you understand how things really work, without relying on someone else's abstraction.

Having created a small concatenative language myself[1], no, the pure concatenative style with no variables and stack combinators is just too much for a normally-wired brain.

BUT! I tried to cheat a little bit to make things more readable. Take this example from the min front page, which showcases its concatenative style:

     . ls-r 
     (mtime now 3600 - >) 
     filter
Can you guess what it does? You might, but what about this:
     . ls-r :files
     ((mtime > (now - 3600)) ><) =changed-in-last-hour
     @files #changed-in-last-hour filter
Now ok, I went insane with sigils and weird operators but: - creating variables helps - using infix notation via the infix-dequote (><) operator makes expressions much more readable

Why would I use this rather than a traditional language? It helps reasoning in terms of point-free function composition and in some case it is faster to work with, i.e. processing rules, pipelines, task sequences etc.

[1] https://min-lang.org

I agree 100%, but more than anything for me was control: I had been using nanoc (https://nanoc.ws) for years and don't get me wrong, that's an excellent piece of software... but then I "left it" for a few months also because I stopped coding in Ruby for a while (and stopped blogging) .When I came back to it, I discovered that a new major version was out and I had to upgrade, potentially breaking quite a bit of things because I didn't keep the pace with the new changes.

While this is true for nearly all software, I missed being in control of when to upgrade, and I also missed a few little features here and there. The result? I shopped around for it a bit and then decided to roll out my own: HastySite (https://hastysite.h3rald.com) which now powers a bunch of sites of mine like https://h3rald.com and https://min-lang.org

Actually I ended up writing my own markdown processor and my own programming language before doing that (which also needed a Readline/line noise replacement, and wrappers for a regexp and compression library) but... hey, that's part of the fun isn't it? That's the very reason why I love being a programmer: it's not about the final result, it's about how you get there and what you learn along the way.

So kudos to you sir, I wish you all the best and that you build more things yourself.

Well yes it started off for prototyping and then I kept adding more features like JavaScript middleware and token validation... I have used it as a backend for quite a few private projects of mine.

Regarding indexing json... here's how I do it:

     proc createIndex*(store: Datastore, indexId, field: string) =
       let query = sql("CREATE INDEX json_index_$1 ON documents(json_extract(data, ?) COLLATE NOCASE) WHERE json_valid(data)" % [indexId])
       store.begin()
       store.db.exec(query, field)
       store.commit()
Basically, SQLite supports indexes in arbitrary expressions and so you can use it in conjunction with json_extract. In this case, field is an arbitrary json path.

I then added a REST API in LiteStore to create (JSON) indexes... in that way you can make your queries more performant based on the specific json documents that you store in the data store.

Not published unfortunately but I should, really!

In the past I tested importing dumps of the full HTML and CSS documentation docset from MDN and: - Importing files in a directory is relatively fast: I import batches and it can import hundreds of pages in a few seconds - sadly there's no bulk operation yet to insert arbitrary json documents (unless they are stored as files in a folder), so that's quite slow. - full text search and querying indexed (JSON) properties is fast (double-digit milliseconds for searching several hundred of relatively large documents with paged results)

I do need to do some compared benchmarks with similar data stores though.

I beg to (partially) disagree... (shameless plug ahead!)

https://h3rald.com/hastyscribe/HastyScribe_UserGuide.htm

OK, you are right that ordinary markdown is insufficient because a lot of functionalities are missing for proper technical writing and above all proper content reuse...

That's why in my tool I started from an already fairly-advanced Markdown flavor (Discount) which already comes with a bunch of proprietary extension... then on top of that I added things like snippets, transclusions, fields, and even simple macros.

Nim 0.19 8 years ago

Great news! I have been using Nim almost exclusively for my open source projects for years now, since when it was called Nimrod...

It is simply amazing to see how it evolved and improved over time. I love the fact that it runs seamlessly on several different platform, that is so fast and so syntactically expressive and elegant.

Way to go guys, Araq, dom, and everyone who made Nim possible! Really glad you are finally getting the momentum and the attention that you deserve. Keep it up!

While I understand the point that the article is trying to make, i.e. that no "standard" markdown offers sufficient features to write documentation, I don't think that it matters too much as long as the final result is good.

I always wanted to write manuals and documentation in markdown (or any other lightweight markup language for the matter) but not even a specialized flavor of markdown was able to provide all the features that a technical writer expects from a documentation tools (I am talking especially about block-level formatting and content reuse).

So I came up with HastyScribe (https://h3rald.com/hastyscribe/) and then HastySite (https://h3rald.com/hastysite/).

Basically, I used Discount as a base and added features on top of it. I am now using it for all my sites and all the documentation of my open source projects. And I know of at least one company that is using HastyScribe for their own user documentation.

OK, there's some degree of vendor lock-in, but at least the final result is OK and both tools are open source.

For more info and a preview of what an HastyScribe document looks like, here's the user guide:

https://h3rald.com/hastyscribe/HastyScribe_UserGuide.htm

I actually didn't try yet. I presume I will have to remove some of the modules and symbols that are not likely to work in browsers, but other than that yes, it should compile to JavaScript!

Thanks for the suggestion, I'll give it a try!

Show HN: LiteStore 11 years ago

For those who don't want to get through the whole article:

TL;DR: LiteStore is lightweight, self-contained, RESTful, multi-format NoSQL document store server written in Nim and powered by a SQLite backend for storage. It aims to be a very simple and lightweight backend ideal for prototyping and testing REST APIs and client-side, single-page applications.

Useful links:

- Project Page & Downloads: https://h3rald.com/litestore/

- User Guide: https://h3rald.com/litestore/LiteStore_UserGuide.htm

- Github Repo: https://github.com/h3rald/litestore

Indeed it is an article I wrote in 2008! I was quite surprised to see it on Hacker News only now... oh well, maybe I should write another one at some point.

Things are changing, but not that fast I must say. Go is definitely the biggest omission on that list, but again, it didn't exist back then!