<remexre>
is there a way with ocamllex to emit multiple tokens?
<remexre>
I have rational literals, but ideally "001/000" would lex as [int; slash; int] rather than [rational]
<remexre>
oh wait never mind, I could just make the associated data be a pair of ints and handle it in the parser
<quartz>
Hello. I'm trying to write a simple functio in OCaml that returns the max value of a list of ints. Can someone tell me why the compiler is complaining at line 11? https://godbolt.org/z/e1r7hs7Y1
<d_bot_>
<Alistair> function application is left-associative, so `maxVal max List.tl l` is being parsed as `((maxVal max) List.tl) l`
<quartz>
Ahhh
<quartz>
Alistair: Can you tell me why the function does not work? I'm not sure what I did wrong: https://godbolt.org/z/YohdMWWTE
<quartz>
It is suppose to return the highest value in the list.
olle has quit [Ping timeout: 250 seconds]
bgs has quit [Read error: Connection reset by peer]
bgs has joined #ocaml
adanwan has quit [Remote host closed the connection]
adanwan has joined #ocaml
cedric has quit [Quit: Konversation terminated!]
<quartz>
Anyone?
waleee has quit [Ping timeout: 240 seconds]
waleee has joined #ocaml
rgrinberg has quit [Ping timeout: 240 seconds]
waleee has quit [Ping timeout: 240 seconds]
waleee has joined #ocaml
Haudegen has quit [Ping timeout: 250 seconds]
quartz has quit [Quit: WeeChat 3.4]
vicfred has quit [Quit: Leaving]
waleee has quit [Ping timeout: 250 seconds]
<d_bot_>
<hcarty> quartz check your comparison of max against the first list element
waleee has joined #ocaml
waleee has quit [Ping timeout: 250 seconds]
rgrinberg has joined #ocaml
waleee has joined #ocaml
waleee has quit [Ping timeout: 260 seconds]
<gopiandcode>
hi!
<gopiandcode>
Does anyone familiar with the mirage crypto libs know whether the following python code is equivalent to my OCaml implementation?
rgrinberg has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
rgrinberg has joined #ocaml
hackinghorn has quit [Ping timeout: 256 seconds]
rgrinberg has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
epony has joined #ocaml
troydm has joined #ocaml
gravicappa has joined #ocaml
mro has joined #ocaml
Serpent7776 has joined #ocaml
mro has quit [Remote host closed the connection]
mro has joined #ocaml
mro has quit [Remote host closed the connection]
mro has joined #ocaml
kaph has quit [Ping timeout: 260 seconds]
<d_bot_>
<NULL> quartz: To work on lists, you should use pattern matching rather than List.{hd,tl}. You should forget about those functions, they have little to no use in (good) OCaml code
dextaa_ has quit [Read error: Connection reset by peer]
dextaa_ has joined #ocaml
bartholin has joined #ocaml
azimut has quit [Remote host closed the connection]
<hannes>
where "`Digest digest" could also be "`Data (Cstruct.of_string "hello"))" (and then PKCS1.sign takes care about the hashing
mbuf has quit [Ping timeout: 272 seconds]
mbuf has joined #ocaml
mbuf has quit [Ping timeout: 240 seconds]
mbuf has joined #ocaml
<gopiandcode>
hannes: I see, thanks! I think I was probably doing something completely wrong there
<gopiandcode>
I've been using the X509 library to generate and store my keys, so would the above be equivalent to: Base64.encode (X509.Private_key.sign `SHA256 privkey (`Message (Cstruct.of_string str)) |> Result.get_ok |> Cstruct.to_string)
mro has joined #ocaml
<hannes>
gopiandcode: nearly, add a ~scheme:`RSA_PKCS1 to the Private_key.sign call
mro has quit [Quit: Leaving...]
<gopiandcode>
hannes: perfect, thanks!
bartholin has joined #ocaml
Haudegen has quit [Quit: Bin weg.]
<d_bot_>
<Bluddy> update: for now, since I don't need good performance, I'll use what's there and just utilize `char Seq.t` to read buffers
gravicappa has quit [Ping timeout: 240 seconds]
<d_bot_>
<sarna> hey, is there any way of producing deflate output with the adler-32 checksum at the end using ocaml libraries? I swear I tried every one and even tried to patch the code by hand but I haven't succeed
<d_bot_>
<sarna> hannes: if I use the Higher module it doesn't seem include adler at the end unfortunately - I'm missing exactly one byte at the end
Haudegen has joined #ocaml
<d_bot_>
<sarna> and all the others are too low level for me to understand :/ it's the third day I'm trying
<d_bot_>
<dinosaure> did you use `De` or `Zl`?
<d_bot_>
<sarna> I tried both
<d_bot_>
<dinosaure> hmmhmm, `Zl` should emits at the end the checksum
<d_bot_>
<dinosaure> if you have an example of what you do, I can help 🙂
<d_bot_>
<sarna> just a sec, let me just delete like three hundred lines I tried to change by hand '^^
<d_bot_>
<dinosaure> so, just to be clear: `Zl` corresponds to `zlib` (so you have an header at the beginning and the checksum at the end)
<d_bot_>
<dinosaure> if you don't want the `zlib` header and you want the checksum (`adler32`, what ever), the best is to do a mix between `De` and `Checkseum.Adler32` - and put by yourself the checksum at the end
<d_bot_>
<sarna> okay, so now I remember: with `Zl` I had to change the level from 4 to 6 (not an issue) but then at the end I miss exactly one byte
<d_bot_>
<sarna> I'm comparing it with a ruby impl, I run them like `echo foo | deflate | hexdump -C`
<d_bot_>
<sarna> ruby code is just `puts Zlib::Deflate.deflate(STDIN.read)`
<d_bot_>
<sarna> for ocaml I can make a minimal example, but I just use `Zl.Higher` with the `deflate_string` function from `zl.mli`, nothing fancy
<d_bot_>
<dinosaure> And it seems correct (checksum of `foo\n` is `03D1014F`)
<d_bot_>
<dinosaure> Depending on which block Ruby on to generate unfortunately. Let me check what is `0002` but I think it's a new block
<d_bot_>
<sarna> 000a.. is the LF character
<d_bot_>
<sarna> god damn it
<d_bot_>
<dinosaure> yes, `000a` is LF 🙂
<d_bot_>
<sarna> I'm so sorry for taking so much of your time
<d_bot_>
<dinosaure> no it's normal 🙂
<d_bot_>
<sarna> at least I learned something. thanks a ton!
<d_bot_>
<dinosaure> but yeah, if you want DEFLATE + Adler32, you can mix `De.Higher` and just put the result of `Checkseum.Adler32` at the end (in big-endian)
<d_bot_>
<sarna> no this is perfectly fine, thank you :))
<d_bot_>
<dinosaure> ok cool P)
<d_bot_>
<sarna> I got badly confused
<d_bot_>
<dinosaure> (me too, I made `hxd` to help to implement `decompress` then, my brain was died to check bit per bit `zlib` output: https://github.com/dinosaure/hxd)
Serpent7776 has quit [Read error: Connection reset by peer]
Serpent7776 has joined #ocaml
Haudegen has quit [Quit: Bin weg.]
gravicappa has joined #ocaml
perrierjouet has joined #ocaml
kaph has quit [Read error: Connection reset by peer]
quartz has quit [Quit: WeeChat 3.4]
zebrag has joined #ocaml
rgrinberg has joined #ocaml
vicfred has joined #ocaml
rgrinberg has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
Haudegen has joined #ocaml
kaph has joined #ocaml
<d_bot_>
<mbacarella> There seems to be an effort to position OCaml as a security technology. Is that right? What are the selling points?
<d_bot_>
<mbacarella> * memory safety, though lots of languages have that
<d_bot_>
<mbacarella> * still fast, unlike most of the above languages
<d_bot_>
<mbacarella> * easier to reason about and audit because strongly typed and FP
<d_bot_>
<mbacarella> * exciting paths to unikernel/mirage that can lead to eliminating legacy C/C++ attack surface from the app stack
<d_bot_>
<mbacarella> ?
<d_bot_>
<mbacarella> missing anything?
<d_bot_>
<darrenldl> algebraic data types ig?
<hannes>
mbacarella: with https://github.com/formal-land/coq-of-ocaml and Coq's ability to extract OCaml code, the road to seemlessly integrate proven code (or prove existing OCaml code) is paved
<d_bot_>
<darrenldl> you still need experts to prove code via coq tho
<d_bot_>
<darrenldl> though there are a fair number of automated verification toolchains too
<hannes>
mbacarella: (of course depending on style) purity of (protocol) implementation allows testing (fuzz / unit / quickcheck) without expensive (mutable) IO setup.
<hannes>
mbacarella: using asynchronous tasks (e.g. lwt) avoids race conditions (makes asynchronous programming easier than e.g. C + pthreads approach)
<d_bot_>
<darrenldl> other fp would also share the easiness of testing part, tho good point
<d_bot_>
<darrenldl> is asynchronous task inherently immune to race conditions? or is it due to lwt coorperative concurrency model?
<hannes>
darrenldl: thanks exactly cooperative multitasking is what I meant.
vicfred has quit [Ping timeout: 240 seconds]
<d_bot_>
<darrenldl> sorry wrong press
<d_bot_>
<darrenldl> aha that is a very good point, since very few cases would one want absolutely no critical sections, and cooperative multitasking removes a lot need for locking, even when lwt becomes multicore
<d_bot_>
<darrenldl> actually not sure about the last line about after lwt becoming multicore hm..
<d_bot_>
<darrenldl> i guess it still yields easier analysis and tuning compared to preemptive scheduling
rgrinberg has joined #ocaml
rgrinberg has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<d_bot_>
<Et7f3> I guess lwt is better than pthread since it has a scheduler used by many project and with pthread you schedule manually. But this argument is can be adapted in C if a lib become a de facto and manage that for us. Also ocaml has memory barrier, does this help preventing race condition for heap variable ?
perro_ has quit [Quit: WeeChat 3.0.1]
<companion_cube>
Lwt + domainslib for background cpu tasks!
<companion_cube>
(pthread doesn't make you schedule manually, the OS does it for you)
quartz has joined #ocaml
Techcable has quit [Ping timeout: 240 seconds]
vijon has joined #ocaml
vijon has quit [Client Quit]
tomku has quit [Quit: Lost terminal]
gravicappa has quit [Ping timeout: 256 seconds]
<quartz>
Can someone explain line 9 of this code? https://godbolt.org/z/bjsqYzxdG It's basically: | hd :: tl -> hd + sum tl;; This is pattern matching based on if there are elements in the list?
<quartz>
so translated into English, the line " | hd :: tl -> hd + sum tl;;" means: "if the list is not empty, than add the first element to the remainder of the list"
tomku has joined #ocaml
<d_bot_>
<Butanium (@me on answer)> Yzs
<Corbin>
Sure. It sounds like you've got it.
<d_bot_>
<Butanium (@me on answer)> hd stands for `head`, the first element of the list
<quartz>
The expression "hd :: tl" is just so weird.
<quartz>
Yes
<d_bot_>
<Butanium (@me on answer)> And `tl` for `tail`
<d_bot_>
<Butanium (@me on answer)> The rest of the list
<d_bot_>
<Butanium (@me on answer)> What do you find it weird ?
<d_bot_>
<Butanium (@me on answer)> Another common notation is `x :: xs`
tomku has quit [Client Quit]
<quartz>
Well, it's weird because "hd :: tl" means "append the head of the list to the remainder of the list"
<quartz>
If pattern matching is like switch statements in C or Java, than how is "hd :: tl" a pattern.
tomku has joined #ocaml
<Corbin>
It means "detach the head of the list from the remainder of the list".
<quartz>
Corbin: I thought :: meant "append"
<Corbin>
quartz: As an expression, yes. But as a pattern, every constructor becomes a deconstructor.
kaph has quit [Ping timeout: 256 seconds]
Serpent7776 has quit [Quit: leaving]
<quartz>
Corbin: I'm trying to write a function that gets the max value of a list. I'm not sure how to do this because I can't store variables in OCaml. My function header is: let rec maxVal (l : int list) : int = ...
<quartz>
Unless I pass in a variable like an int into the function like I did for my function that gets the sum of a list at line 15 here.
<quartz>
So, I guess what I"m asking is: how can I write the function that gets the max value without some way to store a variable.
<d_bot_>
<glennsl> `::` means _prepend_, not _append_. I.e. it adds an element to the _front_ of the list, not to the _back_.
olle has quit [Ping timeout: 240 seconds]
<d_bot_>
<glennsl> Also, it's useful to think of lists not as arrays, but as nested "cons" cells, which are essentially tuples . For example, `[1; 2; 3]` is essentially represented as `( 1, ( 2, ( 3, () ) ) )`.
<d_bot_>
<glennsl> From that it's easier to understand the syntax `1 :: 2 :: 3 :: []` which, if we make the associativity explicit, is parsed as `1 :: (2 :: (3 :: []))`.
<d_bot_>
<glennsl> And `hd :: tl` is essentially the same as `(hd, tl)`
<quartz>
Why is everyone ignoring me? haha
<d_bot_>
<Butanium (@me on answer)> ?
<d_bot_>
<Butanium (@me on answer)> Just use the same as sum
<d_bot_>
<Butanium (@me on answer)> But instead of `+` you'll need `max`
<quartz>
I just asked about my stupid function that is suppose to get the max value for a list. How can I do it, because you can't declare variables in OCaml
<quartz>
Butanium: Yes, but is it necessary to pass in a value alongside the list? Why can't I just write the functin so that it only accepts a list
<Corbin>
quartz: You will have to open your mind a little. The trick is understanding `rec`, and I imagine that that is the point of the homework.
<quartz>
Corbin: This isn't a homework question at all actually, I'm doing it to learn this language
<Corbin>
glennsl showed part of the trick. Because a list is really like a series of nested cells, we can talk in terms of recursion: either a list is the empty list, or it's a cell containing a value and a list.
<quartz>
But yeah I do have homework to do
<Corbin>
Sorry. I was going to say "the point of the assignment", but I felt that that would be an unhelpful pun.
<quartz>
I'm not asking anyone to do my homework for me :) It's not helpful to me anyway as I have an exam on this, so what good will it do if someone does my homework for me, as I"ll be clueless when it comes to taking the exam :)
kaph has joined #ocaml
<quartz>
Anyway... OK, use a rec... but can't it be done WITHOUT a rec?
<quartz>
As all these OCaml functions are so elegant.
<Corbin>
Maybe it could be done without `rec`. I don't know OCaml well enough to say for sure. But `rec` is a powerful hint: it means that your function should call itself, recursively, in at least one case.
<quartz>
OH! Recursion haha I thought you were talking about something else, sorry
<quartz>
Corbin: Yes of course I'll use recursion, but what I'm asking is, how can it be done without the ability to STORE a value? I need to compare "hd" with a stored value that contains the largest int seen so far.
<octachron>
Yes, it can do without rec using either: a fold (a higher-order function that describes a limited class of recursive functions), a while loop and a mutable reference, or a Z-combinator.
<octachron>
You can store values as function arguments. But for the first version of the function, you don't need to "store" anything.
<octachron>
If I have a element x, and the maximum m of a list of elements, can you compute the maximum of the two values, x and m?
<Corbin>
quartz: Not a stored value, a computed value. And the computation is recursive. Let's consider the case where a list is a value and another list. The maximum would be computed by comparing the value to the maximum of that other list.
<d_bot_>
<Alistair> Recursion can be done without `rec`
<Corbin>
What octachron said. I think I'm being confusing.
<d_bot_>
<Alistair> It's possible to implement a fixed point combinator using recursive datatypes
<quartz>
Corbin: But how do you get the max of the "other list"
<Corbin>
Have your function recursively call itself.
<octachron>
quartz, with recursion, you need to basically consider that you have already done the computation for the rest of the list and ask yourself how can I compute max (head :: rest) if I know max rest?
<quartz>
But I need some sort of evaluation... like maxSeen < hd
<octachron>
No, no, you are trying to do to much.
<quartz>
Wtf this is so confusing... lol
<octachron>
Recursion is all about being lazy and doing one step at each time.
<d_bot_>
<Butanium (@me on answer)> Ok quartz
<octachron>
Do you know how to compute `max []`?
<quartz>
So I don't need some type of evaulation statement?
<octachron>
Do you know how to compute max (x::rest), if you know max rest?
<octachron>
Then with recursion, you know how to compute max for all lists.
<d_bot_>
<Butanium (@me on answer)> Recursion is like "it'll work at last step (here you know the max if a list with one element) and I have to make it work at steps k"
<d_bot_>
<Butanium (@me on answer)> Step k is what otachron describe
<d_bot_>
<Butanium (@me on answer)> Assume you know what the max of rest is
<quartz>
Rest being tl?
<d_bot_>
<Butanium (@me on answer)> How you compute the max of x and rest
<d_bot_>
<Butanium (@me on answer)> Yes
<d_bot_>
<Butanium (@me on answer)> The rest of the list
<quartz>
Well, you can't? I need two ints to compare
<quartz>
I can't do int < list
<d_bot_>
<Alistair> You have two ints, the head `x` and the maximum of `rest`
<quartz>
But how do you compute the max of "rest"?
<quartz>
That's using the problem to describe the answer
<d_bot_>
<Alistair> Using recursion, we can just use `max rest` to compute the max of `rest`
<octachron>
That's recursion, you can use `max rest`, aka the function that you are defining.
<quartz>
But at what point do I compare the values?
<octachron>
(And that's work because `rest` is smaller than the original list)
<quartz>
Can someone write out an example of a working function that does this?
<quartz>
Just so I can see
<octachron>
Note that you can totally write `| x :: rest -> let max_rest = max rest in `
<Corbin>
You've got all the pieces here already. We've got `x : int` and `rest : list int` and `max rest : int` and `x > max rest : bool`.
<octachron>
Maybe an example of the length function: `let rec len l = match l with | [] -> 0 | x :: rest -> 1 + len rest`
<quartz>
Corbin: So I DO need some type of comparion
<quartz>
Comparison
<d_bot_>
<Alistair> Yes
<quartz>
So the function signature will have 4 parameters?
<d_bot_>
<Butanium (@me on answer)> `max i j` give you the max of i and j
<d_bot_>
<Alistair> Should we move to #beginners so we can write some more code?
<quartz>
If you like.
<quartz>
Ahhh BRB, need to move locations.
quartz has quit [Quit: WeeChat 3.4]
<sleepydog>
recursion is such a wonderful concept :)
<d_bot_>
<colin> The `max = List.hd` is very suspicious.
<d_bot_>
<colin> Generally, you'd you use structural recursion over the list to destructure it, rather than using h(ea)d and t(ai)l.
rgrinberg has joined #ocaml
<d_bot_>
<colin> However, if you want to do it this way, fix the logic and maintain the current "max" as a parameter. You must exhaust the list to make sure you've found the "max". So, if max < List.hd l, then then you do maxVal (List.hd l) (List.tl l) else you do the same except maintain the current max.
<d_bot_>
<colin> So, in other words, if the list is non-empty, you can do `maxVal (if max < List.hd l then List.hd l else max) (List.tl l)`, but this is a mess. You can factor out the common subexpressions.
<d_bot_>
<colin> I use "max" in scare quotes because seeding max with 0 may not work if all your numbers are negative, for example. You really need to seed it with an element from the list for it to truly be working out the maximum.
Tuplanolla has joined #ocaml
<quartz>
Ohhh right
<d_bot_>
<colin> The functional generalisation of looping with an accumulator would be to do this with List.fold_left.
<quartz>
It's best to just get rid of the accumulator thing
<quartz>
Rather, max
rgrinberg has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
<quartz>
God I'm dumb as dirt
<d_bot_>
<colin> Maintaining the current maximum as a good idea. Lots of code in functional programming is written in this way. It's not uncommon to define a function in terms of an initial application of an inner function (partially applied).
<d_bot_>
<colin> Such as the style of doing `let foo = let rec go x = function ... in go y`
<d_bot_>
<colin> Your code isn't very idiomatic because if `List.hd` and `List.tl` do not throw an exception, then the provided list must be non-empty (it must be a cons cell). So these extractions from cons can be more succinctly captured using pattern matching on the list.