24 ms·
When I first learned OCaml (knowing only Python), I swore a lot at the type checker for refusing to compile code that I knew would work at run-time (e.g., a var
by gnuvince 10y ago
When I first learned OCaml (knowing only Python), I swore a lot at the type checker for refusing to compile code that I knew would work at run-time (e.g., a variable having multiple types, but on strictly disjoint execution paths). It seemed insane to me that people would want to subject themselves to this kind of bondage and discipline. And yet, many years later now, I have learned and internalized how type systems work, I have learned not to try and simply replicate Python patterns in OCaml, and as a result I use OCaml to write code quickly and without any headaches; and not only is the type checker no longer an obstacle, it's now a valuable assistant.
I believe that we are seeing the same kind of phenomenon in Rust: we are trying to replicate C or C++ code directly in Rust, and we get frustrated when our efforts are foiled by the borrow checker. It's going to take some time and some efforts before we learn and internalize how borrowing works in Rust and how to change the way we write programs so that it is no longer an obstacle. The Rust team looks very receptive to comments about taking away some pain points (e.g., non-lexical lifetimes), but we also need to accept that, for a little while, we are going to feel like we did when we were new programmers and were trying to make sense of these new constraints.
- tejinderss 10y agoNot related to the topic but how do you find ocaml as compared to python or rust? Do you think its worth learning today as opposed to rust for high level general purpose programming?
- njs12345 10y agoIt occupies a slightly different niche to Rust as it has a GC. If you can live with that, it's probably going to be more productive than Rust for you. It's definitely worth playing around with a language from that family. OCaml is maybe slightly more practical than Haskell and it has some nice resources available - in particular Real World OCaml looks really good: https://realworldocaml.org/ https://realworldocaml.org/
- lmm 10y agoIt is well worth learning an ML-family language. In addition to Rust, OCaml or Haskell as njs12345 mentioned, F# or Scala might be options. OCaml is probably more mature than Rust, has more libraries available, and has automatic memory management which takes some of the load off you (especially if you're writing a GUI application, IME). But it's not got Rust's "hot right now" factor, it doesn't have Rust's ease of embedding in other languages, and it doesn't have quite the same focus on high-quality documentation. If you already know Rust I wouldn't bother learning both - they're very similar languages.
- krat0sprakhar 10y agoAbsolutely! If you're looking for fast, GC'd, native functional language I'd say OCaml is a great option. There's actually a very comprehensive set of blog posts migrating an open-source python based project to OCaml, that I'd recommend reading if you're looking for a more thorough comparison - http://roscidus.com/blog/blog/2014/06/06/python-to-ocaml-retrospective/ http://roscidus.com/blog/blog/2014/06/06/python-to-ocaml-ret... Personally, I used OCaml while at university to write a programming language (http://jsjs-lang.org http://jsjs-lang.org) and totally loved it. Real world OCaml is a great resource and I'd definitely recommend giving OCaml a try. My only regret is that I don't get to write OCaml as much as I want to due to the kind of projects I work on, but given that Bucklescript[0] and Reason[1] are moving ahead in full steam, that might change shortly too :) [0]- https://bloomberg.github.io/bucklescript/ https://bloomberg.github.io/bucklescript/ [1] - https://facebook.github.io/reason/ https://facebook.github.io/reason/
- jackmott 10y agoIt is worth looking at F# as well, which is basically OCaml on the .NET platform. With the advantages of having the entire .NET ecosystem of libraries available for use, being able to use more than one core of your cpu, a solid IDE, and some other features like type providers. There are some disadvantages as well, such as not being able to compile to a native executable. Anyway the syntax is so similar you can learn one and switch to the other with very little pain.
- nickpsecurity 10y agoI'll also add to their recommendations that GC'd languages can be used for OS's or system code. You can do that with a number of strategies: 1. Go unsafe on lowest-level operations that simply can't be GC'd. Quite a few of these can be expressed as finite, state machines which can be model-checked for correctness. Static analyzers are also really good these days in whatever code you can avoid dynamic allocation in. The rest of the code is GC'd. That's what the Oberon operating systems do. 2. Use a real-time, low-latency, concurrent GC that basically knocks low single or two digit performance out of the system. Lots of products in embedded Java have special GC's for that. Buy a faster CPU. Trade dollars or performance for productivity and safety. 3. Use a mix of GC's in the system where each one is tuned for the job at hand. You might use a real-time, concurrent one in the kernel. Maybe just reference counting in one more about performance. Maybe a straight-forward one for stuff that's not performance-critical. Could even use one that's mathematically verified for correctness in that situation. JX Operating System is an example of OS that mixes up GC strategies. That's for software. Your options open up a bit if you can also deploy custom hardware. At the least, a modified soft-core on an FPGA. The LISP machines & maybe a Java CPU of the past often included hardware acceleration for garbage collection. One built the GC right into memory subsystem/interface of the processor where neither the processor nor applications had to be aware of its existence. It just did its thing in parallel to execution of the app. A concurrent, low-latency one integrated with virtual, memory hardware shouldn't take much hardware resources to pull off.
- jnbiche 10y ago> I believe that we are seeing the same kind of phenomenon in Rust: I don't know. I picked up OCaml fairly quickly, but I have consistently struggled with Rust, trying it for a while before abandoning it in frustration with lifetimes, 2 or 3 times. I can program in Rust, but it still seems like an ongoing struggle, as opposed to the smooth brain to text programming I've gotten used to in Python, JavaScript, OCaml, and Lua, and to a lesser extend C, Go and Elixir (just because I haven't used to latter 3 as much, at least recently). I think Rust may be ideal for embedded software development, or low-level systems software, but for general application development, I think OCaml or perhaps Swift or Scala are more ideal, at least for me (or at least until I decide to try Rust again, perhaps it will stick this time). Edit: Oh yeah, and I was even able to become productive enough in Scala to build a significant project (a programming language) in a relatively short period of time. Now, I'm not silly enough to think I've really mastered Scala in such a short period of time, but I was using it productively as a functional language as I would OCaml with little difficulty. On the other hand, I've started 3 (3!) programming languages in Rust but have yet to get beyond much beyond the parser/AST stage before I quit in frustration.
- smt88 10y ago> smooth brain to text programming This isn't a good thing, in my opinion. Brains make mistakes. I don't want smooth, uninterrupted coding. I want the compiler to tell me when I'm making the mistake, even if it makes things choppier. It's a lot less painful to write code in fits and starts than to write a million tests or spend hours debugging.
- jnbiche 10y ago> I want the compiler to tell me when I'm making the mistake, even if it makes things choppier. You don't think the OCaml type system would do this? OCaml gives you just as much safety as Rust does, it just doesn't also give you no GC like Rust does. And the price Rust pays for the absence of GC is the lifetime concept, which adds a very significant layer of complexity to the language. Much like OCaml, Swift and Scala also provide very safe type systems. Again, if you can't have a GC, then Rust is an excellent option, and the only really safe GC-less language unless you use C with FramaC or similar static analysis (and FramaC also requires lots of training and time to use, just like Rust).
- rbehrends 10y agoThis is a different issue. The problem that the author is observing is that Rust operates on the hypothesis that the ownership relation is mostly left-unique and acyclic and that you run into problems when this hypothesis doesn't hold. And this affects not only explicit data structures, but also the implicit structures that involve stack frames (local variables, closures, etc.). While Rust has mechanisms to deal with this (copying, Rc<T>, etc.), all these mechanisms add pain points, and for problems that are not just theoretical. It affects a number of design patterns, closures that survive the scope they were created in, functional-style programming, functional data structures, any data structure that naturally involves a DAG or cycles. The difference compared to a (good) static type system is that a good [1] static type system does not measurably reduce expressiveness; Rust's ownership model does. This is not to say that there isn't a point to Rust's model. Rust directly competes with garbage collection as the main alternative model to achieve memory safety and is an obvious choice in cases where garbage collection is not a realistic option. But where garbage collection is an option, the tradeoffs that Rust makes become much less attractive. [1] Obviously, primitive static type systems (example: Java up to version 1.4) do pose a problem.
- humanrebar 10y agoFirst, the expressiveness is all there. You just need to explicitly say you are responsible by using unsafe blocks. So risky pointer and allocation logic becomes the programmer's job, not the borrow checker. Second, this article only considers the costs of a stricter borrow checker, not the benefits. It will be more work for the coder to have to think about how allocation and ownership is communicates. But I've been through much bigger headaches in production code at inconvenient times (for the business plan) due to dangling pointers, multi-writer concurrency bugs, and ill-defined memory models in software designs. Even if Rust is much harder than alternatives instead of just different, and even if that's inherent in borrow checking, it's not clear that it's still not worth it in the long run.
- jackmott 10y agoIt might be worth it over C++, but assuming the task at hand is not hindered by garbage collection, is it ever worth it over an ML style language? It certainly takes a lot more typing to get things done.
- aomix 10y agoTo me it seems like Rust has an additional wrinkle with safe and unsafe code. A new Rust user needs to figure out both "How do I do this" and "Is this possible in safe code". The limits of safe code seems to be something people are figuring out at all levels. Rust projects seem to start out with a relatively high amount of unsafe code. Then as the project matures the unsafe sections are reduced or eliminated.
- maffydub 10y agoI think whether you feel you need unsafe when you first come to Rust depends on the angle from which you're coming. Coming from C/C++, I know that there are structs in memory and can visualize what they look like - surely I can just go and tweak them? (No I can't because either it wasn't safe to do that anyway, or I need to explain to the Rust compiler why it is safe, and that can be quite difficult.) Coming from something like Java, I (probably) don't think too much about what the underlying structure in memory is, so I'm less likely to try to do this. Either way, it feels like part of the learning curve is learning the "Rustic" way to do something - in general, you probably shouldn't be reaching for "unsafe" until you know what you're doing! ;)
- readittwice 10y agoI am not so sure about this, at least for Java for one simple reason: it is so easy to have back-pointers/cycles in your object graphs. In Java you don't even have to think about that. This was quite hard for me to figure out when starting with Rust.
- drbawb 10y ago>Either way, it feels like part of the learning curve is learning the "Rustic" way to do something - in general, you probably shouldn't be reaching for "unsafe" until you know what you're doing! ;) I tend to agree with this sentiment. The moment I saw that OP was doing pointer arithmetic: I knew they were in for a bad time. It's not that you can't do it -- it's moreso that Rust's raison d'etre is to highlight the flaws inherent in that approach. I hadn't thought about it, but I think you're right, my background in managed languages is probably why I didn't run into these sorts of issues until after I was already comfortable with Rust. I wasn't trying to make maximally storage-efficient collections right out of the gate, instead I was building application-level stuff on top of `std::collections`.
- eternalban 10y agoYou came from interpreted Python to compiled OCaml and I suspect that your initial encounter with a compiler is the underlying issue. (For example, being new to FP but very friendly with compilers -- C, C++, Java, C# -- I found the initial OCaml encounter surprisingly pleasant. Haskell was something else though :)) I looked at Rust specs 1.0 when they were released and immediately recognized that Rust is not a 'dating' language, but rather a very serious 'marriage' till death do us part sort of deal. (I would say the same for Haskell, & Scala.) And imho the initial promise of addressing the out of control complexity of C++ was not met. I have no doubt that Rust is a thoughtful, and powerful, language. But you have to be prepared to exchange vows at the alter.
- gcp 10y agoAnd imho the initial promise of addressing the out of control complexity of C++ was not met. I'm not sure. Type traits seem to be much more manageable than how the same thing is handled in C++ template code, no? Also, if we can bring in ecosystem effects such as cargo...
- eternalban 10y agoI guess I should have added that I last touched C++ in '96 and never (ever) have had an urge to look back. :)
- gcp 10y agoI've you've never seen template programming, but just C with classes, then yes, I can see how you arrive at this conclusion. C++ in 2017 is very different from what it was in 1996.
- eternalban 10y agoI was using STL and RTTI. I know the language has substantially improved. These days I've actually rediscovered the joy of plain C.
- 10y ago
- pmoriarty 10y agoI never got past the pain-in-the-ass stage of dealing with the OCaml compiler. I hated wrestling with it for something simple. It really slowed me down to no end. I remember asking on freenode's #ocaml for help with a convoluted error message, and when I was told what it meant and how to fix it, I asked how the person who helped me knew what it meant. He told me he'd taken two semesters of type theory courses at uni. Having to spend a year taking university-level courses in order to effectively program in OCaml seemed like way too much pain for too little gain when there were so many other less painful languages to program in. Later I discovered Lisp and then Scheme. Both were a sheer joy to use compared to OCaml. I didn't have to wrestle with the type checker, my programs were quick and easy to write and understand, and in their own way the languages were just as powerful as OCaml was. Sure, OCaml had them beat at safety (at least if you were comparing ordinary Lisps and Schemes, not statically typed versions or extensions with more safety features) but it way, way more painful and slow to program in, for me. I recognize that if you need the safety, then the pain might be worth it. But even then it might be worthwhile to program in a dynamic language like Lisp/Scheme and then once the program matures, rewrite it in a safe language like OCaml. But even then, I think I'd just rather dial up the safety features of Lisp/Scheme or use one of the static versions. That's just me. I know some people love OCaml. And I'm sure I'm missing some of its wonders that are only apparent when you dive deep enough in to the language. But from what I did learn of it, it just wasn't for me.
- sfilargi 10y agoWhat helped me when starting with OCaml is always declaring the types in the function's arguments. The compiler errors started making a lot more sense.