Show HN: Matterhorn, a terminal-based chat client for Mattermost
github.com7 pointsby andolanra2 comments
data Term t where
Num :: Integer -> Term Integer
Bool :: Integer -> Term Integer
Add :: Term Integer -> Term Integer -> Term Integer
IsZero :: Term Integer -> Term Bool
IfThenElse :: Term Bool -> Term a -> Term a -> Term a
With this AST, you can express well-typed programs like `Add (Num 2) (Num 3)`, but the Haskell type system will stop if you express an incorrectly-typed program like `Add (Num 2) (Bool False)`. data CompilerPhase = Parsed | Resolved
data Expr (phase :: CompilerPhase)
= Lam (Name phase) (Expr phase)
| App (Expr phase) (Expr phase)
| Var (Name phase)
type family Name (t :: CompilerPhase) :: *
type instance Name Parsed = String
type instance Name Resolved = Int
Using this example, an `Expr Parsed` will contain variables that are just strings, while an `Expr Resolved` will contain variables that are integers, and you can write a pass `resolve :: Expr Parsed -> Expr Resolved` which just modifies the AST. (This is a toy example: in a real compiler, you'd probably want to create a new type for resolved variables that still keeps a copy of the name around and maybe some location information that points to the place the variable was introduced.) def foo(kwargs = {}, frob:)
kwargs
end def foo(kwargs = {})
kwargs
end
foo({k: 1}) # ok: passing hash argument
foo(k: 1) # ok: keywords coerced to hash
One of the strongest arguments for avoiding this sugar is that it makes the code more brittle in the face of future changes. In particular, in the example above, if we add a new keyword argument to `foo`, then any call which omitted the curly braces will break, while calls which used them will keep working fine: # added a new keyword arg here
def foo(kwargs = {}, frob: false)
kwargs
end
foo({k: 1}) # still ok: `frob` defaults to false
foo(k: 1) # ArgumentError: no keyword: :k
This is touched on in the blog post describing the extensive changes made to keywords in Ruby 3: https://www.ruby-lang.org/en/news/2019/12/12/separation-of-p... bitfield! {
pub struct Color(u32);
red, set_red: 0;
green, set_green: 1;
blue, set_blue: 2;
alpha, set_alpha: 3;
}
Don't get me wrong: it's cool that functionality like this is built-in in Zig, since having to rely on third-party functionality for something like this is not always what you want. But Zig is not, as this article implies, uniquely capable of expressing this kind of thing. func getTopUsers(posts []Post) []UserLevelPoints {
return posts.GroupBy(func (v Post) string { return v.Level })
.Values()
.Map(getTopUser)
}
This pipeline style is significantly easier to read (especially without having to put all those extraneous type parameters in your call to compose3!) and doesn't actually lose any of the core advantages of the functional style: purity, testability in isolation, equational reasoning, and so forth. Sure, the Haskell equivalent might use composition… but composition reads more or less naturally in Haskell, and I don't think it does at all here in Go. If your specific approach to "functional programming" makes your code theoretically easier to reason about but practically harder to both read and write, then is it really helping you much?
Since then, aside from some interesting bits of work that didn't actually make shipping games easier, the engine really languished. My understanding is that a big part of the reason the engine was removed was that it made work on other parts of Blender more difficult, and that dispensing with the (little-used) engine in favor of the (increasingly popular) modeling tool was clearly a net benefit to being able to develop Blender, especially since the mantle of "open source game engine" had been taken up by other competent projects like Godot.
So yes, they may have at some point aspired to becoming a "mainstream game engine", but there's more to that effort than just aspirations and demos. (And at the same time, the fact that the BGE faltered doesn't mean that other open source game engine efforts would necessarily face the same fate.)
It's probably also worth saying that people have forked the game engine and you can still use it: the forked version is called UPBGE, and there are people out there trying to make it work. By and large, though, the Blender project seems to point people at projects like Godot, with the idea that a focused game engine is probably better suited to modern games than something that strapped a game engine onto a piece of modeling software.