Do you ever think of developing in other languages than C++?

DSP, Plugin and Host development discussion.
Post Reply New Topic
RELATED
PRODUCTS

Post

Super Piano Hater 64 wrote: Tue May 18, 2021 12:29 am If your code is strictly and reliably single-threaded, don't use Rust. Many of the safety features are specifically designed around the hazards of concurrent code.
Whilst I would agree (as a Rust user) with most of what you posted, the above makes little sense. Much of the benefits of Rust are from the borrow-checker ensuring safe memory access - sure that's helpful in concurrent situations but it also ensure a lot more safety (and thought) around single-threaded/non-concurrent code.

The overall memory-safety is (IMHO) the biggest value proposition. As to whether it's really 'ready' for mainstream plugin development yet - I'm not sure, but without people starting to use it, the problems will never be uncovered and therefore addressed.

Post

The first step would be to have some multiplatform library abstracting away the different plugin standards and hosts as e.g. JUCE does.

Post

Here's an update from the front:

Zig - Let's me stick a method in my struct for good namespacing and basic objects. But, it lacks a for loop. Yup. It has the keyword, but it only performs foreach type looping with really, really poor semantics. 99+% of my for loops are integer array indices! Just a "for i in [0..10]" type will do. Instead, you have to use "while", which exposes your index to the larger namespace, unnecessarily, and splits the logic into 3 separate locations. Barf...

Jai, Odin - won't let me stick a method in my struct, namespacing only by packaging (i.e. breaking out my code into tons of little files.) Got rid of headers--finally!--but still stuck with hundreds of files to open in parallel... Barf....

Still waiting for a new language to take on C++. They are all soooo close, but all fail due to being hoisted by their own petards. They say they want to make programming fun again, but then throw away the very basic tools needed to be expressive.

In regards to objects, I don't necessarily need interfaces and inheritance, or even polymorphism, but I have many use cases where a struct with one or two methods makes for simpler, more elegant and readable code. Longer method names and manually passing around the implicit struct pointer is just tedious.

Are there any other languages that I'm missing here that I should be seriously considering?
I started on Logic 5 with a PowerBook G4 550Mhz. I now have a MacBook Air M1 and it's ~165x faster! So, why is my music not proportionally better? :(

Post

Z1202 wrote: Fri Mar 19, 2021 11:17 am As for the template metaprogramming, I agree, it's a nightmare to debug, but actually I'm missing anything of similar power in Rust. I'd rather have it than not. Error messages depend on the compiler and become better.
Hmmm.. this is an interesting take.

I think one would be hard pressed to find examples of things that can be made with C++ template meta programming that can't be done with Rust macros. Anyway, for the most common template use-case, parametric types, Rust has C#/Java style generics anyway.

Rust macros are essentially there to cover both template and #define use-cases, or Ruby meta proggamming use-cases, or whatever macro thing some language offers, but in a hygienic, less footguns than if you do it with string preprocessing way. They're generally inspired more by Lisp macros than anything from Algol lineage so that's why they might seem odd.

That said, as with all types of meta programming Rust macros also cause hard to debug error reporting :hihi:

Still, look at https://rocket.rs/

That's entire HTTP serving and parsing semantics wrapped for you in a simple to use and reason about macro. In a use case like this, where you as the customer-developer don't really need to have any idea what the hell that thing is doing under the hood, they're a blessing -- until there's bugs in the macros themselves :D

Rust is already huge in where it started from - lower-level web development. It's used all over the place by cloud providers (most notably Amazon, but Azure and GCP also have tons of stuff written in Rust) and that's the niche they have targeted well. I'd argue a language widely used and evangelized by Microsoft, Google, Amazon and used as a major source of inspiration for current development of Swift by Apple is already mainstream. I don't think it's really a good match for the requirements of plugin developers apart from UI programming -- as the functional leanings of the language are a great match for Elm-style UI dev paradigm like this https://github.com/antoyo/relm but there aren't as many UI libs for Rust that are compact in runtime and convenient in development enough for the needs of plugin devs IMO.

A lot of Rust evangelists are really an obnoxious bunch which puts a lot of people off, but I'd take it over C++, or conversely Go and C, in web and distributed services/systems development anyday.

Post

syntonica wrote: Tue May 18, 2021 8:25 pm One language I haven't seen mentioned here yet is Pony:
https://www.ponylang.io/
It has a very interesting concurrency model that would solve scads of DSP vs editor issues with inter-communication and it would be interesting to see if could be adapted to real-time DSP processing.

Along with Nim and Zig, it's another language for me to keep an eye on.
Interesting. However, it has become a bit confusing to decide what to follow, since there are so many similar alternatives, and I don't understand how different languages differentiate themselves.

I've thought that Nim is the most potential general language, while Zig is possibly the most promising C/C++ extension language (essentially, for modernizing C/C++, while still keeping their libraries). On a quick look, Pony seemed like it could be "Haskell for the masses" and "the contemporary Smalltalk". I am not sure, how it'll differentiate from Nim.

Post

soundmodel wrote: Tue Mar 08, 2022 12:26 pm
syntonica wrote: Tue May 18, 2021 8:25 pm One language I haven't seen mentioned here yet is Pony:
https://www.ponylang.io/
It has a very interesting concurrency model that would solve scads of DSP vs editor issues with inter-communication and it would be interesting to see if could be adapted to real-time DSP processing.

Along with Nim and Zig, it's another language for me to keep an eye on.
Interesting. However, it has become a bit confusing to decide what to follow, since there are so many similar alternatives, and I don't understand how different languages differentiate themselves.

I've thought that Nim is the most potential general language, while Zig is possibly the most promising C/C++ extension language (essentially, for modernizing C/C++, while still keeping their libraries). On a quick look, Pony seemed like it could be "Haskell for the masses" and "the contemporary Smalltalk". I am not sure, how it'll differentiate from Nim.
I do like the looks of Zig, but the lack of a basic indexed for loop is truly a WTF. I don't see that being remedied at this point. I'd like to see Pony's concurrency model used in a more low-level type language as it seems more on the level of Go. I think it's better than co-routines.

It is confusing, especially when each programmer has their own shopping list of features they want. I need/want all the basic features so I'm not doing too much boilerplate and can express myself easily and fluently. I don't need Draconian safety features getting in my way. I like programming dangerously! 8)

Language designers, even when they say they aren't tackling the "big issues" really are. They're just not seeing the forest for the trees. I see all these different designs being put out there and I'm hoping that some of the good ones bubble up and get some traction.

My "big issue" seems to be not using "let" as a keyword. I'm looking at you, Rust and Swift! It's a semantically empty token and it takes me back to TRS-80 BASIC. Level I! :lol: Both languages seem to be overly complex, otherwise, for the sake of complexity.

I'm not sure what the hubbub over Haskell is all about. My coworker was raving about how great it was, so I looked at it. It was LISP. Well, with lazy eval, so Scheme, if I remember my Lispoids properly. I didn't see anything new or exciting about it.

Nim seems to be a very good choice over C(C++/etc. but for some reason, I just can't warm up to it. It might be it choice of significant whitespace over brackets, like Python. It just feels too constricting to me. Yeah, it sounds petty. :lol:

Anyway, I've sort of given up on finding a new language. I'm just going to write a transpiler that right's C's wrongs (in my eyes) and will let me code how *I* want and not how someone else dictates. I'm going to add methods to structs with UFCS, which is a lot cleaner and more elegant to me. No vtables, though. I'll unwind variable declarations and do away with headers. Some fat pointers and some memory management options to top it off. It's currently in design phase as I make my ultimate feature list.
I started on Logic 5 with a PowerBook G4 550Mhz. I now have a MacBook Air M1 and it's ~165x faster! So, why is my music not proportionally better? :(

Post

syntonica wrote: Wed Mar 09, 2022 12:37 am [...] the lack of a basic indexed for loop
Not knowing this specific language, but it's usually there. But not as you know it. Eg pseudo-code:

Code: Select all

forEach (i in Integers:list(1, 10) ) {
   ...
}
We are the KVR collective. Resistance is futile. You will be assimilated. Image
My MusicCalc is served over https!!

Post

syntonica wrote: Wed Mar 09, 2022 12:37 am I'm not sure what the hubbub over Haskell is all about. My coworker was raving about how great it was, so I looked at it. It was LISP. Well, with lazy eval, so Scheme, if I remember my Lispoids properly. I didn't see anything new or exciting about it.
Disclaimer: I am not a Haskell programmer, but I'm just a programming language nerd.

In super-simplified sense, if you take Lisp and add guaranteed tail-call elimination, you get Scheme. If you then take Scheme and add infix-syntax and static type-system with Hindley–Milner inference, you get the ML-family of language (eg. SML/NJ, Ocaml). If you then take the ML family and add referential transparency and lazy evaluation, you get Haskell.

It is really the referential transparency that is important and it means that an expression and a value are equivalent and this is what enables lazy evaluation to work, because when the expression and the value are equivalent, it no longer matters when an expression is evaluated, hence it can be evaluated when (and if) the actual value is needed.

In order to have a referentially transparent language though, you have to completely eliminate side-effects from the language. You can't have variable assignments, you can't functions that read/write some files, because these things depend on the time at which they are evaluated.

Haskell solves this in an elegant way (and again, this is kinda simplified): rather than treating side-effects as operations in the language, make them a type (kinda) and then evaluate the value of this type by performing the operations. The trick here is that the monadic "bind" operation allows one to construct this in a way that forces the desired order of evaluation where it matters and only where it matters. If a function does not have an IO type, then it does not perform IO and we need not worry about side-effects. So at the end of it all, literally every function in Haskell can be a pure "mathematical" function (no side-effect of any kind), but you still have a "practical" language that can actually do things in a reasonable way. I believe this is the main reason some people love it so much.

Post

Haskell was always intended as a vehicle for researching the design and implementation of programming languages. It was critically important to the development of features that have appeared in "mainstream" languages (like JS, C#, and Python) and even some of the design decisions that are core to languages like Rust. In this sense, it was worth all the hype, and it has already paid off handsomely. But outside the niche of programming language development, it doesn't have much to offer that isn't done better by some other language in 2022.
I hate signatures too.

Post

koalaboy wrote: Tue Jun 22, 2021 9:12 am
Super Piano Hater 64 wrote: Tue May 18, 2021 12:29 am If your code is strictly and reliably single-threaded, don't use Rust. Many of the safety features are specifically designed around the hazards of concurrent code.
Whilst I would agree (as a Rust user) with most of what you posted, the above makes little sense. Much of the benefits of Rust are from the borrow-checker ensuring safe memory access - sure that's helpful in concurrent situations but it also ensure a lot more safety (and thought) around single-threaded/non-concurrent code.

The overall memory-safety is (IMHO) the biggest value proposition. As to whether it's really 'ready' for mainstream plugin development yet - I'm not sure, but without people starting to use it, the problems will never be uncovered and therefore addressed.
I somehow missed this reply before, so this is somewhat belated. Even so, I should come clean about that particular comment of mine: It was kind of sarcastic. Code that runs in an environment where there's absolutely no concurrency happening is vanishingly rare. Even if your program itself is nominally single-threaded, it's possible for system calls and interrupts to twist it into a pretzel until it explodes.

I've seen so many C and C++ veterans step on concurrency rakes where the equivalent Rust would not have compiled. Plugin developers are no exception, especially now that there's a rush to port everything to VST3. C and C++ culture emphasizes having a complete mental model of the entire program so you know by heart what operations are legal (or required) in what situations. That's a ridiculous demand on anyone writing any kind of plugin, let alone someone dealing with a messy, under-documented API that's interpreted differently by every single host.

Rust has problems, but I think the level of sanity it brings to concurrent code is the single biggest feature that sets it apart from other modern languages, which mostly just shake their heads and look the other way. The developer of one such language even claims that concurrency itself is inherently bad, and his preferred solution is to just avoid it. In the 21st century, that simply isn't the reality we live in. Any programming language seeking long term success has to deal with concurrency head-on and adopt a reliable solution.
I hate signatures too.

Post

mystran wrote: Wed Mar 09, 2022 7:05 pm
syntonica wrote: Wed Mar 09, 2022 12:37 am I'm not sure what the hubbub over Haskell is all about. My coworker was raving about how great it was, so I looked at it. It was LISP. Well, with lazy eval, so Scheme, if I remember my Lispoids properly. I didn't see anything new or exciting about it.
Disclaimer: I am not a Haskell programmer, but I'm just a programming language nerd.

In super-simplified sense, if you take Lisp and add guaranteed tail-call elimination, you get Scheme. If you then take Scheme and add infix-syntax and static type-system with Hindley–Milner inference, you get the ML-family of language (eg. SML/NJ, Ocaml). If you then take the ML family and add referential transparency and lazy evaluation, you get Haskell.

It is really the referential transparency that is important and it means that an expression and a value are equivalent and this is what enables lazy evaluation to work, because when the expression and the value are equivalent, it no longer matters when an expression is evaluated, hence it can be evaluated when (and if) the actual value is needed.

In order to have a referentially transparent language though, you have to completely eliminate side-effects from the language. You can't have variable assignments, you can't functions that read/write some files, because these things depend on the time at which they are evaluated.

Haskell solves this in an elegant way (and again, this is kinda simplified): rather than treating side-effects as operations in the language, make them a type (kinda) and then evaluate the value of this type by performing the operations. The trick here is that the monadic "bind" operation allows one to construct this in a way that forces the desired order of evaluation where it matters and only where it matters. If a function does not have an IO type, then it does not perform IO and we need not worry about side-effects. So at the end of it all, literally every function in Haskell can be a pure "mathematical" function (no side-effect of any kind), but you still have a "practical" language that can actually do things in a reasonable way. I believe this is the main reason some people love it so much.
Thanks for the lengthy explanation. I guess I tend to conflate tail-call optimization with lazy eval. However, none of this particularly excites me. Do I need to turn my programming language nerd card in? :lol:

I've never been interested in Lisp or Prolog or their families. I don't want to define functions and politely ask for results, I want to just tell the computer what to do. It's probably the 8/16-bit in me.

I like side effects. That said, I prefer *my* side effects rather than guessing what they are in *somebody else's* code. I finally gave up on Java for general purpose/cross-platform. Not only is it inconsistent, it's inconsistently inconsistent. Thus, my search for a decent replacement, preferably something that isn't class mad with a taxonomy that looks like intertwined vines. Since that search has been fruitless so far, I've decided to go it alone...

One project I should mention is nappgui.com. Although I don't like some of the choices the author made, it's mostly complete and viable. I hope to end up with something similar when I am done, but not locked in to the quirks of C.
I started on Logic 5 with a PowerBook G4 550Mhz. I now have a MacBook Air M1 and it's ~165x faster! So, why is my music not proportionally better? :(

Post

BertKoor wrote: Wed Mar 09, 2022 5:49 pm
syntonica wrote: Wed Mar 09, 2022 12:37 am [...] the lack of a basic indexed for loop
Not knowing this specific language, but it's usually there. But not as you know it. Eg pseudo-code:

Code: Select all

forEach (i in Integers:list(1, 10) ) {
   ...
}
It sort of is, but it's still based on iterating over an array, or a slice of an array. You can acquire the value and index as named variables, but the syntax is very clumsy, and not quite elegant.

I have multiple instances of needing to directly index or derive indices for 6 different arrays. Using "for index in [0..1023] {}" is far simpler than "for (array1[0..1023]) |_, index| {}" where the underscore is the unused value. (I believe that's how it works, but it's a weird indirection.)

I have concerns over optimization as well, that are probably unfounded. But...
I started on Logic 5 with a PowerBook G4 550Mhz. I now have a MacBook Air M1 and it's ~165x faster! So, why is my music not proportionally better? :(

Post

Haskell is a great language to talk about. For actual coding there are better languages available. :D

Post

True that.
Haskell Fanboy wrote: Monad
Image
Here's a talk titled "Never change state & still get things done". It does your mind in, which is not a bonus while writing or reading code.

https://www.youtube.com/watch?v=69dDHea4A4o
We are the KVR collective. Resistance is futile. You will be assimilated. Image
My MusicCalc is served over https!!

Post

Jai seems like an interesting language (developed for video games development).

There was a language developed a few years by a DSP developer specifically for the sorts of optimisations DSP and games developers would need to make, but I can't recall what it was called.

But there are quite a few languages fitting that description now, and then you've got Carbon from Google, which could give us exactly what we want if they can pull it off.

Post Reply

Return to “DSP and Plugin Development”