<discocaml>
<._null._> Responding to <companion_cube> I'm not personally convinced ocaml would be great as a data science language, tbh (15/11/2024 22:48 my time)
szkl has quit [Quit: Connection closed for inactivity]
<companion_cube>
I can't comment on R, but it's not easy catching up to python
<companion_cube>
And the contenders are more like mojo and Julia and whatnot afaict
<dh`>
was that only yesterday? it feels like maybe a year ago
<dh`>
sorry to snark, everyone replies to scroll occasionally by accident, plus it's a perfectly good topic
<dh`>
anyway, I agree with cube, ocaml is the wrong kind of language
<dh`>
"data science" is generally either numerics or statistics and both tend to be about large mutable tables and matrices
<dh`>
neither fits well onto a cons-based language
<dh`>
they can be bolted on, but it'll never be natural
szkl has joined #ocaml
myrkraverk has joined #ocaml
_whitelogger_ has quit [Remote host closed the connection]
_whitelogger_ has joined #ocaml
Tuplanolla has quit [Quit: Leaving.]
tremon has quit [Remote host closed the connection]
_whitelogger_ has quit [Remote host closed the connection]
_whitelogger_ has joined #ocaml
_whitelogger_ has quit [Remote host closed the connection]
f[x] has quit [Remote host closed the connection]
_whitelogger_ has joined #ocaml
toastal has joined #ocaml
_whitelogger_ has quit [Remote host closed the connection]
Haudegen has quit [Quit: Bin weg.]
_whitelogger_ has joined #ocaml
szkl has quit [Quit: Connection closed for inactivity]
toastal has left #ocaml [Disconnected: Hibernating too long]
mbuf has joined #ocaml
_whitelogger_ has quit [Remote host closed the connection]
_whitelogger_ has joined #ocaml
GreaseMonkey has quit [Remote host closed the connection]
greaser|q has joined #ocaml
greaser|q has quit [Changing host]
greaser|q has joined #ocaml
toastal has joined #ocaml
bartholin has joined #ocaml
szkl has joined #ocaml
zozozo has quit [Ping timeout: 252 seconds]
Tuplanolla has joined #ocaml
toastal has left #ocaml [Disconnected: Hibernating too long]
Serpent7776 has joined #ocaml
toastal has joined #ocaml
euphores has quit [Quit: Leaving.]
bartholin has quit [Quit: Leaving]
euphores has joined #ocaml
Haudegen has joined #ocaml
_whitelogger_ has quit [Remote host closed the connection]
_whitelogger_ has joined #ocaml
tremon has joined #ocaml
mbuf has quit [Quit: Leaving]
toastal has left #ocaml [Disconnected: Hibernating too long]
f[x] has joined #ocaml
<f[x]>
let f (A x) b = ... where to put [@warning "-8"] on (A x)? I know can put on `let` but then technically need to reenable +8 on the body which is a chore
<discocaml>
<softwaresirppi> guys im looking for a set of web standards that define stuff like html, css and js which can be expected in a browser implementation?
<discocaml>
<donderdag> unless you mean you want to implement a browser yourself
_whitelogger_ has quit [Remote host closed the connection]
_whitelogger_ has joined #ocaml
<discocaml>
<softwaresirppi> but these are like the features browsers tend to implement. like a uniform standard?
<discocaml>
<softwaresirppi> i would like to implement web protocols and stuff
<discocaml>
<softwaresirppi> web looks too complex for me. so trying to simplify with barebones
<discocaml>
<donderdag> just because it's in the standard doesn't mean browsers will implement it, and even if multiple browsers do, their implementations are often not compatible
<discocaml>
<donderdag> writing browser-agnostic websites is something of an arcane art
<discocaml>
<._null._> It's also way less used than rustacean
<discocaml>
<donderdag> neither Rust nor C are functional, so it'll probably be a bit tricky
<discocaml>
<donderdag> you'll have to do some unlearning
<discocaml>
<contificate> I think the presence of ADTs and pattern matching in Rust are a good start, so then it just becomes functional idioms
<discocaml>
<alyxshang> Unlearning sounds a bit dramatic. Perhaps getting used to a new paradigm of writing code?
<discocaml>
<contificate> I'd say writing Rust is more complicated than writing OCaml
<discocaml>
<alyxshang> I should add I'm well aware of the differences between imperative and functional languages.
<discocaml>
<donderdag> well... former programming experience does help. but you'll find that your experience and muscle memory works against you
<discocaml>
<contificate> there are various ideas core to functional programming that you will probably not have dealt with
<discocaml>
<contificate> that is where the differences are
<discocaml>
<alyxshang> Hey, don't spoil the ride. I just feel like I've peaked professionally and skill-wise and want to sink my teeth into something new and exciting.
<discocaml>
<donderdag> FP is a good place to look for that
<discocaml>
<alyxshang> To quote a certain Mr. Clarkson: How hard can it be?
<discocaml>
<alyxshang> FP?
<discocaml>
<donderdag> Functional Programming
<discocaml>
<alyxshang> Ah!
<discocaml>
<alyxshang> What is OCaml used for and why would anyone want to use it?
<discocaml>
<alyxshang> Genuinely asking, not being sassy.
<discocaml>
<donderdag> it's general purpose, just like Python
<discocaml>
<alyxshang> I've heard a lot about it but nothing concrete.
<discocaml>
<alyxshang> Results and pattern-matching included? I love those two features the most about Rust tbh.
<discocaml>
<donderdag> yes
<discocaml>
<alyxshang> The borrow-checker is a pain sometimes.
<discocaml>
<donderdag> it's garbage collected, so no need for memory management
<discocaml>
<._null._> OCaml has less sugar around result types than Rust though
<discocaml>
<contificate> I prefer OCaml to Rust because, for many things I deal with, actually caring about memory management, ownership, etc. is not relevant or important to the domain.
<discocaml>
<alyxshang> I guess I'll see 🤷♀️
<discocaml>
<octachron> (or more sugar counting let* operator)
<discocaml>
<alyxshang> Me crying in `const char***********`.
<discocaml>
<._null._> It's more customisable, but this means it's less baked in
<discocaml>
<alyxshang> Oh good, not a lot of bloat then?
<discocaml>
<alyxshang> I was thinking of porting this over to OCaml to get started.
<discocaml>
<._null._> There are comparatively very few magic things happening in OCaml
<discocaml>
<alyxshang> Would that make sense as a first project?
<discocaml>
<yawaramin> OCaml has exceptions and a lot of idiomatic code uses exceptions
<discocaml>
<contificate> Possibly. There are a lot of neat ideas in functional programming - idioms etc. that usually require explicit experimentation. A lot of people just write imperative OCaml when they get started and then dismiss it
<discocaml>
<alyxshang> Not `try-catch`????
<discocaml>
<alyxshang> Please
<discocaml>
<alyxshang> no
<discocaml>
<alyxshang> Would that be terrible?
<discocaml>
<yawaramin> ```ocaml
<discocaml>
<yawaramin> try ... with
<discocaml>
<yawaramin> | Exn1 -> result1
<discocaml>
<yawaramin> | Exn2 -> result2
<discocaml>
<yawaramin> ...
<discocaml>
<yawaramin> ```
<discocaml>
<contificate> Not terrible, but it misses the point for me.
<discocaml>
<donderdag> it's like only writing unsafe Rust
<discocaml>
<alyxshang> It's giving `match`.
* discocaml
<alyxshang> terrified crab noises
<discocaml>
<._null._> You can even do `match expr with A -> ... | B -> ... | exception Exc1 -> ...`
<discocaml>
<yawaramin> not exactly. unsafe Rust means that you are doing manual memory management. imperative OCaml is still safe in that sense
<discocaml>
<donderdag> yeah it's not a perfect analogy
<discocaml>
<octachron> a cli validation tools looks reasonable for a first project
<discocaml>
<._null._> It's like going to Rust *from C* and only writing unsafe Rust
<discocaml>
<donderdag> yeah
<discocaml>
<alyxshang> Once I'm done, where could I post the project? So that criticism may be dispensed?
<discocaml>
<alyxshang> About my possibly non-idiomatic code?
<discocaml>
<alyxshang> I mean over here.
<discocaml>
<donderdag> #working-on
<discocaml>
<alyxshang> Bit pointless.
<discocaml>
<._null._> Exactly
<discocaml>
<alyxshang> Much obliged
* discocaml
<alyxshang> curtsies
<discocaml>
<contificate> the point is just that functional programming - as a whole - can involve all kinds of neat ideas that you typically can't find an avenue to explicitly learn about from mainstream resources about mainstream languages
<discocaml>
<contificate> for example: continuation passing style, defunctionalisation, zippers, etc. to name a few
<discocaml>
<contificate> so it's not just about being able to reimplement some stuff in OCaml for OCaml's sake
<discocaml>
<yawaramin> as far as OCaml goes, it's a multi-paradigm programming language, so imho it's for pragmatists who like having a Swiss-army knife
<discocaml>
<contificate> it has been comfortably used by various companies for almost 20 years for multi-threaded networked programs
<discocaml>
<contificate> it's pretty comfy even if you just use it as a statically typed, garbage collected, language to invoke functions from the Unix module
<dh`>
I'll offer a counterpoint to the above: functional programming is just programming and people who think it isn't haven't gotten enough experience yet :-)
<discocaml>
<azur1s> i just moved from rust to ocaml after writing a compiler and having to deal with lifetimes and stuff and id say it is a pleasant to work with
<discocaml>
<contificate> I am of the genuine belief that if your programming language lacks an ergonomic encoding of ADTs and pattern matching, it is effectively an esolang to me.
<discocaml>
<azur1s> at the cost of, of course, speed but im sure my zero userbase will complain about that
<discocaml>
<yawaramin> the OCaml compiler is faster than the Rust compiler, which goes to show that speed is a very complicated thing to measure 😁
<discocaml>
<azur1s> wait really?
<discocaml>
<azur1s> oh wow
<dh`>
you might end up surprised about speed, ocaml's faster than you might think in a lot of cases, and from what I've seen the rust community has a whole pile of speed/performance fetishes that don't really seem to be grounded in reality
<discocaml>
<azur1s> i see
<dh`>
rustc is phenomenally slow
<dh`>
ocamlopt is quite fast
<discocaml>
<contificate> The compilation speed of Rust and C++ etc. just make me want to scream. A more tedious development practice just to then wait for longer for results. Brilliant.
<dh`>
like, I would guess at least 10x faster compiling a 100,000-line project
<discocaml>
<azur1s> id say it is slow to develop something in it after sometime when your codebase grew
<discocaml>
<azur1s> lifetimes leaking everywhere
<discocaml>
<._null._> There's a reason why a sourcecode-based package manager is viable
<discocaml>
<contificate> We have this file at work that takes OCaml 17 seconds to typecheck. Of course, it's well known that you can create pathological generalisation examples and make most HM impls manipulate exponentially sized type expressions, but this is just like 22k lines of code that use a lot of modules etc.
<dh`>
anyway I'd agree that languages without ADTs are defective, but that includes scheme as well as java
* dh`
whistles innocently
<discocaml>
<contificate> Yeah, I'll never understand the draw people have to Scheme.
<dh`>
me either
<discocaml>
<contificate> I personally only understood Scheme after learning OCaml. I went back and was like "oh, this is just a worse way of doing X"
<discocaml>
<donderdag> Racket has amazing macros, that’s the main reason
<dh`>
the thing I most want from any new language is a pattern-matching concrete syntax that doesn't result in O(n) indentation
<discocaml>
<contificate> Python recently got a `match` as a language feature. So, if we're choosing a dynamically typed language to act as a kind of untyped ML, I'll probably end up going with Python over Scheme (even with pattern matching libraries for Scheme).
<discocaml>
<contificate> The problem with Python's `match` structure is that any pattern variable it introduces doesn't actually create a lexically distinct binding - nor does it undo the mutation to the environment if the match case structurally matches but the guard fails.
<dh`>
rust has some frobs for trying to avoid this but they don't work very well
<discocaml>
<azur1s> what is O(n) indentation?
<discocaml>
<contificate> So you can corrupt the environment with control flow alone.
<dh`>
azurls: suppose you want to do N things in a row and each thing returns a 't Result.t or a 't option
<discocaml>
<contificate> Have you seen the deboostrapping paper for OCaml? I'm pretty impressed they got it to work and did a lot of it in Guile.
<dh`>
each step has to be indented inside the success case for the previous one
<discocaml>
<azur1s> ohh
<dh`>
and yes this isn't haskell and it doesn't _have_ to be indented but it's really ugly if oyu don't
<discocaml>
<yawaramin> didn't gasche propose a style which does exactly this in OCaml? is it really ugly?
<dh`>
another problem is that if you have O(n) operations there's a tendency to have O(n) corresponding undo operations and you end up with tons of cutpaste
<dh`>
in C code people use goto to fix this but that's not exactly desirable
<dh`>
yeah, that's basically what I thought it would be, it's ok as long as the alternate paths are all small
<dh`>
and gets confusing if they aren't
<companion_cube>
Rust is slower to compile but in practice you wait mostly on rust-analyzer
<discocaml>
<yawaramin> not if i'm making an htmx app and adjusting my markup, recompiling, and waiting to reload the page 😉
<companion_cube>
Ah well, that's fair
<companion_cube>
It's also a bit slow in ocaml in my setup tbh :(
<discocaml>
<yawaramin> lightning-fast for me with bytecode compilation in dev and live reload that refreshes the page automatically on build
<companion_cube>
But with rust in debug build it shouldn't take more than 2s to run
<companion_cube>
Bytecode?? Hu ok
<discocaml>
<yawaramin> in dev
<dh`>
one way to deal with this is to allow early returns from functions; then you can do let y = match foo with | Err x -> return (Err x) | Ok y -> y end
<dh`>
(not all on one line obviously) and it has neutral indent
<dh`>
I have never entirely understood why certain kinds of purists hate early returns so much; it complicates the typechecker but only slightly
<companion_cube>
Wish we had `return` for sure
<dh`>
and it is really, really helpful for certain kinds of complex code
<companion_cube>
Rust has a few things for non indenting match, btw
<companion_cube>
Like `let else`
<dh`>
yeah, I know, so far my experience is they don't work that well
<companion_cube>
They work well for result
<dh`>
provided you don't have any significant amount of logic needed in the error paths
<companion_cube>
You have a block, but yeah I assume you're not going to want more than 5 lines
<companion_cube>
Honestly I like result in rust, but in ocaml it's too painful
<dh`>
it depends on what kind of code you're writing
<dh`>
compiler code just doesn't hit a lot of this stuff and you don't have to care
<companion_cube>
I just use exceptions for compiler code
<dh`>
for compilers what I tend to do is mark a failure, make up a value, and continue
<dh`>
so for example if you find an invalid integer constant, print an error about it, set the global failure flag, then produce 0
<dh`>
(global failure flag gets tucked inside the error reporting module so it's nicely localized away)
<dh`>
s/localized away/encapsulated/
<dh`>
then at strategic points (typically between passes) check the failure flag and exit
<dh`>
this means you aren't exiting on the first error, which users generally appreciate
<dh`>
(and panic-level conditions can just exit immediately and can have type () -> 'a0
<dh`>
none of this works for systems code though
mbuf has quit [Quit: Leaving]
rynite has quit [Quit: WeeChat 4.4.1]
<dh`>
anyway I can't remember the specifics because it's been a couple months since I last touched rust but my recollection is that the "let else" patterns are special-case syntax that's special-cased at the wrong level so they only work for simple uses
<dh`>
anyway my idea for this is to have an "exists x, e" expression that binds x, but in order to be feasible restricts the use of x in e to equality of constructor applications
<dh`>
so you can write "exists x, Foo x = bar" but not "exists x, x + y = z"
<discocaml>
<._null._> `if let Foo x = bar then` ?
<discocaml>
<barconstruction> Rustfmt's default indentation settings introduces a lot of indentation if you use two or three nested matches. I think it would be more friendly towards nested matches if it was not so deeply indented
<dh`>
null: and so also you can write "exists x y, A x = a && B x = b"
<dh`>
which you can't in the rust syntax
<discocaml>
<._null._> Rust's syntax could be easily extended, but ok. I don't like the need to repeat your variables, so I would imagine something like `if a matches A x and b matches B x then`
<dh`>
it could, but isn't
<discocaml>
<._null._> ("matches" could become "is" if the keyword looks too long)
<dh`>
<dh`> anyway I can't remember the specifics because it's been a couple months since I last touched rust but my recollection is that the "let else" patterns are special-case syntax that's special-cased at the wrong level so they only work for simple uses
<dh`>
anyway the other part of this is that you want flow-sensitive case analysis so after if (exists err, result = Err err) ... you can write let (Success x) = result without complaints that it's an incomplete match
<discocaml>
<._null._> Why would you not match from the first construct ?
<dh`>
which is also fairly straightforward but I can also understand why language designers haven't generally rushed in that direction
<dh`>
because the goal is to avoid nested indentation
<discocaml>
<._null._> But this new if construct is already there, and already naming variables
<discocaml>
<holmdunc> The other dodgy thing about Python's `match` statement is that it just silently falls off the end if no patterns match. Ruby's equivalent (`case ... in ...`) at least raises `NoMatchingPatternError`
<discocaml>
<donderdag> and Ruby’s is an expression
<dh`>
it's there in rust, like I said, it's inadequate because it wasn't done right
rgrinberg has joined #ocaml
<companion_cube>
You haven't said why let else is inadequate though
Everything has joined #ocaml
Stumpfenstiel has joined #ocaml
toastal has quit [Quit: Gateway shutdown]
toastal has joined #ocaml
toastal has quit [Client Quit]
toastal has joined #ocaml
<discocaml>
<alyxshang> Duly noted. ❤️
<dh`>
I did? it's a statement, not an expression form, so you can't combine it with other expression pieces
<dh`>
or am I thinking of something else? like I said, it's been a bit and I wasn't ever super on top of rust syntax
<companion_cube>
Ah sure, yes, it's a statement
<companion_cube>
I haven't seen anything better in other languages though :/
<dh`>
that's why this is something I want, not something I have :-)
Everything has quit [Quit: leaving]
rgrinberg has quit [Quit: My Unrecognized Mac has gone to sleep. ZZZzzz…]
<discocaml>
<azur1s> also kinda cumbersome than i cant just print with {:?} like rust in ocaml 😭 even with ppx-deriving its still somewhat hard
<discocaml>
<azur1s> or i am just lazy
<companion_cube>
With deriving it's %a plus the printer, it's annoying but manageable
<discocaml>
<._null._> dh`: What's the issue with "let / else" being a "statement" ? (I'd rather call it a binding, it can be as much a statement as "let" without "in" is)
oriba has joined #ocaml
rgrinberg has joined #ocaml
Everything has joined #ocaml
rgrinberg has quit [Quit: My Unrecognized Mac has gone to sleep. ZZZzzz…]
zenes has joined #ocaml
zenes has quit [Changing host]
zenes has joined #ocaml
zenes has quit [Client Quit]
<discocaml>
<azur1s> oh. i've always used show_... when i dervied it, maybe ill try that out
zenes has joined #ocaml
<dh`>
null: it's restricted to the specific form if let Foo y == x
<dh`>
as opposed to say if q && let Foo y == x
<discocaml>
<azur1s> im just so used to convenient stuff that i just do 'failwith "todo"' now 😭
zenes has quit [Changing host]
zenes has joined #ocaml
<dh`>
or if let Foo b = a && Bar c = d
<dh`>
(is it "if let" or "let if"? can't remember)
<discocaml>
<._null._> Pretty sure it's `if let`, since the binding is only valid in the then branch
<discocaml>
<._null._> So you would want a guard in your `let / else` ? Something like `let Foo b = a and Bar d = c when q in ... else ...` ? This doesn't sound like being a statement / binding is an issue
<discocaml>
<._null._> `let Foo b = a and Bar d = c when q else _ and _` I mean
<discocaml>
<._null._> Ok it's a bit weird when you mind multiple variables
<discocaml>
<._null._> bind*
<companion_cube>
dh`: in theory you can use a tuple for that, I think
zenes has quit [Quit: zenes]
zenes has joined #ocaml
<dh`>
it's more that it might want to be part of a more complex expression
<dh`>
including on the shortcut side of a && or ||
zenes has quit [Client Quit]
<discocaml>
<._null._> Wouldn't more complex expressions use `if let` instead of `let else` ?
zenes has joined #ocaml
zenes has quit [Changing host]
zenes has joined #ocaml
<discocaml>
<._null._> Also, I can't see how `&&` and `||` can be used, only `and` and `|` (as in, you can't have all boolean operations when you introduce variables)
Serpent7776 has quit [Ping timeout: 248 seconds]
rgrinberg has joined #ocaml
zozozo has joined #ocaml
<dh`>
sure you can
<dh`>
first of all, if (a && let Foo y = x) { ... } neither binds y nor executes the block if a is false, and that's perfectly fine
<dh`>
second, in if (a || let Foo y = x) { ... } clearly the scope of y doesn't include the block
<dh`>
and while that's useless you could imagine if (a || (let Foo y = x && x < 10))
<dh`>
er
<dh`>
if (a || (let Foo y = x && y < 10))
mange has joined #ocaml
<dh`>
you could even allow if ((a && let y = 0) || (let Foo y = x)) { ... }
<dh`>
and then you have a binding for y on all paths
<dh`>
the reason to lift the binding out to an exists like I suggested originally is to be able to scope it explicitly
<discocaml>
<._null._> This has so little structure it would be hell to track
<dh`>
it's not that difficult
<dh`>
basically a dominator analysis like any of a dozen other things
<dh`>
however, the ultimate conclusion I have eventually come to is that all of this is only actually useful for error handling and doesn't extend to other cases of sums and matching
<discocaml>
<._null._> What other thing ? I can't see any in OCaml
<dh`>
lots of backend stuff
<discocaml>
<._null._> This sounds like it's only useful for optimisations, not for typing
<dh`>
it's _used_ for optimizations
<dh`>
I'm just saying that the typing rules for the above are the same thing and it's a well understood thing
<dh`>
and (re ultimate conclusion) instead of ganking up special-case things for using sums for error handling, new languages should have first-class error handling
<discocaml>
<._null._> You also need to forbid arbitrary boolean functions and shadowing of && and ||
<dh`>
shadowing of && and ||, maybe, overloading operators with things that don't share the original semantics is generally a mitsake
<dh`>
arbitrary boolean functions I don't see
<discocaml>
<._null._> if (my_bool_function (let Foo y = x)) then ... else ...
<dh`>
why is that a problem? it will always execute the binding
<dh`>
it would create problems in haskell, granted
<discocaml>
<._null._> What if "my_bool_function" is "not" ?
<dh`>
executing the binding isn't sufficient
<dh`>
blah, I had something in mind for this the last time I was actively fiddling with it, which was probably a year ago
<dh`>
oh right, the exists form makes that work
<dh`>
for if (exists y, my_bool_function (Foo y = x)), it's false outside my_bool_function if the binding doesn't go
<dh`>
for if (my_bool_function (exists y, Foo y = x))) the scope doesn't extend past where it's bound
<dh`>
and you can avoid any need to implicitly lift the binding through && by making the user write if (exists y, a && Foo y = x)
<dh`>
and if the user writes if (exists y, a || Foo y = x) then when a is true y is uninitialized, which isn't an optimal semantics but is acceptable
<dh`>
I knew there was a good reason for wanting that "exists"
<dh`>
(then you just need adequate restrictions to keep from needing to link every program to an SMT solver)
<companion_cube>
That a variable might be uninitialized sounds really bad :)
<companion_cube>
Just ban || in these, tbh
<dh`>
it's easy to deal with
<dh`>
uninitialized variable warnings (or errors) in C are only vague/unreliable in the face of considerably more complicated control flow
<dh`>
(plus various possible lossage involving pointers that presumably doesn't apply to these cases)
<discocaml>
<._null._> There are no variables in OCaml, it will never have uninitialisation issues
<discocaml>
<._null._> Mutable variables I mean, it sounded redundant but it's not
<dh`>
there are definitely ways to have uninitialized values in ocaml
<dh`>
but we aren't really talking about ocaml, we're talking about things rust might have done and didn't, or in some unspecified new language
<discocaml>
<._null._> Outside of things that "aren't part of the language" ? (I'm thinking either Obj or similarly low-level stuff)
<discocaml>
<._null._> All of this are about alternatives of pattern matching, it could have its place in OCaml or similar languages
<dh`>
see for example Array.create_float
<dh`>
"create_float n returns a fresh float array of length n, with uninitialized data."
<dh`>
why that specific special case exists, idk, but it does
<discocaml>
<._null._> Of course it's something about floats. But at least it's limited to values with a precise semantics, and all possibme values are valid
<companion_cube>
Still can't have an uninitialized _variable_ afaik
<discocaml>
<._null._> Well `(create_array 1).(0)` would be as close to that as possible
<dh`>
for ocaml, the only reason not to just use match is to avoid O(n) indents as we were originally talking about, and if constructs don't help with that
<companion_cube>
(didn't know about this specifics of float arrays but I'm not surprised either)
<discocaml>
<._null._> `create_float_array`*
<dh`>
all possible values of type float are valid? only if you consider NaNs valid...
<companion_cube>
Yeah but like you say it's always valid
<dh`>
particularly signaling NaNs
<companion_cube>
Ofc nans are valid
<companion_cube>
They're valid float values
<discocaml>
<._null._> Way more valid that `(Obj.magic 56 : unit)`
<dh`>
true
<dh`>
but still, an array that ends up full of signaling NaNs is not going to provide expected behavior
<companion_cube>
Obj doesn't count :)
<discocaml>
<._null._> Of course it doesn't, it's "not part of the language"
<companion_cube>
It clearly should have been named with unsafe somewhere
<companion_cube>
Like unsafe get set
<discocaml>
<._null._> At least "magic" sounds a bit unsafe
<companion_cube>
Heheheh the stdlib maintainers should add an alert on it
<dh`>
on a related subject, Array.make says "All the elements of this new array are initially physically equal to x" -- does that mean the array is internally an array of pointers to boxed values, and they start out all pointing at the same thing?
<dh`>
or does the behavior described arise because mutables are themselves pointers, so the array can be an array of boxes but if you assign the same pointer into all of them it'll still share that pointer's underlying state?
<dh`>
I am clear on the semantics of 'a ref, not so much on some of the other manifestations
<discocaml>
<._null._> It's all about "OCaml values", which are either immediates or pointers to boxes on the heap
<dh`>
(and mostly I use ocaml for writing compilers, and systems code gets written in something else, so I generally don't have to care about such things)
<discocaml>
<._null._> When you know what values are, `Array.make` can only do what it does, but when you don't, you can make an array of arrays for a matrix and not understand why all internal arrays are the same
<discocaml>
<._null._> The array works exactly as any other array in any other language (well, it's sized so not exactly like C's arrays)
<dh`>
ok, I see, so it's an array of values and make stuffs it full of pointers to the same box
<dh`>
makes sense, just don't think I'd ever had cause to investigate
<discocaml>
<._null._> No, it fills it with the value directly
<dh`>
which is a pointer to a box, so they're all pointers to the same box
<discocaml>
<._null._> Doesn't have to. Integers are never pointers
<dh`>
integers are also not mutable
<discocaml>
<._null._> Sure ? What I mean is that an array of integers is a pointer to an array on the heap, containing integers directly
<dh`>
right
<dh`>
random trivia: in fortran integer constants are mutable and you can update them by screwing around using pass-by-reference arguments
<dh`>
although with normal unix fortran compilers attempting to do so will give you SIGSEGV because they live in read-only data
<companion_cube>
I often use Array.init to build an array of non immediate values
<dh`>
hmm, I wonder what happens on arm32 with fortran integer constants vs. the constant pool stuff in the assembler