Whenever my compiler comes up the first question tends to be why? I found that everyones "why" are specific. Some people want to know how many libraries exist, others want to know specifically how many high level (or low level) libraries there are for easy of use (or performance). Some want to know what's unique others want to know the goals. It's hard to know what people want so I'll do my best on answering questions
Would you accept a short answer? The 'short' answer is the compiler tracks various things such as memory owner (for alloc) and lifetime (for constructors/destructors). The compiler enforces rules so it's clear (to the compiler) if the memory owner belongs to the caller function (for example ReadEntireFile), the parent function (itoa causes the calling function to pass in a hidden buffer for it to use) and if it's on the stack, heap or belongs to an object (class struct or array)
I'm not sure what details you want. The easy one to explain is itoa. Since 64bit ints can be at most 20 digits the function returns a fixed length array. Currently it's u8[21] because I've wanted an extra byte for null (for testing before I had print implemented). I'm not sure if I'll keep the extra byte, anyway since 21 bytes fits on the stack the caller function will allocate it on the stack so it doesn't need to copy it. But it doesn't have to be on the stack, if you write `obj.data = itoa(anInt)` the compiler will pass `obj.data` in. If it's a local variable then the compiler would have to decide if it should be on the stack or heap. Passing in a buffer gets rid of useless copies for the case where optimizers can't inline the function.
I guess the broader question is how do you achieve automatic memory management without something like Automatic Reference Counting (like swift), the ownership/lifetime systems from rust, or the generic effect system of Pony?
Ergonomically solving this problem is a major research area, so if you’ve found a solution to it’d be worth presenting that front and center.
Are you saying I should write a paper? I'm not sure how much it would help when a lot of it is intricate to the design of the language. I have no idea what the page limit of papers are and what the point would be besides for fun. I never had fun writing a paper either
I'm mostly suggesting that if you implicitly claim to have solved some huge, difficult research problem but provide no real details about how, people are going to be skeptical. This doesn't have to mean a formal research paper. Even one page on your website describing your approach (potentially with comparisons to other state-of-the-art languages like Swift, Rust, and Koka) would be helpful for potential users trying to understand your language's capabilities.
Just as some basic questions you might want to answer:
1. If I allocate some memory and store a reference to it in a struct or object, how do you track ownership for that memory? Can I alias it? Store references to it in multiple structs? How do you know that it's safe to free that memory without reference counting?
2. Am I allowed to allocate memory in a function and return a reference to that memory? How do you ensure that memory lives long enough for those references to be valid?
3. Are multiple aliases allowed to overlap with each other? If so, how do you prevent (e.g.,) type confusion from one mutiple alias changing the data out from under the other?
Not GP but it is why I asked this question and the follow up. There are a lot of PL folks who are exploring this particular design problem (static analysis in the compiler to take care of the hard problems of memory management).
What would be very compelling are some code examples and either high level descriptions of what the compiler is doing or some analysis of the type system and IRs the compiler uses to verify correctness.
Particularly things like ownership and lifetimes. These can be pretty nuanced in degenerate cases and it would be interesting to see how you solved them.
Like take Rust. It has ARC to be sure, but the core semantics behind its "compile time GC" are pretty well defined and easy to follow so people have faith that they work (they're also provably correct). If you have some motivating examples and descriptions of how the language solves them it would be very compelling to see!
Essentially this isn't an attack on the project, it's just curiosity about the approach and implementation. It's easy to poke at code examples and see that you're right, what is more valuable to folks that are approaching the same problems is how you got there.
Personally I would have simplified its syntax a little bit more, if possible.
For instance, the following example code
main() {
sum := 0
for v in [5, 7, 11] index i //index is optional
{
if v == 11 { break }
sum += v
if sum > 20 { break }
print("$i: $v")
}
_OnBreak { //<-- must be immediately after loop
print("Index $i broke out of loop")
}
_OnComplete { //<-- Will not execute on break
print("Array is OK")
}
}
would have wrote it as follows:
main() {
sum := 0
for v in [5, 7, 11] index i //index is optional
{
break if v == 11
sum += v
break if sum > 20
print("$i: $v")
}
_OnBreak :: print("Index $i broke out of loop") //<-- must be immediately after loop
_OnComplete :: print("Array is OK") //<-- Will not execute on break
}
I honestly like simple, well-written code that is easy to follow.
Funny that you wrote `break if v == 11`. In a prototype I wrote 5 years ago (to learn syntax handling) I implemented this. What ended up happening is if I could do `break if ...` then I'd wanted to do expr if. Like `fn() if v == 1`. But at that point it gets confusing to read. Maybe I can try implementing this only for `break`, `continue` and `return` but it might annoy people because expressions aren't allowed. If expressions are then it's back to the problem I had in the prototype
I don't know if it'll make things more clear to you but curlys aren't nessicary when you use return/break/continue. I didn't write it because I didn't want to scare people off with the lack of curlys or confuse people on the front page
The `::` part looks nice. Would you want the statement to be forced on the same line? Or not like how C allows statements after `else`? As mentioned the compiler forces curly braces so it'll have to be forced to be on the same line as the on statement and I don't know if you'll find that to be a dealbreaker
Comparing perl to a language that wants to be readable is very funny to me
For me, the problem is when my expression got long or if I call a function with multiple parameters. The more complex the line is the easier it is to not notice the `if`. Also I agree with what the other person said, it doesn't match the order if you read top down left to right
Ruby has "expr if cond" and is very readable. I use it all the times if cond is short.
I like the _OnBreak _OnComplete _OnEmpty . I think they simplify some loops and make those found_something variables go away. However I don't like that they start with an underscore. It feels so old (C and Python, which was designed at the end of the 80s.)
Case conventions are a little strange, something is lower case (main, for), something is camel case, something are upper case (methods?)
= := .= could be a little confusing. Why not only one? The compiler should know what to do because of the mut, out keywords.
About style: { sometimes leads a line, sometimes doesn't.
> However I don't like that they start with an underscore
Early on _[A-Z] meant reserved variable so that's why it's currently _On. Many keywords are a single word and common enough that it shouldn't bother anyone that it's reserved. However I'm not great coming up with a style guide. On empty is two words, I have no idea how it should be written and everyone seems to have their own style.
Do you have a suggestion for the _On keywords?
> Why not only one? The compiler should know what to do because of the mut, out keywords
You noticed the out keyword? It's not recommended we only use that to interface with C code. Returning multiple variables is much better IMO (I won't speak for everyone). Accumulator and dynamic arrays are common enough that I didn't want to force people to write mut each time. It's simply `:=`
Let's suppose that in the future you want to add an argument to the break keyword to signal why the loop returned early. I use a string (btw, does the language have symbols / atoms?)
break "found"
break "eof"
break "invalid input"
Then you could have
on "found"
on "eof"
on "invalid input"
with only one keyword. And
on "complete"
on "empty"
> Returning multiple variables is much better IMO
I agree but declaring a name for what you return is nice because it explains the purpose of the returned values. They could go outside the ()s.
I'm thinking more about your suggestion but off the top of my head I don't know why one would want a break reason. If one comes up anytime soon I'll 100% remember this post
> I agree but declaring a name for what you return is nice because it explains the purpose of the returned values. They could go outside the ()s.
So you're not suggesting an 'out' keyword your saying names on return values? I like the idea but in practice I'm not sure if any IDE would show you the names? I think many do show comments if you place them the line before so that could be an alternative solution
One reason I don't like out params is because it conflicts with the design of the language. The language prefers you to assign variables and people will want to modify their variables (or arrays and struct members) with the out param and having something be declare OR assign causes problems because its too easy to make a typo and not find it for many many minutes. Writing the type then using out goes against the flow of the language which is why I prefer returning multiple values.
But I don't know all the use cases and everyones preference so there very well be a good reason you'd want an out parameter
> If expressions are then it's back to the problem I had in the prototype
If it’s C like then the ExpressionStatement, umm…statement covers this; it’s how “if (foo=1) bar();” works (or leads to bugs depending on your point of view).
Also curious on how the automatic memory management works, might be on the website somewhere but I didn’t look past the first page.
I wrote some specifics in this thread over a few comments but that and the type system are complex. It can be a talk and writing short post probably will satisfy no one
I don't know why people are downvoting you for sharing your suggestions. Your syntax suggestion for _OnBreak and _OnComplete does seem better for the following reason - 1. Both are related to the for loop, and the usage of :: makes them stand out and seems to gives them more context. 2. Easier and elegant to read. (But is that because the example uses a 1 line code? What would be the best way to present multiline code without confusion?)
(I would have preferred if the _OnBreak and _OnComplete statements was inside the for loop as that removes any ambiguity that it is part of it and effects the for loop).
However, `if v == 11 {break}` is definitely more readable than `break if v == 11`. If you are using curly braces as part of your syntax, and for blocks of code, it's better to use it with consistence. That can be confusing with `break {if v == 11}` as it breaks the syntax grammar, when you consider what break does.
That's silly - this isn't Ruby. It's a new language still under development and thus will have its own syntax. Obviously any language will be unreadable if you don't understand its grammar (syntax). Readability is tied to the syntax of a programming language. (And Ruby is great example of this - I am used to Python and I found reading Ruby code to be very cumbersome because of its weird syntax, which I didn't bother to learn). This a C / C++ / D like language.
A colleague and I used to talk about features we would throw into some hypothetical language. They were mostly really bad ideas that would have made INTERCAL look elegant, but it was fun to dream.
Kudos to you for turning your own programming language dreams into a reality!
I won't speak for teammates but I found everytime I list features people don't really think about it. Maybe it's because they never seen it so they never thought about it and as a consequence don't think it's noteworthy. If you browse through the pages and read the examples you'll see many. The On statements for loops are my favorite and elsewhere someone told me they have no idea why I would want to know if a loop is complete (meaning you didn't break or return out of it) or why I would want a special handler for when you break a loop.
> If you browse through the pages and read the examples you'll see many
Respectfully, I browsed all the examples I could find on the site (Highlights, Examples, and Quick Start) and I'm not really sure what you expect to be recognized as novel ("Has features not found in any other language"). You may have a combination of features that is unique, but nothing individually stood out as something never seen before. Perhaps you just need to highlight these things better.
Allow for Error short circuits. This has slowing been adopted by other languages - An error can be handled/or not and continue cleanly without crashing anything (erlang style) or typed semantics (Java style). Go can return an error message, as part of the multi-return semantics, similarly allowing for error short circuits. Because of Bolin's multiple return semantics, you can implement this pattern as well, but it's nice to not bake it in.
The for-loop conditional exit handlers are novel enough.
Some unique syntax choices, like .= for assign and mutable/immutable assignment dynamically is great. Ponylang has typed containers that act similarly, but they are not dynamically declared.
I know I've seen lazy type signatures before, but I don't remember where. So I'd consider it novel enough to note:
ie you don't need to specify int every param -> add(int a, b) and implicit void on main()
I can't speak to under-the-hood compiler optimizations, but there's a little bit here and there that's interesting.
> Is the `try` keyword in the highlight section what you're looking for?
I worded it poorly.
> Allow for Error short circuits
I was trying to say that I liked the feature as-is, because it Allows for Error short circuits. There are a lot of common patterns that modern languages avoid idiomatically, despite their widespread use in roundabout ways.
I'm not good with this site. Do most people have some kind of notification when someone replies to them?
Is the problem with short circuits that you can ignore the error? It's not documented yet but `error return` requires the function to be an error type so the error can propagate. If thats not good enough do you have some insight on how to fix it? What's worse and was designed intentionally by me is `fn() error { return }` not requiring the function to have an error return (although this would be a void return type). I make the assumption if you have a block (instead of `error return`) you're handling the error. You can also propagate by doing something like this `nonErrVal = fn() error { print("write a better error log"); return error }`.
_OnComplete works on while and for loops. There's an empty as well and I'm not sure if empty should also execute complete or not. I figure I'll know after writing real code in more than one project
I'm not going to give out my email address in order to try out your language, sorry. Your EULA is a big turn-off as well. In this day and age, with so many niche programming languages popping up, I think it's going to be hard to gain a following with a proprietary compiler that you have to sign up to even download.
More to the point, I think your site could do a much better job on describing what's actually unique about this.
For example, I'm not convinced that the `_OnBreak`/`_OnComplete`/`_OnEmpty` machinery is useful enough to be part of a language. A bigger example where these features come in handy would be helpful to understand them.
Just skimming the highlights and examples page, it looks very similar to C++. So I think it could use some side-by-side examples to show how it makes ordinary programming easier/more readable/etc.
The Quick Start guide is a bit obtuse and feels incomplete. I'm having trouble understanding some features, and I feel the standard library is underdocumented---for example, I couldn't find what `.WSNL()` does, and it's used for your MIME type parsing example.
I apologize if I'm sounding a bit harsh; I'm trying to provide some constructive criticism here. I appreciate how hard it is to get something out the door and I wish you the best of luck.
I'll explain why there's a EULA and write another comment for the rest
At the point that it was clear we're going to have a usable compiler I asked my entire team what license we should release this under. Absolutely everyone had a problem with each and every open source license. The more we talk the more apparent that none of us wanted to wake up one day to find out a trillion dollar (possibly cloud related) company took our code and want to compete with us. We don't want embrace, extend, and extinguish to happen to this project if we could help it. So we settled on a EULA (which very likely will change at 1.0) that says you can learn for free which lets face it, is the only thing people would want to do in its present state
Figuring out a license is in the set of bare minimums I would look for in evaluating a language. I mean no offense in saying this, but I give a team which can't come to an accord on this basic thing very low odds of getting a language to 1.0.
The language field is very crowded. I'm all about new languages, I wish each and every one success and yours is no exception.
If it's going to succeed, you'll have to beat people over the head with it. The current situation won't reach escape velocity. Good luck.
No idea. As someone learning Zig currently and finding it quite pleasant, it disappoints me to see that happening.
But I guess it depends on what your goals are. If you want this language to be used by as many people as possible, you want to remove any obstacles to that, and a sign-up wall is a big one. You also have to consider the competition. I can go to my package manager and download compilers and runtimes for probably over 200 languages right now without having to submit any information about myself - I did it for Zig the other day. If your language and compiler are so mind-blowing that I should be glad to subject myself to the friction I have to go through to use yours instead, you really need to sell that to me with more than, as mentioned in another subthread, a promise of ambiguous features not found in other languages.
So free your code. Sell it to me as much as possible on the web site with all of its amazing capabilities and features and libraries. And if some company rips it off and passes it off as their own thing, make hay from it - write up a blog post about how the nasty big evil company stole the work of a plucky li'l FOSS team, but you're just going to keep plugging away and improving your code regardless. Then post it to HN. You'll get updoots through the roof and plenty of sympathetic new eyes on the project.
You may want to check out the official statement [1] from the Zig foundation as well. Even though forking is not necessarily stealing, what they have done seems more accurately described as stealing.
Not really. Like, I would't use Zen personally and it's fair for Zig to highlight their concerns, but still none of this is stealing, and seems more like a petty disagreement, the cause of many forks on other projects in history.
I think many people just fundamentally don't understand sharing or friendly coexistence. The drive to dominate and control is sooo maladaptive for society but very widespread.
Especially in a pre-production state, it's unlikely that anyone will want to use this commercially anyway. It'll eliminate a big barrier to any adoption you're hoping to get.
> you can learn for free which lets face it, is the only thing people would want to do in its present state
Deciding to learn something in the first place is a question of how I want to use my limited time. I don't think I want to learn something with a presently-bad EULA that might change arbitrarily in the future.
It's totally fine that your team wants to keep this project close to you, it is your work and copyright privileges after all. You don't have to be open source if you don't want to. [1] Don't let anyone tell you what to do with your own work.
Just don't be surprised when you find that nobody's interested in it.
[1] I do think it's a bit hypocritical to require people to be "a part of the community" to download the thing when the license doesn't resemble a community or copyleft license. This is no different than downloading from the Oracle Download Center.
I get where your coming from but do you have an example of this happening for a programming language? I can’t think of any language that a company tried to extend and was successful with it. Its not a SaaS offering so the value add is very low for a company to try and take over development.
> I think it could use some side-by-side examples to show how it makes ordinary programming easier/more readable/etc.
That's a fantastic idea. I'll focus to improve this by the next release. Do you want short side by sides or real code examples? I'm worried that short ones may look contrive which is probably why you don't think it's useful? But I'm not certain people would look at anything that isn't short
Correct. I wasn't sure if I'll rewrite the reader class so I only used it in the example program section. The standard library is pretty nonexistent. We didn't want to make the language for only ourselves so we thought we should launch sooner rather than later
> I think your site could do a much better job on describing what's actually unique about this.
In another comment I mentioned that listing features tends to be ignored. Do you have any suggestions on how to counteract it? Maybe your side by side suggestion is ideal https://news.ycombinator.com/item?id=32460252
> In another comment I mentioned that listing features tends to be ignored.
I can see where you're coming from, it might be different from person to person. I personally would've been happy to read through a short feature list highlighting the most interesting ideas that the language introduces. For example, you mention automatic memory management without reference counting and garbage collection, which sounded interesting but wasn't specific enough for me to figure out what's unique. In another comment I saw that you expanded on it and mentioned it tracks lifetimes across scopes, which then sounds super interesting. But I didn't find where to learn more about it.
> Do you want short side by sides or real code examples?
I think short examples can do the trick, if they are not toy examples but can work as part of a bigger program, if that makes sense. Coming to think of it, ideally it would be best to have an actual program written in the language. That's what I usually do to feel out a new programming language---seek out a codebase written in it and read through. So if you have something like that, maybe you could showcase features using small snippets from the program itself, maybe side-by-side with equivalents in a well-known language.
I felt having `.` on a loop would be weird because it isn't working on an object
A few people said they want single statements on conditionals. If `=>` (or `::` as someone else suggested) forced the statement to be on the same line would you be fine? I can imagine people wanting to use it on it's own line like people use else without braces which leads to bugs
Curious if you have any blogs on your experience with the development process over the past 13 years. How was that time spent, what did you find most challenging, and what did you learn in the process? Is the website and forum written in your language?
Multiple times there are several months without me considering or refining a feature. Development was less than that.
I wouldn't know what people want to know about. In real life with friends and coworkers don't really want to hear about details or why I designed something
You might consider, instead of creating a new language, providing a set of macros that expand the syntax of a well developed language that has a macro preprocessor. (It’s almost literally trivial in Lisp.)
Fyi "this language has been under design for a long time" is not always perceived as a good thing since it can be associated with navel gazing. IMO I'd advertise the language based on the core benefit you think it provides
Why write a new language rather than expand on an existing one or an existing ecosystem? Maybe I'm not the intended audience, but personally, I struggle to think of any reasons to use a new language except to get access to an ecosystem of packages I wouldn't be able to use otherwise.
Something like TypeScript, for example, really caught my attention because of how well it integrated into the existing JS ecosystem, adding sanity while still not sacrificing interoperability.
All these choices you have to make had me wonder: we've made formatting entirely part of a language but it seems a lot of it could be moved into the editor. Does it really matter if:
It could just be whatever the user chose in their editor (with an option to publish their custom solution) The code in the actual file can be any of the existing languages which would put some limitations on the formatting choices but if that gets annoying it could be addressed at many levels.
Does this sound fun or should we pretend no one ever mentioned it?
Sounds like it would confusing to read due to inconsistent styles. A few people write transpilers for fun to change syntax of simple languages so it's not an uncommon thought
If arrays are passed by reference, how does the bounds-checking code deal with aliasing? For instance (apologies if this syntax is wrong):
munge_arrays(int n, int[] a, int[] b) {
if (n < 0) || (n >= b.size)
return
a.Pop()
return b[n]
}
// good callsite
first_array := [1,2,3]
second_array := [4,5,6]
munge_arrays(1, first_array, second_array)
// callsite
target := [1,2,3,4]
result = munge_arrays(target.size-1, target, target)
The "Array Bounds" section on the "Highlights" page suggests that the compiler will try to spot indexing errors (like accessing target[target.size]), but thanks to aliasing b can change size "at a distance" if the right parameters are passed to munge_arrays.
---
What are the scoping rules for enum and bitflag names? The page in the Quick Start is unclear - sometimes they are qualified with the type name (Fruit.Apple) but not always (Banana, Dir farther down). Is this like Haskell records where every name has to be globally-unique?
---
Similar question for "extend" - the last couple lines of the "Struct and Class" page hint at a feature, but it's unclear what the scope of extension is. Is that based on the type of the first argument of the function being extended (Test in this case)?
---
One more scoping question: what names are in scope in an _OnBreak clause? For instance, in the nested part of the "LoopsWithExits" example, can that inner _OnBreak see v2?
---
How does constructing an instance of a class with arguments work (if at all)? The examples of constructor() functions are all arity zero, is the intent that an instance be constructed "blank" and then subsequently mutated?
---
One feature notably absent from the examples is passing functions as parameters. For instance, is it possible to write a "mapIntArray" function that takes an "int[]" and a function (that takes an int and returns an int) then returns the result of applying the function to each element of the array?
---
Has features not found in any other language
IMO you should either list them, or change the marketing language. I'd recommend the latter - people don't pick languages because they have unique features, they pick them because they NEED what the unique features help them accomplish. What's some code that Bolin makes easier/clearer/safer/whatever to write?
---
(e) Licensee shall not publish or disclose to any third party the results
of any benchmark tests or other evaluation run on the Software without the
prior written consent of DeLellis.
Is this 1994? Did I accidentally click on a link to Oracle.com? If I downloaded the software and did some experiments to answer my own questions above, would I have to ask for PERMISSION to post the results?
You want "the community" to contribute feedback and ideas for free, but you want to retain absolute control over both the software and the conversation. That's not a good trade.
Ironically enough I do want people to benchmark Bolin. It's very performant. I didn't want to modify the EULA and accidentally put a hole in it. I'll definitely have a new one when the compiler gets to 1.0
The compiler should complain about aliasing but I should check when I get home. The problem here is array's have an invalidation function (it may resize and the pointer may change). It's not allowed to have aliases.
If the compiler knows what type is expected (for the enum/bitflag) it can figure out the value. 2. No, its highly dependent on knowing the type.
Yes, first argument.
_OnBreak can see the index if you have it but I can't remember if it lets you see v2. It should but I never actually tested it
> they pick them because they NEED what the unique features help them accomplish
If you read it off a list would you recognize what it does? People in the last 24hrs told me they don't understand why I would want onbreak and didnt notice you can chain breaks so you don't need a goto
> That's not a good trade.
It's tough. One goal is how to make the developers lives easier. I heard about people quitting their project because of comments over github
82 comments
[ 3.2 ms ] story [ 41.1 ms ] threadErgonomically solving this problem is a major research area, so if you’ve found a solution to it’d be worth presenting that front and center.
Just as some basic questions you might want to answer:
1. If I allocate some memory and store a reference to it in a struct or object, how do you track ownership for that memory? Can I alias it? Store references to it in multiple structs? How do you know that it's safe to free that memory without reference counting?
2. Am I allowed to allocate memory in a function and return a reference to that memory? How do you ensure that memory lives long enough for those references to be valid?
3. Are multiple aliases allowed to overlap with each other? If so, how do you prevent (e.g.,) type confusion from one mutiple alias changing the data out from under the other?
You do realize you can download the compiler and confirm for yourself that it's all working right this very moment?
There's probably a few aliasing bugs since I add new features. types and haven't tried to break my code or find difficult to run into bugs
What would be very compelling are some code examples and either high level descriptions of what the compiler is doing or some analysis of the type system and IRs the compiler uses to verify correctness.
Particularly things like ownership and lifetimes. These can be pretty nuanced in degenerate cases and it would be interesting to see how you solved them.
Like take Rust. It has ARC to be sure, but the core semantics behind its "compile time GC" are pretty well defined and easy to follow so people have faith that they work (they're also provably correct). If you have some motivating examples and descriptions of how the language solves them it would be very compelling to see!
Essentially this isn't an attack on the project, it's just curiosity about the approach and implementation. It's easy to poke at code examples and see that you're right, what is more valuable to folks that are approaching the same problems is how you got there.
Personally I would have simplified its syntax a little bit more, if possible.
For instance, the following example code
would have wrote it as follows: I honestly like simple, well-written code that is easy to follow.I don't know if it'll make things more clear to you but curlys aren't nessicary when you use return/break/continue. I didn't write it because I didn't want to scare people off with the lack of curlys or confuse people on the front page
The `::` part looks nice. Would you want the statement to be forced on the same line? Or not like how C allows statements after `else`? As mentioned the compiler forces curly braces so it'll have to be forced to be on the same line as the on statement and I don't know if you'll find that to be a dealbreaker
What's confusing about that? Perl has that, I use it all the time.
Perl is my main, and I never use that feature.
A for loop also doesn’t match what’s being executed. It’s s actually a do/while loop
For me, the problem is when my expression got long or if I call a function with multiple parameters. The more complex the line is the easier it is to not notice the `if`. Also I agree with what the other person said, it doesn't match the order if you read top down left to right
I like the _OnBreak _OnComplete _OnEmpty . I think they simplify some loops and make those found_something variables go away. However I don't like that they start with an underscore. It feels so old (C and Python, which was designed at the end of the 80s.)
Case conventions are a little strange, something is lower case (main, for), something is camel case, something are upper case (methods?)
= := .= could be a little confusing. Why not only one? The compiler should know what to do because of the mut, out keywords.
About style: { sometimes leads a line, sometimes doesn't.
Early on _[A-Z] meant reserved variable so that's why it's currently _On. Many keywords are a single word and common enough that it shouldn't bother anyone that it's reserved. However I'm not great coming up with a style guide. On empty is two words, I have no idea how it should be written and everyone seems to have their own style.
Do you have a suggestion for the _On keywords?
> Why not only one? The compiler should know what to do because of the mut, out keywords
You noticed the out keyword? It's not recommended we only use that to interface with C code. Returning multiple variables is much better IMO (I won't speak for everyone). Accumulator and dynamic arrays are common enough that I didn't want to force people to write mut each time. It's simply `:=`
Let's suppose that in the future you want to add an argument to the break keyword to signal why the loop returned early. I use a string (btw, does the language have symbols / atoms?)
Then you could have with only one keyword. And > Returning multiple variables is much better IMOI agree but declaring a name for what you return is nice because it explains the purpose of the returned values. They could go outside the ()s.
> I agree but declaring a name for what you return is nice because it explains the purpose of the returned values. They could go outside the ()s.
So you're not suggesting an 'out' keyword your saying names on return values? I like the idea but in practice I'm not sure if any IDE would show you the names? I think many do show comments if you place them the line before so that could be an alternative solution
One reason I don't like out params is because it conflicts with the design of the language. The language prefers you to assign variables and people will want to modify their variables (or arrays and struct members) with the out param and having something be declare OR assign causes problems because its too easy to make a typo and not find it for many many minutes. Writing the type then using out goes against the flow of the language which is why I prefer returning multiple values.
But I don't know all the use cases and everyones preference so there very well be a good reason you'd want an out parameter
If it’s C like then the ExpressionStatement, umm…statement covers this; it’s how “if (foo=1) bar();” works (or leads to bugs depending on your point of view).
Also curious on how the automatic memory management works, might be on the website somewhere but I didn’t look past the first page.
I wrote some specifics in this thread over a few comments but that and the type system are complex. It can be a talk and writing short post probably will satisfy no one
(I would have preferred if the _OnBreak and _OnComplete statements was inside the for loop as that removes any ambiguity that it is part of it and effects the for loop).
However, `if v == 11 {break}` is definitely more readable than `break if v == 11`. If you are using curly braces as part of your syntax, and for blocks of code, it's better to use it with consistence. That can be confusing with `break {if v == 11}` as it breaks the syntax grammar, when you consider what break does.
the break, food out break out of the if block? Or somewhere else? It’s confusing
Kudos to you for turning your own programming language dreams into a reality!
Do you have a list of those features?
"If you look through the docs you'll find many reasons"
Respectfully, I browsed all the examples I could find on the site (Highlights, Examples, and Quick Start) and I'm not really sure what you expect to be recognized as novel ("Has features not found in any other language"). You may have a combination of features that is unique, but nothing individually stood out as something never seen before. Perhaps you just need to highlight these things better.
> value = fn1() error { return }
Allow for Error short circuits. This has slowing been adopted by other languages - An error can be handled/or not and continue cleanly without crashing anything (erlang style) or typed semantics (Java style). Go can return an error message, as part of the multi-return semantics, similarly allowing for error short circuits. Because of Bolin's multiple return semantics, you can implement this pattern as well, but it's nice to not bake it in.
The for-loop conditional exit handlers are novel enough.
Some unique syntax choices, like .= for assign and mutable/immutable assignment dynamically is great. Ponylang has typed containers that act similarly, but they are not dynamically declared.
I know I've seen lazy type signatures before, but I don't remember where. So I'd consider it novel enough to note: ie you don't need to specify int every param -> add(int a, b) and implicit void on main()
I can't speak to under-the-hood compiler optimizations, but there's a little bit here and there that's interesting.
P.S. Typo in: https://bolinlang.com/quickstart/basics //you don't need to specificy int every param
Is the `try` keyword in the highlight section what you're looking for? You can write `var = try fn()`
Thanks. I fixed the typo when I first saw this hours ago but it's been busy and I forgot to reply
I worded it poorly.
> Allow for Error short circuits
I was trying to say that I liked the feature as-is, because it Allows for Error short circuits. There are a lot of common patterns that modern languages avoid idiomatically, despite their widespread use in roundabout ways.
Is the problem with short circuits that you can ignore the error? It's not documented yet but `error return` requires the function to be an error type so the error can propagate. If thats not good enough do you have some insight on how to fix it? What's worse and was designed intentionally by me is `fn() error { return }` not requiring the function to have an error return (although this would be a void return type). I make the assumption if you have a block (instead of `error return`) you're handling the error. You can also propagate by doing something like this `nonErrVal = fn() error { print("write a better error log"); return error }`.
Never used it myself but it is probably handy, handy enough to be included in the language at least.
More to the point, I think your site could do a much better job on describing what's actually unique about this.
For example, I'm not convinced that the `_OnBreak`/`_OnComplete`/`_OnEmpty` machinery is useful enough to be part of a language. A bigger example where these features come in handy would be helpful to understand them.
Just skimming the highlights and examples page, it looks very similar to C++. So I think it could use some side-by-side examples to show how it makes ordinary programming easier/more readable/etc.
The Quick Start guide is a bit obtuse and feels incomplete. I'm having trouble understanding some features, and I feel the standard library is underdocumented---for example, I couldn't find what `.WSNL()` does, and it's used for your MIME type parsing example.
I apologize if I'm sounding a bit harsh; I'm trying to provide some constructive criticism here. I appreciate how hard it is to get something out the door and I wish you the best of luck.
At the point that it was clear we're going to have a usable compiler I asked my entire team what license we should release this under. Absolutely everyone had a problem with each and every open source license. The more we talk the more apparent that none of us wanted to wake up one day to find out a trillion dollar (possibly cloud related) company took our code and want to compete with us. We don't want embrace, extend, and extinguish to happen to this project if we could help it. So we settled on a EULA (which very likely will change at 1.0) that says you can learn for free which lets face it, is the only thing people would want to do in its present state
The language field is very crowded. I'm all about new languages, I wish each and every one success and yours is no exception.
If it's going to succeed, you'll have to beat people over the head with it. The current situation won't reach escape velocity. Good luck.
But I guess it depends on what your goals are. If you want this language to be used by as many people as possible, you want to remove any obstacles to that, and a sign-up wall is a big one. You also have to consider the competition. I can go to my package manager and download compilers and runtimes for probably over 200 languages right now without having to submit any information about myself - I did it for Zig the other day. If your language and compiler are so mind-blowing that I should be glad to subject myself to the friction I have to go through to use yours instead, you really need to sell that to me with more than, as mentioned in another subthread, a promise of ambiguous features not found in other languages.
So free your code. Sell it to me as much as possible on the web site with all of its amazing capabilities and features and libraries. And if some company rips it off and passes it off as their own thing, make hay from it - write up a blog post about how the nasty big evil company stole the work of a plucky li'l FOSS team, but you're just going to keep plugging away and improving your code regardless. Then post it to HN. You'll get updoots through the roof and plenty of sympathetic new eyes on the project.
Also: forking /= stealing
[1] https://ziglang.org/news/statement-regarding-zen-programming... (HN discussion: https://news.ycombinator.com/item?id=24481142 )
I think many people just fundamentally don't understand sharing or friendly coexistence. The drive to dominate and control is sooo maladaptive for society but very widespread.
Especially in a pre-production state, it's unlikely that anyone will want to use this commercially anyway. It'll eliminate a big barrier to any adoption you're hoping to get.
Deciding to learn something in the first place is a question of how I want to use my limited time. I don't think I want to learn something with a presently-bad EULA that might change arbitrarily in the future.
It's totally fine that your team wants to keep this project close to you, it is your work and copyright privileges after all. You don't have to be open source if you don't want to. [1] Don't let anyone tell you what to do with your own work.
Just don't be surprised when you find that nobody's interested in it.
[1] I do think it's a bit hypocritical to require people to be "a part of the community" to download the thing when the license doesn't resemble a community or copyleft license. This is no different than downloading from the Oracle Download Center.
That's a fantastic idea. I'll focus to improve this by the next release. Do you want short side by sides or real code examples? I'm worried that short ones may look contrive which is probably why you don't think it's useful? But I'm not certain people would look at anything that isn't short
Correct. I wasn't sure if I'll rewrite the reader class so I only used it in the example program section. The standard library is pretty nonexistent. We didn't want to make the language for only ourselves so we thought we should launch sooner rather than later
> I think your site could do a much better job on describing what's actually unique about this.
In another comment I mentioned that listing features tends to be ignored. Do you have any suggestions on how to counteract it? Maybe your side by side suggestion is ideal https://news.ycombinator.com/item?id=32460252
I can see where you're coming from, it might be different from person to person. I personally would've been happy to read through a short feature list highlighting the most interesting ideas that the language introduces. For example, you mention automatic memory management without reference counting and garbage collection, which sounded interesting but wasn't specific enough for me to figure out what's unique. In another comment I saw that you expanded on it and mentioned it tracks lifetimes across scopes, which then sounds super interesting. But I didn't find where to learn more about it.
> Do you want short side by sides or real code examples?
I think short examples can do the trick, if they are not toy examples but can work as part of a bigger program, if that makes sense. Coming to think of it, ideally it would be best to have an actual program written in the language. That's what I usually do to feel out a new programming language---seek out a codebase written in it and read through. So if you have something like that, maybe you could showcase features using small snippets from the program itself, maybe side-by-side with equivalents in a well-known language.
I think it would be hard to avoid a lisp-like {{{ hell though
I felt having `.` on a loop would be weird because it isn't working on an object
A few people said they want single statements on conditionals. If `=>` (or `::` as someone else suggested) forced the statement to be on the same line would you be fine? I can imagine people wanting to use it on it's own line like people use else without braces which leads to bugs
I wouldn't know what people want to know about. In real life with friends and coworkers don't really want to hear about details or why I designed something
I forgot to answer this. It isn't but that'd be a good milestone.
Something like TypeScript, for example, really caught my attention because of how well it integrated into the existing JS ecosystem, adding sanity while still not sacrificing interoperability.
All these choices you have to make had me wonder: we've made formatting entirely part of a language but it seems a lot of it could be moved into the editor. Does it really matter if:
It could just be whatever the user chose in their editor (with an option to publish their custom solution) The code in the actual file can be any of the existing languages which would put some limitations on the formatting choices but if that gets annoying it could be addressed at many levels.Does this sound fun or should we pretend no one ever mentioned it?
---
If arrays are passed by reference, how does the bounds-checking code deal with aliasing? For instance (apologies if this syntax is wrong):
The "Array Bounds" section on the "Highlights" page suggests that the compiler will try to spot indexing errors (like accessing target[target.size]), but thanks to aliasing b can change size "at a distance" if the right parameters are passed to munge_arrays.---
What are the scoping rules for enum and bitflag names? The page in the Quick Start is unclear - sometimes they are qualified with the type name (Fruit.Apple) but not always (Banana, Dir farther down). Is this like Haskell records where every name has to be globally-unique?
---
Similar question for "extend" - the last couple lines of the "Struct and Class" page hint at a feature, but it's unclear what the scope of extension is. Is that based on the type of the first argument of the function being extended (Test in this case)?
---
One more scoping question: what names are in scope in an _OnBreak clause? For instance, in the nested part of the "LoopsWithExits" example, can that inner _OnBreak see v2?
---
How does constructing an instance of a class with arguments work (if at all)? The examples of constructor() functions are all arity zero, is the intent that an instance be constructed "blank" and then subsequently mutated?
---
One feature notably absent from the examples is passing functions as parameters. For instance, is it possible to write a "mapIntArray" function that takes an "int[]" and a function (that takes an int and returns an int) then returns the result of applying the function to each element of the array?
---
IMO you should either list them, or change the marketing language. I'd recommend the latter - people don't pick languages because they have unique features, they pick them because they NEED what the unique features help them accomplish. What's some code that Bolin makes easier/clearer/safer/whatever to write?---
Is this 1994? Did I accidentally click on a link to Oracle.com? If I downloaded the software and did some experiments to answer my own questions above, would I have to ask for PERMISSION to post the results?You want "the community" to contribute feedback and ideas for free, but you want to retain absolute control over both the software and the conversation. That's not a good trade.
The compiler should complain about aliasing but I should check when I get home. The problem here is array's have an invalidation function (it may resize and the pointer may change). It's not allowed to have aliases.
If the compiler knows what type is expected (for the enum/bitflag) it can figure out the value. 2. No, its highly dependent on knowing the type.
Yes, first argument.
_OnBreak can see the index if you have it but I can't remember if it lets you see v2. It should but I never actually tested it
> they pick them because they NEED what the unique features help them accomplish
If you read it off a list would you recognize what it does? People in the last 24hrs told me they don't understand why I would want onbreak and didnt notice you can chain breaks so you don't need a goto
> That's not a good trade.
It's tough. One goal is how to make the developers lives easier. I heard about people quitting their project because of comments over github