back
166 comments
Hi project owner (Mark) here. It is a bit late in the evening for me but I will try to answer any questions when I can.

The Bosque language is currently in a very early state with lots of work to do and not ready for practical use. However, I am very excited by the potential in the concepts and wanted to make the project a collaborative endeavor, including both other academics and developer community, from the start. At this point the goal is to explore interesting options in the language design space – whether the Bosque language becomes mainstream or just provides useful ideas for other languages to adopt. So, please take a look, expect plenty of rough edges, and we would love comments, suggestions, and PR’s on the GitHub repo.

Hello! Disclaimer: I haven’t read the full publication yet and I’ve only skimmed it.

A lot of programming languages that are coming out these days talk about simplicity, lowering “cognitive load”, increasing expressiveness, being nimble/lightweight/easy/whatever, and—this one stated by you—reducing “accidental complexity”. When I looked at your grammar and some examples, I saw atomic building blocks that don’t lead to any less complexity than what I’d get if I strung together similar building blocks in Lisp or Python or ML.

To me, “accidental complexity” doesn’t seem like a very well defined concept. I might say such a term in a meeting room arguing to upper management that we need to pay off tech debt. Or I might blog using such a term to talk vaguely philosophically about software engineering. But I don’t think I’d find myself using it in a formal context to argue the merits (or lack thereof) of a technology. I admit that this may be due to my ignorance of a term of art.

The introduction to your publication is even more bold: “Regularized programming” (and hence Bosque) will (supposedly) unleash a revolution on programming the same way structured programming did the paradigms before it, ushering a “golden age” of programming and the like.

Focusing on the term “accidental complexity”, can you elaborate what that means? What is an example of accidental complexity and how does it naturally come about with the current crop of languages. And how—in the large—does this programming language avoid it (or help the programmer avoid it)?

Edit: I see in your publication, upon the mention of “accidental”, you cite “Frederick P. Brooks, Jr. 1987. No Silver Bullet Essence and Accidents of Software Engineering. Computer 20 (1987), 10–19.” But in reading this [0], Brooks says:

> The complexity of software is an essential property, not an accidental one.

He only speaks of certain difficulties as being “accidental”, and past ways in which we’ve improved the impedance of such difficulties.

[0] http://www.cs.nott.ac.uk/~pszcah/G51ISS/Documents/NoSilverBu...

I hope you do not mind, if I make some comments. The first is that you should try to include realistic examples in your documentation and promote good coding styles. For example, I do not see the benefit of a 'sign' function with an optional argument. Or have a 'sign' function that uses a local variable, while this could also be done with an if-statement or the ?-operator.

I do not understand the concept op typed strings. Would that not be simple a subtype of strings (implementing additional restrictions on the values of the strings, a true substype)?

Also, when I see something like: 'args.all(fn(x) => x % 2 == 1)' I do experience it as 'simple, obvious, and easy to reason about for both humans and machines' because it only makes sense if you already have a lot of knowledge about languages like TypeScript. I think that something like: 'All x in args: x % 2 == 1' is easier to read. BTW, why does 'fn(x)' not have a type? Are types optional in your langauge?

I would not give examples of mechanisms that have not been implemented and seem to go against your principle ideas, such as references. What happens, I pass a part of a value to a 'ref' argument of a function?

There are some other language out there that are only based on immutable values. If you are fond of immutable values, why not implement them in an existing language and see how far you get. This has the benefit that people do not have to learn a new language and keeps you from reimplementing a lot of stuff that others already have implemented.

Thanks for your work, this looks exciting!

I am curious about the following:

> Since the semantics and design of the language ensure fully determinized execution of any code there is actually no real need to perform logging within a block of code. So, logging is not available in the compute language.

While this may be true for execution, this is not true of data on which the program operates. For example, when processing large amounts of data, how should one keep track of statistics, performance information, data irregularities (which don't cause errors but may be useful to look into further), and other such events which might otherwise be logged?

Similarly, suppose the program performs some operation which depends on the system time which fails at runtime for certain system times. If run in deployed mode, it would restart and run the same thing in debug mode, but the environment would be different. How would such an operation be able to be traced back to the particular conditions which caused the error?

I was keen to read about this lang bc it came from m$, but this looks like it needs some work: I'd highly suggest changing "var" and "var!" definitions.

From your doc:

>var z = 5;

z = y; //error z is not updatable

"var" is shorthand for 'variable' as you're no doubt aware, so use "const", or use something else altogether to indicate a var.

I stopped reading after coming across your unintuitive "var!" syntax. Let an apple be an apple and an orange an orange.

You seem to have some goals in common with Floyd. Maybe you want to get in touch.

https://github.com/marcusz/floyd https://www.reddit.com/r/ProgrammingLanguages/comments/arwjl...

Hi Mark! What's this language's purpose and how will it be better at that than existing languages?
Could you comment on how you came up with the name, or its meaning?
There's an English error on the very first sentence of the description on the Microsoft site.
Some comments on the code, based on Tictactoe example (https://github.com/Microsoft/BosqueLanguage/blob/master/docs...):

1. overall quite nice looking and easy to understand

2. too verbose in places, e.g. this constant structure:

    const winPositionOptions: List[List[[Int, Int]]] = List[List[[Int, Int]]]@{
        List[[Int, Int]]@{ @[ 0, 0 ], @[ 0, 1 ], @[ 0, 2 ] },
        List[[Int, Int]]@{ @[ 0, 1 ], @[ 1, 1 ], @[ 2, 1 ] },
        List[[Int, Int]]@{ @[ 0, 2 ], @[ 1, 2 ], @[ 2, 2 ] },

        List[[Int, Int]]@{ @[ 0, 0 ], @[ 1, 0 ], @[ 2, 0 ] },
        List[[Int, Int]]@{ @[ 1, 0 ], @[ 1, 1 ], @[ 1, 2 ] },
        List[[Int, Int]]@{ @[ 2, 0 ], @[ 2, 1 ], @[ 2, 2 ] },

        List[[Int, Int]]@{ @[ 0, 0 ], @[ 1, 1 ], @[ 2, 2 ] },
        List[[Int, Int]]@{ @[ 0, 2 ], @[ 1, 1 ], @[ 2, 0 ] }
    };
Has types defined in 10 places, 9 of which are redundant.

Also you are using @{...} for lists and @[...] for tuples; a more usual convention (in e.g. Python or Haskell) would be [...] and (...) respectively.

3. String types aren't intuitive (at least to me). E.g. in this code:

    const playerX: String[PlayerMark] = 'x'#PlayerMark;
It appears that a String[PlayerMark] is a subset of String that can have the values 'x' or 'o'.

I would have preferred something like:

    type PlayerMark = 'x' | 'o';
    type PlayerMarkOrBlank = 'x' | 'o' | ' ';
Got to say, after reading the description in the linked URL, I was really surprised with just how complex the syntax is in the code samples. I don't want to be overly negative, but it doesn't look like it's going to reduce complexity to me - if anything it looks like one of the most incomprehensible languages I've come across in decades of experience.
A random thought about the code samples. What do we gain from having to write

    point<~(y=value)
instead of other languages'

    point.y = value
?

I believe that syntax should be designed to make things simple for developers, not for the designers of languages or for compilers.

I don't know anything about the language but the first form suggests immutability (return a new point with the y property = to value), the second looks like mutating a struct
<~ looks like an expression for a bulk update of an immutable record.

"point.y = value" is typically a statement for a single update of a mutable record.

I'm not sure how you'd extend the latter to support the features of the former. The meaning is completely different. Different things should look different.

Or to use Scala's syntax which is more clear to me:

  point.copy(y=value)
"Choosing the equal sign to denote assignment is one notoriously bad example that goes back to Fortran in 1957 and has been copied blindly by armies of language designers since. This bad idea overthrows a century-old tradition to let = denote a comparison for equality, a predicate that is either true or false. But Fortran made this symbol mean assignment, the enforcing of equality. In this case, the operands are on unequal footing: The left operand, a variable, is to be made equal to the right operand, an expression. Thus, x = y does not mean the same thing as y = x. Algol corrected this mistake with a simple solution: Let assignment be denoted by :=."

--Niklaus Wirth (Good Ideas,Through the Looking Glass)

This is a bulk record update, according to what I can find in the docs. It's an atomic operation -- meaning, if instead of updating one field, you updated thirty fields, all would appear to take place as one operation.

Obviously someone please correct me if I'm wrong.

Are there plans to actually measure "simple, obvious, and easy to reason about" with people?

As I mentioned in the discussion two days ago, PL researchers throw around these terms but never actually measure them. You can learn a lot from a small user study.

I am very tired of the phrase "easy/hard to reason about." It sounds so hand-wavy every time.
Am I the only one who really can't stand the expression "easy to reason about"? Everywhere you look everything that isn't exactly CORBA, ASN1., EJBs or XMLs is E2RA...
> Thus, Bosque does not have any undefined behavior

I think this is the one that should be highlighted most. Otherwise, from an engineering perspective, many of the other language features have already been implemented and widely used in other languages

Typed strings look really nice, something I tend to wish every language had eventually - though I'm not sure why you'd limit them to Strings and not allow them for all types? I really like the Logarithm example shown in the Dotty docs for instance: https://dotty.epfl.ch/docs/reference/other-new-features/opaq...
Direct link to github repository:

https://github.com/Microsoft/BosqueLanguage

The description suggests the syntax and type system are based on TypeScript. After looking through the docs I have to say I wish this were much more true. It seems like Microsoft Research has thrown out half the good ideas TypeScript has in favor of overly noisy, complex syntax.
Please consider using a license other than MIT. MIT assumes all contributors work for a single institution, and doesn't protect licensees from later patent infringement claims.

https://writing.kemitchell.com/2019/03/09/Deprecation-Notice...

Either Apache 2.0 or Blue Oak Model would be better choices.

Is this coming out of MS Research as one of these "look, we came up with a way to do this" but it's not something that has a concrete use case? It reminds me of their MSR's project where they made a bootable operating system kernel in C# which, if I recall correctly, influenced the Midori project, elements of which have percolated into refactorings that have shipped with Windows 10. It also makes me think of F# which is a very useful language on its own but serves as more of a test-bed for future features for C#.

I suppose if the learnings of Bosque find their way into TypeScript that might be useful but I don't see a practical use for Bosque as it is. Either that or I've completely missed the point.

>Bosque programming language is designed for writing code that simple, obvious, and easy to reason about for both humans and machines.

var v: List[Int ?] = List@{1, 2, none, 4};

OK! I think it needs some work. AM I supposed to intuitively know what ? and @ mean?

A project language with a reference implementation written in...TypeScript?

O.o

Also, there is a slack group dedicated to future programming languages. I am the acting char of the next gen language developer's association, and am trying to get all the next gen language designers to be in communication with each other. Right now there is the Luna project (poland), Red, Parasail, Beads, Elm, Dark, and others. i will be sure to add an entry in our database for Bosque.
>For typed strings, String[T] the compare operator ignores the generic type and is based on the order of the underlying raw string e.g. both arguments are coerced to String.

Why? What even was the point in making them 'typed' then?

Also, what exactly are the relevant language-level details which BOSQUE contributes? It seems more like a large library than anything else.

Only thing that caught my eye is the require syntax, which is nice, but then I thought what happens if this contract fails? Its possible you'd want to return false, or raise exception, or log error, or even correct value and continue. So whilst a nice feature, not practical IMO if it would always result in an exception.
Reading the publication, I don't see that big a difference to existing purely functional languages. It almost reads like a rediscovery and refinement of the main value propositions of e.g. Haskell.

That said, some of the refinements, especially the (TypeScript-inspired?) record typing and manipulation facilities, look quite pleasant.

i challenge the decision to not have explicit loops. the beauty of the original C construction was that it allowed for 3 events to occur inside each iteration: 1) normal execution of the body, 2) skip over the body but increment the counter, 3) exit the loop. When you have nested loops JS and AS3 let you name the outer loop and break out of it (thus re-introducing the FORTRAN GOTO which although that crank Dijkstra hated so much, occasionally is needed for this purpose). How are you going to stop a loop that might go on too long? sometimes you want to stop early. I don't see how you can stop the map().. or filter() operators. Just because early abort of a loop is not common doesn't mean it doesn't come up; it does inevitably so.
Looks a lot like TypeScript to me.
this is interesting (emphasis mine):

> Bosque is designed to encourage limited uses of recursion [and using map/filter etc instead]. This is done by introducing the rec keyword which is used at both declaration sites to indicate a function/method is recursive and again at the call site so as to affirm that the caller is aware of the recursive nature of the call

i don't think i've seen a way marking functions that might not terminate at the call site. (though termination doesn't seem to be a specific focus here)

It says typescript and ML, but it looks quite a bit like Rust/Swift, which is great for my tastes.

I'm still not sure what is the raison d'etre here.

Why would I use this instead of, say, Rust to WASM?

I was hoping this was a programming language written in Basque
Fix the grammatical error: The Bosque programming language is designed for writing code that simple, obvious, and easy to reason abo
"The Bosque programming language is designed for writing code that simple, obvious, and easy to reason about for both humans and machines. The key design features of the language provide ways to avoid accidental complexity in the development and coding process. The goal is improved developer productivity, increased software quality, and enabling a range of new compilers and developer tooling experiences."

Along with literally every other language. I really wish the splash pages for new languages would cut the boilerplate and just open with a list of the specific traits that make this one different from its peers.

Edit: it appears that this is relatively easy to find after visiting the repository. Still, that opening paragraph is meaningless, and many languages don't even make the worthwhile bits easy to find for those who actively seek them.

> The categorization and coverage results of these semantic loop idioms shows that almost every loop a developer would want to write falls into a small number of idiomatic patterns which correspond to higher level concepts developers are using in the code, e.g., filter, find, group, map, etc.

The fact that there are idioms that they could use doesn't mean those idioms are natural to the way people think, in particular, to the way they think when trying to solve problems.

I avoided a fully functional style in my language[1] (even it has a functional kernel) because I've watched people write code while working with them or as interview candidates, and observed them (and myself, tbh) having trouble solving problems with "big" elements.

Thinking about the whole array makes it "big" mentally. I'm not a psychologist or a linguist, so I can't tell you what that means, just that I've observed a pattern. When I was doing interviews, we had the infamous stars question, which goes like this: "Imagine you're trying to find the (maximum distance) of all the stars in the sky. How do you compute this?"

Candidates reliably get hung up on "all the stars in the sky" and don't realize they can break the problem into the current maximum star plus all the rest of them. (That some people get it and some just don't is why I don't use the question.)

With the humble for loop, you're naturally dealing with a single thing at a time. That's why I think it's unwise to throw it out and only use functional constructs.

And that said, often we do want to address the whole structure. When you look at problem solving, it's about reexpressing a question in such a way that the answer falls from it naturally. To do that, we need a multitude of idioms that can expose different aspects of a problem and be composed reliably.

> We believe that further work, such as identifying recursive idioms or other fundamental algorithmic patterns, can further reduce the need for unstructured recursion – eventually limiting it to an infrequently used part of the language.

I do agree with this. If you're going to have find, map, filter, etc. then it makes sense to have a generalized tree-walking algorithm. That's how I'd probably like to express it.

But, again, when I'm solving the problem initially, I need to be able to deal with small things to keep it all in my brain at once. That's how we teach it and often how we will want to express it to ourselves when we're in the fog of solving an unknown.

I absolutely would love something that could describe boundaries, enforce invariants and make guarantees that a traversal won't hang, but I wouldn't want that to be the only way to express such traversals. Development is an evolutionary process; we often start with something that might suck but is viable, and then iterate and improve it.

[1]: https://tenet-lang.org/basics.html#control-statements

Why capital I though for integer. Not only doesn't it seem to fit in line with the rest of the syntax, the capital I and l in some fonts is a well known psychological annoyance for many.

Edit: Funnily the issue ( I & l )is now visibly noticeable with HN's font choice

Might be a bit over-critical, but when I read that it's main selling point is making it more human readable, this seems a bit troll

yetanother#