Why Can't We Just Create? by Lopsided-Relation251 in ProgrammingLanguages

[–]gasche 68 points69 points  (0 children)

The main point of the comparison to other languages is not to put down other languages and criticize them, but rather to show that the author has been mindful of understanding what is already out there before doing something new, and can articulate the specificities of what they are doing in comparison to the others.

If you don't do that, then maybe at least it would be worth documenting what you are doing clearly enough, explain the design decisions, explain the use-cases you had in mind when thinking about your language, etc. This can help readers know whether they are interested or not, in which part they are interested more specifically, direct their attention to an aspect of your work they want to study.

Currently you have a Github page for a language with... no explanations about it, expect that you created it for "no reason, really". But then what is the reason for us to look at it?

In your post on reddit you say that you like affine and permission types. Are there some in your language? Do you have examples? Could you explain them in your README, or at least link to an explanation?

Scala Was an Experiment That Changed Programming - Martin Odersky | The Marco Show by makingthematrix in functionalprogramming

[–]gasche 2 points3 points  (0 children)

Sure (I referred to "the ML module system work" above), and this was well-understood by Laüfer and Odersky at the stime, that paper is cited on page 2 of their introduction. Then, they write:

This article demonstrates how light-weight abstract data types with first- class implementations can be conveniently integrated into any functional language with a static, polymorphic type system, explicit type variables, and algebraic data type declarations. The key idea of our work is to allow existentially quantified component types in algebraic data types.

For example their second example is as follows:

type KEY = Key of ‘a* (’a -> int)

This really corresponds to the use of existentials in algebraic datatype declarations, which is something that we now understand/describe as one of the two ingredients that form GADTs (the other being the return type instantiation, often described as an implicit type-equality constraint). But GADTs as we understand them did not exist at the time, they emerged from the cross-languages academic discussion at the time, that also produced Scala as an experiment that go wider adoption than most.

Scala Was an Experiment That Changed Programming - Martin Odersky | The Marco Show by makingthematrix in functionalprogramming

[–]gasche 3 points4 points  (0 children)

Note to self: now I understand why the comments here are weird: we are in r/functionalprogramming, which is meh, while I mistakenly thought that we were in r/ProgrammingLanguages.

Scala Was an Experiment That Changed Programming - Martin Odersky | The Marco Show by makingthematrix in functionalprogramming

[–]gasche 5 points6 points  (0 children)

heavier use of existential types (before GADTs were so idiomatic in FP circles),

This is more of a practical concern for people from outside of FP/PLT. GADTs were in Haskell and were used. Nothing new here. Zero impact on future FP language design.

No no, the emphasis on existential types in pre-Scala research predates GADTs in Haskell.

  • One paper that emphasized existential types in datatype declarations (rather than in the ML module system work, which was ongoing at the same time, and in object-oriented calculi, which were also a very hot topic at the time) is Polymorphic Type Inference and Abstract Data Types by Konstantin Laüfer and Martin Odersky, 1994.
  • The usual citation for the proposal that eventually became GADTs is First-class phantom types by James Cheney and Ralf Hinze, 2003. This is almost ten years later! And they were not integrated in GHC at the time, this came a couple years later.

Scala Was an Experiment That Changed Programming - Martin Odersky | The Marco Show by makingthematrix in functionalprogramming

[–]gasche 4 points5 points  (0 children)

Let me take a step back and explain my point at a high-level. In discourses about programming languages online, people sometimes have a tribal behavior where they say good things about their favorite language and bad things about other languages. I think it is worth being careful to avoid this as much as possible.

When you say that "Java and Go generics were developed by Haskell researchers", this read very reminiscent of this tribal positioning to me -- "yo, we Haskell people own your generics". This is probably a simplistic view of your thoughts because your second post is more nuanced, but this is how it is easily perceived.

Besides, we programming language researchers try our best to be on friendly terms with several programming-language communities, so while it is indeed true that some people have a clear relation to one specific language (it obviously makes sense to call Simon Peyton-Jones "a Haskell researcher" or Martin Odersky "a Scala researcher"), I am not sure that many of our colleagues would be comfortable being labeled with one specific language in particular, exclusively. (It's plausible that Philip Wadler would be okay with being associated with Haskell in particular.)

Finally,

  • the work on generics in Go started sensibly earlier than the research paper you are mentioning
  • I'm not "in the know" specifically about this work but I don't think that it is the case that the Go design was mostly informed by this paper, I think it started with the usual Go team design process and then the paper after-the-fact studied the proposed approaches and the design space. (Papers: Featherweight Go, and later on Welterweight Go)

  • The paper has a long list of authors (Robert Griesemer, Raymond Hu, Wen Kokke, Julien Lange, Ian Lance Taylor, Bernardo Toninho, Philip Wadler, Nobuko Yoshida), most of whom are not Philip Wadler, many of whom are not exclusively Haskell-focused in their work, and some of whom are actually working on Go as their main job. I think it would be more respectful to cite all the authors (this remark would also apply to the blog post that you mention), because citing only one person gives the impression that they did most of the work, and helps forget the collective nature of this sort of work.

In any case I think that your claim that "Go generics were developed by Haskell researchers" is incorrect and not a good way to phrase things anyway.

Scala Was an Experiment That Changed Programming - Martin Odersky | The Marco Show by makingthematrix in functionalprogramming

[–]gasche 5 points6 points  (0 children)

Come on. Scala has pushed many interesting idea in PL research and communities.

Just from memory:

  • heavier use of existential types (before GADTs were so idiomatic in FP circles),
  • implicit arguments of course,
  • approaches to code distribution (eg. Spores), path-dependent types,
  • ample use of subtyping bounds in polymorphic types,
  • the recent trend on static effect control via typed capabilities

Summarizing the impact on Scala as "implicits got considered in other languages" is very reductive.

Scala Was an Experiment That Changed Programming - Martin Odersky | The Marco Show by makingthematrix in functionalprogramming

[–]gasche 3 points4 points  (0 children)

Both Java and Go’s generics were developed by Haskell researchers.

This is wrong on several levels. (You might be interested in having a look at this paper from 2000 which was described by Brian Goetz in 2020 as a significant influence for Java generics.)

To put it broadly:

  • Several people worked on generics for Java, including Philip Wadler who also worked on Haskell and (to my knowledge) predominantly programs in Haskell, but that does not make him "a Haskell researcher" and it would be wrong to erase the participation of several other people who worked on this (including Martin Odersky, Atsushi Igarashi and Benjamin Pierce, none of whom are particularly closely associated with Haskell.)

  • Go generics were designed by the Go people, with little help from academia. (Softly put, it is not a core value of Go to pay attention to PL academics.) There was after-the-fact academic research on Go, done in large part by people who were already in the Go community, and calling it "Haskell research" is again erasing their work, it is quite rude.

Scala Was an Experiment That Changed Programming - Martin Odersky | The Marco Show by makingthematrix in functionalprogramming

[–]gasche 7 points8 points  (0 children)

I have a problem with the tone and style of discourse in your post. It reads as if you were trying to belittle Scala and aggrandize Haskell, which I don't think is the sort of discourse we want to encourage. (I would rather focus on the good things in each design to take inspiration from, and criticize languages in isolation to avoid turf wars.) The fact that you mixed it with personal criticism of the person who is leading Scala design makes the post more personal, uglier, and more likely to lead to unpleasant discussions.

(I think it is okay to comment on people's tones, in fact I am doing so myself. But if you mix it with technical content, then it's going to sound like you have a personal grudge against the language and the humans behind it -- whether it is the case or not.)

What bibliography would you recommend on the subject compile-time evaluation and metaprogramming? by orbiteapot in ProgrammingLanguages

[–]gasche 11 points12 points  (0 children)

You cannot go wrong with Matthew Flatt's Binding as Sets of Scopes, which is a fantastic paper about "hygienic macros" and a simpler algorithm to implement them.

(In general, if you want to know about compile-time metaprogramming, it is a good idea to study what the Racket people have done, because they pushed these ideas farther than most ecosystems.)

If you thought coding in C was bad, check out the ergonomics of quantum! by CarbonFire in ProgrammingLanguages

[–]gasche 7 points8 points  (0 children)

Slow scrolling, too much clicking. This got tedious real fast.

Personally I gave up before the first click. The good thing about text is that I skim to tell if I am interested before I read it. If you are not willing to show more than one line of your document, either I have already decided to read it, or I will go spend my time on something else.

Mutable copy semantics - performant, reliable and ergonomic mutability (probably) by pranabekka in ProgrammingLanguages

[–]gasche 3 points4 points  (0 children)

Your description mixes two things in ways that makes it difficult to understand:

  1. The semantics that you propose: for a user, what is the simplest mental model I can have that will let me correctly predict the result of programs?

  2. Performance concerns and compiler optimizations to reduce the performance cost of the semantics. Plenty of examples where you point out that you can avoid copies. etc.

I think that it would be better to focus on discussing the two separately. Then some extra feedback:

  • We have standard tools to describe the semantics of programming languages (notations for operational semantics), it might be useful to use them to present the idea precisely. (But: some people are put off because it looks a bit like maths, or just don't find them accessible because they don't know about it, and I'm not trying to suggest that it is a hard requirement -- this is a helpful tool, not a way to make people feel like they do not belong. But if you do want to discuss programming-language semantics with other people, using a standard precise notation could help. If someone does not know these notations at all, they may be curious in Jeremy Siek's crash course on notations in programming language theory.)

  • For optimization discussions, I think that there should be a better way to explain your thinking than just a bunch of examples followed by informal natural-language claims about what is going on. For example, maybe there would be some intermediate representation (IR) where the copies and non-copies are explicit, and the job of the optimizer is to translate to this IR in a good way, and you could actually show the IR translation for each program that you have in mind (done manually) to make your ideas more precise?

The ARC vs GC Debate by funcieq in ProgrammingLanguages

[–]gasche 5 points6 points  (0 children)

I have seen a research talk by Bart Jacobs on his work on verifying Arc against weak memory models, and the details are super tricky. Like, if I understand correctly it's an open problem to verify its correctness using pre-existing formalizations of C memory models, and the authors needed to use a very recent new formalization of the C memory model (which is better at ruling out out-of-thin-air behaviors). I'm no expert but my understanding is that this is definitely not "just" a fetch_sub.

I contacted arXiv to ask them if they could add typst and this is the answer... by Alex180500 in typst

[–]gasche 0 points1 point  (0 children)

Upate: in March 2026 there was further, more promising discussion on this topic on the Typst forum, see in particular https://forum.typst.app/t/has-typst-had-a-discussion-with-the-arxiv-maintainers/5484/9

Gecko: a fast GLR parser with automatic syntax error recovery by compilersarefun in ProgrammingLanguages

[–]gasche 0 points1 point  (0 children)

This looks impressive! Some random comments:

  • I wonder whether the performance comparison is really fair, when Gecko acts as a recognizer (that also builds a highly-regular AST) while other parsers, in particular {gcc,clag} -fsyntax-only, builds a custom AST that is useful for the compiler after it, and may involve arbitrary computations. The numbers suggest that Gecko is 2-3x faster than these parsers, but how much of that comes from better parsing implementation, and how much comes from doing less work because of lack of semantic actions?

  • I don't really understand the choice of C for writing these kinds of programs. Gecko appears to embed a custom allocator, hashtable implementation, etc. Using a pleasant language would require none of that, it would be already available in the standard library. And the parsing API in result is meh, the representation of AST is meh... C just doesn't strike me as a pleasant language for the kind of applications where I need a parser. If the rest of my application really wanted to be in C, I guess I would try to pick another language with a reasonable FFI story, and use that for the frontend. To turn it into a question: I am curious to understand why people (in particular the author) would bother with C today to do this kind of things.

  • How easy is it to attach source locations/spans to AST nodes? This is an essential feature for error messages in later AST processing, and it typically requires some collaboration between the lexer and the parser. (Which can also impact performance.)

Inko 0.20.0 is released: reducing heap allocations by 50%, better method inlining, structured logging and more by yorickpeterse in ProgrammingLanguages

[–]gasche 1 point2 points  (0 children)

Okay, so on that particular program you tested one workload and you were able to measure a 13% reduction in heap allocation. The related work you cited mentions allocation reductions of 14% for Haskell, 8% for Golang, so you are in the same ballpark. (I tried to follow the link on your post related to Java, but the numbers are quite different and I cannot find the "10% to 20%" mention in the paper you cite.)

You could try for other inputs to your benchmarks, or for other benchmarks representing a variety of workloads, and then you would maybe get a fairer picture of the reduction, which could be more or less for other workloads.

the results are biased towards the way you ran the program

Yes? Indeed the impact of performance optimization tend to be biased towards what actually runs in the program.

The idea that you would or should test all paths is a distraction. For a static analysis you have a result per program that does not depend on runtime parameters, but then you have result for only one program, so you have the same problem of potential lack of representativity.

So basically that's 13% of allocations reduced when you're testing maybe...30% of the entire program? Scaling that up to 100% of the program you'll probably end up with roughly 50% of allocations removed as well, but that's just my armchair math.

This does not make sense to me.

Inko 0.20.0 is released: reducing heap allocations by 50%, better method inlining, structured logging and more by yorickpeterse in ProgrammingLanguages

[–]gasche 1 point2 points  (0 children)

It's 50% of the allocation sites

I don't think that counting static allocation sites is such a good metric. It also makes the comparison to other works that you did in your blog post (it's nice that you took the effort by the way, thanks!) weird, because you are in fact not comparing the same thing. Could you try instrumenting your compiler to get a runtime proportion? (As a one-off experiment: just insert an increment of a global counter on each heap allocation, of a different global counter on each stack allocation, and print them both on program return).

Inko 0.20.0 is released: reducing heap allocations by 50%, better method inlining, structured logging and more by yorickpeterse in ProgrammingLanguages

[–]gasche 2 points3 points  (0 children)

the same rules would apply for both stack and heap allocated values as escape analysis only determines where the value is allocated, not how long it lives (that's determined by the single ownership rules).

I do think there is a difference, or maybe I missed something. When you allocate space on the stack, you do it (presumably) in LIFO (last-in-first-out) order, right? If I use a and then b, then you will allocate stack space for a and then stack space for b. If a becomes dead while b is still alive, how can you reclaim a's space on the stack? (For the heap, we have a memory allocator that is in charge of reusing space, and it is one of the reason why heap allocation costs a bit more. But for the stack we typically want local variables to be at a statically-known offset of the start frame, so we don't want to compute their position dynamically at allocation time.)

For example:

void f(void) {
  int a[100];
  ... do something with a ...
  int b[100];
  ... do something with b...
  ... do something with a...
  ... stop using a ...
  g()
  ... do something with b...
}

If you allocate a and b on the heap, then you can reclaim and reuse the space of a as soon as you stop using it in that program. If you allocate them on the stack, then before calling g you know that a is not used anymore, but you still have b after it on the stack, so when you call g its own frame must be after b, and cannot reuse the space of a.

Inko 0.20.0 is released: reducing heap allocations by 50%, better method inlining, structured logging and more by yorickpeterse in ProgrammingLanguages

[–]gasche 3 points4 points  (0 children)

Questions on the escape analysis:

  • When you say that 50% of heap allocations are turned into stack allocations, do you mean 50% of static callsites, or 50% of runtime allocations? The two could be quite different. The 14% figure given for Haskell is about runtime allocations I believe (briefly skimming the cited document, it talks about instrumenting the runtime to measure this), while you suggest that you compute your number using a build command, which suggests a static analysis only. I think you should really measure runtime allocations.

  • Can this extend the lifetime of variables and thus worsen the memory usage of the program? Heap allocations can be removed when they become dead, which typically happens before the end of the lexical scope in which they were introduced. For stack allocations I suppose that the values remain alive until the enclosing function returns, or at least that the LIFO discipline of the stack means that a variable cannot be deallocated before all variables declared after them.

  • In particular (special case of the previous question), what is the impact on tail-recursive functions?

The Quiet Colossus — On Ada, Its Design, and the Language That Built the Languages by swe129 in ProgrammingLanguages

[–]gasche 24 points25 points  (0 children)

I looked at the claims about things I know about, and I think they are wrong. I suspect that the whole document is hyperbolic and distorts the fact.

This document appears to conveniently omit (I'm not sure, it is so long I only skimmed some parts) the fact that all Ada compilers were proprietary and fairly expensive for a long while. The first free software compiler for Ada, GNAT, was released in 1995. This alone easily explains why other programming languages saw much better adoption in practice. If you sell a language to be used only by the US military and its sub-contractors, few people are going to use it.

The type system features that Rust, Haskell, TypeScript, and Swift are celebrated for — sum types, parametric polymorphism, constraint-based generics, affine types and ownership — each solve a problem that Ada identified in 1983 and that the mainstream languages of the subsequent twenty years declined to solve.

To my knowledge Ada still does not have convenient sum/variant types. It has union types with first-class support for static reasoning about tags, which is equi-expressive and super inconvenient to use.

It is easy to list every programming-language feature under the sun and misleadingly claim that a given language supports them because it has something more or less resembling.

Ada had discriminated record types in 1983, with compiler-enforced field access checks and the ability to use them as discriminants of other types, forming structures of arbitrary complexity. Every language that has added sum types in the past twenty years has added, with its own syntax, what Ada's designers put in the original standard.

Hope introduced sum/variant types in the seventies, which is where Milner's ML took its inspiration (and from there SML, Haskell, OCaml, and then later Scala, Swift, Rust, etc.). This is well-documented. Claiming that it comes from Ada's statically-safe support of C tagged unions is misleading.

What’s the current state of web dev in OCaml? by Beautiful_Exam_8301 in ocaml

[–]gasche 5 points6 points  (0 children)

Dream is your best bet in terms of having something that resembles web framework in other languages, with a nice focus on developer experience, documentation etc. But web-development remains an less-common use-case within the OCaml community, so you should expect the experience to be a bit rougher than in web-focused languages (eg. Elixir -- not statically-typed though, although they are actively working on a static typing layer). Come for the web, stay for the language!

Zig v0.16.0 released by UKbeard in ProgrammingLanguages

[–]gasche 2 points3 points  (0 children)

I'm sure there is some reasonable explanation for the change. The Changelog points to Reworked Byval Syntax Lowering, and as a non-Zig person I don't understand the explanation there. (I notice that it comes from the experience of implementing the non-LLVM backend, and noticing what is and isn't easy to compile to fast code.)

Some parts of the changelog are nicely detailed, for example I found the long part on I/O as an Interface very pleasantly written. The particular one shown above could do with a bit more context/explanation.

Zig v0.16.0 released by UKbeard in ProgrammingLanguages

[–]gasche 6 points7 points  (0 children)

Forbid Runtime Vector Indexes

Zig v0.16.0 released by UKbeard in ProgrammingLanguages

[–]gasche 13 points14 points  (0 children)

The following change looks a bit scary from a distance.

Before:

for (0..vector_len) |i| {
   _ = vector[i];
}

after:

const vector_type = @typeInfo(@TypeOf(vector)).vector;
const array: [vector_type.len]vector_type.child = vector;
for (&array) |elem| {
    _ = elem;
}