Blog and Conversation of FP/OCaml/Elixir/Scala

They already exist. ^.^

1 Like

Or, you mean Vex? I’m thinking about something that feels more like language extension. Flow for Elixir but with capabilities of Ecto validations/changesets :slight_smile:

2 Likes

You should make it then! :slight_smile:

No promises, but something I hope to look into :slight_smile:

2 Likes

@OvermindDL1 After reading everything here, I have to wonder:

What do you use OCaml for mostly? I quite frankly struggle to take a language seriously if it cannot execute multi-core code. But you are right that if you want something done quickly on a single-core with less fuss then a strongly typed static language is the way to go.

Can you give a few examples about what you use such languages (like OCaml) for?

Question also goes to @lakret and everybody else having insights to share.

I know Golang and want to learn more but to be fair the Context thing and the fact that many complain that you essentially have to pass void* left and right if you don’t want to work on a 1-day task for weeks is discouraging me. Still, I know people using it successfully and they don’t complain (maybe I should go grab a beer with them and ask them the same questions).

I am looking for a language to replace C/C++ with and the choice pool is so big lately that I started despairing – I don’t have so much time to evaluate them all! Rust, Go, Nim, D, Haskell and even Pony… and I heard about more of them, OCaml included.

As a criteria, I am not as liberal as yourself that we must always use C bindings when we have them; then why learn any strongly typed static language at all? Let’s just use Python! The damn thing has bindings for a heckton of stuff. So from my side I’d look for a language that has rich stdlib and I think Go is still unsurpassed in this regard. Not to mention that many C libraries probably have never been tested with fuzzing and have lingering buffer overflows / underflows just waiting for the perfect zero-day. No thanks. I prefer languages that protect me from such mistakes. Hence me and many people prefer languages that give us a lot out of the box.

What do you think?

2 Likes

I haven’t had much chance to use OCaml specifically in production. No support for multi-core and absence of libraries (not counting C libs through FFI, since also not an option for me) were barriers for me as well. I hope to use it for the frontend work with BuckleScript/Reason, though. I also expect OCaml community to grow in the next couple of years, so hopefully we’ll see some improvement in useability for backend workloads as well (though I’m betting on Elixir for it right now).

At the same time, it’s not correct to tell that OCaml is not used in industry - it’s a language people tend to use when they write compilers, so a lot of both general purpose and experimental languages were written originally in OCaml. Rust before bootstrap, Flow, Coq, … It seems to be the best tool for the job as well.

I used quite a lot of F#, which is an OCaml dialect targeting .Net. My experience with it was quite good. Though F# misses OCaml’s excellent module system, it does have something to offer that OCaml doesn’t: multi-core support, mature ecosystem, etc. Sadly, the community seems to be in decline now…

Scala is still the safest bet in statically-typed functional languages land. It’s also the language that I used the most in production. Akka is not quite as good as OTP is, but it’s still decent. Spark, Play, etc. are all widely used. Performance is quite good if you master dark arts of JVM tuning :smile: On the downside, the language is uglier and less consistent than pretty much any other statically-typed functional language we’ve discussed in this thread.

For C/C++ replacement, I think Rust is the best option, esp. long term. Community is growing, language is improving, there are already quite a lot of libraries, and I like the linear type system (all this borrowing-ownership stuff). I used it for some smaller script-like jobs, and it was quite pleasant. Go is just too verbose for me.

3 Likes

Thank you. I will have to give Rust a weekend in the next few months for sure. I quite like Go’s [mostly] mature approach and rich stdlib but if I am gonna have to give up strong type guarantees for productivity then why not just use Elixir? So if Go requires compromises for productivity it becomes kind of a moot point to use it.

Reading through your message, I’d definitely learn OCaml as well (and have @OvermindDL1 help me occasionally if he’s willing) and try to reach a productive level with Rust.

As for the JVM, learning to fine-tune it is a necessary evil at this point IMO. Whether we like Oracle or not (and Sun before it) the JVM remains one of the best pieces of software written in the modern history. But I am more looking to learn Clojure and not Scala. Any other strongly typed languages targetting the JVM? (For .NET you said F# but also said the community is in decline.)

To recap, I’d want to learn these:

  • Rust (supposedly because it has a strict type system and is less verbose than Go?)
  • OCaml because so many people recommend it (not sure that’s a valid reason but I got kind of intrigued).
  • Clojure due to a huge untapped potential to consult for Java / .NET shops that need extensions or repairs of big legacy systems.
1 Like

Clojure is an excellent language, but sadly, had no luck using it - startup times just kill it for me. Also, it seems to be unnecessarily slow. However, there definetely are people who use it in production and most of them seem to be quite happy (one example). At the same time, I wouldn’t go Clojure way in hopes to land a job in JVM shop, for example. Scala is much, much more popular + it has better distributed systems development support.

Main Rust advantage is prevention of data races and memory leaks via type system. + it has lots of functional goodies in it. Do expect some headache initially, though :smile:

OCaml is good to learn even if you would never use it in production: ideas and techniques that you’ll learn there will be helpful in many other languages + even JavaScript now takes cues from it :slight_smile:

1 Like

I agree Clojure’s startup time is a huge turn-off but I heard there are workarounds (haven’t tried any of them yet). Plus never tried it under .NET, things might be better there? No idea yet.

As for consulting, yeah I agree – I don’t want to learn it because it will positively bring me income (it will most likely not) but mostly to have a few more doors open. :slight_smile:

So Rust is imperative + functional? If that’s the case, I’d dislike it.

As for OCaml, agreed – not all knowledge should be directly applicable to business and some of these languages improve you as a professional. True.

1 Like

‘Mostly’ as a replacement of Python (which has the same problem). However, just like Python, you can multi-core it the same way just be making more of the processes (or just use a single process and call out to other things, which will release the GIL, just like in Python). Or you could use the current MultiCore testing OCaml version too, with the usual caveats. ^.^;

I also use it to generate javascript on the couple SPA’s that exist at work as well.

Honestly anything that Python does I see it as a better replacement (assuming libs exist that you need) at the very least. It is significantly faster and more reliable than Python. Once (whenever) Effects/MultiCore OCaml land then I could see being able to build an OTP layer on it.

I lot of people use Javascript, Java, and Cobal without complaint too. ^.^

When you have a hammer, everything looks like a nail. :slight_smile:

Depending on the specifics of what needs to be done, I’d use either OCaml or Rust personally.

Because you still ‘type’ the interfaces to the C calls, they are not untyped, which still forces you to look at how it is used and see how to call it.

If that’s an issue for you then even Go is out of the running as it uses substantial C code behind it. You’d probably be looking at Rust with as little unsafe code as possible. OCaml and Haskell could be useful there as well but they do a lot of backend binding to lower level code as well, where the Rust ecosystem seems to be highly driven to rewrite everything in Rust to removed unsafeness in everything, where most languages would generally just prefer to bind to the existing libraries (like OCaml does), as well as Rust has the community large enough to actually pull this off. However that does mean that things may not be at feature parity to a C API version (it may have less, it could even have more, but at least it is safe).

Most compilers may be written in C++ (mostly thanks to LLVM), but runner up is easily OCaml, and the ones written in OCaml run circles in speed around compilers built in C/C++, not because OCaml is faster (it’s the same speed in general), but rather because the typing system really fantastically helps you to write ‘Good’ code at the start.

Scala is decent, I like it (better than any other JVM language), but it is indeed a bit ugly, and the community likes the Haskell’isms of operator-overloads-everywhere… ^.^;

+1

I’m not sure where getting the ‘mature’ part from? Every time I hear about it, it is heavily in flux, and they seem hostile to adding things that make it so you don’t get the Color issue (contexts) or having to essentially void* cast interfaces (yay safety goes bye bye)…

Ask away, I love helping. ^.^

Learn it for the type system, it will truly teach you how a good type system helps you to write better code. Idris is a better type system but it is a bit hell to program in, in comparison… ^.^;

+1

That’s because everything is boxed in it (at least it was when I tried binding it at one point to an existing Java backend…), even functions are boxed!

It too has a lot of haskellisms sadly, but they work well. :slight_smile:

Why is that? C++ is imperative + functional too, as is even Go to an extent. The thing is that Rust scopes all access to imperative constructs, so you have no worry about screwing things up with how they are accessed like you would in C/C++/Go/Etc…, that is where it truly shines.

3 Likes

Can you elaborate? I was under the impression that most of Go’s stdlib is written in Go itself and compiled on the spot. If they make extensive use of C bindings themselves than I might as well just go code in Pony which compiles to native code, has zero-copy message passing mechanism and tries to emulate the OTP (although I am not sure how far they got, the language is pretty new but looks promising).

This is by far my only, but very big, gripe with Rust. The unsafe construct is basically a pleasure room and an escape hatch for all former C and C++ elitists who scream “I know exactly what I am doing, I am a pro!” in any forum they have access to. Our profession has suffered enough elitists. I want a language with ZERO unsafe constructs. No buts, no “however”-s. Just NO. No you don’t know what you’re doing, you’re a flawed human being. I am strongly irritated by technology authors who fail to finally admit we’re all flawed and we all make mistakes. That takes some emotional maturity that I feel too many of us the devs lack. We’re as naive a cocker-spaniel pups, honestly. It’s not doing us any favours. :expressionless:

And that’s why I am very hesitant in picking up Rust; even if I apply 100% cold and effective discipline I have zero guarantees that the devs of the dependencies I use have this discipline. And it becomes the C crapfest all over again but in a new clothing.

By “mature” I mostly mean they are heavily dogfooding themselves (see above, I thought Go’s stdlib is almost entirely written in Go?) and they try to contain the most commonly known and universally agreed upon libs (HTTP, JSON, ASN.1 etc.) inside their garden – no 3rd party dependencies. To me that’s mature – taking control and not applying wishful thinking that maybe THIS time the always-wrong C devs got things perfectly right. Know what I mean? I am tired of people making believe they can’t be wrong.

As for Context and passing interface{} / void* everywhere, I am in full agreement with you! Go’s team announced a while ago that they thought shoving Context everywhere was a mistake and they are working to reverse part of that – was a pretty vague statement, was posted in HN some months ago and I quite frankly didn’t understand most of it… but I am hopeful they will come around. There are some very disciplined and strong programmers behind Go’s development. They can still pull through. To me their general approach is good but they have some details to work out.

One thing that’s a big turn-off however is that they are pretty deep in their current type system and I am not seeing them revisiting that, ever. So not sure if the void* problem is gonna be fixed anytime soon. :frowning:

I realize that and I am sad about it. I’d like a language that gives you less freedom, like Elixir – it’s basically 99% immutable and side-effect free, with touch of these exactly where you need them. You have to make a conscious effort to have those which to me means you’ll think hard before using them (not a guarantee though, just a gentle push to behave? :smiley:) and hopefully that improves the overall code quality of everyone.

Having languages with too much freedom IMO historically has netted almost zero benefits, in most of the commercial programming anyway (obviously I am not including the kernel and several very ambitious and hard projects; people there need all the freedom they can get).

So again, I am looking for a strongly typed compiled language, but that language must also not allow you to shoot yourself in the foot. Not sure if that exists as of today. Maybe Pony?

1 Like

Unsure about the stdlib but I know a lot of libraries use C libraries, and even go itself uses a C event poller last I checked.

I keep intending to look in to Pony, it’s on my list. ^.^;

Except that having unsafe in a library means that you know who to yell at and where, rust should never fault except in unsafe’s, and unsafe’s allow the language to do anything, thus not needing to bind to some lower level C libraries or so like almost every other language eventually has to. ^.^

But still, unsafe's are actually used quite sparingly, people get yelled at otherwise, the community hates unsafe usage. :slight_smile:

Still though, you need something like that to be able to implement low level construct. Like look at Rusts stdlib, look at, oh, Arc<...>, it uses unsafe code internally, but it is highly tested and very well confirmed as safe, but that unsafe code is absolutely necessary, you would not be able to implement something like Arc<...> in Rust (or even many other languages), and now it can be used in safe code all over the place without them needing to touch unsafe.

Really though, don’t worry about it, the community really really dislikes the use of unsafe. :wink:

Yeah, especially outlawing generics because they are ‘hard to reason about for users’, like what on earth! Do they really think programmers are that stupid?!

That’s why I like both OCaml and Rust, they are both ‘default safe’ and they both do have escape hatches that allow you to do ‘anything’, but using those escape hatches requires extra work that makes it far more difficult to use than just doing it ‘right’ from the beginning. Compare that to Go where passing void* interfaces is so easy that everyone does it, because doing the right thing (copy/pasting hundreds of times) is an unholyhugepain.

There are kernels built in both OCaml and Rust (dang fast and safe too! fantastic for microcontrollers!). There is not (nor do I think there ever will be) a kernel built in Go. :wink:

Maybe pony, but honestly I prefer languages like OCaml and Rust, where they are safe by default and they encourage doing things right via the easy path, but they have a hard path to break out of it if you really need to, which I need to due to language issues far more often than I’d prefer (not really in OCaml or Rust though, I only really need to break them if I need to perform some major optimizations, which I try to minimize anyway).

3 Likes

Sounds good but can you add some logging prefix specifically for every unsafe block for example? So you know exactly where the unsafe code broke? I mean, what kind of error pinpointing mechanisms you have in Rust regarding the unsafe blocks?

Corporate teams that are fully isolated from the healthy practices of a community and are just copy-pasting their way to the next paycheck haven’t been known to adhere to those practices though. There exists no language whose awesomeness cannot be corrupted by unmotivated idiots. I have already seen several pretty crappy Elixir projects myself. Truth is, bad coders can produce bad code in any language.

BTW, can you give me a few examples or point me to an article? I’d really like to see this problem in action. I wrote 15+ microservices in Go but none of them exceeded 2000 lines of code so I didn’t stumble upon this problem. Guess it rears its head when your project grows a bit?


All of the rest of what you said I fully agree with. You convinced me. :stuck_out_tongue: I’ll definitely code my next microservice in Rust and OCaml and Go and see how well they do. Or I might just rewrite some of my older ones I keep around for educational purposes.

1 Like

Probably some way, a macro or something, but thus far I’ve managed to avoid unsafe code in my rust code so I can’t say. ^.^;

Happens everywhere, I’m sure someone somewhere is even using the oop library in elixir unironically… ^.^;

It rears its head more when you are writing libaries rather than applications.

Like say you are writing a library that, oh, makes packed arrays of integers or something. Well, what integer should it be? Probably support all of them of course. In almost any language this is pretty easy to support, but in Go you need a unique implementation for every-single-integer-size, everything about each one can be absolutely identical in every way except the initial integer type it takes. Things like that.

Plenty of googling about it, here’s the first result I got:
https://medium.com/@ivanjaros/less-is-more-in-go-but-you-write-more-code-anyway-75fa0afcccd0

Definitely blog that and post it here, I’d love to read it! :slight_smile:

If you have questions about OCaml (design, code, whatever) then I can definitely answer it.
If about Rust then I ‘might’ be able to answer it (still learning, but I think I have it mostly down pretty well now, enough to be functional without having manuals up all the time at least).
If about Go, err, good luck? ^.^;

3 Likes

Sigh. I really do like Go’s concurrency though. How is Rust in this front? Any actor model library? Or is it plain old threads?

(OCaml you said is single-core for now, save for a beta-level library.)

It has libraries for everything from very safe threads to multiple actor libraries and about everything in between (transactional memory, etc… etc…). There is an RFC in dev right now to potentially add coroutines to Rust as well, so with those things like actor’s will become even more simple!

Well, OCaml is not single-core technically, it has a GIL, like Python, so OCaml code uses a lock to ensure that OCaml code is only executed on one core at a time, but calling out to C or so allows for full parallelization, just like in Python. I.E. if you are comfortable with Python threading, then OCaml’s is identical (so calling libraries releases the GIL, you can start multiple communicating processes, etc… etc…). In effect OCaml works on multiple cores fairly decently as long as you are doing IO work or calling foreign functions or so at any time. It’s just not to the sheer scale that the BEAM or so can do. :slight_smile:

2 Likes

My personal experience… As a novice to functional programming, I found the Eilxir language pretty easy to follow. But as I started learning more about functional programming in general it seemed to me that you could never really write and use the proper abstractions without type information.

I feel that learning FP in a typed language like oCaml or Haskell would help me write better code if / when I move back to Elixir. I’m still early on that plan. I’ve been using Reason as a way to learn, and I find the type system difficult at times I think because it’s my first use of a strongly typed language.

2 Likes

If you have questions or need help, feel free to ask! :slight_smile:

Oh, I cannot disagree more! This is exactly the way of thinking that a lot of bad managers has. I’d rather use sharp knives.

It doesn’t mean that people don’t make mistakes; it’s just in those 5% of cases you really need those unsafes/macros/monkey patching. Languages/tools without escape hatches are usually unusable in practice. Look at Haskell, this approach (always safe) is terrible in practice. Erlang has process dictionaries and ETS — using it without them would’ve been tricky as hell. And yeah, if it supported local mutability, we could’ve had Spark on BEAM — and it’s bad that we don’t.

I don’t believe that this is the case. Typing is an additional cherry on the cake. I’d suggest checking SICP out. Things like higher-order functions, continuations, recursion schemes are the same and basis for both typed and untyped languages.

However, you are correct assuming that typed FP structures your thinking; OCaml is an excellent choice! Even though you’re using Reason, I’d still suggest reading Real World OCaml, the book is superb.

And, if you have any questions about both typed and untyped functional languages, don’t hesitate to ask — I’d also try to help! :slight_smile:

1 Like

If you wan’t higher level concurrency https://github.com/rust-unofficial/awesome-rust#concurrency

2 Likes