183 karma · joined July 30, 2024
The views and opinions expressed in this account are those of my own and do not represent those of my employer, NVIDIA
Vim macros are not that hard to write, but I do agree with you, visual feedback is better. It can be annoying to have to re-record a macro, that's why I tend to use :s (search & replace) or Visual Block mode over using a macro (most of the time I don't need a macro).
I understand you state vim is "just an example", but you use this example as the main backbone of your article. Add more detail. You're arguing with vague anecdotes which requires the reader to read between the lines.
An aside: visual feedback, multi-cursor support and sane defaults is likely what led to new modal editors being created, such as Helix and Kakoune.
This seems super useful for pairing and multiple machine work.
Honestly I wish something like this could replace git, but my guess is you’d need to build specialized editors for this. In the direction of: https://www.inkandswitch.com/upwelling/
I was wondering if I could use this for multiple processes (codex, nvim) on the same machine, but then I realized this use case is unnecessary (brain fart).
1. Constructing a "deterministic algorithmic approaches with complex pipelines" is an ML approach. You're simply changing how you optimize (e.g. gradient descent with human constructed rules) and what you are optimizing (i.e. the model from a statistical one to a set of rules similar to a decision tree)
2. "Models can be intentionally poisoned or tricked" this is adversarial examples. Your deterministic and complex pipeline will have attack vectors, but just of a different distribution compared to an LLM (or neural net in general). Adversarial examples are likely unavoidable, you will always have a set of inputs that will cause your model to mis-classify examples. You can aim to minimize the size of this distribution/set, but for language: the set of possible inputs is so large that you will never fully be able to train or test on them all, and thus you will always have a back & forth between finding new attack vectors vs. defending against them: "deterministic" or not.
To expand on 1:
How do you construct a complex pipeline? Hopefully, by following roughly standard ML principles.
That is, you have a train set that you observe and find patterns/rules in. Then you iteratively construct your complex pipeline until you've minimized the error for a train set. Hopefully after this initial version is constructed you evaluate it on your (independent) val set. Then you iteratively improve your complex pipeline until your validation numbers improve. In the end, since you've optimized a val set, you need to use a third independent test set to ensure that you haven't overfit to your val&train sets. This is standard ML practice.
In other words, this process is what an "ML approach" is, just manually performed by a human possibly using some data analysis. Again, you've just replaced the optimization process (e.g. from gradient descent) and the underlying ML model (e.g. an LLM with differentiable parameters) with a more "deterministic approach" similar to a decision tree.
Yes you could automate this process to construct the rules and chain them, in which case your process and your complex pipeline will likely look similar to a decision tree (e.g. xgboost), but you're simply closer to the thing you think you are trying to avoid.
For example, what does https://miguelmartin.com/blog/nim2-review#implementing-a-sim... look like with C++26's std::meta::info?
My guess is: libclang is more suited for this situation if you care about compile times, even if Python is used.
I would be interested to see if there’s a significant quantifiable difference.
My guess is this would only enable a read-replica and not backups as Litestream currently does?
I would much prefer a cup of instant coffee to most coffee that is served at diners, brunch/lunch restaurants, etc. in the US. I prefer espresso still, but there's a lot of burnt tasting coffee in America.
I don't think it's fair to assume the author doesn't understand how transformers work. Their intention with this instruction appears to aggressively reduce output token cost.
i.e. I read this instruction as a hack to emulate the Qwen model series's /nothink token instruction
If you're goal is quality outputs, then it is likely too extreme, but there are otherwise useful instructions in this repo to (quantifiably) reduce verbosity.
In my opinion: there is a better argument for making new languages not have methods, or more accurately member functions (as what the author describes).
Consider the following situation: you are user of a library that declares a type called SomeType which has "methods" (member functions) in it. You want to add more "methods" to this type.
Now, there is a problem regarding consisteny w.r.t syntax, your new "methods" now have to be called via `foo(&bar)` instead of `bar.foo()`. You as a user of the library and language have to choice to make (regarding code style):
1. Accept this difference in syntax. Maybe you like this style difference, because now you can clearly see what procedures are declared in your codebase vs. the library's codebase, or:
2. Use freeform functions everywhere. Well actually, you can't do this without a refactor of the library (or with additional language features), i.e. you will need to fork the library and rewrite SomeType and the associated member functions in this freeform function/procedure style.
From a language designer's perspective, you can choose to solve the problem by either (a) forcing the declaration of procedures to be consistent or (b) introducing language features to make the calling code consistent. Odin obviously chose (a), but languages like Swift and C# chose (b) - whereas languages such as Nim chose both (a) & (b).
For (b), here's some possible features you could add:
* Extension methods (Swift, C#). This let's user declared "methods" feel like like "proper methods" of the class/struct, or
* UFCS (Nim, D). Declare everything as a freeform procedure/function but enable the syntax `arr.push(10)` when the procedure is declared as `proc push(arr: var Array, x: int)`
From this, you can see why languages such as Odin chose to go with option (a). It's simpler.
In addition, RAII has it's own complexities that need to be dealt with now, i.e. move semantics, which obviously C does not have nor will it likely ever.
These are really high quality and performant libraries.
Here is video demonstrating text rendered with Blend2D in real time (NO glyph cache used) - on the CPU!