BiDOrD has quit [Read error: 110 (Connection timed out)]
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
seafood has quit []
<palomer>
so Buf.contents is not O(1) ?
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
komar_ has quit [Remote closed the connection]
<thelema>
palomer: no, you can't copy an arbitrary large string in constant time.
komar_ has joined #ocaml
<palomer>
let me explain
<palomer>
I'm building a text_view widget
<palomer>
class text_view (r:string ref) = object ... end
<palomer>
now, everytime the text_view will be updated, I want to point r to the new generated string
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
<palomer>
so every time the buffer will be updated, we're looking an O(n) pause
<palomer>
kind of a bummer
<thelema>
why use a standard buffer?
<thelema>
make your own, and use a substring ref for your text_view
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
seafood has joined #ocaml
ccasin has joined #ocaml
seafood has quit [Read error: 60 (Operation timed out)]
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
AxleLonghorn has joined #ocaml
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
olegfink has quit [Read error: 104 (Connection reset by peer)]
komar_ has quit [Remote closed the connection]
olegfink has joined #ocaml
olegfink is now known as Guest49480
Guest49480 is now known as olegfink
komar_ has joined #ocaml
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
shortc|desk has quit ["Probably rebooting."]
xevz has quit [Read error: 60 (Operation timed out)]
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
shortc|desk has joined #ocaml
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
AxleLonghorn has left #ocaml []
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
Camarade_Tux has joined #ocaml
ccasin has quit ["Leaving"]
Camarade_Tux has quit [Read error: 110 (Connection timed out)]
Camarade_Tux has joined #ocaml
ttamttam has joined #ocaml
ttamttam has left #ocaml []
xevz has joined #ocaml
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
flx_ has joined #ocaml
flux has quit [Read error: 104 (Connection reset by peer)]
flx_ is now known as flux
<flux>
palomer, wouldn't displaying said string be O(n) already?
<flux>
palomer, so what's a few O(n)'s among friends..
<flux>
palomer, if your widget isn't displayed at the time of update, perhaps you can make use of lazy values?
<flux>
I imagine it's O(1)
_zack has joined #ocaml
seafood has joined #ocaml
seafood has quit []
seafood has joined #ocaml
seafood has quit []
<mrvn>
Is the text in the widget even long enough that copying the string is a factor?
<flux>
I think he has tons of widgets, most not seen
<flux>
of course, copying short strings can be much faster than doing other complicated stuff
<mrvn>
Coyping a 32 byte string will still be better than some complicated substring reference construct
<mrvn>
Probably 64 or even 128 too.
<mrvn>
Only thing I would startworrying is with multiline text fields with scrollbar and editor function. But maybe there a string isn't the right storage structure.
<tsuyoshi>
hmm.. when should you quit using a string then?
<mrvn>
when you have insert/delete operations in the middle of the string.
<tsuyoshi>
but when you're appending, a string can be slow too
<mrvn>
tsuyoshi: nah, allocate a bigger string and remember how much is used.
<tsuyoshi>
at a certain point using a rope would be faster
<mrvn>
how do you covert a rope into char*?
<flux>
rope is immutable, but can it be safely used as it really were immutable from multiple threads?
<flux>
because it is my understanding it does some mutations under the hood
<flux>
or have I misunderstood it :)
<mrvn>
flux: wouldn't that first create a new rope and then modify that on under the hood?
<flux>
mrvn, well, I wouldn't call it modifying then
<tsuyoshi>
flux: I dunno.. it depends on the implementation doesn't it?
<flux>
tsuyoshi, well, I was thinking the Batteries implementation naturally :)
<mrvn>
Time to extend the Batteries docs about threading safety then
<tsuyoshi>
oh.. well if it mutates under the hood it should protect that with mutexes
<flux>
well, perhaps my worries are unfounded
<flux>
for example the balance operation returns a new rope
<flux>
nice to see that the ropes documentation mentions the complexities
itewsh has joined #ocaml
pants1 has joined #ocaml
Alpounet has joined #ocaml
mlbot has joined #ocaml
pants1 has quit [Read error: 113 (No route to host)]
pants1 has joined #ocaml
rwmjones_ has joined #ocaml
komar_ has quit [Remote closed the connection]
komar_ has joined #ocaml
hkBst has joined #ocaml
itewsh has quit [Read error: 110 (Connection timed out)]
willa has joined #ocaml
willa has left #ocaml []
itewsh has joined #ocaml
LeCamarade has joined #ocaml
Yoric[DT] has joined #ocaml
itewsh has quit [Connection timed out]
itewsh has joined #ocaml
itewsh has quit [Connection timed out]
itewsh has joined #ocaml
LeCamarade has quit [Read error: 60 (Operation timed out)]
LeCamarade has joined #ocaml
itewsh has quit [Read error: 60 (Operation timed out)]
itewsh has joined #ocaml
<Alpounet>
@batteries dev : monad related stuffs pushed on git
itewsh has quit [Read error: 110 (Connection timed out)]
itewsh has joined #ocaml
slash_ has joined #ocaml
itewsh has quit [Read error: 110 (Connection timed out)]
itewsh has joined #ocaml
verte has joined #ocaml
itewsh has quit [Read error: 110 (Connection timed out)]
<flux>
so $ is really taken into use in batteries, it's not problematic regarding language extensions?
<flux>
or arity
<flux>
uh, s/arity/precedence/
<flux>
and whatnots :)
<petchema_>
(camlp4 ?)
<thelema>
I don't think we've changed the rpecedence of ($)
<thelema>
(yet)
<thelema>
iirc, the real problem was the associativity of ($)
itewsh has quit [Connection timed out]
itewsh has joined #ocaml
_yziquel has joined #ocaml
_yziquel has quit [Client Quit]
_yziquel has joined #ocaml
itewsh has quit [Read error: 110 (Connection timed out)]
itewsh has joined #ocaml
Alpounet has joined #ocaml
mlbot has joined #ocaml
willb has joined #ocaml
jeremiah has quit [Read error: 104 (Connection reset by peer)]
itewsh has quit [Read error: 110 (Connection timed out)]
itewsh has joined #ocaml
<kaustuv>
I think 'a Map.S.t should not be covariant on 'a
<_yziquel>
How do you sort efficiently (and lazily if possible) the sums of distinct elements of a given sorted int list?
<flux>
I don't see how lazy it can be
<flux>
you either have the result or don't?
<flux>
hmm, I must've misread
<flux>
what are 'the sums of distinct elements'?
<_yziquel>
i do not have a the result.If a and b are sorted lists, i guess you can compute "sorted a+b" lazily. Sums of distinct elements of the list are, for instance: sorted list is [1;3;7], and the sorted sum of distinct elements is [0;1;3;4;7;8;10;11].
jeremiah has joined #ocaml
<flux>
I'm pretty sure someone one #haskell can be baited to find out an algorithm for you ;-)
<flux>
s/ one//
<_yziquel>
i'll give it a try...
<flux>
hm, I meant to say 'on' actually, but I reparsed my message wrong :)
<palomer>
I don't think the haskell people could give the answer in ocaml
<_yziquel>
i do not mind if the answer is ocaml, haskell, or even cobol. i just care for the algorithmic idea.
<palomer>
with haskell you get lazy for free
<petchema_>
recursively, the sums of all distinct elements of h :: q (h not in q ?) is the sums of all distinct elements of q and the sums of all distinct elements of q with h added to each element... both lists are also sorted, easily mergeable... I suppose it's the idea
<petchema_>
(afk)
<_yziquel>
sure, but you get partial information when you compare small partial sums. Information you could use to merge more efficiently the bigger elements of the sorted lists you describe.
<_yziquel>
i mean, (+) is not just an associative operation.
<_yziquel>
it's also compatible with the order.
<mrvn>
Go through the list recursively and at each step merge sort the list with and without the element added.
<mrvn>
actualy not merge sort but go recursively through creating the new list. The one with the element added is offset by a bit to the one without. you can use that.-
itewsh has quit [Connection timed out]
<mrvn>
Saves you a List.map
itewsh has joined #ocaml
th5 has joined #ocaml
<Alpounet>
Not sure but a bit of monadic syntax can be of help.
<mrvn>
The whole thing is O(2^n) anyway. Not much you can do there.
<mrvn>
kaustuv: why use continutation passing style?
<_yziquel>
Concerning the O(2^n), it does not really matter. The algorithm should not evaluate everything. That's why I need lazyness. But needs to be able to go as far as needed. So you do not go to the full 2^n computation, only a portion of it.
<Alpounet>
mrvn, not really about complexity but implementation and details.
<mrvn>
_yziquel: like only output the first x elements?
<_yziquel>
Yes, but be ready to continue to y > x, and so on...
itewsh has quit [Read error: 110 (Connection timed out)]
<kaustuv>
making either mine or mrvn's solution lazy is a simple matter of changing all the list operations to be lazy (or use a lazy language)
itewsh has joined #ocaml
sOpen has quit [Read error: 110 (Connection timed out)]
itewsh has quit ["There are only 10 kinds of people: those who understand binary and those who don't"]
flux has quit [Read error: 104 (Connection reset by peer)]
<_yziquel>
Thanks for the suggestions. Unfortunately it does not answer my needs. I'll restate my question with more details later on.
flux has joined #ocaml
<mattam>
4444
flux has quit [Read error: 104 (Connection reset by peer)]
<mrvn>
O(1) stack, O(n) space, O(n) initial time, O(n) time per result
<mrvn>
(i think)
<mrvn>
# print (sum [3;2;1]);;
<mrvn>
0, 1, 2, 3, 3, 4, 5, 6,
<mrvn>
Even work with unsorted lists
<Alpounet>
> m7fd849ad1spam
<Alpounet>
personal
<Alpounet>
proprietary
<Alpounet>
other
<Alpounet>
send abuse reporttype work = {
<mlbot>
Syntax Error
<Alpounet>
head : int option;
<Alpounet>
next : unit -> work;
<Alpounet>
}
<Alpounet>
damned.
<mrvn>
wrong window
<Alpounet>
nope
<Alpounet>
I wanted to paste a part of your code to mlbot
<Alpounet>
but my mouse selection went over "report abuse" etc links in pastebin
<mrvn>
> type work = { head : int option; next : unit -> work; }
<palomer>
did anyone resolve skolem's problem from yesterday?
<mlbot>
Syntax Error
<Alpounet>
mrvn, ";;"
<Alpounet>
> type work = { head : int option; next : unit -> work; } ;;
<mrvn>
> type work = { head : int option; next : unit -> work; };;
<mlbot>
type work = { head : int option; next : unit -> work; }
<mlbot>
type work = { head : int option; next : unit -> work; }
<mrvn>
That part?
<Alpounet>
yeah.
<mrvn>
What did you expect to hapen?
<mrvn>
> let rec none = { head = None; next = (fun () -> none) };;
<mlbot>
val none : work = {head = None; next = <fun>}
<mrvn>
Wow, mlbot remebers past lines.
<mrvn>
> start;;
<mlbot>
- : work = {head = Some 0; next = <fun>}
<kaustuv>
> Sys.interactive ;;
<mlbot>
Type Error
<kaustuv>
> Sys.word_size ;;
<mlbot>
Type Error
<kaustuv>
Sys is turned off too?
<Alpounet>
Yep.
<Alpounet>
mrvn, nevermind.
<Alpounet>
And yes, it remembers past lines until "Thread killed" appears
<Alpounet>
> start ;;
<mlbot>
- : work = {head = Some 0; next = <fun>}
<Alpounet>
> let rec f () = f() in f () ;;
<mlbot>
Thread killed
<Alpounet>
> start ;;
<mlbot>
Type Error
<Alpounet>
(I could arrange that, but it would be quite confusing)
<mrvn>
Desn't seem to like long lines though, like the next function.
<Alpounet>
mrvn, which one ?
<mrvn>
> let rec next x low high = match (low.head, high.head) with (None, None) -> none | (None, Some y) -> { head = Some (y + x); next = (fun () -> next x low (high.next ()));} | (Some y, None) -> { head = Some (y); next = (fun () -> next x (low.next ()) high);}| (Some y, Some z) ->if y < z + x then { head = Some (y); next = (fun () -> next x (low.next ()) high); } else { head = Some (z + x); next = (fun () -> next x low (high.next ()));}
<mlbot>
Syntax Error
<mrvn>
> type work = { head : int option; next : unit -> work; }
<mlbot>
Syntax Error
<mrvn>
> let rec none = { head = None; next = (fun () -> none) };;
<mlbot>
Type Error
<Alpounet>
> let rec next x low high = match (low.head, high.head) with (None, None) -> none | (None, Some y) -> { head = Some (y + x); next = (fun () -> next x low (high.next ()));} | (Some y, None) -> { head = Some (y); next = (fun () -> next x (low.next ()) high);}| (Some y, Some z) ->if y < z + x then { head = Some (y); next = (fun () -> next x (low.next ()) high); } else { head = Some (z + x); next = (fun () -> next x low (high.next
<Alpounet>
()));} ;;
<mlbot>
Syntax Error
<mrvn>
> type work = { head : int option; next : unit -> work; };;
<mlbot>
type work = { head : int option; next : unit -> work; }
<mrvn>
> let rec none = { head = None; next = (fun () -> none) };;
<mlbot>
val none : work = {head = None; next = <fun>}
<mrvn>
> let start = { head = Some 0; next = (fun () -> none); };;
kaustuv has left #ocaml []
<mlbot>
val start : work = {head = Some 0; next = <fun>}
<mrvn>
> let rec next x low high = match (low.head, high.head) with (None, None) -> none | (None, Some y) -> { head = Some (y + x); next = (fun () -> next x low (high.next ()));} | (Some y, None) -> { head = Some (y); next = (fun () -> next x (low.next ()) high);}| (Some y, Some z) ->if y < z + x then { head = Some (y); next = (fun () -> next x (low.next ()) high); } else { head = Some (z + x); next = (fun () -> next x low (high.next ()));}
<mlbot>
Syntax Error
<mrvn>
That should work.
<Alpounet>
mrvn, ;;
<mrvn>
*patsch*
<Alpounet>
(it is a toplevel, in fact)
<mrvn>
Maybe that should be implicit
<Alpounet>
it should have given you the right answer in private :)
<Alpounet>
mrvn, "implicit" ?
<Alpounet>
What should be implicit ?
<mrvn>
> print (sum [2;3;5;7]);;
<mlbot>
- : unit = ()
<mrvn>
Alpounet: When it is missing add ;;
<mrvn>
mlbot can't printf.
<Alpounet>
mrvn, hmm...
<Alpounet>
it can, but it's been disabled.
<Alpounet>
here is your answer, I guess : 0, 2, 3, 5, 5, 7, 7, 8, 9, 10, 10, 12, 12, 14, 15, 17,
<Alpounet>
By the way, you can keep the result as a list, and as mlbot behaves like toplevel, it'll give you your result.
<mrvn>
I should filter out the duplicates.
<Alpounet>
> sum ;;
<mlbot>
- : int list -> work = <fun>
<mrvn>
> sum [1;2;3];;
<mlbot>
- : work = {head = Some 0; next = <fun>}
<mrvn>
Not a list
<Alpounet>
(the 0,2,3,5 etc stuffs can be put in a list)
<Alpounet>
(that's what I meant, sorry)
<mrvn>
> let to_list work = let rec loop acc work = match work.head with None -> List.rev acc | Some x -> loop (x::acc) (work.next ()) in loop [] work;;
th5 has quit [Read error: 110 (Connection timed out)]
<palomer>
hrmph, anyone know what the standard key_repeat time and interval are?
<palomer>
oh wait, nevermind
Amorphous has quit [Read error: 110 (Connection timed out)]
<palomer>
next question: how do you add a unicode character to a lowly string using camomile? it's really easy with extlib
kaustuv has joined #ocaml
Amorphous has joined #ocaml
<mrvn>
> type base = { x : int; y : int; } let set_x r x = { r with x = x } type more = { x : int; y : int; z : int; };;
<mlbot>
type base = { x : int; y : int; }
<mlbot>
val set_x : base -> int -> base = <fun>
<mlbot>
type more = { x : int; y : int; z : int; }
<mrvn>
> ((Obj.magic (set_x (Obj.magic { x = 1; y = 2; z = 3; }) 4)) : more);;
<mlbot>
Type Error
<mrvn>
Damn, doesn't work in the bot. I get - : more = {x = 4; y = 2; z = 1019}
<mrvn>
A rather interesting result.-
jeanbon has joined #ocaml
<kaustuv>
not really --- {r with ...} allocates a new base, not a new more
<mrvn>
(and yes, I know why that won't work)
<mrvn>
kaustuv: the interesting part is that it doesn't crash.
_zack has quit ["Leaving."]
flx_ has joined #ocaml
<mrvn>
if z where any boxed types it would segfault I think.
<kaustuv>
that's because the .z offset it's probably still in allocated space. If you try it with a thousand fields, it might crash
kaustuv_ has quit [Remote closed the connection]
<mrvn>
yeah.
kaustuv_ has joined #ocaml
flux has quit [Read error: 104 (Connection reset by peer)]
kaustuv_ has quit [Nick collision from services.]
det has quit [Read error: 104 (Connection reset by peer)]
det has joined #ocaml
<Alpounet>
mrvn, Obj disabled
<Yoric[DT]>
good thing
<Alpounet>
I think so, yep.
<Alpounet>
Yoric[DT], have you seen my ML post ?
<Yoric[DT]>
Seen the post: yes.
<Yoric[DT]>
Acted upon it: no :/
<Yoric[DT]>
I guess I'm a little out of touch with monads currently.
* Yoric[DT]
was burnt out on monads a few months ago :)
<kaustuv>
just say no to monads
th5 has joined #ocaml
<Alpounet>
The man whose paper on error handling with monads is known worldwide... waw :-p
th5 has quit [Client Quit]
<hcarty>
kaustuv: I somewhat agree... I like the fact that monads aren't shoved down your throat in OCaml
<Alpounet>
hcarty, my current work just aims at providing monads in OCaml for either old Haskellers or people that just want to discover what monad are without having to implement them or switch to Haskell.
<hcarty>
Alpounet: Given their popularity in Haskell-land, it is probably useful
<hcarty>
Both for utility and recruitment
<hcarty>
"Come to the OCaml side, we have monads"
<Alpounet>
Yeah, something like that :-)
<mrvn>
our monads are shinier than yours.
<kaustuv>
monads are popular in Haskell land in the same way that oppressive rule by despots is popular in North Korea
flx_ has quit [Read error: 104 (Connection reset by peer)]
flux has joined #ocaml
xevz has quit [Remote closed the connection]
xevz has joined #ocaml
\xs has joined #ocaml
kaustuv has quit ["f49c1faeb04e8f65f9f26a9c7fd0cb50"]
sOpen has quit [Read error: 110 (Connection timed out)]
ReinH has joined #ocaml
<ReinH>
Hi folks
<ReinH>
quick philosophical question: Why do ML languages not use "instance methods" on objects? for instance s.length instead of String.length s ?
<mattam>
The type [string] of [s] and the module [String] have no formal relationship in the type system (altough [string] may happen to be one of the types defined in the [String] module).
<ReinH>
mattam: can you dumb that down a level and give it to me again please? ;)
<ReinH>
Are you saying that it would make type inference more difficult / impossible?
<mattam>
[s] is not an object. It's just a string.
<ReinH>
ah
<ReinH>
because strings are just literals
<mattam>
Like 0 is just an int.
<ReinH>
right
<olegfink>
objects aren't used in standard ocaml environment.
<ReinH>
Ah.
<mattam>
They are mutable arrays of characters.
<ReinH>
So there's nowhere to hang the method
<ReinH>
so to speak
<mattam>
You can build a [string] class if you like though.
<olegfink>
so to speak, ocaml is a language with an object system, not an object-oriented language.
<mattam>
Yep.
<ReinH>
mattam, olegfink: Ok, that makes sense. Thanks!
<ReinH>
s doesn't have a method table like String does.
<ReinH>
because it isn't an object
<ReinH>
cheers
<olegfink>
by the way, does it hold for F#?
<ReinH>
Do people actually use that? o_O
<olegfink>
all I know about F#'s object system is that it is that of .NET, not like ocaml's
<ReinH>
kill it with fire ;)
<Yoric[DT]>
Actually, it would be possible to do things such as [s.length] without method tables.
<mattam>
String does not really have a method table either.
<ReinH>
well, no, I reserve the fire for X#
<olegfink>
Yoric[DT]: camlp4? :-)
<Yoric[DT]>
But it does complicate the type system a lot.
<olegfink>
ah, no, it won't do that
<mattam>
It's a just a collection of types and values/functions.
<Yoric[DT]>
olegfink: more complicated than that :)
<Yoric[DT]>
ReinH: X# is the new Polyphonic C#, isn't it?
<ReinH>
mattam: so no method table because in a functional language, "methods" are just values of a field?
<mattam>
Yoric[DT]: type classes all over again?
<Yoric[DT]>
Well, essentially, yes.
<olegfink>
yeah, by the way, I'm yet to really discover ocaml's object system, but its strict "duck typing" looks like fun (and constraints too)
<ReinH>
mattam: I expect I'm getting some terminology wrong
<Yoric[DT]>
mattam: (although I was more thinking along the lines of "static overloading")
<Yoric[DT]>
(which in turn is along the lines of intersection types)
<olegfink>
Yoric[DT]: by the way, speaking of camlp4, have you seen xoc?
<olegfink>
it's a preprocessor for C very, very much like camlp4
<mattam>
ReinH: I mean, method tables are used to support overloading (redefining one method) where modules do not support that. No late binding involved.
<olegfink>
save for the fact that preprocessor's own language is a special one, not C
<Yoric[DT]>
Interesting.
<Yoric[DT]>
ReinH: in object languages, everything is an object, which means among other things that everything has a method table.
<Yoric[DT]>
ReinH: in OCaml, most things are not objects, hence have no method table.
* mattam
's off to eat something
<Yoric[DT]>
hence "nowhere to hang" stuff indeed.
OChameau has quit ["Leaving"]
<mrvn>
ReinH: as instance method you would have to write s.String.length so the type inference could know that you s is a String.t.
<mrvn>
Yoric[DT]: In C++ you don't haveto have a methoud table for objects. Not always.
<ReinH>
Yoric[DT]: right, that's what I was getting at :)
<mrvn>
ReinH: I would think the main reason for using "String.length s" instead of "s.String.length" is
<mrvn>
> String.length
<mlbot>
Syntax Error
<mrvn>
;;
<mrvn>
> String.length;;
kaustuv has joined #ocaml
<mlbot>
- : string -> int = <fun>
<mrvn>
It is a function which means it is a value like any other thing and you can pass that as argument to other functions.
<ReinH>
right
<mrvn>
Allowing for s.String.length as well as String.length s would just give 2 ways of doing one thing.
<ReinH>
I don't see much value in s.String.length
<ReinH>
so that makes sense
<ReinH>
so my original guess that it would make type inferrence impossible was correct as well
<ReinH>
(the s.length version)
<ReinH>
cool, thanks for the discussion :)
<mrvn>
ReinH: nah. the type inference of "s.length" and "length s" both doesn't work.
<ReinH>
right
<mrvn>
You can write a string class.
<mrvn>
> class string s = object val s = s method get = s method length = String.length s end;;
<mlbot>
Symtable.Error(_)
<mrvn>
Huh, no classes allowed in the bot?
<Alpounet>
They are.
<Alpounet>
> object end ;;
<mlbot>
Symtable.Error(_)
<Alpounet>
hmm
<mrvn>
# let s = new string "Hallo";;
<mrvn>
val s : string = <obj>
<mrvn>
# s#length;;
<mrvn>
- : int = 5
<Alpounet>
> class foo x = object val bar = x method get = bar end ;;
<mlbot>
Typeclass.Error(_, _)
<Alpounet>
weird.
<mrvn>
With a class you actually have the instance method syntax. But if the string class is defined in a module S then you have: # let str = new S.string "Hallo";;
<mrvn>
val str : S.string = <obj>
<mrvn>
# str#length;;
<mrvn>
- : int = 5
<ReinH>
ah
<ReinH>
but that's not very idiomatic
<mrvn>
# let f s = s#length;;
<mrvn>
val f : < length : 'a; .. > -> 'a = <fun>
<mrvn>
# f str;;
<mrvn>
- : int = 5
jeanb-- has joined #ocaml
<mrvn>
The types get kind of complicated that way though.
jeanbon has quit [Nick collision from services.]
jeanb-- is now known as jeanbon
<mrvn>
# let f s = String.length s;;
<mrvn>
val f : string -> int = <fun>
<mrvn>
That gives a much nicer type.
<mrvn>
methods in ocaml are always virtual and never final or static. And they are (in C++ terms) either public or protected.
<mrvn>
Alpounet: Any idea what's wrong with the bot?
monadic_kid has joined #ocaml
itewsh has joined #ocaml
<Alpounet>
mrvn, nope... It just runs a toplevel (using the Toploop module)
<Alpounet>
so it should work !
<kaustuv>
> let ( |>> ) x y = let s x y z = x z (y z) in let k x y = x in let i x = x in s (s (k s) (k i)) (s (k k) i) x y ;;
<mlbot>
val ( |>> ) : 'a -> ('a -> 'b) -> 'b = <fun>
<kaustuv>
> "hello, world" |>> (fun x -> x) ;;
<mlbot>
- : string = "hello, world"
<kaustuv>
seems fine to me
<mrvn>
kaustuv: and you don't say let ( |>> ) x y = y x because?
<mrvn>
> let rec reset () = reset () in reset ();;
<mlbot>
Thread killed
<aij>
heh
<mrvn>
aij: Batteries does.
<mrvn>
It misses const strings though.
jonafan_ has joined #ocaml
<aij>
mrvn: what's the distinction you're making?
* aij
hasn't used batteries
<kaustuv>
aij,mrvn: it works better in French
<kaustuv>
> let module M = struct type bull = Vrai | Faux let string_of_bull = function Vrai -> "Vrai" | _ -> "Faux" end in String.blit "Faux" 0 (M.string_of_bull M.Vrai) 0 4 ; M.string_of_bull M.Vrai ;;
<mlbot>
- : string = "Faux"
<mrvn>
> let str = "Hallo" in let immutable_str = (str : ['Read] string) in str.[0] = 'h'; immutable_str;;
<mlbot>
Syntax Error
<mrvn>
(whatever the batteries syntax is to make a string read only)
<aij>
kaustuv: I think your string_of_bull doesn't have the same problem as the one in Pervasives
<mrvn>
aij: An immutable string might still have mutable references to the string hanging around that can change the string.
<aij>
mrvn: that defeats most of the point of having immutable strings
<flux>
aij, it doesn't, if the such holders don't change it :)
<mrvn>
aij: Passing an imutable string to a function garanties that that function can not alter the string. returning an immutable string means that the reciever can not alter it.
<kaustuv>
aij: I thought that example demonstrates that it has exactly the same problem
<mrvn>
kaustuv: it did
<mrvn>
aij: Problem is just that recieving an immutable string does not mean the string never changes. Just that you can not change it.
<aij>
kaustuv: oh, right, I'm dumb :P
<flux>
mrvn, unless an immutable string can only be constructed from a mutable one by copying
<kaustuv>
I think the problem is that "false" does not mean "allocate a string of length 5 and fill it with f, a, l, s, e"
<mrvn>
flux: then that would be costly.
<aij>
kaustuv: for some reason I thougth your function would be creating a new string each time
<mrvn>
kaustuv: no, "false" is an object in the text section that can be freely modified.
<aij>
mrvn: do they at least use a good representation for immutable strings?
<flux>
mrvn, well, you could use mutable strings when you need performance
<aij>
or is it just an abstract type that is equal to string, but doesn't come with mutating functions?
<flux>
mrvn, very likely when you construct a string you are using Buffer anyway
<flux>
mrvn, or otherwise doing it very inefficiently
<mrvn>
aij: ['Read | 'Write] string
<flux>
mrvn, other string constructing functions (like .init, .make, .of_enum) could be in the string module and they could overcome that performance limitation
<mrvn>
flux: but you could easily have both const and immutable strings where const means copying.
<flux>
mrvn, I'm not sure if that kind of distinction is required, or useful. even java does without mutable -strings- ;)
<flux>
while it it true that ocaml's polymorphism could handle that kind of things more nicely (for example one function could accept all kinds of strings, or just immutable/const, or just const), it doesn't always work
<flux>
as you may have noticed with objects.. did the constraints ever work with the forall construct in methods?
<mrvn>
flux: All it would take is adding "let const (s : [> 'Read ] string) = ((String.copy s) : ['Const] string)"
<flux>
mrvn, and how about interfacing with libraries that are not aware of this string?
<mrvn>
flux: constraints in objects are not for methods so that can never work.
<mrvn>
flux: they have to be made aware of Read/Write already. Adding the Const doesn't make it more work.
<flux>
mrvn, so batteries' string literals of type other than ocaml's string?
<mrvn>
flux: yes
<flux>
well, in that case, Const doesn't sound that bad
<kaustuv>
what is the difference between [ `Const ] and [ `Read ]?
<flux>
I wonder how much of an intellectual boundary all this represents to a guy trying to get into ocaml :)
<mrvn>
flux: All I mean is that the Batteries ['Read 'Write] types could/should also have the Const phantom type.
<mrvn>
kaustuv: Read means you can not alter the string, Const means the string can not be altered period.
<kaustuv>
how can you enforce the latter when the runtime has only mutable strings?
<flux>
kaustuv, simply don't provide mutators for that type..
<mrvn>
kaustuv: by defining a function that creates a const string by using String.copy and no way to un-const it.
<flux>
and the copying thing as mrvn just showed
<mrvn>
kaustuv: Obj.magic-ing the string to be mutable doesn't count as violation of the constness. That is the users problem then.
jonafan has quit [Read error: 110 (Connection timed out)]
<flux>
actually wouldn't they always be [`Read | `Const] strings, not just plain [`Const]..
<kaustuv>
the way I see it, `Read and `Write are abilities whereas `Const is an assurance. They are different things and should not be m{i,u}xed
<kaustuv>
might be better to have `Readble, `Writable and `Mutable
<flux>
`Writable and `Mutable sound too much same
<flux>
I think the distinctions `Read, `Write, `Const do make sense more, while they are different kinds of attributes
<kaustuv>
the only distinction that matters is Const | Mutable. They should not be poly. variants
<kaustuv>
"There ain't no such thing as a const write-only string"
<flux>
I have no problem with types without values :)
<mrvn>
Maybe one realy does need [`Const | `Mutable] * [`Read | `Write] t. I think otherwise let f (x : [> `Const | `Read] t) = x;; f (x : [`Const] t) would add `Read to the type.
<mrvn>
or Const if it is only Read
<kaustuv>
Const | Mutable is nature, Read | Write is permission.
sporkmonger has quit []
<kaustuv>
with the proviso that Const * Write is uninhabited
<mrvn>
kaustuv: yes. and both can be needed. Although Const isn't used often.
<mrvn>
By the way, why do phantom types only work if I hide them in a module?
<flux>
yes
<flux>
oh, why
<flux>
well because they are just type aliases
<flux>
type t = string let a : t = "str" let _ = (a : string) works just fine
kaustuv has quit [Read error: 60 (Operation timed out)]
<mrvn>
But that means that inside the module if one function calls another then the Read/Write phantom types will be completly ignored.
<flux>
yes
<flux>
they are for the external interface
ttamttam has joined #ocaml
<mrvn>
Can I use module M = struct type `Read type `Write end type `Read = M.`Read type `Write = M.`write?
<mrvn>
Or is there another way to make them work inside the module as well?
<flux>
type `Read is nonsense?
<flux>
you can put the phantoming part into a module inside your module
<flux>
the constness does make the interface a bit more complicated
<flux>
if you want to provide performant operations for converting from a phantom string back to a regular string
<flux>
because you need to have two functions: one for const strings, one for non-const..
<kaustuv>
> let strdup s = "" ^ s ;;
<flux>
unless you put a flag inside the string to indicate whether it's const or not
<mlbot>
val strdup : string -> string = <fun>
<kaustuv>
> let a = "a" in let b = strdup a in b.[0] <- 'b' ; a, b ;;
<mlbot>
- : string * string = ("a", "b")
<flux>
kaustuv, String.copy not good enough for you?-)
<flux>
or just testing string concatenation with that?
itewsh has quit [Connection timed out]
<palomer>
whoa, there's already a sexplib clone
<kaustuv>
""^ is fewer chars than String.copy
<flux>
I suppose the compiler or runtime library could even optimize that away
<flux>
kaustuv, it's also likely less efficient.. marginally, atleats :)
<flux>
palomer, hm?
<palomer>
ocamltarzan
itewsh has joined #ocaml
<flux>
Your search - ocamltarzan - did not match any documents.
<kaustuv>
ocamltarzan competing with ocamljane (st. capital)?
<flux>
sexplib is great
<flux>
how would one improve on that :)
<palomer>
it's on caml-list
mlbot has quit [Read error: 60 (Operation timed out)]
<flux>
ah
<flux>
if there's something missing it's pattern matching sexps
<flux>
but that's not a biggie
<palomer>
pattern matching sexps?
<flux>
ah, it's a fork
<flux>
palomer, yeah, like match foo with (a (bar baz)) or something
<flux>
in general a syntax extension for expressing sexps
<palomer>
that's cool!
<kaustuv>
flux: basically you want to turn OCaml into Scheme, don't you? Admit it!
<palomer>
we could make a programming language based on sexplib
<palomer>
let's call it...lisp
<flux>
kaustuv, argh, you got me!
<flux>
palomer, but actually ocaml already comes with pa_lisp
<flux>
s/palomer/kaustuv/, but it goes for both of you ;)
<flux>
or was it pa_scheme
<flux>
ocamltarzan seems pointless to me
<flux>
it only makes the camlp4 off from the compilation procedure
<flux>
you generate the code once and use that
<flux>
"better control on the code generation as can easily customize later the generated code" - no thanks, I don't want to edit generated code I might want to regenerate some day
<flux>
but apparently the author has been bit by this camlp4 version thingy and bugs :)
<palomer>
I have to say...putting PA_TYPE_CONV everywhere is a little bit of a bummer
<palomer>
and it changes the syntax errors
jeanb-- has joined #ocaml
<flux>
PA_TYPE_CONV is a little price to pay for using sexplib
<flux>
and apparently it serves some purpose although I'm not sure what :)
<palomer>
but the syntax errors!
<flux>
yes, that sucks
<palomer>
also, it seems that camlp4's syntax is a little more relaxed
<palomer>
some stuff camlp4 allows that caml doesn't (from my experience)
jeanbon has quit [Nick collision from services.]
jeanb-- is now known as jeanbon
<mrvn>
flux: the of_const needs to copy.
<palomer>
the biggest bummer, however, is that you can't sexplib if you have external libraries
<flux>
mrvn, ah, right
<palomer>
so as someone whose writing a library, I'm having to sexplib all my datatypes for my users, even though my library doesn't use sexplib
<flux>
mrvn, actually I was thinking that as an interface to 'old code' that doesn't understand strings but still handles them as const
<flux>
which is, most of the code :)
<flux>
palomer, that is true
<kaustuv>
palomer: this problem exists for any library writer --- how many type classes to provide instances for
<mrvn>
flux: but that gives no garanties. You can not assume that.
<flux>
palomer, but how else would sexplib know how to sexpise your data structures.. you might even want to have custom handling at cases.
<flux>
mrvn, you know what: I'll rename it to unsafe_of_const :)
<flux>
mrvn, it'd work similarly to c++'s const_cast
<flux>
now, updated
<flux>
there's no need to use it if you don't want to
<mrvn>
flux: you might want an unsafe_of_rdonly too.
<flux>
yeah
<flux>
in any case, that is not meant to be used, I imagine batteries has a well-thought version of that. but without the `Const..
<mrvn>
rename string to make and have string and unsafe_string
<mrvn>
and safe_string to convert from a writable string to string
<mrvn>
It is too bad one can't have a function that copies only if `Write is not given.
<flux>
bah, write your own fork, I shall give that as public domain :)
Alpounet has quit [Read error: 110 (Connection timed out)]
<flux>
mrvn, you mean `Const?
<flux>
or not?
<mrvn>
no, `Write.
<kaustuv>
is = optimized for `Const strings?
ztfw has joined #ocaml
<mrvn>
kaustuv: = just copies the value, the pointer to the block
<mrvn>
or rather binds the value
<kaustuv>
I mean ( = ), the operator
<flux>
kaustuv, how would it be optimized for const strings?
<kaustuv>
to be the same as ( == )
<flux>
kaustuv, it does check for identity AFAIK in 3.11 atleast
<flux>
before doing the full check
Alpounet has joined #ocaml
<ztfw>
hi, i'd like to know if the keyword "where" actually exists or not, i've seen it many times but can't figure out how to use that
<flux>
kaustuv, well, it's the same, regardless of constness?
<mrvn>
let ( = ) x y = x == y || x = y?
<kaustuv>
ztfw: it's not part of the core ocaml language
<flux>
I'm not sure if that holds in general
<flux>
but iirc that holds true for strings in the latest caml
<mrvn>
> let f x = match x with x when x = 1 -> 1;;
<ztfw>
kaustuv: i see, thanks.
<mrvn>
ztfw: do you mean when?
<ztfw>
mrvn: the one that works like "in" but the other way around
<mrvn>
ztfw: urgs. No, please no.
<flux>
:)
<kaustuv>
ztft: that's a batteriesism
<ztfw>
a what?
<flux>
pa_where has existed before batteries
<mrvn>
That is perlism
<kaustuv>
a syntax extension that has been embraced and extended by batteries
<flux>
I'm not particularly a fan or 'where' - it makes more sense in haskell with its laziness and pureness
<ztfw>
huuh alright
<mrvn>
It totaly screws up the flow. The execution order is totaly reversed.
<ztfw>
i'm not a perl-user anyway
<_yziquel>
anyone knows of a type for sorted data that can be accessed both as a tree and as a list?
<flux>
then again I've never used it. perhaps "where" is really great. most of the code is pure anyway.
<kaustuv>
type 'a sorted = 'a tree * 'a list?
<_yziquel>
and thanks for the code samples, though it's not exactly what i'm looking for...
<mrvn>
_yziquel: Set?
<_yziquel>
kaustuv: that's the type for users, but the implementation?
itewsh has quit [Read error: 110 (Connection timed out)]
<_yziquel>
mrvn: is their an equivalent in constant time for hd?
<kaustuv>
if you have a tree, you can get a list-like view of its traversal. To see an example, get the ocaml source and look inside stdlib/map.ml and stdlib/set.ml
itewsh has joined #ocaml
<_yziquel>
kaustuv: thanks.
<mrvn>
_yziquel: Set.min_elt. No idea if that is O(1) or O(log n)
<kaustuv>
it's O(log n)
<mrvn>
_yziquel: You an build a tree where all elements in the tree are also linked in order.
Smerdyakov has joined #ocaml
<flux>
nice idea
<flux>
I wonder how much it affects the complexities, if at all
<kaustuv>
good luck implementing O(log n) insert and delete with that
<mrvn>
But an List.tl equivalent won't give you a subtree. That won't work nicely I think.
<_yziquel>
mrvn: ok, but when i take the tail of the list, it's not anymore a tree.
<mrvn>
_yziquel: exactly.
<mrvn>
_yziquel: unless you remove the head, which makes it O(log n)
<kaustuv>
Look, O(log n) is practically O(1) unless you are dealing with O(Google) data
<mrvn>
kaustuv: that is trivial. Removing an element from a double linked list is O(1)
<kaustuv>
oh, you want a mutable ds
<_yziquel>
i got a O(2^n) algorithm, that's why...
<_yziquel>
s/got/got to deal with/
<mrvn>
kaustuv: only way to do it I think.
ttamttam has left #ocaml []
<mrvn>
_yziquel: do you really need List.tl in O(1)?
<flux>
..could zippers help with this?
<mrvn>
One important fact though: All this assumes an imperative tree, not a functional one.
gl has joined #ocaml
<flux>
iirc oleg had a functional doubly linked list
<gl>
good evening #ocaml
<_yziquel>
Yep, but i do not care about remove or insert. I only care about merged this ordered structure.
<mrvn>
flux: how do you do that without copying the complete list every time?
<kaustuv>
_yziquel: sounds like you need a heap
<flux>
mrvn, by doing something very olegishly clever perhaps
<_yziquel>
mrvn: but i need it pure, not imperative.
<mrvn>
_yziquel: what exactly do you need for operations?
<_yziquel>
mrvn: Taking subtrees, consing subtrees, hd, tl, and accessing the data.
<_yziquel>
mrvn: and also consing lists.
<mrvn>
flux: That is cheating. It uses IM.IntMap, which is either a functional hashtable [O(n) insert] or a tree [O(log n) insert]
<mrvn>
or verry memory inefficient
<mrvn>
_yziquel: no balancing of trees?
<kaustuv>
int maps can be O(log k) insert where k is 31 or 63
<_yziquel>
no balancing needed. at all.
<mrvn>
kaustuv: radix tree
<mrvn>
kaustuv: why log k and not k?
<kaustuv>
err, right, O(k)
<mrvn>
and k > log n
<kaustuv>
ah, but O(k) < O(log n)
<mrvn>
never.
<flux>
never?
<mrvn>
kaustuv: To allow for n > 2^31 or > 2^63 you need k > 31 or > 63.
<flux>
it all depends on the constant factors which cannot be seen
<flux>
you can't just take the number inside the parens and compare that
<mrvn>
What they do here is say that all keys can be indexed as int and int is a fixed size k so we can do this in O(k).
<flux>
tada :)
<mrvn>
But that is just cheating. Correctly the index for all keys must be >= log(n).
<flux>
but, I'm off to sleep
<mrvn>
By claiming it is const you limit the maximum n you can have and then O(n) is const too.
<kaustuv>
If you have > 2^63 elements in your list, I want to know where you bought your computer
<mrvn>
kaustuv: sure. but that is not how O() works.
sOpen has joined #ocaml
<mrvn>
_yziquel: what do you mean by accessing the data?
<mrvn>
_yziquel: for random access you do want some balancing.
<_yziquel>
nothing: when the tree is a leaf, just obtaining the data inside.
<mrvn>
head will do that
<mrvn>
So far everything can be done with just a list except taking subtrees.
Smerdyakov has quit ["Leaving"]
<mrvn>
Do you want the subtree of all elements smaller than x?
_andre has quit ["Lost terminal"]
<_yziquel>
mrvn: what is want is to be able to construct such a structure (and yes, I need to take subtrees), and if it gets unbalanced, i.e. light on the head side, it's quite fine with me: I need to access data lazily, and it's better if i get the small data faster (small data on the head side).
<mrvn>
but what form of subtree?
sOpen has quit [Read error: 104 (Connection reset by peer)]
<_yziquel>
From small trees, you merge them with respect to the order, and you get a bigger tree. Then, you can use the structure to recursively descend into left subtree (small data) and right subtree (bigger data).
<mrvn>
So split at the root. That is easy.
<_yziquel>
Yes, but I need to access the head of each subtree in constant time...