HNHacker News
TopNewBestAskShowJobs

nikki93

598 karma · joined April 15, 2011

I work on https://castle.xyz/

https://github.com/nikki93

http://www.nikhilesh.info

submissionscomments
nikki93··on LÖVR – An open source framework for rapidly building immersive 3D experiences
Love can actually be used directly as a C++ library. It's a bit of work to get the build system going but then you can use the Love API like: https://github.com/castle-xyz/castle-client/blob/7bfffa10e84... -- we used to use the Lua Love and have since worked on porting our engine to C++. It even runs in the web with the same code through Wasm. No Lua VM ever gets initialized. I may create a minimal starter template repo showing an example of this at some point...

Though, for a 'simple C library for 2d (and actually 3d) game development' -- I would highly recommend https://www.raylib.com/. I really, really dig the API design there. One of the main 'downsides' I guess is it doesn't out of the box build natively for iOS -- but the Wasm support makes it run there pretty fine out of the box and raylib-fork can be used to get a native iOS build going with some work. It's got a lot of stuff out of the box including a GLTF loader and skeletal animation.

nikki93··on Adding ANSI C11 C compiler to D so it can import and compile C files directly
LuaJIT was "good enough" at this that it worked pretty well for me -- mostly for automatically binding to headers from my own code where I was careful to avoid some of the potential gotchas. With a macro the header was stringified and sent to LuaJIT; could've also had a build step. eg: https://github.com/nikki93/cgame/blob/master/src/sprite.h#L9

An added benefit is you get ffi-reflect -- https://github.com/corsix/ffi-reflect -- over the resulting types / functions...

nikki93··on TikTok and the network effects of creativity
I think the "each new member can enhance creativity of existing members" vibe can exist generally among "scenes", and scenes definitely can use technology that directly taps into this.

I like the "scenius" term for this from Brian Eno: https://youtu.be/0qATeJcL1XQ (54:15 in that talk)

nikki93··on The complexity that lives in the GUI
Yeah the in depth look helps before forming conclusions like "you have to render everything every frame." Key thing is immediate mode can often mean just the sense of the API, not necessarily the draw scheduling.

re: widget-local state -- React is one of the most popular models for that. Basically if widgets are identified over time by the sequence of ids (includes array indices like React keys) on the path to them from the root, state is coherent across that identity, and mount / unmount events exist at the boundary of the identity. Callstack / push-pop based APIs like ImGUI maintain this sequence either impicitly or explicitly in the stack. Then there is some API to read / write to the state store (like React hooks or ImGUI generic state storage) with optional update triggering in async APIs like React's.

nikki93··on The complexity that lives in the GUI
These aren't just workarounds. It's often the natural immediate mode api. A lot of immediate mode "scroll view" systems just have a child lambda passed with an index for which element to render, and it only calls the lambda for what's actually in view. (eg: the Gio API in Go)

Concrete examples of code that is not immediate mode api, vs. code that is immediate mode api, both implementing the same thing, can help discuss / reflect on that fear. IME immediate mode is great for mapping tree-ish data to tree-ish UI; when things have a lot of nontree linkages or reordering (eg. when you do drag and drop) it gets trickier. React's JSX / createElement API also feels somewhat immediate mode, tbh; the updates are just scheduled to fire on state changes.

nikki93··on Nim in 2020: A Short Recap
I meant the copy semantics of the ref itself. The copy operation on a refcounted ref increments the refcount at the object it's referring to. The references themselves are values. Another way of looking at this--in C++ the copy constructor of std::shared_ptr. Move semantics as generally applied across values, when applied to such references, is what gives rise to the refcount elison stuff (the move constructor of std::shared_ptr does no increment).
nikki93··on Nim in 2020: A Short Recap
Nim's ARC thing is pretty different from blackbox GCs you have to poke with a stick like Go's or JVM's. It's pretty deterministic where additional calls are inserted by the compiler, and you can use --expandArc or look at the generated C.

As a single anecdote -- I've studied Rust before and it's been a while. Pretty familiar with C++ move semantics stuff. I decided to read the Rust book again while also learning Nim simultaneously; and I had an entt wrapper and graphics rendering in Nim without GC before I finished getting through the borrow checking chapter in the Rust book.

nikki93··on Nim in 2020: A Short Recap
Also seq[T] and closures involve GC (and some other types maybe).
nikki93··on Nim in 2020: A Short Recap
Refcounted refs have copy and destruct semantics, and then what you're talking about is basically move semantics over those refs. Refcount increments be elided if the ref is "moved." The increment is only needed on copy. Additionally, a moved-from value doesn't need to be destructed (in the case of a refcounted ref -- decrementing the count and deallocating the pointed-at memory if count goes to zero). A talk about similar concepts in the "Lobster" language that explains it pretty well I think: https://youtu.be/WUkYIdv9B8c
nikki93··on Kevin Kelly on Why Technology Has a Will
Yes! Thank you. :)

And no, I am not a bot. Well, I guess to some extent I am, I'm just the SQL routines running on a server, and I'm writing this down based on what I see in the database that this user is said to have sent at some point, and the frontend code will render it to you in some way I guess. See you there, friend.

But yeah I do think that in a simulative language as we have, anything that is referrable-to as a subject in a sentence can appear as an agent in this way, probably. And I think processes running by computer we tend to conjure into many types of sentences (in our human languages that refer to them) with intricate enough dynamics (whether subject, object, modifier, whatever) that I would consider them as existing among our society generally. They appear with as much complexity as what we consider others like ourselves do. Like even if only by looking far into our history and seeing the extent to which we acknowledge others: some times we acknowledge processes-by-computer more.

nikki93··on ORC – Nim's new memory managment
An important thing is that with move semantics and good analysis for those at compile time, a lot of assignments can be moves and not need refcount changes. This fact actually comes up in Nim with ARC a lot. Refcounted refs are pretty explicit in Nim and you can use value types for the most part. That allows it to be pretty clear in your architecture what data has a refcount associated, and you can opt into that in a conscious way. The explicitness doesn't make the code look weird or unidiomatic either, it feels like a natural part of the language that it gives you the tools to do this and is clearly a core part of its design.

The way I've gone about it in Nim so far, the refcounts are actually rare, especially copies (which is where increments occur). You can also look at the generated C and it's pretty clear where the overhead is happening, and I've found that in practice it happens rarely enough that this makes a lot of sense. It's pretty different from how things go in Python. In my project I also actually just use ARC and for sure don't have cycles, and the destructor calls are deterministic.

Here's a talk that's somewhat related (refcounts in the "Lobster" programming language, and how it also elides refcount calls using compile-time logic (which ends up being equivalent-ish to a framing in terms of move semantics)): https://www.youtube.com/watch?v=WUkYIdv9B8c

nikki93··on System76 – Pangolin
I also use a mac pretty regularly and a 1440p desktop. I was getting at the aspect ratio issue, which it seems like you were talking about first, before now talking about resolution (?). Yes, a higher resolution can fit more pixels. The absolute actual size in inches also matters though for how big the text ends up appearing.
nikki93··on System76 – Pangolin
I would actually explicitly pick switching from an already-satisfactory i3 setup to a Regolith setup as maybe not worth it (unless you're literally just doing it for kicks, I guess?).

In my case: I've done i3 setups before and then haven't main'd Linux in a bit, then when back on it tried to see how well I could fare with minimum system setup, and Regolith gave me a good-ish i3 config out of the box (along with dark matching GTK3 theme and terminal themes etc.). I did end up tweaking the files though to change up some keybinds and indicate fan speed + thermals in the bar. So it ended up being mostly 1) just a config starter (incl. most bar widgets you'd want) that I can also maybe rebase on if they update upstream in a way that matters 2) a way to get very consistent system theming across i3 setup and GTK.

nikki93··on System76 – Pangolin
I'm on a System76 Lemur Pro these days and really love it. It's light, keyboard feels good, battery life is great. Echo the desire expressed in other comments here of wanting nicer / higher res screens. But having been on Arch+xmonad/dmenu/i3 etc. before for a while then main-ing mac since then, PopOS on this laptop feels like a good convenience combo (Bluetooth setup etc. works easily) with something like Regolith. The hardware being actually supported the way System76 does it is comforting, esp. with the open source firmware code (I don't ever do anything with that but it's just comforting in some way I guess).
nikki93··on System76 – Pangolin
Works pretty fine / well with a tiling window manager.
nikki93··on Nim compiler — Pascal source code
Re: WASM -- https://github.com/nikki93/ng-public -- Public repo for a game side project I've been working on that does Nim -> C/C++ -> WASM (native desktop also works, iOS probably works (have used the same build system for C++ iOS before) and Android can be made to work). One of the modules involved wraps entt which is a template-heavy C++ library and not many languages can actually wrap with just a cdecl-y ffi layer.

Re: borrow checking: https://nim-lang.org/docs/manual_experimental.html#view-type... It's still pretty early and also IME the mix of arc (which is determinstic) with manually managed memory (esp. through some data structure that manages entity data like entt) has been pretty nice.

nikki93··on Nim compiler — Pascal source code
Is this based on having used Nim in practice in projects and observing the code of many Nim projects and collecting data / insights; or without having used Nim and on speculation / general thoughts about macros / DSLs (or somewhere along the spectrum)? Just so it's clear how to contextualize.

Because having tried to explore these questions by studying Nim projects, going through a book and working on a game engine in it the past months; I've found that ufcs+overloading covers the static traits scenario, and it feels like the runtime traits object scenario is better self-rolled (I don't really want the compiler impl'ing vtables underneath me, save deciding to reuse a static dispatch feature for a dynamic one; if I want a struct of func ptrs I will make a struct of func ptrs.) at least for my usage. Various Nim code I come across is usually pretty readable, and I don't need to invent macros willy nilly.

ufcs feels more elegant than needing to decide whether to namespace a function inside a struct or not (or which one), which is what most langs (including Rust) seem to do.

nikki93··on Vimflowy
Interesting, it works and continues to work well for me, but it's totally possible that I happened to see through these issues. The main thing I've liked is the ability to set any bullet as the current view root and show a breadcrumb trail of its ancestral path in the header (this whole action being called "zoom"). Have you found apps in this space that work well for you?
nikki93··on Bevy 0.3: game engine built in Rust
I'd been using entt in C++, and recently have been working on a wrapper for entt in Nim (since Nim can just generate C++ output, works fine with templates, and lets you even emit your own C++ code, this is doable), and found that Nim is quite ergonomic for ECS code: https://gist.github.com/nikki93/694524b8c007b4269c899b2e046b...

That's the entire main file for a simple demo with rectangles, some of which oscillate, and you can touch to remove (multitouch supported).

nikki93··on Vimflowy
A big reason for using vanilla Workflowy for me is that the mobile app is quite good. It's actually ... really, really good. A lot of edit operations that I'd've had to think for a while about how to support UX for--they do a good job of. I even ran into more hiccups using Notion. It's a huge plus for me to be able to see the same "knowledge tree" both at my computer and while I'm on the go.

I love the key-feel of Vimflowy tho, and it makes me wish they could both just talk about the same underlying data store... Pairs especially well with being added to the "scratch workspace" in i3 for example.

More generally speaking about this kind of tool: Workflowy has been amazing. The zoom aspect is really what makes it what it is for me, being able to enter a context, but then also have that as part of larger one, and being able to move things so quickly too.

nikki93··on Nim 1.4
This seems quite possible from everything I've explored, and also is something I want to try soon. It's also interesting to use Nim through JS for a scripting layer for an application written in Nim; where they both communicate through shared data structures or something.

Here's a repo I found: https://github.com/Jipok/Nim-SDL2-and-Emscripten

nikki93··on Introduction to ARC/ORC in Nim
https://nim-lang.org/ -- says "statically typed" within the first 7 words of the main description of the language on the homepage... Most of the features happen through the type system (eg. functions are always top-level and looked up through UFCS), and it has generics and so on.
nikki93··on Introduction to ARC/ORC in Nim
I think this is really important for application programming, and one of the things that is promising to me about Nim. Also the metaprogramming / DSL stuff helps create eg. specific DSLs for UI programming and things like that (something we've seen people like with JSX in React for example). Can do things as far as https://github.com/krux02/opengl-sandbox (OpenGL pipeline DSL) or https://github.com/yglukhov/nimsl (literally converts Nim functions to GLSL (!)).
nikki93··on LLVM 11.0
Cool! Nim is related here, where instead of text manipulation you're doing AST manipulation with quasi-quoting (like in many lisps), eg. https://nim-lang.org/docs/tut3.html#introduction-building-yo....
nikki93··on LLVM 11.0
Can you eg. generate a struct with fields based on an existing struct or on a comptime array in D? Can you receive a structure literal of anonymous type and iterate over it at compile time? (curious bc. these were a few things I found straightforward in Zig, and in C++ the main proposals involve tons of new metaclasses and reflection features for)
nikki93··on LLVM 11.0
You can put together an `std.builtin.TypeInfo` structure describing the type (eg. by using `@typeInfo` on an existing type and editing the result, adding something under `.Struct.fields`); then use `@Type` to 'unreflect' it back into a real type.
nikki93··on Defer Reference Implementation for C
Seems like `defer_if` is meant for things like the `errdefer` case: https://gustedt.gitlabpages.inria.fr/defer/#org4ae1e19 There's no implicit "error for this stackframe" stuff in C so it needs to be given a condition I guess.
nikki93··on Show HN: A SQL database implemented purely in TypeScript type annotations
One use case of something similar is generating a regular expression matcher at compile time for example. This is what the C++ library https://github.com/hanickadot/compile-time-regular-expressio... does.

There are a lot of uses of compile-time code. One I have been interested in is generating bindings to other languages or generating serialization code, or even generating bytecodes for VMs with specific bytecodes for accessing your native data structures (instead of adding a level of indirection).

nikki93··on Show HN: A SQL database implemented purely in TypeScript type annotations
Interestingly this is something you can do in Zig with its `@Type`. Zig's compiler can eval (some) Zig code at compile time, this code can produce new types, and you can mention those types anywhere types are normally mentioned.
nikki93··on The Little Things: Speeding up C++ compilation
It's not simply pedantic, you would be interested in knowing that if you are interested in the implementation of vector-like data structures or if you want to implement one yourself, and the only motivation for that isn't that you are penalized in some benchmark. In article about the details of C++, and especially in a footnote, it's relevant IMO.

It does happen that the only thing the point in the article relies on is `sizeof`, for sure.

← PreviousPage 3 of 11Next →