Hacker News new | ask | show | jobs
by throw009 1212 days ago
Running with the json example you don't need a json library in lisp because you'd just dump an s-expression holding the data you want directly. You don't need a library to parse it because it's already in a format that lisp can understand.

Hilariously enough the project that made me switch to lisp from python as my scripting language was writing a lightweight parser for ascii delimited files - https://en.wikipedia.org/wiki/Delimiter?useskin=vector#ASCII... - instead of csv files. After doing it in both I had the eureka moment of using nested s-expressions in the scheme version instead of special characters. All of a sudden I had access to a csv like file which could be arbitrarily nested and didn't require me to worry about escaping. The next mind blowing moment was when I realized I could embed the code of the parser as the header of the format as the type definition and use it to evaluate the format with the program that was used to create it.

You don't even need some deep insanity to do it just:

    (eval `(,(car ls) (cadr ls)) (interaction-environment))
It also shows why I wouldn't use lisp for everything: if I wanted to ingest a file of a known csv dialect that won't fit in memory I'd do it in C after doing the prototype/master version in lisp. I also wouldn't trust running unverified source code from the internet. But for internal projects it's better than sliced bread.
1 comments

Well, I wrote a genetic programming library, and it was fun to parse a Lisp-like representation from Python. You still have recursion and everything (albeit no tail call optimization).

Here, `_from_source` goes from a plain array of tokens to a nested one (tree), depending on their arity:

https://github.com/danuker/symreg/blob/7c6593d3046f6c52dfb92...

S-Exps are almost valid Python. The exception is the single-element tuple which needs a comma: (x,)

But I still preferred to use Python as a programming language, and Lisp as a sort of AST. It's just easier. I am curious what roadblocks you faced in your ASCII delimited parsing.

Do you by any chance still have the two parsers? I'd love to see them. If you are worried about your anonymity, you can find my e-mail on my blog, and my website on my HN profile. I promise not to disclose your identity publicly.

>Here, `_from_source` goes from a plain array of tokens to a nested one (tree), depending on their arity:

You're 90% there. Lisp notation obviates the need for arity tracking, which is why in lisp + and sum are the same function:

    scheme@(guile-user)> (+)
    $416 = 0
    scheme@(guile-user)> (+ 1)
    $417 = 1
    scheme@(guile-user)> (+ 1 2)
    $418 = 3
    scheme@(guile-user)> (+ 1 2 3)
    $419 = 6

Add higher order functions, e.g. (λ (x) (x x)), and lisp notation is the simplest/only way to deal with the general case where you don't know ahead of time the arity of the function you'd be applying because of partial currying and data persistence.

As for the parsers this was 10 years ago at university. I've long since lost the source code. There weren't any problems with python, it's just that once I wrote the lisp version I realized just how useful the brackets actually are. There's a reason why every computer language is more or less context free. Lisp just takes that to its logical conclusion.

Well, thank you for your feedback. I don't know why I bothered with the flat list in the first place. I might rewrite this library in Clojure. And I might blog about my findings.

Cheers!

Some advice: move to emacs regardless of what editor you use. Evil mode is the best vi clone there is. Use paredit for any lisp like language, you are editing the sexpression tree directly, not it's incidental textual representation. Use the mode for the dialect of your choice. You will never need to exit emacs and will be able to experience the repl as it was it was meant to be.
Thanks between clojure sbcl racket and scheme which is the fastest language of am lisps?
If you are referring to fastest in terms of wall & CPU time running. Without spending a lot of time optimizing your code yourself, I suspect SBCL would take the crown for vast majority of cases. If you do hyper optimize, the gap with scheme largely closes (sometime scheme wins, sometimes SBCL). So I'd go with SBCL if all else is the same feature wise to you. That said, the last serious benchmark I did of lisps was ~2010 so optimization may have changed since then and of course they were not very rigorus benchmarks (just my compute-bound workload at the time, that primarily boiled down to mostly integer ops). Debian language benchmarks game has some benchmarks written for sbcl and racket that may be good for comparing implementations yourself if interested. https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
SBCL, probably. Scheme would be a close second depending on the implementation (Chicken, Gerbil or other compile-to-C impls.) Racket and Clojure are closer in performance to scripting languages like Python.
In the TechEmpower benchmarks, Clojure is about 2.75x slower than Java, while Python is 5.59x slower.

The fastest composite Python "framework" is uvicorn at 17.9% of the fastest run in Java (officefloor). The fastest Clojure run is Aleph at 36.4%.

https://www.techempower.com/benchmarks/#section=data-r21&l=z...

About SBCL, I get conflicting results. The Benchmarks Game shows it roughly as fast as Java for many problems:

https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

But here it's significantly worse than the Clojure runs, likely due to the slow DB bindings (the other test types show it roughly in line with Clojure; though it uses a "Stripped"/unrealistic HTTP implementation):

https://www.techempower.com/benchmarks/#section=data-r21&l=z...

I am not sure which Lisp implementation is used; is it SBCL? Does this file speak to you?

https://github.com/TechEmpower/FrameworkBenchmarks/blob/73eb...