Show HN: Lisp in C#
github.com
Show HN: Lisp in C#
1–10 of 70 posts
Re: Show HN: Lisp in C#
#2Re: Show HN: Lisp in C#
#3Re: Show HN: Lisp in C#
#4Cool! I didn't get a chance to run it but I dug around the code a little bit. I noticed there is a Macro class, but no mention of macros in the README. Are macros working?
So far there has been no shortage of more important features at the scale of programs it's currently viable for.
Re: Show HN: Lisp in C#
#5I'm afraid I've been out of the C# loop too long to know what's fast and what isn't these days.
Now that maybe I have the attention of some serious C# nerds, any assistance in making this thing run faster would be much appreciated.
It's not terrible atm, given a managed host language, but I'm sure there are plenty of knobs left to turn.
See the benchmarks section in the README for more info, and the same benchmarks ported to Python in python/fib.py.
Oh, and there's some undocumented yet potentially useful stuff in /Libs; strings, terminal control and IO mainly.
Re: Show HN: Lisp in C#
#6Author here. I'm afraid I've been out of the C# loop too long to know what's fast and what isn't these days. Now that maybe I have the attention of some serious C# nerds, any assistance in making this thing run faster would be much appreciated. It's not terrible atm, given a managed host language, but I'm sure there are plenty of knobs left to turn. See the benchmarks section in the README for more info, and the same…
Was: 686 98 1195
Now: 226 79 293 (with net9.0 preview: 201 70 269, another release another free >10%)
The reason for such a significant difference is that `ArrayStack` only implements `IEnumerable`, which prevented the Enumerable.Last(stack) call from seeing that the type has an indexer which can be used to quickly access the last element instead of traversing it in its entirety.
Now, it still requires JIT (or, in this case, compiler back-end and ILC) to reason about the actual type of ArrayStack to optimize away type tests, inline Last() call and devirtualize indexer access, but the better option is simply replacing it with just [^1] which does the same on any indexable type.
Generally speaking, it's recommended to use out of box collections whenever appropriate like Stack, List, etc. which already implement all the necessary interfaces which the standard library takes advantage of unless there's a specific need to do otherwise.
Also, it is always nice to have .net's aot emit "canonical" native binaries, so it took me about 45s to find the bottleneck by bumping up the numbers in benchmarks.sl and clicking "Sample" in macOS's Activity Monitor.
All in all, the code in the project is terse and thanks for showcasing it!
Re: Show HN: Lisp in C#
#7Author here. I'm afraid I've been out of the C# loop too long to know what's fast and what isn't these days. Now that maybe I have the attention of some serious C# nerds, any assistance in making this thing run faster would be much appreciated. It's not terrible atm, given a managed host language, but I'm sure there are plenty of knobs left to turn. See the benchmarks section in the README for more info, and the same…
https://github.com/codr7/sharpl/pull/1 Was: 686 98 1195 Now: 226 79 293 (with net9.0 preview: 201 70 269, another release another free >10%) The reason for such a significant difference is that `ArrayStack ` only implements `IEnumerable `, which prevented the Enumerable.Last(stack) call from seeing that the type has an indexer which can be used to quickly access the last element instead of traversing it in its entire…
I'll have a look later, the only part I didn't get was [^1], could you elaborate?
About the ArrayStack, I wanted a stack backed by a fixed array, because my suspicion was using a fixed array for fundamental collections would be faster. Hence the VM.Config object to set the max sizes.
There is also a DynamicArrayStack that supports reallocation, which is currently used by OrderedMap.
The plan is to eventually benchmark the alternatives, but start with the simplest thing that could possibly work.
Re: Show HN: Lisp in C#
#8I wrote a lisp in C# based on that, it was only a 100+ ish lines of code. It was a great way to get into Lisp.
Re: Show HN: Lisp in C#
#9Earlier quoted context omitted.
https://github.com/codr7/sharpl/pull/1 Was: 686 98 1195 Now: 226 79 293 (with net9.0 preview: 201 70 269, another release another free >10%) The reason for such a significant difference is that `ArrayStack ` only implements `IEnumerable `, which prevented the Enumerable.Last(stack) call from seeing that the type has an indexer which can be used to quickly access the last element instead of traversing it in its entire…
Nice work, thanks! I'll have a look later, the only part I didn't get was [^1], could you elaborate? About the ArrayStack, I wanted a stack backed by a fixed array, because my suspicion was using a fixed array for fundamental collections would be faster. Hence the VM.Config object to set the max sizes. There is also a DynamicArrayStack that supports reallocation, which is currently used by OrderedMap. The plan is to…
Internally, `.Last()` will try to optimize for the common cases where a type implements `IList` and uses an indexer to simply get the last element. However, because ArrayStack does not implement IList, .Last() does not know that this is possible, therefore costs O(n) as noted above.
Instead, we can simply use an index operator `[^1]` which gets the first element from end, which is short-hand for `[stack.Count - 1]`.
Other than that, it’s a good idea to lean towards out-of-box tools to avoid investing effort into reinventing another language within C# and use spans for slicing data types - you almost never need to call methods like Array.ConstrainedCopy - this is something quite ancient. The idiomatic way of copying a portion of array today is `source.AsSpan(start, length).CopyTo(dest)`, slicing destination as well if you need so. The prime slice types in .NET are Span and ReadOnlySpan, and can wrap memory of any origin.
Re: Show HN: Lisp in C#
#10Earlier quoted context omitted.
Nice work, thanks! I'll have a look later, the only part I didn't get was [^1], could you elaborate? About the ArrayStack, I wanted a stack backed by a fixed array, because my suspicion was using a fixed array for fundamental collections would be faster. Hence the VM.Config object to set the max sizes. There is also a DynamicArrayStack that supports reallocation, which is currently used by OrderedMap. The plan is to…
Here, calling `.Last()` on `ArrayStack ` traverses it from the start. `.Last()` is a static extension method defined on `System.Linq.Enumerable` class and has a signature `static T Last (this IEnumerable source)`. Internally, `.Last()` will try to optimize for the common cases where a type implements `IList ` and uses an indexer to simply get the last element. However, because ArrayStack does not implement IList , .L…