79 comments

[ 3.4 ms ] story [ 140 ms ] thread
Why?
I have the same question. The documentation does a good job presenting the language, but not the motive or sweet spot use case.
From the guidelines[0]:

> Please don't post shallow dismissals, especially of other people's work. A good critical comment teaches us something.

[0] https://news.ycombinator.com/newsguidelines.html

No, it is actually good feedback. Any project should have a good background page why they sre being build, by who and with what expertise.
There's a Discord where you can probably get the answer to your question: https://discord.gg/9dq6YB2
Official Discords/Slacks for programming languages should be considered an antipattern - especially if they end up replacing documentation or a discussion group.

It's as if the new generation of developers doesn't realize the difference between transient conversations (which is what happens on Discord/Slack) and creating knowledge (which needs to be persistent and searchable, neither of which is afforded by aforementioned chat services).

Did programming language projects utilize IRC channels in the past?
They did. Some software tooling still does. It's still an antipattern if it replaces documentation.

This applies to communities in general (on-line and off-line). Knowledge needs to be captured outside of the minds of select participants. It's e.g. why, in our local Hackerspace, I always insisted on the rule that anything said on IRC (or later, Telegram) is non-binding - the only things that matter are ones decided on the mailing group or documented on the wiki. To do otherwise is to force out everyone who can't keep pace with the common chat.

The above are persistent and searchable, unless you're using the free version of Slack which sets a limit on persistence

But regardless, my experience is that once languages reach a critical mass they do get real documentation in a more browsable format. And I think Discord is a totally valid temporary solution for documentation, and a totally valid replacement for discussion groups.

FWIW, I 100% agree with you for the same reasons you outline.

I was simply stating that the Discord channel exists and that the answer to the question can be found there. Sorry someone took personal offensive to that.

it's not a "new generation of developers" problem

it comes down to the intelligence of a person

having low IQ makes you do that kind of mistakes

it's the same for feedback, some people prefer lies so you don't hurt people saying the truth

they even institutionalize that as a rule, and they then silent you, because you hurt people by telling them actual facts without artificial rounded edges aka lub

As always, all languages, especially the new one, should have a "why" section. Small caveat: maybe it's still under construction and the person that posted it just found it too early. But once you're ready to show it to the world, please include the why! Note that anything is valid in the "why", even "just for fun" or "because I could". For now there is:

> Senegal is a powerful, small-but-fast, concurrent, class-based, and dynamically-typed programming language with a modern syntax.

I think the closest thing to it is Wren? https://wren.io/. The difference being that Senegal is compiled and Wren is interpreted.

A few things of interest:

- there are exceptions

- you can call some C code: https://lang-senegal.web.app/docs/cimport

- you can "enhance" (monkey patch?) classes: https://lang-senegal.web.app/docs/enhance

- classic C-style for, while, switch keywords

- there's a pipeline operator, but it's <| https://lang-senegal.web.app/docs/pipeline

- the reference to "switch statements" probably means that switch and if are statements, not expressions

Support for Windows, MacOS, and Linux is also a plus.
Also picking a name that can easily and unambiguously searched on is a big plus.
That's true, though many languages don't respect that (Go, Java, Rust).
(comment deleted)
Rust and especially Go have no excuse. Java is old enough that "SEO" wasn't much a priority back then.
I always just search for golang, rustlang, etc.,.
When Java was created, this wasn't a factor to consider yet
Surely this is the responsibility of the person posting this on HN, not the person who put the code on github. The owner of this repo owes absolutely nothing to random commenters on HN.
As I've said:

> maybe it's still under construction and the person that posted it just found it too early. But once you're ready to show it to the world, please include the why!

So I don't think we disagree here.

> The owner of this repo owes absolutely nothing to random commenters on HN.

It's not about "owing" anything to anyone, it's about giving useful feedback. If the language has no way to do IO, and nowhere it says that it's a feature, I would have included the lack of IO in my feedback. The author is free to ignore my feedback, just like I'm free to give constructive feedback.

I'm not sure I'm a fan of the 'Enhance' concept[0]. It seems to be similar to prototype Pollution in JavaScript[1] which is generally considered bad practice. I can't tell, is `Enhance` scoped to the current context? Or does it affect all of that type throughout the rest of the program?

[0] https://lang-senegal.web.app/docs/enhance [1] https://portswigger.net/daily-swig/prototype-pollution-the-d...

The "enhance" seem to be monkey patching, which is a common practice in dynamic languages. Prototype pollution is when malicious people use monkey patching to introduce vulnerabilities.
There are non-malicious issues related to prototype pollution. The most recent that comes to mind are packages overwriting each other. How do you handle two enhances that add the same function name? In JavaScript the second overwrites the first, which can cause issues if the functions do different things.
This may be apocryphal, but I thought JS's `Array.includes` method was so-named when it was added to the spec to avoid conflicting with popular libraries that were adding a `contains` method to the Array prototype. In order to avoid conflicting and breaking existing sites, a less-common name was chosen for the spec.
That was the case with Array.prototype.flat, that was supposed to be Array.prototype.flatten but flatten was already used by MooTools, and they respected the "don't break the web".
so many new programming languages come out that are almost identical to existing ones. Where's the crazy ideas (aside from the esoteric languages, which are different because they're intentionally difficult). I'd love to see more entries in the areas other than OO or procedural languages (or even just a variation on those, like an actor-model language). There's so many ideas in the programming language theory space that deserve a swing.
I'm working on one! It's not ready to be shown off yet, but I outlined the core ideas here: https://www.brandons.me/blog/the-bagel-language
I only read the beginning as it's pretty late for me, but I like the idea, and it innovative. I think you also did a great job at converting quickly the "why".
He converted me just by having a "why".
> To get down to brass tacks: Bagel will be a statically-typed, JavaScript-targeted language. It will keep many of the same syntaxes and semantics as JavaScript/TypeScript, except where there's significant benefit to breaking away from them. It will involve lots of nice little refinements and additions to the JavaScript paradigm, but it's mainly driven by two key ideas, which are really what make the whole project worth doing in my opinion:

> 1. A hard, enforced separation between stateless functional code and stateful procedural code

> 2. Reactivity as a first-class citizen

Hell yes, I'm in. These two features are interesting enough to try by themselves, I don't even care about the details.

The next most important thing is that JS/TS FFI just works, so I really hope it does.

I was originally planning not to expose FFI to users (only the standard library would use it), but I think I've come around on it. It undercuts some of the guarantees I want Bagel to provide, but you could say the same about unsafe blocks in Rust and those haven't stopped its safety-checking from being useful.

However going the other way - calling Bagel from JS/TS - has been on the roadmap from day one and should work pretty seamlessly. Bagel already compiles to TS in fact, including type info.

The function vs procedure difference reminds me of VBA actually. In VBA, functions can return values and subs can't. That always made sense to me. VBA has it's issues, but there are some good qualities.
That's how I learned programming at the university. A function returns something, a procedure doesn't. Koka has something a bit like that with typed effects https://koka-lang.github.io/koka/doc/index.html.
This is one of the big things I love about Haskell. Its way of making effects explicit and easy to spot in the function signature always struck me as insanely useful for exactly those reasons (though, obviously, it goes a step further where every function always has to return something, even if it is an effect or an effected state). In retrospect, I wish Rust had adopted something like this since it took a lot of inspiration from Haskell anyways, but I am very glad that there are people like you out there that are trying to remind people of this insanely useful concept of making effects more explicit!

Wish you all the best with Bagel!

> In retrospect, I wish Rust had adopted something like this since it took a lot of inspiration from Haskell anyways

Aside from the traits (typeclasses), most of the inspiration actually comes from OCaml/ML rather than Haskell. The philosohpy is also way closer to the pragmatism of OCaml. I think Rust wouldn't be as popular as it is right now if IO needed a monad, like in Haskell. This would have been too much for a single language. I also don't think that monadic IO is the way. Maybe effects system will bring a more usable way of typing effects (Koka, OCaml soon), but I doubt that they'll come to Rust.

I agree, and I intend for Bagel to be a pragmatic language (striking a balance between idealism and pragmatism very similar to what Rust strikes), which is why I'm not going the monad route. I believe that the combination of the functional subset + reactivity to any state that does exist will get you 90% of the benefits without the learning curve
Looks promising, thanks for sharing!

Your idea of having functions that don't have effects and procs that don't return, reminds me of https://en.m.wikipedia.org/wiki/Command%E2%80%93query_separa... - so there's some prior work there for reassurance and reference.

First class reactivity would be extremely useful - I've thought the same thoughts as you around how reactivity is only partially solved with the current generation of UI libraries (or moreso with RxJS, but the syntax is full of baggage) so I wish you every success with solving it more comprehensively.

Thanks!

I have heard of Eiffel though I don't know much about it. I am honestly surprised this concept hasn't been explored more, given how long it appears to have been around.

I'm still waiting for the programming language that doesn't take off on tangentially obscure ideas, but address the three fundamental dimensions of a computer program, state, functionality, and interaction dynamics, on an equal footing and with a clean orthogonal architecture. I've only met this mindset way back in Object-Oriented Modeling and Design 1st Edition, by James R. Rumbaugh et.al. The book is not about programming language design but about how to use these ideas when programming in existing languages. Despite it being otherwise somewhat immature I remember it as a very inspirational read.
Alternative theories of programming are exactly why I want to see new, innovative language concepts; not just for the wacky factor, but as an implementation of a different approach, hopefully one based in a logical theory rather than random tweaks.
And not less ideas that could improve usability of existing ones, like conditionals, loops and self-reference in object literals,

  {
    if (cond) set {a: 1},
    for (x of values) set {[x.name]: x},
    b: thisob.x,
    c: {d: thisob.c},
  }
enhanced data transfer,

  dest.{a, b, [key]} = src
default values,

  var x = arg ?? 1
optionality and mandatoryness,

  var x = f?(…)?.info![key] ?? "<not found>"
scope objects and flow control in these,

  function foo(a=1, b=2) {
    scope bar {
      let c = 3
      scope {
        let c = 4
        log(a, b, bar.c, c)
        baz(scope.this) // a, b, c, bar
        baz(scope.arguments) // a, b
        break bar
function environments,

  global.{*} = {a:1, b:2}
  var t = proxify({a:3, b:4}, global)
  withenv (t) foo() // 3 4

  function foo() {
    console.log(a, b)
  }
and so on. It seems everyone jumps on to “new same language” train when there is so much to do in what’s already not done.
We can get rid of the var and let keywords if we embrace single assignment like Erlang.
What is a "modern" syntax?
For this one, JavaScript. For statically typed programming languages, it usually means ML-style type declaration, that TypeScript uses too.
and anything with significant-whitespace would ofcourse be a "post-modern" syntax
Small suggestion: The 'docs' link in the README should link directly to /docs rather than a place that shows less than where I came from.

Reading through the docs I was wondering 'why' as mentioned in another comment. I hoped to find it in the concurrency section and was disappointed to see that it's only single-thread async:

> Coroutines are light-weight thread-like objects allowing you to write asynchronous non-blocking code as well as handle errors in Senegal. The key difference between threads and coroutines is that a program with threads runs several threads concurrently, whereas coroutines run a single coroutine and cooperatively. A coroutine is not paused so that control can be given to another unless and until you tell it to.

There still was a section about C interfacing, but many languages do that. In the end, it seems to be about syntax which is the least interesting thing about a language. What can a new language do that an existing one doesn't do well? If it's a hobby project that's well and good. Only wasn't clear what the intentions/target is from the too brief README.

Senegal is the name of a country
Java is the name of an island in Indonesia. C# is a note commonly used in 12-tone chromatic scale. Ruby is a gemstone. Bash is a violent action. Racket is a fraudulent scheme, which…
and so what? it's not the same as using the name of a prominent country

it's disrespectful, stupid, and won't help you for SEO or searchability anyways

they probably looked for name of birds and stopped there, uncultured

Why is it disrespectful? Or “stupid”? What SEO benefit do you think any project expects to get from choosing to share a name with any country?
i find this incredible that i have to justify and explain why it is
Also the name of a river and a bird.
I'm curious as to why they have 'this.' to access class fields.

JavaScript uses this because the architecture for accessing fields predates the existence of classes (even then I feel it should be extended to allow fields be accessed without 'this.' if the field and usage exist within the same class definition.)

Surely a compiler should be smart enough to not require a 'this.' if the name is in the scope of the class and not hidden behind something like a parameter with the same name.

> JavaScript uses this

Python goes one further and requires you explicitly name your this (commonly self) as a parameter. Which is one thing I particularly like about Python, as it’s clear class instance methods are just sugar over plain functions/routines without any magic.

I find the Java-style name resolution that doesn’t require qualification utterly confusing. It would be especially weird/probably a footgun in a JS-like language where functions are frequently used as values and where their names can be shadowed locally.

I dislike implicit 'this' immensely. It is very common for local variables to shadow instance variables, e.g. in a constructor. Habitual use of shadowing can lead to bugs, for instance if you mistype a local variable declaration a later use of the intended name might default to the instance variable. Ruby is my favourite with @foo, it's concise but explicit. Because of this, languages with implicit this tend to have a convention such as "instance variables must start with an underscore", which is just a poor man's sigil.

Here's an example:

In early versions of Swift, using print("hello world") in a UI class would open a print dialog, because it dispatched the print: instance method on NSView, instead of the global print function.

(comment deleted)
Mistyped variable will lead to unused variable warning. The swift example is problem of API, not shadowing.
It is possible to attempt use a variable more than once.

The Swift example was caused by shadowing. There was a global print() function and a instance print() method (taking one parameter, sender: AnyObject). If you called print() in a class not descending from NSView it printed the string in the console as expected. But if you called it in a class descending from NSView you got a print dialog as the instance method shadowed the global function. They fixed the issue long ago of course.

I was wondering where all the traffic on the repo was coming from after months of inactivity lol.

Most comments (so far) are asking "why?". Its honestly a fair question, what does this language offer that others dont? Nothing really, this project isn't anything serious I just wanted to have some fun with it. Regardless, I'll put up a why section.

Why is it called Senegal?
I've got a Senegal parrot (hence the pixel art) and im bad at naming things and...the rest is history i guess
Not a bad name or reason. Thanks for sharing.
Might be off-topic but how did you get notified about the high traffic? If my website had a high traffic I would not notice at all. I do not feel like writing a script to notify me either.
Discord webhooks with GitHub, a lot of people were starring(?) it on github
Nothing wrong with that! The world would be a lot less interesting if every project were useful
Why writing a 2021 language in C, instead of Rust?
Two reasons:

- If the author already knows some language well, it’s rather inefficient to master another language just to create a new one.

- Rust is likely to be relevant for 11 more years, C is likely to be relevant for 43 more years. Things that have existed for a long time, tend to keep existing longer.

I hugely despise the Rust-like Code of Conduct. Also please provide actual build instructions instead of giving binary files to add to PATH and execute.