14 ms·
OxCaml - a set of extensions to the OCaml programming language.
- legobmw99 1y agoThe first feature that originated in this fork to be upstreamed is labeled tuples, which will be in OCaml 5.4: https://github.com/ocaml/ocaml/pull/13498 https://github.com/ocaml/ocaml/pull/13498 https://discuss.ocaml.org/t/first-alpha-release-of-ocaml-5-4-0/16722/7 https://discuss.ocaml.org/t/first-alpha-release-of-ocaml-5-4...
- debugnik 1y agoImmutable arrays were ported from this fork as well, and merged for 5.4; although with different syntax I think.
- andrepd 1y agoAnonymous labeled structs and enums are some of my top wished-for features in programming languages! For instance, in Rust you can define labelled and unlabelled (i.e. tuple) structs struct Foo(i32, i32); struct Bar{sum: i32, product: i32} But you can only e.g. return from functions an anonymous tuple, not an anonymous labelled struct fn can() -> (i32, i32) fn cant() -> {sum: i32, product: i32}
- tialaramex 1y agoHmm. Let me first check that I've understood what you care about struct First(this: i8, that: i64) struct Second(this: i8, that: i8) struct Third(that: i64, this: i8) struct Fourth(this: i8, that: i64) struct Fifth(some: i8, other: i64) You want First and Fourth as the same type, but Second and Third are different - how about Fifth? I see that this is different from Rust's existing product types, in which First and Fourth are always different types. Second though, can you give me some examples where I'd want this? I can't say I have ever wished I had this, but that might be a different experience.
- cAtte_ 1y agothey're not asking for a structural typing overhaul, just a way to make ad-hoc anonymous types with named fields and pass them around. a lot of times with tuple return types you're left wondering what that random `usize` is supposed to represent, so having names for it would be very convenient. i don't see why, under the hood, it couldn't just be implemented the exact same way as current tuple return types
- zozbot234 1y ago> they're not asking for a structural typing overhaul, just a way to make ad-hoc anonymous types with named fields and pass them around. And their point is that the two boil down to the same thing, especially in a non-trivial program. If switching field positions around changes their semantics, tuples may well the most sensible choice. As for "what that random usize is supposed to represent" that's something that can be addressed with in-code documentation, which Rust has great support for.
- tialaramex 1y agoAlso, if it's not just a "random usize" then you should use the new type paradigm. In a language like Rust that's not quite as smooth as it could possibly be, but it's transparent to the machine code. Rust's Option<OwnedFd> is the same machine code as C's int file descriptor, but the same ergonomics as a fancy Haskell type. We can't accidentally confuse "None, there isn't a file descriptor" for an actual file descriptor as we so easily could in C, nor can we mistakenly do arithmetic with file descriptors - which is nonsense but would work (hilarity ensues) in C. If these aren't "random" usizes but FileSizes or ColumnNumbers or SocketTimeouts then say so and the confusion is eliminated.
- munificent 1y agoIn Dart, we merged tuples and records into a single construct. A record can have positional fields, named fields, or both. A record type can appear anywhere a type annotation is allowed. So in Dart these are both fine: (int, int) can() => (1, 2); ({int sum, int product}) alsoCan() => (sum: 1, product: 2); (int, {int remainder}) evenThis() => (1, remainder: 2); The curly braces in the record type annotation distinguish the named fields from the positional ones. I don't love the syntax, but it's consistent with function parameter lists where the curly braces delimit the named parameters. https://dart.dev/language/records https://dart.dev/language/records
- afiori 1y agoHow do you distinguish a tuple with both positional and named fields from a tuple that has a record as a field Like how do you write the type of (1, {sum:2}) ? Is it different from (1 , sum :2)?
- munificent 1y agoThe syntax is a little funny for mostly historical reasons. The curly braces are only part of the record type syntax. There's no ambiguity there because curly braces aren't used for anything else in type annotations (well, except for named parameters inside a function type's parameter list, but that's a different part of the grammar).
- afiori 1y agoso my examples would be (1, (sum:2)) and (1, sum:2)?
- munificent 1y agoYes, exactly.
- int_19h 1y agoIt's interesting that languages which start with purely nominal structs tend to acquire some form of structurally typed records in the long run. E.g. C# has always had (nominally typed) structs, then .NET added (structurally typed) tuples, and then eventually the language added (still structurally typed) tuples with named items on top of that.
- munk-a 1y agoPHP has it all! I think the main dividing line here is whether you want to lean into strict typing or whether you prefer a more loose typing structure. The extremes of both (where, for instance, the length of an array is part of its type definition or there are not contractual guarantees about data) are both awful. I think the level of type strictness you desire as a product is probably best dictated by team and project size (which you'll note changes over the lifetime of the product) with a lack of typing making it much easier to prototype early code while extremely strict typing can serve as a strong code contract in a large codebase where no one person can still comprehend the entirety of it. It's a constant push and pull of conflicting motivations.
- aseipp 1y agoYeah, pretty excited about this one even though it seems minor. A paper and talk by the author of this particular feature from ML2024, too: - https://www.youtube.com/watch?v=WM7ZVne8eQE https://www.youtube.com/watch?v=WM7ZVne8eQE - https://tyconmismatch.com/papers/ml2024_labeled_tuples.pdf https://tyconmismatch.com/papers/ml2024_labeled_tuples.pdf
- munchler 1y ago> Because sum:int * product:int is a different type from product:int * sum:int, the use of a labeled tuple in this example prevents us from accidentally returning the pair in the wrong order, or mixing up the order of the initial values. Hmm, I think I like F#'s anonymous records better than this. For example, {| product = 6; sum = 5 |}. The order of the fields doesn't matter, since the value is not a tuple.
- rwmj 1y agoIsn't that just the same as the ordinary OCaml { product = 6; sum = 5 } (with a very slightly different syntax)?
- munchler 1y agoThe difference between { … } and {| … |} is that the latter’s type is anonymous, so it doesn’t have to be declared ahead of time.
- rwmj 1y agoOh I see, good point. I'm wondering how this is represented internally. Fields alphabetically? I've also desired extensible anonymous structs (with defaults) from time to time, but implementing that would involve some kind of global analysis I suppose.
- reycharles 1y agoOne reason why they're not the same is because the memory representation is different (sort of). This will break FFIs if you allow reordering the tuple arbitrarily.
- thedufer 1y agoLabeled tuples are effectively order-independent. Your implementation's order has to match your interface's order, but callers can destruct the labeled tuples in any order and the compiler will do the necessary reordering (just like it does for destructing records, or calling functions with labeled arguments). I don't think this is materially different from what you're describing in F#, except that labeled tuples don't allow labeling a single value (that is, there's no 1-tuple, which is also the case for normal tuples).
- IshKebab 1y agoSo this is "oxidized" because it tries to achieve the same features as Rust (e.g. "fearless concurrency" is mentioned, and avoiding GC)... Not because it actually uses Rust in any way right? Slightly confusing.
- debugnik 1y agoCorrect, Jane Street has been publishing a series of blog posts titled "Oxidizing OCaml" for a while.
- deleted 1y ago[deleted]
- zozbot234 1y agoRust will probably become usable with custom tracing GCs (which is helpful if you're dealing with general graph-like data but still want the highest performance as far as practical) way before this effort reaches genuine feature parity with Rust. Not seeing much of a point in this, unless they perhaps intend to focus on the lowest-hanging fruit and have big O(x)Caml codebases that they care about.
- greener_grass 1y agoOxCaml takes a different approach to encoding locality to Rust. Rust (arguably) overburdens the type-system with this information whilst in OxCaml this is orthogonal to the return types. In that sense it's a bit like algebraic effects. Personally I'm quite bullish on OCaml these days.
- aseipp 1y ago> Not seeing much of a point in this OCaml is a good language and these extensions are very welcome to existing OCaml programmers and programs, as well as many of the other extensions Jane Street has added. I don't understand what you mean here.
- zozbot234 1y ago> > Not seeing much of a point in this > ...I don't understand what you mean here. Yeah it seems there was a mistake there, it looks like my comment got cut off while you were reading it. Try reloading the page maybe?
- avsm 1y agoIf anyone's trying out the new opam switch, I found it helpful to use: env OCAMLPARAM="alert=-unsafe_multidomain,_," opam install cohttp-lwt-unix Because alerts are promoted to errors, they break existing package installs unnecessarily. The OCAMLPARAM environment variable just forces that alert to be disabled and allows the package installation to continue.
- WEwWGH3U5L 1y ago[dead]
- Lyngbakr 1y agoThe Janet Street folks, who created this, also did an interesting episode[0] of their podcast where they discuss performance considerations when working with OCaml. What I was curious about was applying a GC language to a use case that must have extremely low latency. It seems like an important consideration, as a GC pause in the middle of high-frequency trading could be problematic. [0] https://signalsandthreads.com/performance-engineering-on-hard-mode/ https://signalsandthreads.com/performance-engineering-on-har...
- enricozb 1y agoHaven't looked at the link, but I think for a scenario like trading where there are market open and close times, you can just disable the GC, and restart the program after market close.
- deleted 1y ago[deleted]
- spooneybarger 1y agoIt is a common strategy.
- rauljara 1y agoGC compactions were indeed a problem for a number of systems. The trading systems in general had a policy of not allocating after startup. JS has a library, called "Zero" that provides a host of non-allocating ways of doing things.
- debugnik 1y agoI wasn't aware that this fork supported SIMD! Between this, unboxed types and the local mode with explicit stack allocation, OxCaml almost entirely replaces my past interest in F#; this could actually become usable for gamedev and similar consumer scenarios if it also supported Windows.
- TheNumbat 1y agoYeah, this would be great! Currently only 128-bit SSE/NEON is working but AVX is coming very soon. There's also nothing blocking Windows, but it will require some work. (I added the SIMD support in OxCaml)
- aseipp 1y agoFWIW, the "Get OxCaml" page actually says that SIMD on ARM isn't supported yet. If it actually works it would be worth removing that from the known issues list https://oxcaml.org/get-oxcaml/ https://oxcaml.org/get-oxcaml/
- TheNumbat 1y agoIndeed, it says that because we don't have a library of NEON intrinsics (like ocaml_simd_sse) yet, but the extension itself works.
- aseipp 1y agoAh, that clears it up a bit. Thanks! Looking forward to all of this. (For the interested readers, here's the SSE library: https://github.com/janestreet/ocaml_simd/tree/with-extensions/sse https://github.com/janestreet/ocaml_simd/tree/with-extension...)
- debugnik 1y agoCool to hear there aren't any technical blockers to add Windows support! You just convinced me into giving OxCaml a try for a hobby project. 128-bit SSE is likely to be enough for my use case and target specs.
- croes 1y agoSo OxCaml is the extension of the extension of a dialect of ML. Can’t wait for the next level
- munchler 1y agoCan I interest you in F#?
- jasperry 1y agoI had a similar thought to this, but then I thought, who is worse: programmers who keep bloating up existing languages with new features, or programmers who create yet another new language to add to the already crowded field? (I'm in that latter category.) I guess programmers are just genetically incapable of leaving their tools the way they are.
- debugnik 1y agoThis did actually halt my hobby programming language project, whose features overlap a lot and is advancing slowly anyway. At the very least I'll give OxCaml a try to compare. Best case I drop mine and use this, worst case I learn what works and what doesn't.
- WEwWGH3U5L 1y ago[dead]
- anthk 1y agoOcaML's micro cousin: http://t3x.org/mlite/index.html http://t3x.org/mlite/index.html
- JHONWALTER 1y ago[dead]
- iLoveOncall 1y agoThe sunk cost fallacy at Jane Street is strong.
- ackfoobar 1y agoMaybe it's sunk cost fallacy for them. But without them there wouldn't be a language that gets me 80/20 benefit/effort of Rust.
- fuzztester 1y agowhat is the sunk cost fallacy in the Jane Street case?
- ackfoobar 1y agoI said "maybe" as granting the root comment's premise - I don't believe that.
- abathologist 1y agoWhat are you talking about?
- wk_end 1y agoThe implication here, I think, is that "Jane Street has foolishly invested heavily into Ocaml and, rather than sensibly change course and migrate away, they continue to invest heavily into it in the hopes that one day the investment will pay off." Which is a ridiculous take: Jane Street has done extraordinarily well for themselves, possibly at least in part because of their investment in Ocaml, and any sort of migration would be a huge undertaking, and an absurd and unnecessary risk.
- abathologist 1y agoAh yeah, that is absurd, given how successful they have been, and how much they attribute that success to their technical decisions. People love to sulk in their parochial pits, I guess? Thanks for clarifying :)
- dingdingdang 1y agoProbably spoilt here but being used to the excellent vscode plugin (well vscodium in my case) for Golang but... any plans to integrate with vscode ecosystem? Makes setup so straightforward!
- jasperry 1y agoThe OCaml vscode plugin seems to have already integrated a lot of new syntaxes (dune, menhir, reason), so if OxCaml gains traction it should only be a matter of time. (can't really speak for that myself, though, I use emacs)
- clancon 1y agoIf you follow the installation instructions on oxcaml.org, you’ll get a patched Merlin with LSP support etc. It’s not perfect, but does mostly work out of the box with VSCode and the OCaml Platform extension.
- debugnik 1y agoError squiggles and ocamlformat stopped working for me after the first time I restarted VS Code, compared to regular OCaml. They do work fine through the Dune CLI though.
- clancon 1y agoHmm. Did you install ocaml-lsp-server on the OxCaml switch? I also tend to run dune in polling mode (-w), not sure if that matters…
- frexe 1y agoFwiw I had the same experience as debugnik with ocaml-lsp-server installed, irrespective of whether I built in polling mode.
- liam-stevenson 1y ago
- bhamta 1y agoWhat are the chances that they are releasing this so that LLMs can index this information for free and they can use public models in their codebase rather than finetuning public models?
- debugnik 1y agoGiven how poor LLMs are at regular OCaml, which has so much more training data that OxCaml, probably none. An MCP for docs would have been more productive for that purpose.
- jdiff 1y agoNot good at all. It's not a strong enough signal. For instance, LLMs are absolute dogshit at completing Gleam, even if given files with the exact pattern they need to mimic just lines away, or given explicit instructions on common mistakes it makes.
- reverseblade2 1y agoJust use F# for sake
- debugnik 1y agoI actually see this as an escape opportunity for F#-ers. I love the language, but the runtime and C# ecosystem are not only holding it back from having cleaner semantics (until the C# team sees the value in them), they've been actively kicking it down the ladder with breaking changes and new incompatible APIs.
- reverseblade2 1y agoF# is mostly liberated from .net thanks to Fable. Although the compiler strictly is .net
- debugnik 1y agoFable is the complete opposite direction to .NET and OxCaml, though. Nice for people doing web I guess (I'd rather do TypeScript than deal with interop), but the JS runtime and ecosystem are pretty much useless for my use cases. Maybe a pure WASM target could actually liberate F#.
- JHONWALTER 1y ago[dead]
- JHONWALTER 1y ago[dead]