companion_cube changed the topic of #ocaml to: Discussion about the OCaml programming language | http://www.ocaml.org | OCaml 5.2.0 released: https://ocaml.org/releases/5.2.0 | Try OCaml in your browser: https://try.ocamlpro.com | Public channel logs at https://libera.irclog.whitequark.org/ocaml/
wingsorc has quit [Quit: Leaving]
theze__ has joined #ocaml
wingsorc has joined #ocaml
mange has joined #ocaml
theze_ has quit [Ping timeout: 252 seconds]
Tuplanolla has quit [Ping timeout: 276 seconds]
inline has quit [Remote host closed the connection]
Frostillicus has joined #ocaml
inline has joined #ocaml
Frostillicus has quit [Ping timeout: 245 seconds]
inline has quit [Quit: Leaving]
humasect has joined #ocaml
inline has joined #ocaml
Frostillicus has joined #ocaml
humasect has quit [Quit: Leaving...]
Frostillicus has quit [Ping timeout: 260 seconds]
Frostillicus has joined #ocaml
Frostillicus has quit [Ping timeout: 265 seconds]
casastortaAway has quit [Quit: ZNC 1.10.0 - https://znc.in]
casastorta has joined #ocaml
theze__ has quit [Ping timeout: 260 seconds]
Frostillicus has joined #ocaml
casastorta has quit [Quit: ZNC 1.10.0 - https://znc.in]
Frostillicus has quit [Ping timeout: 252 seconds]
casastorta has joined #ocaml
bartholin has joined #ocaml
Serpent7776 has joined #ocaml
Frostillicus has joined #ocaml
Frostillicus has quit [Ping timeout: 252 seconds]
reynir has joined #ocaml
reynir has quit [Ping timeout: 252 seconds]
Haudegen has joined #ocaml
reynir has joined #ocaml
bartholin has quit [Remote host closed the connection]
<reynir> what is zip called in OCaml? I'm blind
<reynir> (not literally blind, I just can't find the function in the docs)
<discocaml> <uberpyro181> I think combine
<reynir> Thanks!
dhil has joined #ocaml
Frostillicus has joined #ocaml
YuGiOhJCJ has joined #ocaml
Frostillicus has quit [Ping timeout: 260 seconds]
Frostillicus has joined #ocaml
Frostillicus has quit [Ping timeout: 252 seconds]
Frostillicus has joined #ocaml
Frostillicus has quit [Ping timeout: 260 seconds]
Frostillicus has joined #ocaml
<discocaml> <froyo> though zipwith is map2
wingsorc has quit [Quit: Leaving]
inline has quit [Quit: Leaving]
Haudegen has quit [Quit: Bin weg.]
inline has joined #ocaml
<discocaml> <gooby_diatonic> Oh, I thought there was only Seq.zip so I've been converting all my lists to seq for those purposes :derp:
wingsorc has joined #ocaml
Frostillicus has quit [Read error: Connection reset by peer]
johnridesabike has joined #ocaml
mange has quit [Quit: Zzz...]
wingsorc__ has joined #ocaml
wingsorc__ has quit [Read error: Connection reset by peer]
wingsorc has quit [Read error: Connection reset by peer]
Frostillicus has joined #ocaml
wingsorc__ has joined #ocaml
Haudegen has joined #ocaml
<discocaml> <contificate> Doesn't combine have that annoying behaviour, different from Haskell, where it won't truncate the list, it'll throw exception in case where lists are unequal length
<discocaml> <._null._> (It does)
<discocaml> <contificate> making it, in my mind, not as nice as zip
<discocaml> <._null._> But also, why do you have lists of different lengths ? Haskell does since they have the list of positive integers, but OCaml doesn't
<discocaml> <contificate> it's a useful side effect I think
<discocaml> <contificate> Haskell can zip lazily evaluated infinitely long lists with finite ones
<discocaml> <deepspacejohn> Seq.zip works like that, fwiw.
<discocaml> <contificate> slay
<discocaml> <._null._> seqs are (can be) infinite, so that makes sense (also the naming is consistent)
inline has quit [Remote host closed the connection]
YuGiOhJCJ has quit [Quit: YuGiOhJCJ]
tronexte has quit [Ping timeout: 260 seconds]
tronexte has joined #ocaml
Frostillicus has quit [Ping timeout: 252 seconds]
inline has joined #ocaml
<reynir> all my zippers are finite
* reynir ducks
<discocaml> <yawaramin> if we had `( let+ )` and `( and+ )` then we wouldn't have the naming problem...
<discocaml> <contificate> bro is zipping the zipping of zippers
nirvdrum741 has quit [Ping timeout: 268 seconds]
Frostillicus has joined #ocaml
nirvdrum741 has joined #ocaml
Frostillicus has quit [Ping timeout: 252 seconds]
Humean has joined #ocaml
Haudegen has quit [Quit: Bin weg.]
<discocaml> <dubious245> What is let+ and and+
<discocaml> <deepspacejohn> Binding operators https://ocaml.org/manual/5.3/bindingops.html
Haudegen has joined #ocaml
nirvdrum741 has quit [Ping timeout: 272 seconds]
nirvdrum7418 has joined #ocaml
Frostillicus has joined #ocaml
bartholin has joined #ocaml
Serpent7776 has quit [Ping timeout: 245 seconds]
<discocaml> <deepspacejohn> They're very useful for monads and DSLs.
<discocaml> <contificate> anything in CPS generally
<discocaml> <deepspacejohn> I tend to use a generic `let ( let@ ) = ( @@ )` a lot. Very handy.
dhil has quit [Ping timeout: 244 seconds]
Anarchos has joined #ocaml
<companion_cube> for sure
<discocaml> <barconstruction> I don't understand this
Frostillicus has quit [Quit: Frostillicus]
<discocaml> <barconstruction> `let@ x = e1 in e2` should be equivalent to `(@@) e1 (fun x -> e2)` which is just `e1 (fun x -> e2)` right?
<discocaml> <shadowkestrel> i think i see but i also dont see
<discocaml> <contificate> yeah, so `@@` is applicaton, letting you write CPS in what appears to be direct style
<discocaml> <barconstruction> Ah, okay, that makes sense
<discocaml> <contificate> as monadic style is a generalisation of CPS, using a monadic bind as the definition of the operator is also common - but I think anything sequentialised through continuations benefits from these operators
<discocaml> <shadowkestrel> ohhh that's what you meant by CPS
<discocaml> <shadowkestrel> i am too tail_mod_cons pilled to think about continuation passing /lh
<discocaml> <yawaramin> see also https://github.com/ocaml/ocaml/pull/13698
<discocaml> <deepspacejohn> `let@` works with anything that takes a continuation. So you can use it for functions like `let@ chan = In_channel.with_open_bin stdin` or generically for any "bind" rather than define a bindop for each one `let@ a = Result.bind b in let@ x = Option.bind y`
<discocaml> <deepspacejohn> the former is what I tend to use it for the most.
<discocaml> <barconstruction> Are there any implementations of functional languages that actually optimize away tail calls in general (not necessarily recursive) so that a series of function calls in CPS style use constant stack space? Does scheme do this?
<discocaml> <deepspacejohn> doesn't OCaml do that?
<discocaml> <deepspacejohn> I guess I don't actually know.
<discocaml> <deepspacejohn> it does optimize tail calls in general but I don't know the details.
<discocaml> <barconstruction> If it's not recursive then the caller and callee have different shapes for their stack frames, different numbers of arguments, different numbers of local variables and so on. So it's a bit more complicated to overwrite it in place
inline has quit [Remote host closed the connection]
inline has joined #ocaml
<discocaml> <shadowkestrel> I feel like OCaml does tail-call optimise everywhere, while looking through docs I've seen references to using CPS to avoid stack overflows from "the old times" when native-code programs used a conventional callstack instead of the GC-provided one we have now
Anarchos has quit [Ping timeout: 260 seconds]
<discocaml> <Kali> pretty sure the ocaml compiler guarantees tailcalls everywhere
<discocaml> <Kali> if you're ever in doubt, you can always use the [@tailcall] attribute to check
<discocaml> <Kali> pretty sure the ocaml compiler guarantees tailcalls everywhere it's possible to have one
<discocaml> <shadowkestrel> oh yeah i think where i saw it mentioned was in discussion of `format6` and its associated functions, which uses a lot of TCO
<discocaml> <Kali> (f [@tailcall]) x
<discocaml> <shadowkestrel> oh yeah i think where i saw it mentioned was in discussion of `format6` and its associated functions, which uses a lot of CPS
<discocaml> <Kali> lua is a rare example of an imperative language that does tailcalls everywhere it can too
Anarchos has joined #ocaml
<discocaml> <Kali> it's actually where i first learned about the concept
<discocaml> <shadowkestrel> the ES6 spec includes tail call optimisation
<discocaml> <shadowkestrel> the big 3 implementors (v8, spidermonkey, javascriptcore) do not care, so it doesnt really matter
<discocaml> <shadowkestrel> the ES6 spec includes tail call optimisation
<discocaml> <shadowkestrel> the big 3 implementors (v8, spidermonkey, javascriptcore) do not, so it doesnt really matter
<discocaml> <barconstruction> Can someone explain how this works without going into overwhelming detail? So let's say `g` takes three parameters and requires say 4 local variables in the sense of four words in its stack frame. And `f` needs no parameters and needs two local stack variables for its computations, before concluding with a tail call to g. What does the process look like for calling g in a way that allows the computer to reclaim f's stack space?
Serpent7776 has joined #ocaml
<discocaml> <zarakshr> `g`s stack frame will just overwrite `f`s, you just need a `jmp g`
Haudegen has quit [Quit: Bin weg.]
Anarchos has quit [Quit: Vision[]: i've been blurred!]
<discocaml> <Kali> ^ there's nothing left to execute in f, f's result is exactly g's result and so you can just jump straight to g
<discocaml> <shadowkestrel> i was hoping a few minutes in godbolt.org would be instructive but now i am just more confused about how ocamlopt works
inline has quit [Quit: Leaving]
Anarchos has joined #ocaml
reynir has quit [Ping timeout: 252 seconds]
Humean has quit [Read error: Connection reset by peer]
Humean has joined #ocaml
inline has joined #ocaml
Anarchos has quit [Ping timeout: 268 seconds]
Tuplanolla has joined #ocaml
Anarchos has joined #ocaml
nirvdrum7418 has quit [Ping timeout: 268 seconds]
Anarchos has quit [Quit: Vision[]: i've been blurred!]
nirvdrum741 has joined #ocaml
<discocaml> <froyo> > if we had ( let+ ) and ( and+ ) then we wouldn't have the naming problem...
<discocaml> <froyo> right, it'd become a hard-to-lookup syntax/operator problem instead :P
johnridesabike has quit [Quit: johnridesabike]
<discocaml> <yawaramin> solved problem 😉 https://doc.sherlocode.com/?q=let%40
<discocaml> <yawaramin> and https://doc.sherlocode.com/?q=let%2B etc.
Serpent7776 has quit [Ping timeout: 260 seconds]
bartholin has quit [Remote host closed the connection]
humasect has joined #ocaml
inline_ has joined #ocaml
inline has quit [Ping timeout: 260 seconds]
humasect has quit [Quit: Leaving...]
zor has joined #ocaml
itszor has quit [Ping timeout: 244 seconds]
<discocaml> <contificate> 😏 If you faithfully compile CPS (a-la Appel's "Compiling with Continuations"), you can avoid the stack entirely - so "the stack" becomes linked continuation closures on the heap
<discocaml> <contificate> most people think the problem of making anything tail recursive is hard: it's the constant space part that takes effort
<discocaml> <contificate> making something tail recursive amounts to CPS conversion - where all calls are in tail position
<discocaml> <contificate> I don't think there's a generic algorithm for this, as you often have to exploit little tricks - but perhaps I'm wrong
<discocaml> <contificate> to be clear: for using constant stack space, not CPS conversion
<discocaml> <contificate> GC provided?
<discocaml> <contificate> I think you just mean the fiber/cactus stack that OCaml 5 uses now, which is heap allocated
<discocaml> <contificate> my understanding is you explicitly `discontinue` delimited conts in OCaml 5 to avoid leaks, so "GC provided" may not be accurate
Tuplanolla has quit [Quit: Leaving.]