- We are trying to make the entire compiler resilient (error-tolerant), incremental, and parallel. We have managed to make every single compiler phase (of which there are 28) parallel. This has already led to significant speed-ups. We are now trying to increase the degree of parallelism within each phase. We are also working on error resilience to provide LSP support no matter what errors a program contains (syntax, naming, type). For example, it should be possible to rename a variable even if the program currently has multiple errors.
- We are adding support for algebraic effects and handlers. This will allow users to define and handle their own effects.
- We are also exploring a novel way to combine type classes ("traits") and effects.
- We have recently added support for package management and integration with Maven.
In summary, we are already in a great spot, and useful programs can be written in Flix today. I encourage you to check out the documentation: https://doc.flix.dev/ and to try Flix!
(I am one of the developers of Flix).
Are there any [plans for] supply chain attack mitigations?
Naively searching, I find https://github.com/flix/flix/issues/4380#issuecomment-123641... (Proposed Principle: A package can be declared as "safe") and https://github.com/flix/flix/issues/2837 (Add capability-safety to polymorphic effects?) the latter closed with working on something related to this https://github.com/flix/flix/issues/3000 (The Road to Algebraic Effects).
> Flix supports region-based local mutation, which makes it possible to implement pure functions that internally uses mutable state and destructive operations, as long as these operations are confined to the region.
> We can use local mutation when it is more natural to write a function using mutable data and in a familiar imperative-style while still remaining pure to the outside world.
> We can also use local mutation when it is more efficient to use mutable data structures, e.g. when implementing a sorting algorithm.
Another language with a feature like this is F* (or FStar), but I think it uses a different kind of compile-time analysis.
Haskell actually kind of lets you do it through the ST monad (there's a function called runST that turns mutable code inside the ST monad into pure code). But F* (and Flix) can do it implicitly
An Erlang/Elixir process is single-threaded by definition, so there is no contention and in-place mutation could be allowed.
Flix – Safe, reliable, concise, and functional-first programming language - https://news.ycombinator.com/item?id=31448889 - May 2022 (42 comments)
Flix – Next-generation reliable, concise, functional-first programming language - https://news.ycombinator.com/item?id=25513397 - Dec 2020 (84 comments)
The Flix Programming Language - https://news.ycombinator.com/item?id=19928153 - May 2019 (2 comments)
Also this part made me let out an audible "wow":
> We can exploit purity reflection to selectively use lazy or parallel evaluation inside a library without changing the semantics from the point-of-view of the clients.
Will definitely keep an eye on this language! The syntax seems a little odd (inferring type parameters for functions?) but I'm sure I could get used to it.
> Dividing by zero yields zero. https://www.hillelwayne.com/post/divide-by-zero/
That's one interesting point I would love to read any opinions on.
Edit: Here's a HN discussion about the `divide by zero` article - https://news.ycombinator.com/item?id=17736046
[0] https://tutorial.ponylang.io/gotchas/divide-by-zero.html
public double magnitude
{
get
{
double c = max_magnitude;
return c > 0 ? Math.Max(c, c * (this / c)._internal_magnitude) : 0;
}
}
I could delete quite a few if statements in pretty hot codepaths if division by zero just returned zero.In the year since I wrote this post, Pony added partial division. I still don’t know anything about the language but they’ve been getting grief over this post so I wanted to clear that up.
https://tutorial.ponylang.io/expressions/arithmetic.html#par...
I think Hillel's post was just saying that 1/0 == 0 doesn't lead to any mathematical contradictions.
Another way to think about it is that I believe 1/0 == 42 and 1/0 == 43 are just as valid. They don't lead to contradictions.
[In ZF set theory] Since 0 is not in the domain of recip, we know nothing about the value of 1 / 0; it might equal √2, it might equal R, or it might equal anything else.
But I don't think you want to use a language where 1/0 == 42, and likewise for 0.
Example see: https://github.com/Release-Candidate/flix-test
* Example at the top
* Link to playground
* Explanation of all the features, with examples!
* Says which features are unique
The only thing I was found wondering was "why datalog"?
Language looks pretty good.
I always say that purely in terms of design my ideal language is high-level Haskell, low-level C. Conceptually, purely functional design is how programming "should" (note the quotes) be, but doing so down to the level of functions is both not very practical (some algorithms are just easier to express in terms pointers moving around rather than folds, reduces and the like), and makes it hard to reason about performance (especially memory, and most especially if you throw laziness in the mix).
But then again, I write my own stuff in python because I'm a lazy fuck, so probably it's not meant to be :(
That's similar to what I used to say. I was devastated to see the BitC project implode, but then Rust appeared and took up the mantle. It's not perfect by any means but it's influential enough to drag the whole field of PL development kicking and screaming in that general direction.
Similar to OOP, which promised to do this by encapsulating state, FP promised to do this via purity, aka. getting rid of as much state as possible, and only allowing stateful transition at certain well defined sections of the program.
The "market advantage" of OOP was that, via Java, it was already so well established, and so many coders had been trained in OOP languages, that it remained alive. FP on the other hand, coming out of academia and requiring all these industry people to suddenly do things in syntactically and conceptually different ways, never really gained traction. OOP simply came first, it is as simple as that.
Whether FP would have actually solved the problem is anyones guess, since it never gained the traction of OOP and Procedural languages. My best guess is that it wouldn't, because I don't believe in silver bullets.
It should be noted that both approaches contributed valueable things to contemporary languages. E.g. first order functions being the norm comes from FP.
Not really. Lisp is a functional programming language and has existed since at least 1960. Some claim there were many other proto-functional languages since the early 60's, and the FP language [1] (a clearly functional programming language and the result of the famous paper "Can Programming Be Liberated From the von Neumann Style?") appeared in 1977 - was inspired by much earlier efforts like APL.
OOP really only became a thing with Simula in 1967, but was not popular until the 1980's with Smalltalk and Common Lisp's Object System (CLOS) came about (so yes, there was a OOP/FP hybrid already decades ago), and then C++ and finally Java much later... at which time Functional Programming languages already included Miranda (1985) which later evolved into Haskell, and Erlang (1986). That is, FPP languages were at least as common as OOP languages by the 80's.
As far as I know, however, pure functional languages were not really very efficient until Haskell came about, while OOP languages were nearly on par with procedural style: which mattered a lot in 1980's machines.
Many functional zealots aim for a purity beyond all reason and comprehension. When what you really want is something like Erlang/Elixir or even C#.
With the advance of lifetime analysis, mutable value semantics, and local mutability, there’s no need to ban mutable state outright. The push for functional programming will be waning in regarding to purity.
Why / why not?
Other advantages of pure FP might be thread safety but queues take care of most of this (and often locks are not hard to use). Or low-level compositionality. But as Alan Kay said, what we need are bigger objects. John Ousterhout seems to agree. Re-use in the small increases complexity.
I assume that all of this gets funding because ten years later it makes C# programmers more productive, not because of mass appeal.
I've been looking for such a feature for some time. Do I understand correctly that the facts can be established dynamically from, say, IO functions?
Also, are you going to present at FOSDEM?
Also, I agree but I'm not sure what I would propose as a better token. Maybe another colon?
def printAndInc(x: Int32): Int32 \ IO =
becomes:
def printAndInc(x: Int32): Int32 : IO =
Or maybe, since functions need something after the \, even for pure functions, we just drop the \ and use the last argument?
def printAndInc(x: Int32): Int32 IO =
Other languages already have readable keywords in the function definition; extends, raises, where, having, Optional, and so on. They don’t feel unnecessarily verbose.
One thing not clear is what's the reference vs value model, lifetime, and mutable vs immutable model.
Over summer, I built my own little functional language, Crumb (https://github.com/liam-ilan/crumb). Unlike Flix, the scope is tiny, but some pretty awesome stuff has been done with it. (Checkout this pixel art editor in your terminal, 100% Crumb: https://github.com/ronilan/crumbicon).
There’s a template (https://github.com/liam-ilan/crumb-template) and vscode highlighter (https://github.com/liam-ilan/crumb-vscode) for anyone who wants to mess around with it. Any feedback super appreciated :D
This is disappointing. One my main grievances with Go is that it's very difficult to prototype code because it won't compile with unused variables. It massively slows down development. It annoyed me so much that I eventually forked the Go compiler and made a version where unused variables are only a warning.
You’re able to fit more code on a screen, and it’s less visual noise. It’s like Pareto better. I really don’t get why others don’t copy it.
Give me braces and rip a formatter across the whole codebase and be done with it.
Furthermore, I think that the trend of compilers/interpreters caring about whitespace formatting rules should really end. You can't ever force everyone in the world to write aesthetically pleasing code in your language and someone out there will always be able to write a complete trainwreck, and everyone disagrees on what is or is not aesthetically pleasing. Leave the problem up to configurable code linters where it belongs. Let people make "mistakes" (in your eyes) if they want to.
(I am one of the developers of Flix).
Rough edges, but I'm really liking it so far. Let's see how it will handle the upcoming Advent of Code.
Particularly in the sections titled "What features are not supported" (no exceptions or panics, so e.g. indexing has to return an Option in case it's out of bounds) and "What controversial design choices are made". Some pithy remarks towards the end as well.
To follow HN tradition and find the most controversial topic to discuss, my guess is it's either not allowing name shadowing, or divide by zero equals zero. Or the site not working without javascript (see the section on that near the end, but you'll need to turn on javascript to read it I guess)
I'll perhaps be the first to jump on the 1/0 != 0 hate train though; they mention they designed the stdlib to avoid the partial-function pitfalls of Haskell's, but the article they linked to support their design decision of 1/0 being 0 mentions that it boils down to division being a partial function - x/0 is not a case division can handle. Would it not then be reasonable to make division return an Option?
I don't mind the disallowing name shadowing, but I really, really hate (I mean that) websites that are just good ol' text and the odd picture that require Javascript. The excuse of "we used React, it's easy" seems odd given that HTML is much easier.
But I agree, this can be cumbersome. So, Flix allows any unused construct to be prefixed with an underscore to mark it as unused. (But underscored things cannot be referenced.) This seems like a pragmatic trade-off.
(I am one of the developers of Flix).
Any language that does it, is beyond usable (notably go and zig). Like, I would literally fork the compiler before using them with that “feature” on. It’s completely braindead thing to do — like okay, have a separate production release mode and make it an error there. But for quickly testing out stuff, you will inevitably comment something out, which makes a variable unused. Commenting that out will also make something else unused, so you literally have a recursive problem with some random depth, and depending on how deep it goes, you will literally lose all of the context on what you wanted to debug in the first place.
There is literally zero advantage of this idiotic bullshit, my proposed solution of doing it only in prod release gives all the benefits with none of the negatives.
Make those warnings in debug/test builds, and errors in prod builds.
(I am one of the developers of Flix)
Inspirations and ideas from four of the arguably most complex languages of the modern world, all the best with that.
These languages put forth ideas that are extremely powerful. They might be unconventional from an imperative programming lens, but to call them all “complex” as a justification for discarding them entirely is pretty shallow.
With the rapid rise of AI, most tasks will soon involve the management of AI models rather than writing code. However, it is still important to have a basic understanding of coding.
Introducing a new programming language at this point seems silly to me.
;)