Lang Jam: create a programming language in a weekend
github.com
github.com
In the perf site you can see some examples: https://perf.rust-lang.org/
Eventually as optimization point, for the few use cases where the ultimate performance is needed, provide a subset of borrow checker capabilities.
Examples of current efforts into this direction, D, Swift, Haskell, Chapel, some .NET ongoing research.
Reframing the system in this way will (hopefully) make things be flexible enough to Just Work™ without surprises, while providing the same guarantees as the current borrow checker. The video itself has a motivating example or two that shows where this stuff would be helpful.
In Swift, type inference is one thing that can be extremely slow.
There seems to be a pattern here. I'm not saying that LLVM is bad, in fact if it's used by so many projects it's for a reason. But it does have a cost.
Flowtype has horrible performance, which in my opinion partially explains why it has lost so many users to Typescript, which has much more predicable and fast performance even though it's written in JS. The project is basically dead
Darklang is being rewritten to .Net because they were unsatisfied with the OCaml ecosystem.
Horrible performance is generally more a question of algorithms and software architecture than a problem with a language, which only account for a flat percentage of performance.
About Flow, I've never used it so I can't say, but Rescript (which is written in OCaml) compiles 10 to 100 times faster than Typescript.
It's also not memory safe. It's very easy to crash the process.
Also, regarding memory safety, it's not as safe as Rust - it's basically only memory-safe in the single-threaded context, but it's still relatively safe compared to other languages.
I don't really find it easier to crash than Rust - thanks to optionals you get the same guarantees against NPE's. You can choose not to take advantage of it, but you can also force-unwrap in Rust if you want.
In fact I would like to be able to integrate Swift and Rust so that I could also use Rust in my iOS and macOS apps directly. But for now and for the types of applications that I am currently working on it is not worth going down that particular route. But in the future I wish to write some games where I want to write all of the game logic in Rust and use Swift + Metal for the rendering.
When we want to avoid the GC we know how, when we want the productivity we use the GC and fuggedaboutit
That's perhaps not the best wording.
Nonetheless, I do agree with you. D can be very flexible in that regard.
Having spent 20 years mostly working in GC languages, it's totally worth it! However, writing portable libraries like SQLite or libpng are very difficult to do without bringing in unacceptable overhead for your consumers.
I'm not sure I've ever seen a more readable compact fizzbuzz than this version in coffeescript
['fizz' unless i%3] + ['buzz' unless i%5] or i for i in [1..100]All that said I've never been a fan of dynamically typed languages myself. Fast to make things in but difficult to reason about later.
Appending a string to an undefined value, via array addition, which turns them into strings but doesn't turn null into 'null' or undefined into 'undefined'. It's a bit of a hack.
`'a' + undefined === 'aundefined'`
`[ 'a' ] + [ undefined ] === 'a'`
Also the empty string '' evaluates to false.
`[ undefined ] + [ undefined ] == ''`
This is wat - https://archive.org/details/wat_destroyallsoftware
For a second, I thought it was JavaScript
// Generated by CoffeeScript 2.4.1
(function() {
var i, j;
for (i = j = 1; j <= 100; i = ++j) {
[!(i % 3) ? 'fizz' : void 0] + [!(i % 5) ? 'buzz' : void 0] || i;
}
}).call(this);IE, if in my business logic, I write "new Foo()", I'd like to be able to write a unit test where I say something like, "whenever I wrote 'new Foo()' swap in this mock object instead."
Or, in a module that's an entry-point, I'd like to say, "whenever I wrote 'new Foo()' swap in this subclass instead."
I've spent so much time refactoring to make code mocking and dependency-injectable.
If you have a function like:
(defn send-mail [receiver-ids title text]
...)
You can mock it out in your tests like: (with-redefs [send-mail (fn [r-ids title text]
(println r-ids title text))]
;; send-mail will just print
...)
[0] https://clojuredocs.org/clojure.core/with-redefsNeither is popular but they're pretty interesting!
Why? Sometimes there's no "right" style. Sometimes novices need training wheels. In the long run, style doesn't matter, but in big projects code is easier to read when style is consistent. It's also easier to onboard when code follows industry-standard styles.
Would it be better when a language gently pushes everyone to the same style?
I don’t know if I will ever actually put my personal language out for release, but I’ve had two acquaintances repeatedly tell me (along with several HN commenters) that I really should at least release some blog posts about the language. Currently it is just my daily driver for work related programming and it compiles to C++, C, or JavaScript.
It's slowly catching on in other languages, eg. Clang now has clang-format and IntelliJ can auto-reformat your code according to a rule config you set before each check-in.
This is almost always a subjective opinion. I've worked on many projects where people reformat large portions of the codebase to make it "easier to read", and in the end they waste a bunch of time, make using `git blame` a pain, and subjectively either make no difference in code readability or make the code harder for half the team to read.
> I'd like the compiler to reformat code...
Why is this the compiler's job? Most people aren't reading code after it's been compiled. In most of the languages I've worked with, this is handled by a formatter + styleguide/config that either runs in the IDE on save or on a git hook, or both.
Ever start a new job with a bulk of code you didn't write? Worse, ever take over code written by novices who ignore common conventions?
The whole point is to see if having a standard style is easier in the long run.
Yes, I have seen lots of this in scientific computing. However, things like too many/not enough spaces, line widths, etc, are never a huge hindrance for me.
What does make code "hard to read" are things like bad and inconsistent variable/function/class names, bad inheritance practices, bad file organization, and not adhering to common language idioms. That stuff is rarely, if ever, caught by linters.
Great talk by Raymond Hettinger about this: https://www.youtube.com/watch?v=wf-BqAjZb8M
1. That would be telling.
2. Apparently there's going to be a theme? So that might make whatever wacky language I've been mulling a bad fit. I'm rather curious about how that will play out
I would then build a visualization environment which shows what the actors are doing, possibly step-by-step. It would show them moving values between registers and buffers. It would show messages passing between actors. It would show new actors create and finished actors die and errors get dumped into the canvas.
Your concept as an end-user would be that you're programming these automatons. You could clearly visualize what's occurring and debug control-flow or algorithmic issues by stepping through their movements.
Maybe not a great idea in the long run, but if it was a weekend lang jam, that's what I'd do.
fizzes = cycle ["", "", "Fizz"]
buzzes = cycle ["", "", "", "", "Buzzes"]
words = zipWith (++) fizzes buzzes
numbers = map show [1..]
fizzbuzz = zipWith max words numbers
Henney explains in detail in the video, but it makes use of lazy evaluation to create an infinite list of FizzBuzzes, and also uses no if statements. I find it intellectually exciting, but make no claims on readabilityEdit: Nevermind, max is lexicographic, not based on string length. Brain fart.
Also I'm not sure how that solution would work for negative numbers...
Then again what is the right answer for 7i + 24?
Corner cases duck!
Typically it is a counting game, starting at 1 and going up to some arbitrary value.
fizzbuzz = "FizzBuzz" : zipWith...
To make negative numbers work you'd need a new numbers definition numbers = map show [-1, -2..]
Should yield all the negative integers eventually.I've never heard of FizzBuzz defined for complex/imaginary/2-d numbers. That's interesting to consider, I'll be thinking about this for a while
1.) A language for plumbing. Basically, this is a mini-language for defining data structures and how they're shipped around different devices and processed. Think of protobufs or Apache Avro, but also including functionality like conditionals & flow control, rich collection operations like map/filter/fold, account & device management libraries, and most importantly, an Actor-based syntax (somewhat like Erlang) where entities like "The user's iPhone" or "The user's smartwatch" or "the database" just exist like process handles, and you can send messages to and from any of them. It'd then compile down into idiomatic Swift/Kotlin/Java/C/SQL to run on appropriate machine, so that your UI code just includes a library and you don't need to rewrite all your data plumbing, serialization, and business logic for each client platform.
2.) A language where you literally can use machine learning like if-statements. Basically it'd have functionality to dump out a feature vector (an array-of-structs), visualize it in a Jupiter notebook, label it (or send it off to Mechanical Turk for labeling), and then feed the labeled data back into any of multiple classifier types for use in an if-statement. Once trained, the model and training data would be checked in as if they were source code, and could be attached to code and versioned the same way that an algorithm would be. You'd run your program in two modes: in training mode, the program executes as much of the code path it can until it gets to an untrained classifier, then dumps out the data for that and starts the labeling/training process to generate the trained model. In execution mode, it uses the generated models to actually make flow-control decisions.
Doubtful I'll ever have time to implement either one of these, but at least at the moment, they're somewhat timely and don't have convenient solutions. I think syntax is basically a solved problem, and don't really care about it.
You might have a picture represent a program, like Piet [1]. Or you might have a language specifically designed to show certain types of pictures, like TeX or Processing or more narrowly, PlantUML.
Another area to explore is the distributed space. Perhaps a language with Kubernetes capabilities as first-class objects.
[(("fizz" if not i%3 else "")+("buzz" if not i%5 else "")) or i for i in range(1, 101)]
Gotta love list comprehensions.Or something like a lovechild of sed, awk, seq, and cut, with regexp match groups and string interpolation.
That would be XPath/XQuery
I have spent 15 years implementing that in Xidel
>Or something like a lovechild of sed, awk, seq, and cut, with regexp match groups and string interpolation.
Sounds like Perl
It started with XPath, then came XPath 2, then XQuery 1, then XPath 3.0 and XQuery 3.0, and then XPath 3.1 and XQuery 3.1.
Six new languages each more expressive than previous one. That is why it takes forever to implement them. And now people are working on XPath 4.0 and XQuery 4.0.
And Perl got Perl 6 and Perl 7 and Raku
And this is a post about creating lots of new languages. This doesn't have the goal of having languages that run in production, it has the goal of exploring the solution space.
So seems like it should be fine! Go ahead and make a racket :)
> You can build an interpreter or a compiler, so long as it can run or build examples of code in the programming language you create.
No you create a language, but it needs to be able to run. So need to either build a compiler or interpreter to make the language do things.
Designing a language is more about defining a specification. Then 10 different compiler engineers may pick that spec up and implement 10 different implementations of the same language, for example.
https://news.ycombinator.com/item?id=13082825
I followed that guide to implement a simple FORTH-like system in golang:
As I was following the implementation recipe I broke it down into "educational steps". Although it isn't a true FORTH it is pretty easy to understand and useful enough to embed inside other applications.
Now and again I consider doing it again, but using a real return-stack to remove the hardcoded control-flow words from the interpreter, but I never quite find the time.
> You can build an interpreter or a compiler, so long as it can run or build examples of code in the programming language you create.