I wrote a bunch of CoffeeScript back in the day, and everyone I've spoken to about it feels the same, that it was a bad idea in hindsight, and a language dead end. The language was only syntactic sugar, and by not bringing anything else to the table, was unconvincing for ports and support in other ecosystems. It now seems that most codebases have been decaffeinated though.
Civet looks like it adds a little more, but the things that aren't just syntactic sugar are just a grab bag of TC39 proposals. I'm a big fan of language proposals in general, and having a language that adds all of them for research purposes seems like a nice thing to have. Haskell did this well with GHC language options. Is this a research language though? It seems not.
What's the benefit over Typescript? A few less characters? Faster TC39 proposal integrations? What happens if a proposal is rejected, does it get removed from Civet? What's the cost? What happens as Typescript and Civet diverge? What if the TS tooling doesn't support Civet features?
I don't think it was a bad idea in hindsight.
JS of the era was a pain to use; CoffeeScript made writing and reading things much easier, which is the reason it took off. Since then things changed and many "CoffeeScript features" are now "JavaScript features". Only with knowledge of that future would it be a "bad idea", but it was absolutely not clear that was going to happen back in 2010 and in alternative universes we're all writing CoffeeScript today.
I also think CoffeeScript was probably helpful in getting some of these features adopted in the first place.
The same applies to TypeScript – maybe typing will be added to JavaScript, and TypeScript will become redundant – I think there was some proposal and who knows what will happen. In 15 years we can say the same about TypeScript, but that doesn't mean TypeScript wasn't useful today, with the current state of JavaScript and uncertainty what the future may or may not bring.
My point is that it kinda didn't. It looked prettier on the surface, but didn't actually solve any of the deeper problems of writing JavaScript. To write CoffeeScript you had to still know JavaScript and all its oddities.
TypeScript solved those problems, and that's why it has taken off and had a meteoric rise to the point that it's practically synonymous with JavaScript.
> I also think CoffeeScript was probably helpful in getting some of these features adopted in the first place.
This may be true, but if so that suggests a benefit as a research language not a production language.
And then it ruined us with implicit returns, optional parentheses and brackets, and the isnt vs is not fiasco.
I worked a lot with Python and coffeescript at the same time back in the day. In Python you mess up your whitespace and 95% of the time it's an indentation error. In coffeescript it's a valid program that means something completely different than what you intended. Combined with the optional punctuation, which the community encouraged leaning into, it was far too easy to write ambiguous code that you and the compiler would come to different interpretations of.
* `is not` is the textual equivalent of `!==`. You can use `isnt` if you turn on the feature explicitly (or even the weird CoffeeScript `is not` behavior if you want it, mainly for legacy code)
* Implicit returns are turned on by default. They are really useful, most of the time, and don't get in the way much if you use `void` return annotations (which turns them off). But if you don't like them, you can turn them off globally with a compiler flag.
* Civet's compiler is built on very different technology from CoffeeScript's (PEG parsing, similar to Python), and it is much more strict about indentation. None of those weird bugs anymore.
* We do have implicit parentheses and braces and such, but you're free to use explicit parentheses and braces as you like. We encourage people to rename their .ts files into .civet (which mostly just works without any converison) and just embrace the features/syntax they like.
I’ve been eying Civet and I quite like it so far, but I dislike having this option because it means I’ll have to see it in other peoples code. I prefer strict rules for readability.
Regardless, I like pretty much everything else.
What was so ruinous about implicit returns? That's one of the things I missed most when leaving CoffeeScript. ECMAScript only partially adopted it (single statement fat arrow functions) which probably muddies the waters for people trying to learn and understand the language's behavior.
Since it's optional for the caller to use or assign the return value of a function, I don't see much problem with functions defaulting to returning something. Maybe it just fits with my personal preference of functions returning a value and not having side-effects..
easy enough to add an extra line with just 'undefined' as the last statement of the function of course. but then you do need to remember that.
People can adapt either way. You can write more concise code with implicit returns and "everything is an expression".
Oh man, that brings memories. When I joined a coffee-shop (pun intended), and learnt about implicit returns, I was screaming internally until we got rid of all the coffee (which was massive long team-wide migration effort that took like 2y to finish).
Once the migration was finished, everyone was so tired, that at the mere proposal of using TypeScript instead of JS the whole team would just roll their eyes and silently say "nope" in terror. Which was a shame, because large JS codebases are difficult to maintain and explore.
So I think this has more to do with how people are used to thinking with the languages they are fluent in.
Convenience does matter. The less I have to think about nonsense like that, the more I can think about actually writing correct code.
CoffeeScript wasn't perfect in that sense either and had some nonsense of its own. That probably contributed to its demise as much as any thing else.
Many times something would look perfectly reasonable in CoffeeScript but when you would actually read the JS it would be iterating the same dataset multiple times to grab individual items that could have and should have been a single loop.
I don't think TS removed any peculiarities of JS. It just forced you to actually learn them which JS and CS didn't do.
It's also backed – nay, pushed – by one of the largest and most successful tech companies in the world. A company that also made a point of releasing a very capable IDE to go along with it. Surely this has had some impact on its meteoric rise? :o)
(Wait – aren't meteors falling?)
It probably died fueling the whole js build/transpiler landscape that is in use today.
It didn't. Anything you learn / are familiar with will be easier to write - Coffescript was easier to write for people who learned Coffescript. Which in hindsight wasn't time well spent as they would've eventually had to bite the bullet anyway & just learn JavaScript like everyone else.
JavaScript is much much easier to write and read for a person who has chosen to learn JavaScript & has not had the occasion to learn Coffescript (i.e. most people) so you were also doing others a disservice if readability was one of your goals.
> which is the reason it took off
The reason it took off was the Ruby was going through a popularity trend & Rails devs wanted to work in a front-end language that felt syntactically familiar. It was purely aesthetic.
But you're right that you did have to know enough JS to understand what CoffeeScript was doing under the hood when things went wrong.
Was it really?
Outside of arrow functions, I don't really think CoffeeScript had a single important idea. And even then, the aversion to the `function` keyword in the JavaScript community never fails to make me laugh. Sure, sometimes the implicit scoping of the arrow function is nice, but man.
Over time, JavaScript evolved to the point where the few quality of life improvements offered by CoffeeScript no longer justified learning an entirely new syntax.
Admittedly, I don't do much Android development, and that was a big driver of Kotlin's adoption early on. So maybe it has more of a foothold there than on the server.
The "systems" language of the platform, evolves with the platform, is designed alongside the platform.
The guest languages might be better than the platform's "systems" language, on the day of the release, eventually it is bound to diverge with its own library ecosystem built on top (because "ugh" we're not using the platform libraries directly), its own IDE tooling, its additional debugging layer due to platform interop, its own abstractions not native to the platform,.....
Eventually it naturally diverges as the platform takes incompatible decisions,...
C and C++ on UNIX, JavaScript and anything compiles to JS, Java vs Groovy/Scala/Clojure/Kotlin/jTCL/Beanshell/jython/...., C# vs VB.NET/F#/C++/CLI/IronPython/IronRuby,...
The guest languages that are survive, are those that move beyond the platform that gave them birth and create a platform of their own.
In Kotlin's case that is definitely Android, because Android team is doing everything at their disposal to make Java a 2nd class language on Android, rewriting Jetpack libraries in Kotlin, requiring Kotlin for Compose, showing off Kotlin code samples against Java 8 examples(!), I bet they only starting updating Java support, because Android was starting to lose too many Java libraries as the Java ecosystem adopts new versions.
Still, Android 15 being released one year later from Java 21 LTS, is still catching up with Java 17 LTS, introduced in Android 13 and not yet fully implemented, kind of proves the point of them not being in a hurry for proper Java support on the platform.
But JS moved faster and babel was made and eventually we could use JS-future even when browsers hadn't updated yet and CoffeeScript wasn't needed. But it was pretty easy to translate it to JS, commit that and keep rolling. CS was great at the time.
I personally use Civet for all my coding projects, as I'm devoted to it continuing to flourish. But if you ever don't like what Civet is offering you, you can eject at any time by replacing your code with the TypeScript compilation, which we make as close as we can to your input.
What happens if a TC39 proposal is rejected? That's actually the good case for us, because it means we can keep the feature as is. Civet already transpiles all features to TypeScript, so they can live here forever if we think they're good. The trickier part is when Java/TypeScript changes in a way that's incompatible with Civet. Then we plan to change Civet to match Java/TypeScript, so that we don't diverge (though compiler flags allow us to also support the older form with explicit opt-in if we think it's worth doing so).
JavaScript and TypeScript move slow. Largely that's a good thing; they're a stable foundation, and we don't want to mess them up. But it's also exciting to be on the bleeding edge, explore new ideas, and obtain new features as quickly as we can design them, instead of waiting a decade. Many features are also too niche / add to much complexity for the general JavaScript language, but they're still fair game for languages that transpile to JavaScript. See also the recent JS0 vs. JSSugar discussion.
The addition of quick things you whipped up in a couple of hours seems like it'll make the rate of changes impossible to handle. It's unlikely almost by definition that the change you whipped up quickly will stand the test of repeated use and further experience unmodified.
All that said, it's a super fun thing to do, and hats off for such an ambitious project. If nothing else, writing a parser, transpiler, etc. is impressive and fun work, and will undoubtedly enable/force you to learn all the javascript/TS quirks and details extremely well! :-)
I still have gripes about runtimes such as Nodejs, but I don't expect something like Civet to solve those.
The other big one, which unfortunately Civet seems to be doing too, is implicit return combined with “everything is an expression”. You can have one of those, but not both. With both, it’s far too easy to write loops intended to be statements, and which accidentally turn into gigantic multi-dimensional array returns which can’t easily be optimized out by the compiler. Fortunately, this would be only mildly inconvenient to work around with a lint rule that forces explicit return in all functions.
I agree it can be easy to make and throw away big arrays if you're not aware of what's going on. But it can also save a lot of time. For loops as arrays are super useful, integrating the equivalent of "map" into the language itself. We also recently added generator versions (for*). JSX is a nice example where for loops as expressions and implicit return are powerful; see e.g. https://civet.dev/reference#code-children
What might work well is a lint rule to error if a loop expression ends an actual function declaration (i.e. not an inline callback), and the function doesn’t explicitly define a return type. I think that catches almost every bad case, aside from the odd memory leak in really unusual edge cases.
Hang on, how can you have “everything is an expression” without implicit return? If I’m correctly understanding what you’re talking about, implicit return isn’t actually a thing—it’s just that the function body is an expression too.
(Never dealt with CoffeeScript, but I’ve been writing Rust for over a decade now, and learned to love expression-orientation there.)
For example, you might have an “x” in some inner loop within a function. Then later on, you’d add an “x” earlier in the function, not realizing that that name was used down below. Suddenly the inner loop is referencing that new variable, and there was no way to tell other than the surprising ways your code would suddenly malfunction.
Types help quite a bit with implicit returns so you don't accidentally return an iteration results array from a void function.
They also help reduce the downsides of terse syntax, just hover over things in the IDE and see what they are. Missed a step in a pipeline? The IDE will warn you if there's a mismatch.
Getting hands on experience with those proposals could be an argument, learning how they feel, learning how their availability changes the way people write code. Could this be called a research language? Sure, but that categorization would certainly influence the outcome of the observation.
I'm not disagreeing with any of your points though. Perhaps some mitigation could be provided by making their equivalent of decaffeinization a true first class citizen, intended to be run whenever a proposal gets rejected (or implicitly rejected by the language taking a different direction). This would have to be fine grained, and the language/tool would have to make "rolling preview of whatever proposals are currently in consideration" the code of its identity, not any particular set of language features.
I agree a research language feels potentially useful — and in fact that's what CoffeeScript's real legacy is (arrow functions, splats, destructuring assignments, and ES6 classes among others are direct ports of CoffeeScript syntax features, and many of the original JS class proposals that CoffeeScript-style classes replaced were quite bad) — but I'd be similarly leery of using this to ship much.
- "everything is an expression" is a nicer solution for conditional assignments and returns than massive ternary expressions
- the pipe operator feels familiar from Elixir and is somewhat similar to Clojure's threading macros.
- being able to use the spread operator in the middle of an array? Sure, I guess.
I want to like the pattern matching proposal, but the syntax looks slightly too minimal.
The other proposals are either neutral or bad, in my opinion. Custom infix operators? Unbraced object literals? I'm not sure that anyone has a problem that these things solve, other than trying to minimize the number of characters in their source code.
Still, I'm glad that this exists, because allowing people to play with these things and learn from them is a good way to figure out which proposals are worth pursuing. I just won't be using it myself.
Agree there's some good ideas. Pattern matching looks like a great idea with the wrong syntax - let's just get a match statement similar to the switch statement - if we can't reuse switch.
String dedent and chained comparisons look nice. Though I think the latter is a breaking change if it were done in js. I'd also be fine with default const for loop variables.
"Export convenience" is going to confuse people. The syntax looks different than named exports and looks closer to the export form of default imports which is begging for trouble.
Keep it simple. Code should be easy to read. Also, ain't nobody got time to learn yet another obscure abstraction that will add only a marginal productivity gain at best (and probably sacrifice readability + add another build step + add another learning curve to new devs in the process).
That being said, stapling on a compile step maybe isn't the answer.
Like this example: https://civet.dev/#everything-is-an-expression `items = for item of items`, in js you type `for`and copilot wrote nearly the full correct for-code. So you have to type not much and can read it easy.
(Terse Perl may be delightful to write, as long as you still remember exactly what you wrote and why. But not after that.)
``` const result = items.map( i => i.length ? i.toUpperCase() : ‘<empty>’) ```
I think things get interesting here when different kinds of iterators come into play (eg generators, async-await for loops, non-array iterables). Shame the landing page doesn’t touch on that at all.
Copilot is good when working with something where the idiomatic patterns are common, widespread, and hard to screw up. Civet has low adoption, uses much looser syntax (bracing, whitespace), and lacks the rigor of common TypeScript code.
foro
for ($1 of $2) {
$0
}
touc
toUpperCase()
le
length
map
map(x => $0)
And so on.Seriously, typing code is some '90s activity since forever. Using copilot for this is akin to hitting a nail with a microscope.
> Some people don't code for the interns but to have fun.
I don't think the person you were replying to necessarily disagrees with you there. But their post was phrased in such a way that seemed like business was the only focus that mattered, yeah.
I hope so.
> it's mostly logical extensions of the javascript syntax which are easy to understand if you know javascript.
They didn't look thatneasy to understand to me, and a lot of other people judging by the comments.
i see it as moving physical abstraction into mental abstraction
save few lines of code but costs more mental ram
I have a hard time understanding the motivation of this project other than syntactic sugar-maxxing JS/TS.
If you’re interested in targeting JavaScript, languages like this are your only reasonable alternative to JavaScript itself. (If you’re interested in targeting the web more generally, WebAssembly is a better target.)
If you don’t mind I guess you could just render to a canvas but then you lose a ton of functionality provided by the browser. (Eg: making a responsive page in WASM seems hard)
It seems to me for most web applications JS is the only real alternative as of now
It’s completely fine. At present you’ll need to trampoline via JS to make the actual DOM calls, but that’s not typically a performance bottleneck; and such bindings can give you exactly the same API, if you choose.
Yes, work is just about done in browsers for giving you direct access to these things without the JS trampolining, and lots of people are hanging out for that to be dependable, but in practical terms it changes nothing. Nothing. No change in expressiveness; it only gets you probably slightly better performance, and a simpler technique for binding (which is typically immaterial for end users, as libraries were handling that for them).
> Rust began as a personal project in 2006 by Mozilla Research employee Graydon Hoare, named after the group of fungi that are "over-engineered for survival". Mozilla began sponsoring the project in 2009, and would employ a dozen engineers to work on it full time over the next ten years
So by 2013 it was already 7 years old. I very much doubt the original personal project was viewed as "a lot of sense" etc.
B) What are the downsides?
For the languages that target wasm instead, there are different debugging stories. Kotlin's is very good, Rust's is pretty immature.
Source maps work great for TS because it is just "JavaScript with types" at this point.
The one feature that I liked was pattern matching, but I wouldn't use such a different syntax just for that.
What I would like the most from a TypeScript superset is additional runtime features, like being able to validate if an object matches a certain type, and a more comprehensive standard library. The first one got alleviated a lot by Zod becoming a thing, and LLMs integrated into your editor being able to generate the equivalent validation code. The second one seems like it will never become part of the language itself, and it's up to runtimes to provide batteries-included APIs if they want to. Deno and Bun are definitely more inclined that way.
The devs seem pretty happy with it though, so I hope they continue hacking and building the language that they would like to use. :)
- Everything is an expression
- Async imports just work without thought
- Yaml-like object structuring
- JSX improvements
- Multi-line string literals without leading whitespace
Things I’m on the fence about:
- Pipe operators (better than .pipe I guess?)
- Pattern matching (love it in Scala and swift, but this doesn’t feel done right)
Things I loathe:
- Signifiant whitespace (removing brackets in general)
- Optional parentheses in function calls (a foot-gun in VB and Ruby)
- Splats in the middle of function definitions (I can’t imagine how this works with overload definitions)
It is a shame that Bloomberg and Facebook made the whole situation pretty confusing though, but still, it is a nice idea.
Looking at the examples, 1/5th of it looked neat, which probably would be best to submit a proposal for |> to the typescript committee rather than write another alienation.
This is a solution looking for a problem to solve. It introduces an alternative and does so as a superset; which is not only dangerous to existing code bases, but also silly.
How so?
As for the superset comment, I meant that if you introduce a completely different language, you probably have a valid reason; e.g. it does something different. Adding to an existing language with a superset without any need for it is also dangerous. It's not like it's a DSL at a higher level helping people get repetitive or scriptable things done faster. It's only an alternative, leading people down rabbit hole and second guessing with a lot more to remember.
> It's not like it's a DSL at a higher level helping people get repetitive or scriptable things done faster.
I mean, I have to disagree with you there, because several of the comparisons on the main site page show >50% line-count reduction, and many of those that don't have (subjectivity-alert!) representations that more-clearly match my mental model of how the code works - so not only would I be executing fewer keystrokes to encode my idea (not the main bottleneck, but not irrelevant!), but also I'd be carrying out fewer mental translations to get from idea to code.
https://xixixao.github.io/lenientjs/
But this was before Prettier.
The real challenge in languages now is flawless LSP implementation, auto-formatter and AI completion. It’s possible for CoffeeScript like syntax, but just the existence of an auto-formatter mostly removes the need for dropping all the syntax.
I’d maybe take dropping of parens from if, to align with Rust, but even some of Rust’s syntax makes the language hard to read (if let bindings for example, which switch the flow from right to left), so I don’t consider it a golden standard to strive for anymore.
The other thing I would take is custom operators, not for any production code, but for building games and simulations, to simplify vector math.
I’ll check out the Civet IDE experience, but I suspect it’ll have large cons compared with TS.
Kinda feels like someone was forced to work in Typescript and really wanted to scratch their own itch.
value min ceiling max floor
Much of the rest I could take or leave… but then is that just because I’m not familiar with them? Stuff like the pipe operator makes sense to me but it reminds me of .reduce(): there are a few legitimate uses of it but the vast majority will be entirely-too-smart—for-its-own-good show off coding.
I am not convinced that all the syntax nicety is necessary, but improved pattern matching is often a great thing. On the other hand their examples seem to be to pattern match on highly dynamic types, which you can avoid 95% of the time with TypeScript.
Civet's futuristic JSX compiles to actual spec-compliant JSX, to it's compatible with all forms of JSX, including React, Solid, etc. We'd like to support other DSLs like Astro and Svelte as well.
Fwiw it seems a lot of people really like the concept of "significant indentation". I'm thinking Python, YAML, Godot's GDScript. Not a lof of languages implement it but those that do seem to get a lot of users.
Interestingly, it seems like Erik Demain [1] is one of the contributors [2] of this project.
--
1: https://github.com/DanielXMoore/Civet/graphs/contributors
CoffeeScript for TypeScript - https://news.ycombinator.com/item?id=34962782 - Feb 2023 (135 comments)
Show HN: Civet the CoffeeScript of TypeScript v0.4.20 - https://news.ycombinator.com/item?id=33834312 - Dec 2022 (3 comments)
Civet: The CoffeeScript of TypeScript - https://news.ycombinator.com/item?id=33323574 - Oct 2022 (17 comments)
The CoffeeScript of TypeScript - https://news.ycombinator.com/item?id=33198931 - Oct 2022 (2 comments)
Syntactic sugar can’t be the only thing that makes a programming language.
Assembly adds mnemonics and a logical structure to machine code.
C largely does the same, but adds a cross-platform abstraction, mechanisms for organizing and sharing source code, a standard library, and various other things.
That is, something that works the same but looks better (hopefully).
A cross-CPU abstraction, a preprocessor, a standard library all have certain elements of syntax in them, but go well beyond alternative syntax.
without the pipe operator you would write ` fun1(fun2(fun3(fun4(fun5(x, y), z, w), u), v)) `
The order of operations in this line is actually from right to left. Also it's not immediately obvious to which function the u parameter belongs to.
With the pipe operate you would write it in the order that the functions are actually called and you have the arguments in the same location as the function they belong to. So this would be written something like
` fun5(x, y) |> fun4(z, w) |> fun3(u) |> fun2(v) |> fun1() `
I also absolutely cannot parse this, and while I'm open to the idea that eventually this would become readable, right now this just looks like word salad:
value min ceiling max floor
That being said; regular written language (like in a book) has optimal readability. Therefore it makes sense for programming languages to lean towards that. If you could write code like: `draw 600 by 600 graph_of intersection_of data_set1 data_set2 in blue` it would be very easy for basically anybody to tell what the code does. This not only makes it easier for beginners and onboarding, it also reduces cognitive load, even for senior level engineers. In real terms this means less fatigue, less bugs, less time spent reviewing code, higher productivity.
That being said I also prefer the explicitness of parentheses, but I think that's because I'm used to needing that level of explicitness. But maybe there's some paradigm out there that makes it so we don't need that crutch
Now, there's no reason we can't have an explicitly defined syntax that reads like normal written language. That's what SQL tries to do, after all. However, explicitly defined "natural" language has the tendency to get very unnatural very quickly. Human language is fluid and evolving in a way that a programming language just can't be. And no amount of emulating written language can eliminate the need to learn a programming language's syntax.
Also there is the classic issue where you take an if statement that has a line one expression and you add a second line, but now because it didn't have brackets (and you are not using indentation style), you just introduced a bug. Or you have an if statement with an expression and you comment out the expression but not the if, then your next statement is now the if conditional expression, which is not obvious.
I think there's a reason that Python is among the most popular programming languages, and part of it is the indentation-based syntax and lack of brackets. The core of Civet's syntax (originally inspired by CoffeeScript) is like a combination of JavaScript/TypeScript and Python, the two/three most popular programming languages.
But also, if you like brackets, you can include them! Most JavaScript/TypeScript code is also valid Civet. Just use the features you like.
Perhaps, but IMO that will then be because it looks tempting at first glance like YAML. No matter how much Python I write, I never learned to enjoy this and the fact that I can't select inside/around brackets to quickly manipulate a scope is just so frustrating.
In comparison, at least some people would find CoffeeScript and Civet to be hard to read because they solely rely on left-bearing indents. If my eye is pointing to the rightmost column and scanning to left, I wouldn't be sure about any nature of the line until the very first token and thus preceding indent is reached. This problem is not unique but can be somehow alleviated with some tweaks to the syntax. Ruby `if` for example is also prone to this issue but an explicit `end` token keeps it on track in most cases. CoffeeScript did nothing.
[1] The only other case is `lambda ...:` in parenthesized expressions. `lambda` in Python is quite exceptional in its syntax after all...
I didn't realize Civet is indentation-based like Python. That isn't so bad.
operator {min, max} := Math
value min ceiling max floor
At least make them require a certain symbol at the start or something.Dedent and object globs are useful imo and should be added to javascript. Maybe for-of with index too.
Also, I see no flow control in array literals, how do they plan to appeal to jsx/h users?
Kudos to all building & contributing to this!
The big difference, of course, is that Civet fully supports TypeScript, and is up-to-date with the latest JavaScript and TypeScript features.
1. `wxyz = [ 2 8 -5 5 ]` (commas optional for non callables)
2. `console.log \hello` (backslash strings)
Don't know how hard/compatible #1 is, but for #2 I had a tested PR that I could bring around.
(#3 was bulleted lists, but you already added that!)
I loved LiveScript, but it got kinda lost in the wake of ES6.
They planned to add types, but never got around doing it (at least the last time I looked).
Additionally having the integration of Microsoft's AOT experiments with Typescript in MakeCode.
This would also have other implications on the language design. Checking if an expression has a certain type at runtime would mean relying less on structural types to make these checks cheap.
I've been thinking about this exact language a lot recently, but it would not be the same as Typescript. A superset of JavaScript which can be statically optimized based on type information.
Fwiw, I don't think Assembly script is this language either. It's a completely different language than JavaScript with a superficially similar syntax.
I would rather do with a stricter super set of TypeScript with some sugar/conveniences around its many verbose but useful features like branded types.
Not because people want it, but because the "should this exist" argument does really consistently well in the algorithm.
This has made me even more convinced that the future of JavaScript is JavaScript.
We will be seeing JavaScript (natively) having all the types, features and proposals that TypeScript has and the industry will eventually move on from TypeScript.
It's made me realise that much of the sugar I was writing in other languages didn't make me more productive or my code more readable, in many cases it was actually the opposite and the usage of that sugar was more about writing more "succinct" code that was in the long run harder to understand and maintain.
It probably won't share fate of Coffeescript. It won't get popular, influence TS and JS and fade into obsurity due to mostly fulfilling it's goal. I'm afraid it won't get popular enough to do that.
operator {min, max} := Math
value min ceiling max floor
Is that a declaration or an invocation?First line:
* `{min, max} := Math` is a destructuring declaration. It's similar to the destructuring assignment `{min, max} = Math` (i.e., `min = Math.min; max = Math.max`), but also declares min and max as const.
* The `operator` prefix means to treat min and max as new infix operators in the rest of the program.
Second line:
Given that min and max are infix operators, `value min ceiling max floor` is equivalent to `max(min(value, ceiling), floor)`. Yes, the latter is gross. That's why we like to write `value min ceiling max floor` instead. Think of it as "value minned with ceilling (i.e. capped at ceiling), then maxed with floor (i.e. prevented from going below floor)".
I like some of it, but that’s hardly worth the increase in complexity.
In fact, having fewer aesthetic syntax choices is probably more of an improvement — cuts down on pointless/superficial coding style arguments, and leaves code generally more readable.
it was about a decade ago and i liked ruby for the implicit nature and minimal looking code— without the curly braces and shorthand notation whenever possible
return true unless false
that line is roughly why i favor curly braces and javascript’s control flow
lines like return true unless false are so easy to write in the moment, but so much to reason about it post.
in all, i’m in favor of systems that bring future code to today’s code, like polyfilling tc39, but probably won’t bet against core javascript semantics again, like other coffee-script adjacent comments, which was the dominant flavor of js for rubyists at the peak.
The syntax and some other features, no. Some are even anti-features or "magic" that takes the actual semantics away from the developer.
Scala has it. Other languages too.
unhandledRejection: Error: ENOENT: no such file or directory, open 'Civet/integration/unplugin-examples/components/button.civet'
also by default build is broken due to error TS5110: Option 'module' must be set to 'NodeNext' when option 'moduleResolution' is set to 'NodeNext'.
changing it still doesn't fix the not being able to import the civet button
But getting rid of the curly braces alone is enough to get me to adopt it over JS. I really hate writing JavaScript.
<ul class="items">
Should be:
<ul className="items">
Btw, you seem to have missed the new jsx transformer, className has been a thing of the past even in React.
switch x
0
console.log("zero")
/^\s+$/
console.log("whitespace")
[{type: "text", content}, ...rest]
console.log("leading text", content)
Yes, looks very cool, but nobody should ever write code like this, especially not in strictly typed code. And it is extremely rare you need to do similar pattern matching. For the object case, you would want to define interfaces and type guards in TypeScript anyway. This feels like poor man's pattern matching compared to Python and Rust. items = for item of items
if item.length
item.toUpperCase()
else
"<empty>"
If JavaScript has always required statements to end in semicolon, I'm 100% for this. But it's not. So "standalone expression" as return value will only cause chaos.