gentauro has quit [Read error: Connection reset by peer]
gentauro has joined #ocaml
ccx has quit [Ping timeout: 248 seconds]
hyphen has quit [Ping timeout: 244 seconds]
hyphen has joined #ocaml
hyphen has quit [Ping timeout: 260 seconds]
hyphen has joined #ocaml
ccx has joined #ocaml
hyphen has quit [Ping timeout: 240 seconds]
hyphen has joined #ocaml
hyphen has quit [Ping timeout: 258 seconds]
waleee has quit [Ping timeout: 255 seconds]
hyphen has joined #ocaml
gereedy has joined #ocaml
<greenbagels>
so reading ocaml tutorials and books a lot of resources seem to say things along the line of "classes / OOP / mutability / etc. have their place in ocaml, but many programmers find they dont need the features that much"
<greenbagels>
i think im too worried about writing "unidomatic code" as a beginner; would multiple module functions neeeding access to some shared "state" variable be sufficient reason to want classes over something like submodules?
<d_bot>
<Ambika E.> No
<d_bot>
<Ambika E.> You can almost always just stick to modules, so don't worry too much about potentially missing the right opportunity to use the OO features
<gopiandcode>
I'd say it's still idiomatic OCaml to have functions take a mutable state parameter as input - just make sure it's reflected appropriately in the type
<greenbagels>
gopiandcode: right, that seemed like the only other sane choice
<greenbagels>
the downside being that throwing mutable state between functions could be verbose to some i guess
<greenbagels>
or exposing state to users that dont always need to know it i guess
<Corbin>
Maybe you need less mutable state than you think.
<gopiandcode>
mutability is somewhat contagious in some sense - unless the mutable state can be encapsulated within the local scopes of your library, the end users will always need to know that the mutability exists, and this should be exposed from the types I think
<gopiandcode>
(I guess there are edge cases when this can be avoided (such as memoization that doesn't affect the functional correctness), but these are exceptions not the rule)
<greenbagels>
i have issues trying to think of a way to avoid mutability in my case; it's a web client where each message from the server is tagged with an id, and a callback that sends keepalives (containing hte latest id received) sleep-waits using lwt
bobo_ has joined #ocaml
<greenbagels>
so i either need to scrap the model im using entirely or have some way for this infinite recursion callback to communicate with the main handler for incoming data
spip has quit [Ping timeout: 255 seconds]
zebrag has quit [Quit: Konversation terminated!]
<greenbagels>
i will rethink the design; maybe i will tackle a bunch of simpler exercises and study some existing code before thinking about my problem some more
<d_bot>
<nave01314> Why would multiple module functions requiring the same mutable state parameter be unidiomatic? For example, Map.find and Map.change both take the map as the first argument.
<greenbagels>
im not saying its unidiomatic, im just wondering why something like using classes to handle mutable state / encapuslation is avoided so much
<greenbagels>
but i guess you can still hide what you want from the user using just the module system; i'm also reading that ocaml's object oriented features are sometimes not super efficient?
jpds1 has quit [Ping timeout: 240 seconds]
jpds1 has joined #ocaml
Haudegen has joined #ocaml
Serpent7776 has joined #ocaml
gravicappa has joined #ocaml
rak has quit [Ping timeout: 246 seconds]
Sankalp has quit [Ping timeout: 244 seconds]
gereedy has quit [Quit: gereedy]
Sankalp has joined #ocaml
Sankalp has joined #ocaml
jpds1 has quit [Ping timeout: 240 seconds]
jpds1 has joined #ocaml
h11 has joined #ocaml
mro has joined #ocaml
aspe has joined #ocaml
Anarchos has joined #ocaml
mro has quit [Remote host closed the connection]
<d_bot>
<Bluddy> ocaml is a mostly functional language and mutable state is generally frowned upon
<d_bot>
<Bluddy> classes and objects can be used immutably as well. it's just not so popular due to the fact that there are also performance issues with objects
<d_bot>
<Bluddy> so you end up with a barely used OOP side, and when it's used, it's used for mutable data and only in very limited amounts
<d_bot>
<leviroth> Nobody I know frowns upon mutable state. Where are you getting this generalization?
<d_bot>
<Bluddy> that's the whole point of a functional language
<d_bot>
<Bluddy> you try to avoid mutable state
<d_bot>
<Bluddy> you use it when you need it, but otherwise try to avoid it
<d_bot>
<undu> I tend to use immutable data structures, not having mutable state makes the code eeeasier to reason with
<d_bot>
<undu> mutable state has to exist somewhere, but if i can avoid having mutable state in a module, I'll gladly go for it
<d_bot>
<leviroth> The whole point of OCaml is that you try to avoid mutable state? Surely from another perspective, the point of OCaml is to provide quality functional idioms alongside mutability. And surely the point of OCaml also involves, say, modularity or the type system.
<d_bot>
<Bluddy> OCaml is a functional language first and foremost. And functional languages concern themselves with immutable state. OCaml gives you an escape hatch to use mutable state when you need it (e.g. for performance), but functional paradigms (which heavily involve immutable state) are the focus. You can make a whole program with only mutable state and mutable variables everywhere, but at that point you may as well be using something els
bartholin has joined #ocaml
<d_bot>
<Bluddy> The type system also plays along with immutability. If you only use mutation, you'll be returning `unit` everywhere, which isn't very helpful in catching the bugs the type system is supposed to catch.
<octachron>
The relative lack of optimisation for objects mostly matters if you have small method calls in hot loops.
<octachron>
I would rather say that encapsulation and mutable state are already well handled by modules in many situation.
<octachron>
Thus objects end up being the best fitting solution in few cases (for instance, open recursion or extensible data structure defined by their behavior).
Anarchos has quit [Ping timeout: 240 seconds]
<d_bot>
<leviroth> @Bluddy it's certainly not true that mutation means your function must only return `unit`, and even if it were that doesn't mean that you can't benefit from the type system, e.g. in the arguments of the function.
<d_bot>
<leviroth> But this all seems pretty far afield of the original context
<d_bot>
<leviroth> Someone was writing a web client that has to keep track of state sent to it by the server, and they were concerned that it would be unidiomatic to use mutable state in this case.
<d_bot>
<Bluddy> It is unidiomatic. But it may be necessary for performance reasons.
<d_bot>
<leviroth> No, it's not!
<d_bot>
<leviroth> It's just not true that it's unidiomatic to ever use mutable state in OCaml, except that you might have to sacrifice idioms for performance.
<d_bot>
<leviroth> On the contrary it's often immensely painful to have to pass around different chunks of immutable data structures and make sure they are all updated in all the right places, when it's often simpler to just use a hashtable, or a record with mutable fields.
<d_bot>
<Bluddy> there are algorithms that are simpler to implement with mutable state - this is true
<d_bot>
<Bluddy> but the basic idiom is still to try use immutable state where you can
<d_bot>
<leviroth> And I think it's deeply unhelpful when someone has questions about all this and instead of getting advice about the tradeoffs of mutable or immutable approaches for their particular use case, they're met with unsupported blanket assertions about how one approach is "generally frowned upon."
<d_bot>
<Bluddy> just because it's frowned upon in a general sense doesn't mean it can't be useful in particular cases
<d_bot>
<Bluddy> that's what the 'general' part means
<d_bot>
<leviroth> Saying that you should use immutable state "where you can" is giving up the whole game since the question was about whether this *particular* case it's tractable to have an immutable design.
<d_bot>
<Bluddy> do you understand what the word 'generally' means?
<d_bot>
<leviroth> Of course I understand what the word generally means
<d_bot>
<Bluddy> so I don't think there's a real disagreement here. There's a reason I said it's *generally* frowned upon.
Haudegen has quit [Quit: Bin weg.]
<d_bot>
<leviroth> Yes, there is a real disagreement: I think it's unhelpful to make that kind of generalization in the actual context of the conversation.
<gopiandcode>
I wouldn't say the point of OCaml is to avoid mutable state
<gopiandcode>
that would be closer to Haskell
<gopiandcode>
OCaml is a language that allows you to use the best tool for the job
<gopiandcode>
you can use functional code or imperative code depending on which is most appropriate for the problem
<gopiandcode>
for example, a strict purist might avoid using any mutable state at all, and instead use the state monad
<gopiandcode>
this will probably work to an extent, but I wouldn't call it idiomatic code
<gopiandcode>
for one, it would probably be very painfully slow
<gopiandcode>
instead, with OCaml, when the code seems like it makes use of a pervasive state, one can choose to make the state mutable rather than purely functional
<d_bot>
<leviroth> And furthermore, I don't really agree that you should "generally" avoid mutable state for the reasons that gopiandcode is rehearsing right now.
mro has joined #ocaml
mro has quit [Remote host closed the connection]
mro has joined #ocaml
aspe has quit [Quit: aspe]
mro has quit [Remote host closed the connection]
mro has joined #ocaml
mro has quit [Remote host closed the connection]
mro has joined #ocaml
mro has quit [Remote host closed the connection]
<d_bot>
<Bluddy> here is how the cornell textbook introduces ocaml
<d_bot>
<Bluddy> haskell avoids mutable state altogether. OCaml frowns on mutable state but accepts it where necessary, mostly for performance, but sometimes also for simplicity. If you show me an OCaml program that's packed with mutable state with no justification for it whatsoever (not performance, not anything), I would tell you it's not idiomatic and you should try to use at least some immutability to gain the benefits of functional programmin
<d_bot>
<Bluddy> You could also program entirely with objects in OCaml and nothing else. Is it idiomatic? No. Is it possible? sure.
adanwan has quit [Read error: Connection reset by peer]
jpds1 has quit [Read error: Connection reset by peer]
adanwan has joined #ocaml
gereedy has joined #ocaml
waleee has joined #ocaml
jpds1 has joined #ocaml
mro has joined #ocaml
<d_bot>
<leviroth> I don't think anyone in this conversation needs to be linked to the introduction of an OCaml textbook
<d_bot>
<leviroth> gopiandcode and I aren't novice OCaml programmers needing basic instruction about what the language is like; we're experienced OCaml programmers whose experience doesn't gel with how you are characterizing the language.
<d_bot>
<Bluddy> that's fine. we can agree to disagree.
<d_bot>
<Bluddy> would you claim that objects everywhere is idiomatic to ocaml?
<d_bot>
<leviroth> no
<d_bot>
<Bluddy> why not?
<d_bot>
<Bluddy> it's fully doable in the language
<qwr>
i'm not sure that you are even disagreeing... it boil basically down to that its unidiomatic to use mutable state where immutable state would result in clearer/less error prone/easier to understand code...
mro has quit [Remote host closed the connection]
<qwr>
but it makes no sense either to complicate the code with emulating mutation in pure code, where simple ref or mutable field would do
<qwr>
though sometimes it is hard to see alternative, easier solution if you already have one in your mind
<qwr>
(like python programmer might not see how recursion + pattern matching would do, when he thinks about while loop)
Haudegen has joined #ocaml
<d_bot>
<Bluddy> yep definitely agree with all of that
mro has joined #ocaml
azimut_ has quit [Remote host closed the connection]
azimut has joined #ocaml
rak has joined #ocaml
mro has quit [Remote host closed the connection]
mro has joined #ocaml
<d_bot>
<darrenldl> greenbagels: id use hashtable for the mapping from id to states, and make the handler function itself pure ig
<d_bot>
<orbitz> IMO it sounds like you guys are disagreeing on what "idiomatic" means
<d_bot>
<darrenldl> mutable at outer layer is quite common afaik
vicfred has joined #ocaml
mro has quit [Remote host closed the connection]
<d_bot>
<orbitz> There are clearly situtaions where the idiomatic solution to a problem in Ocaml is mutation. We have mutable types with stdlib: bytes, array, queue, hashtbl, bigarray. The Seq stuff requires mutation to accomplish anything as far as I can tell. So it might not be sufficient to say if mutable state in a language is idiomatic, but talk more about the particular scenario. Idiomatic network code is going to have a bunch of mutable
<d_bot>
<Bluddy> so maybe you're right and it is about what idiomatic means.
<d_bot>
<Bluddy> to me, even when you're making mutable code, you should be thinking: is it really important that this be mutable?
<d_bot>
<Bluddy> because the default is immutability
<d_bot>
<Bluddy> now again, this is a general approach, not a specific one
<d_bot>
<Bluddy> it may very well be that given the domain, a mutable approach is best
<d_bot>
<Bluddy> notice the asymmetry though: when writing immutable code, I'm not asking myself if I can write it with mutability
<d_bot>
<Bluddy> I would only do that if certain constraints force me in that direction: either performance or the fact that the alternative mutable algorithm would be far more elegant
mro has joined #ocaml
Anarchos has joined #ocaml
mro has quit [Remote host closed the connection]
gereedy has quit [Quit: gereedy]
mro has joined #ocaml
mro has quit [Remote host closed the connection]
Anarchos has quit [Ping timeout: 258 seconds]
mro has joined #ocaml
mro has quit [Remote host closed the connection]
mro has joined #ocaml
mro has quit [Remote host closed the connection]
<qwr>
accidental mutability usually makes it harder to reason about the code, in porpotion with globality of the mutability (guess why passing arguments in global variables is almost universally shunned)
mro has joined #ocaml
mro has quit [Remote host closed the connection]
waleee has quit [Quit: WeeChat 3.5]
Anarchos has joined #ocaml
Tuplanolla has joined #ocaml
Anarchos has quit [Ping timeout: 244 seconds]
mro has joined #ocaml
mro has quit [Ping timeout: 260 seconds]
bobo_ has quit [Ping timeout: 246 seconds]
spip has joined #ocaml
zebrag has joined #ocaml
Haudegen has quit [Quit: Bin weg.]
favonia has joined #ocaml
<Corbin>
Bluddy: I wonder to what degree this entire argument is about the definition of "functional language". My personal opinion is that it's hard to have a consistent definition of "functional language" which includes OCaml and Haskell but excludes Scheme and Python; as a result, we can't really say that functional languages are about mutability.
<Corbin>
Actually, personally, I think "functional language" is a tribal marker. But we could still try to examine the point, which is that a (pure total) function doesn't have a concept of mutation.
<favonia>
Hi all, I'm created the issue https://github.com/ocaml/ocaml/issues/11185 about embedding the unhandled effect in the exception Unhandled. As a programmer I felt the urge to give it a try. While this sounds like a trivial change, I need to hack the primitive 'caml_perform' written in assembly code. I wonder what would be a good resource for me to learn it if I want to?
<qwr>
today most languages have incorporated parts allowing functional programming, so its now more whether it is comfortable to you use functional style (syntax, library) and whether such code is efficiently executed
<favonia>
PS: not the assembly language itself---but the invariants (e.g., calling conventions) maintained by the current runtime system on *all* platforms. I felt I could easily violate some convention there.
<favonia>
(I'm also happy if someone else would do it. It's probably too challenging for me haha.)
azimut has quit [Remote host closed the connection]
azimut has joined #ocaml
waleee has joined #ocaml
mro has joined #ocaml
mro has quit [Remote host closed the connection]
aspe has joined #ocaml
aspe has quit [Quit: aspe]
Haudegen has joined #ocaml
bartholin has quit [Quit: Leaving]
mro has joined #ocaml
mro has quit [Remote host closed the connection]
mro has joined #ocaml
mro has quit [Remote host closed the connection]
cedric has joined #ocaml
xgqt has quit [Ping timeout: 246 seconds]
xgqt has joined #ocaml
aspe has joined #ocaml
aspe has quit [Remote host closed the connection]
mro has joined #ocaml
mro has quit [Ping timeout: 258 seconds]
mro has joined #ocaml
mro has quit [Quit: Leaving...]
mro has joined #ocaml
mro has quit [Quit: Leaving...]
gravicappa has quit [Ping timeout: 255 seconds]
<d_bot>
<rawburt> "haskell avoids mutable state altogether" is not a true statement. there are plenty of mutability solutions in haskell. the community trends towards functional state via monads, but there are plenty of mutability options in haskell (IORef, STRef, MVar, etc). i'm not sure if you can build a general purpose language and _not_ have some mutable primitive. even Koka built entirely around algebraic effects has a mutable ref
<d_bot>
<orbitz> Those things are within a monad though
<d_bot>
<orbitz> Happens to be a monad that's difficult to get out of
<d_bot>
<rawburt> true true, good point
<Corbin>
There exist non-functional Turing-complete languages without mutability; my favorite example is Wang tiling. Certainly, implementations of languages are going to tend towards mutability; it'd be a shame not to take advantage of mutable main memory.
Serpent7776 has quit [Quit: leaving]
Haudegen has quit [Quit: No Ping reply in 180 seconds.]
Haudegen has joined #ocaml
Anarchos has joined #ocaml
klu has quit [Ping timeout: 240 seconds]
greenbagels has quit [Ping timeout: 258 seconds]
ccx has quit [Ping timeout: 246 seconds]
cedric has quit [Quit: Konversation terminated!]
greenbagels has joined #ocaml
ccx has joined #ocaml
Anarchos has quit [Quit: Vision[]: i've been blurred!]