Alpounet changed the topic of #ocaml to: Discussions about the OCaml programming language | http://caml.inria.fr/ | 3.11.1 out now! Get yours from http://caml.inria.fr/ocaml/release.html - Answer OCaml Meeting 2010 poll https://forge.ocamlcore.org/survey/survey.php?group_id=77&survey_id=1
_unK has quit [Remote closed the connection]
tmaedaZ0 has joined #ocaml
tmaedaZ has quit [Read error: 110 (Connection timed out)]
ski_ has quit ["Lost terminal"]
thrasibule has quit [Read error: 110 (Connection timed out)]
struktured has joined #ocaml
sysop_fb has joined #ocaml
a_m0d has joined #ocaml
Associat0r has joined #ocaml
ulfdoz_ has joined #ocaml
thrasibule has joined #ocaml
ulfdoz has quit [Read error: 145 (Connection timed out)]
ulfdoz_ is now known as ulfdoz
a_m0d is now known as a_m0d|away
Associat0r has quit []
Pimm has quit [Read error: 110 (Connection timed out)]
tab_ has joined #ocaml
julm has quit [Read error: 104 (Connection reset by peer)]
julm has joined #ocaml
tab has quit [Read error: 104 (Connection reset by peer)]
ski_ has joined #ocaml
delsvr_ is now known as delsvr
sporkmonger has joined #ocaml
<a_m0d|away> anyone know any links for writing ocaml bindings to c++ functions?
a_m0d|away is now known as a_m0d
sysop_fb has quit []
Modius_ has joined #ocaml
<mrvn> a_m0d: I think you need to write a C stub for them
<a_m0d> what about if the whole api is class based?
<mrvn> especially then
<a_m0d> oh
<a_m0d> so do I have to pass objects in as pointers in the c code, and then call member functions on the pointers?
<mrvn> extern "C" { int foo_bar(Foo *foo) { return foo->bar(); } }
Modius has quit [Read error: 145 (Connection timed out)]
<mrvn> ocaml doesn't know how to dispatch c++ methods or even what the function name will be. C++ includes the types in the name.
<a_m0d> okay
<a_m0d> thanks
thrasibule has quit [Read error: 110 (Connection timed out)]
a_m0d is now known as a_m0d|away
ttamttam has joined #ocaml
struktured has quit [Connection timed out]
ttamttam has quit ["Leaving."]
csmrfx has joined #ocaml
<csmrfx> Whats the best short intro book into ocaml for developers?
ski_ has quit ["Lost terminal"]
ikaros has joined #ocaml
zhijie has quit [Read error: 110 (Connection timed out)]
valross has quit [Remote closed the connection]
ikaros has quit ["Leave the magic to Houdini"]
ygrek has joined #ocaml
Yoric[DT] has joined #ocaml
albacker has joined #ocaml
a_m0d|away has left #ocaml []
ttamttam has joined #ocaml
tmaedaZ0 is now known as tmaedaZ
Yoric[DT] has quit ["Ex-Chat"]
tmaedaZ is now known as tmaedaZ0
sporkmonger has quit []
ski_ has joined #ocaml
ua has quit [Read error: 60 (Operation timed out)]
alp_ has joined #ocaml
Alpounet has quit [Read error: 113 (No route to host)]
Yoric has joined #ocaml
eni_ has joined #ocaml
albacker has quit [Read error: 60 (Operation timed out)]
tmaedaZ0 is now known as tmaedaZ
dmentre has joined #ocaml
tmaedaZ is now known as tmaedaZ0
<tiz_> The tutorial in the manual is pretty good.
delsvr has quit []
<Yoric> hi
<csmrfx> hm, pretty good != the best
_zack has joined #ocaml
<tiz_> It may be the best, if all the others are less than pretty good :P
<csmrfx> Ah, elementary, Mr. Watson
tmaedaZ0 is now known as tmaedaZ
ua has joined #ocaml
_unK has joined #ocaml
munga_ has joined #ocaml
ygrek has quit [Remote closed the connection]
<Leonidas> hmm, can I do a match on a specific element of a list?
<mrvn> match list with _::_::17::_ ->
tmaedaZ0 has joined #ocaml
<Leonidas> that looks interesting, trying it
_andre has joined #ocaml
<Leonidas> or no, wait, this is the code: http://paste.pocoo.org/show/152392/
<Leonidas> I have a list of pairs and I am trying to match the pair where w equals w2
<mrvn> | (a, b)::xs when a = x2 and b = n ->
tmaedaZ has quit [Read error: 110 (Connection timed out)]
<Leonidas> Ah, I get the type error now :)
<Leonidas> mrvn: thanks, that looks good
<Leonidas> wow, incredibly elegant solution
<Leonidas> can a certain key name be only part of one record type? Because I am using 'name' in two records and the interpreter seems to mix them up
<Leonidas> Error: The record field label name belongs to the type kunde but is mixed here with labels of type ware
<Camarade_Tux> you can't use the same name in several records
<Leonidas> oh, a pity.
<Leonidas> it could at warn me when I define the types..
<Camarade_Tux> true
<Leonidas> http://paste.pocoo.org/show/152393/ - I am impressed how well this works out.
<Leonidas> but why doesn't it complain about the lack of 'let rec'?
<Leonidas> it is a recursive function...
<Camarade_Tux> are you in the toplevel?
<Leonidas> yep, including code via #use
<olegfink> okay, I think I have the stupidest question I have ever asked here: if I want to generate some LLVM assembly with OCaml, should I use ocaml llvm bindings or hlvm? Or hlvm is something completely different?
<Camarade_Tux> you probably have a previous definition of your function
<Camarade_Tux> Leonidas: try closing and reopening the toplevel ;-)
<Leonidas> Camarade_Tux: true. Indeed, that was it.
<Leonidas> can I have polymorphic records? I have this ware-record and I would like to have the type of price parametrized.
ygrek has joined #ocaml
<Leonidas> ok, got it working.
<Leonidas> No idea what went wrong previously
Pimm has joined #ocaml
* mrvn wants prefix types.
<flux> what are those?
<mrvn> type a1 = { x : int } let get a = a.x type a2 = { a1 with y : int } let _ = get { x = 1; y = 2 } ikind of things.
<mrvn> a1 is a prefix of a2.
<flux> well, you've got the source :)
<Leonidas> can I put multiple clauses into a when?
<flux> mrvn, your syntax suggestino seems reasonable. however, how would that interact with type inference?
<flux> leonidas, it's one boolean expression, it can be composed of many expressions
<mrvn> flux: We already have [< ], [> ] and < .. > types.
<flux> mrvn, but they are sort of structural types
<Leonidas> flux: oh, right (shame on me for *that* question)
<mrvn> a1 is < x : int >, a2 is < x: int; y : int > an get takes a < x: int; ..>
<mrvn> except with records instead of classes.
<mrvn> I would think as type it would be { x : int; .. }
<flux> mrvn, wouldn't that completely change the way records are handled..
<mrvn> type a1 = Foo type a2 = Foo | Bar could use [</[> syntax like private types.
<mrvn> flux: How are records handled? acess to members is by offset. That remains.
<flux> mrvn, but the record types would change
<mrvn> flux: and copying like { a with x = 17; } can copy the memory representation of a whatever its length is.
<flux> mrvn, for example the types of let foo a = a.x and let foo a = a.y
<mrvn> flux: I would suggest that they default to strict types like now and one can annotate when they should accept prefixes.
<mrvn> let foo (a : { x:int; .. }) = a.x
<mrvn> maybe { a with .. } so one doesn't have to retype the type.
<flux> definitely with the 'with' if that kind of prefix-limitation is there, otherwise the syntax would allow all kinds of things that are not supported?
<mrvn> No. Don't think so. The "with" would just be saving keystrokes.
<mrvn> foo should accept anything that has an x:int as first element of its record even if it is not derived from a I think.
<flux> well, let foo (a : {x : int; y:int; ..}) = .. let bar (a : {x: int; z:int; ..}) = .. let baz (a : {x: int; z:int; ..}) = .. wouldn't these all accept type a = {a : int; b : int; z:int; }?
<flux> well, I guess not if the name and order of fields is signnificant, which I believe you're suggesting
<flux> however it sounds more fragile
<flux> if you need to state the order of the fields all over the code
<mrvn> The order and type of fields is relevant. The name can be relevant or not.
<mrvn> flux: yeah, the "with" syntax is to void repeating the type all over. WOuld make it error prone and hard to change the type.
<mrvn> The a in { a with ...} is sort of like a class type.
<flux> perhaps you should make a writeup of the idea with all the cases covered
<flux> basically it would be a limited form (for performance reasons) of structural records ala SML, right?
<mrvn> don't know sml
<mrvn> It would be a limited form of ocaml classes with performance benefits.
<mrvn> and less space required
<flux> neither do I, but someone here advocated its features every now and then :)
<mrvn> For the implementation I think only the {a with x = 17; } code generation would have to be changed. All the rest is just type inference.
<flux> hmm.. why would it be changed?
<mrvn> flux: I thing is allocates a new block the size of the resulting type and then copies the data. WIth { a with .. } is has to allocate memory as large as the input type at runtime.
<mrvn> It doesn't know the size at compile time.
<flux> hm, right
<mrvn> Would make it slower than not prefixed types but still a lot faster than objects.
<flux> I might thing that the other advantage of having the capability to share record field names with semantically similar records would even be greater.. not everyone are as performance-obsessed as you :)
<mrvn> flux: You have that in classes. They are just slow and give ugly errors.
<flux> you don't have pattern matching and other nice stuff of records with classes
<flux> well, there's a syntax extension for pattern matching, haven't tried it..
<mrvn> and I think you can't "match a with { x = 17 } ->" with classes, right?
<mrvn> hehe. :)
<mrvn> LAG
<mrvn> flux: If you have type vec2 = { x:float; y:float } type vec3 = { vec2 with z:float } then the speed difference to classes is astronomical.
<flux> maybe that 'with'-kind would be useful even without more complicated typing. conside that vec2/vec3 example. you could have functions like: let vec3_of_vec2 x = { (type vec2) a with z = x } and let vec2_of_vec3 x = (x : vec3 :> vec2)
<flux> no new types. you wouldn't have the polymorphicity you want, though.
<mrvn> flux: yeah. vectors are a bad example anyway. YOu don't want to call Vec2.add on a Vec3.t.
<mrvn> flux: Currently I have a vec2_of_vec3 with Obj.magic
ygrek has quit [Remote closed the connection]
<mrvn> A vec3_of_vec2 is dangerous though.
<Leonidas> I have a question on the type system and I suppose the key to the question are the option types, but i don't yet see 'how':
<Leonidas> I have a function, max which returns the maximum object (for some definition of maximum) of a list. But what if the lsit is empty?
<Leonidas> I could return None, but then the type of the [x] -> x case is incorrect
<Leonidas> as x is not an option type
<tiz_> [x] -> Some x
<Leonidas> tiz_: yeah, I figured that out, but then I get into problems in the case with two elements:
<Leonidas> how do I compare two option types?
<tiz_> Use pattern matching to get the actual values out of the option types and compare them.
aklt has joined #ocaml
<Leonidas> hmm, will try.
<tiz_> This isn't perfect (not tail recursive) but it's the simplest version of what you want and will show the principle:
<Leonidas> tiz_: hmm, interesting.
<tiz_> The alternative is to throw an exception, and make it the callers responsibility to check the list is non-empty.
<Leonidas> no, I think I'll prefer the option types
<tiz_> I probably would too.
<tiz_> It makes it harder for the caller to ignore the possibility of something going wrong.
<Leonidas> Error: This expression has type int ware * int but an expression was expected of type int ware * int
<Leonidas> tiz_: yep. Furthermore, I already know exceptions, but option types are new to me
<tiz_> Do you need that error message explaining?
<Leonidas> tiz_: oh, nice page. Haven't seen that one yet. Thanks :)
<Leonidas> is there a way to unify calculation with numbers like for example the max function does?
<flux> you can get sort of the same effect with objects, but it means you also need to wrap each number into one before proceeding
<Leonidas> for example, if I want to multiply x with y, with both having type 'a
nagnatron has joined #ocaml
<flux> the problem is that you cannot multiply everything
<flux> like lists or sockets
<Leonidas> oh, that sounds like too much of a hassle for what I am trying to do.
<thelema> since ocaml has a polymorphic compare, you can compare anything, though.
<flux> ..except functions
<mrvn> Leonidas: I would write 2 functions:
<mrvn> 1) let rec max_or_default def = function [] -> def | x::xs -> max_or_default (max x def) xs
<mrvn> 2) let max = function [] -> None (* or raise Empty *) | x::xs -> max_or_default x xs
<flux> pft, how often is max_or_default useful? alternatively you could use ExtLib's Option-module to extract values with default values out of an option type..
<mrvn> flux: every time you call max. :)
<mrvn> let max x = let rec max_or_default ... in ... works too.
<mrvn> I believe having a helper function without option type will be much better for the compiler.
<flux> ..if performance is everything :)
<mrvn> easier to read too.
<flux> max_or_default a b, which one is the default?
<mrvn> flux: It is a helper function. YOu probably would not put that into the mli file.
<Jedai> Leonidas: If you want something like that (a multiplication function that works for several types for which it makes sense) you may investigate the typeclasses from Haskell
<Jedai> Leonidas: Or you could try the OO part of OCaml, though that doesn't bring the same kind of facilities
<Leonidas> Jedai: the point is, I am doing my homework and while I would like to have an awesome solution, that works on everything, I don't think that it is a good idea to go into typeclasses.
ikaros has joined #ocaml
<flux> leonidas, well, you could functorize your solution
<Jedai> Leonidas: Well probably not in this case
<flux> leonidas, but I'm guessing you haven't covered functors just quite yet..
<Leonidas> flux: no, not yet. First homework in Ocaml. So far it has been quite fun :)
<mrvn> Leonidas: YOu can define a class arithmetical with methods add, sub, mul, div, ... and then derive classes for int, float, bigint, ... from that. But that is more an execise to show what can be done with OO than real use case.
<Leonidas> mrvn: yeah, sounds as verbose as the java biginteger-stuff which is really tedious to use.
<mrvn> Leonidas: you can overload the + operator to use the class.
<mrvn> let ( + ) = Arithmeical.plus
<Leonidas> Oh, did I already mention that I am seriously impressed with the support I got from this channel? Totally awesome :)
<Leonidas> mrvn: oh, I see. Ok, that would be a possibility.
<flux> mrvn, I wouldn't call it overloading, but redefining..
<Leonidas> but feels a bit out of scope.
<mrvn> shadowing is the right word I believe
willb1 has joined #ocaml
<Leonidas> I guess a take a few minutes break for things to settle in my mind...
Modius_ has quit ["I'm big in Japan"]
willb1 has left #ocaml []
willb1 has joined #ocaml
willb1 has quit [Client Quit]
tmaedaZ0 has quit [Read error: 110 (Connection timed out)]
Yoric has quit []
Yoric has joined #ocaml
ygrek has joined #ocaml
Dodek_ has joined #ocaml
seanmcl has joined #ocaml
Dodek_ has quit [Read error: 104 (Connection reset by peer)]
<Leonidas> I still don't get when to use ;;. Sometimes it works without, sometimes I run into problems if I leave it out. What is the #ocaml folks recommendation?
<mattiase> Leonidas: Basically, you need it if the next top-level thingy doesn't start with a keyword. You can always make this happen by doing let _ = f() instead of just f().
<flux> leonidas, ;; separates processing units
<flux> leonidas, a processing unit is EITHER a list of statements OR an expression
<mattiase> Leonidas: But it doesn't hurt to add it wherever you see fit.
<flux> leonidas, does this make sense?
<flux> of course, you also need ;; whenever you want to process some statements (or expressions)..
<flux> leonidas, I never use ;; unless it's on the toplevel
<flux> leonidas, however, as a newbie it might be useful, because somtimes ;; can give you better location for an error
seanmcl has quit []
seanmcl has joined #ocaml
<mattiase> What we really need is an environment that separates Enter from Return, so there.
Pimm has quit [Read error: 110 (Connection timed out)]
<mrvn> flux: or give starnge errors
<mrvn> mattiase: the revised syntax obsoletes the ;; completly I think
<mrvn> Other apps use return and <shift>-return.
<Leonidas> flux: yeah, somehow.. but see this code: http://paste.pocoo.org/show/152413/
<Leonidas> flux: it doesn't work unless I add ;; at the end of line 46.
<Leonidas> mrvn: revised syntax?
<mattiase> mrvn: The only problem with the revised syntax is that it doesn't go far enough. And, that nobody uses it.
<mrvn> Leonidas: from camlp4
<Leonidas> as you see, the code in my paste is either using ;; or not. And it seems to work, but I don't know exactly why.
<mrvn> mattiase: I think it fixes some thing but I also think it is a verry bad idea to have 2 syntaxes
<Camarade_Tux> I'm looking for a way to easily use RPC functions, like being able to call "M.f 42" and "Remote_M.f 42" as easily, currently ocamlnet's rpc needs that you take care of the marshaling part (and that you open connections), has anyone something like that or heard of something like that?
<Leonidas> mrvn: ah, ok.
<flux> leonidas, line 44: statement line 49: expression
eni_ is now known as albacker
<flux> leonidas, thus it doesn't match neither the rule "list of statements" nor "an expression"
<mattiase> mrvn: Completely agreed, but it is also clear that the standard syntax has problems.
<Leonidas> flux: ah, so I can put as many statements as I want and only put one ;; at the end?
<flux> leonidas, yes
<flux> leonidas, and you can make a statement of any expression: convert <expr> into let _ = <expr>
<Leonidas> but at the end, it needs at least one ;;?
<mrvn> Leonidas: ;; only tels the toplevel "start executing all the input NOW"
<flux> leonidas, no, if it's a file you are compiling
<flux> leonidas, yes if you paste it to toplevel and want to process it..
<flux> but I need to go now, happy coding
<Leonidas> I mostly use #use
<Leonidas> flux: thanks.
<mrvn> Leonidas: Simple rule: Ever only type ;; in the toplevel. :)
<Leonidas> mrvn: ok, I'll try to avoid them.
Yoric has quit []
tmaedaZ has joined #ocaml
tmaedaZ is now known as tmaeda
<Leonidas> http://paste.pocoo.org/show/152417/ - does this look like acceptable OCaml code?
<thelema> Leonidas: [discount] could probably be written using List.map
<Leonidas> It does have a lot of ;;, since I thought it might be a bit ridiculous to wrap everything into let _
<thelema> just wrap the final section in a [let () = ...]
<thelema> from line 100 onward
<thelema> I assume your assignment requires you to have a shopping cart of ints and a shopping cart of floats
<Leonidas> thelema: yep, you're probably right with List.map :) I seem to be on a pattern matching trip :D
<Leonidas> thelema: I don't understand how I can wrap it in a let () = while still retaining the output in the toplevel...
<Leonidas> thelema: the assignment requires me to have a shopping cart with ints, but ints don't make sense when calculating percentages.
* Leonidas decided to guess what the assignment actually wanted.
bohanlon has joined #ocaml
Pimm has joined #ocaml
<thelema> you can do % with int, you just have to convert to float, do %, and convert back
<thelema> if you wrap with let(), you won't get the toplevel output, true.
<thelema> write a print_cart function to print your shopping cart.
<Leonidas> thelema: but when I convert back, it truncates the number which does not sound like a good solution.
<thelema> That's as good as you can do with ints.
nagnatron has quit ["Leaving."]
<thelema> unless you want to write a round function
<thelema> to round properly. It's pretty easy.
seanmcl has quit []
seanmcl has joined #ocaml
ttamttam has quit [leguin.freenode.net irc.freenode.net]
mishok13 has quit [leguin.freenode.net irc.freenode.net]
mishok13 has joined #ocaml
ttamttam has joined #ocaml
<mrvn> Leonidas: let percent x y = 100 * x / y and hope x is small enough not to overflow.
<mrvn> Leonidas: Hve you used hashtbl or map yet?
<mrvn> Leonidas: in discount: preis=preis_rec * (100 - d) / 100
<mrvn> and who cares about rounding in an exercise?
<mrvn> Leonidas: let total_cost (w, n) = w.preis * n
<mrvn> Leonidas: maxlist and maxlist_tail should be unified.
delsvr has joined #ocaml
<orbitz> a lot of people are calling go's type system liek ocamls in terms of structural polymorphism, but I don't see it, you still have to state the name of the itnerface you want which sounds more like a weaker haskell, anyone looked at Go?
<mattiase> Go looks very much like the perfect dream language of 1973. No, I don't find the comparison to ocaml really valid either.
dmentre has quit ["Leaving."]
seanmcl has quit []
Nepomuk has joined #ocaml
seanmcl has joined #ocaml
<orbitz> mattiase: specifically the comparison is in typing
<csmrfx> F# more appr
<orbitz> they say the type system is liek duck typing
<orbitz> but i totally disagree
<orbitz> since you still need the name of the interface
<thelema> it's much more like duck typing than the C++/Java world has seen before.
<mattiase> orbitz: There are plenty of languages allowing polymorphic method invocation on objects of otherwise unrelated types (Java, Objective-C, etc)
ezrakilty has quit ["Puh-peace!"]
<orbitz> what i'm saying though is in ocaml you just use yoru object calling the emthods you want, and the type becomes a union of those mthods, in Go you still are restricted to names of interfaces taht are collectiosn of methods
<mattiase> orbitz: indeed.
<orbitz> i wonder if you can specify a type is of multiple interfaces in go like in haskell though
<mfp> orbitz: you could also argue that it's structural polymorphism without inference
<orbitz> hrm perhaps
<csmrfx> Whats there like duck typing in go? isnt it just lazy init of types
<csmrfx> cough type
<csmrfx> hm, nm
rwmjones_lptp has joined #ocaml
tmaeda is now known as tmaedaZ
<csmrfx> Any Ocaml video lectures. Stanford had some for scheme, cpp and python, that was great. I wish Ocaml had some too
smimou has joined #ocaml
seanmcl has quit []
zhijie has joined #ocaml
ikaros_ has joined #ocaml
ikaros has quit [Read error: 145 (Connection timed out)]
Pimm has quit [Read error: 110 (Connection timed out)]
delsvr has quit []
<thelema> csmrfx: there's some video of the ocaml meeting paris here: http://www.cocan.org/events/europe/ocamlmeetingparis2008
aklt has quit ["leaving"]
_zack has quit ["Leaving."]
ikaros_ is now known as ikaros
Narrenschiff has joined #ocaml
jcaose has joined #ocaml
Narrenschiff has quit []
ttamttam has quit ["Leaving."]
slash_ has joined #ocaml
ua has quit [Read error: 113 (No route to host)]
ski_ has quit ["Lost terminal"]
Pimm has joined #ocaml
Pimm has quit [Remote closed the connection]
Pimm has joined #ocaml
<Leonidas> mrvn: maxlist and maxlist_tail shouldnt be unified, the assignment asks explicitly for both :)
<Leonidas> mrvn: haven't used hashtables in ocaml yet. The assignment asks for records, so they get records.
<Leonidas> but total_cost is nice, should have done it your way
<thelema> Leonidas: a hashtbl would be more appropriate than the list for holding all the items.
<thelema> items in the cart
<Leonidas> thelema: yep, you're right. That would also take care of duplicate keys.
<thelema> exactly.
<Leonidas> thelema: I guess the people who make our assignments don't value common sense very much...
<Leonidas> or maybe they think that a list might be easier to get started with.
<thelema> simplicity often wins over proper design.
<Leonidas> exactly
Amorphous has quit [Read error: 110 (Connection timed out)]
Pimm has quit [Read error: 110 (Connection timed out)]
Amorphous has joined #ocaml
<mrvn> thelema: howcan that be? Simplicity often is the proper design.
<mrvn> Leonidas: You can habe both but one should call the other.
<mrvn> Leonidas: or both call a third that doesn't use options.
<thelema> mrvn: simplicity is usually easier to implement, and gets the job done in many cases.
<mrvn> Leonidas: Was the option type for maxlist_tail required? Because it suspiciously looks like you were to implement maxlist_tail without option and then extend that in maxlist to handles empty lists as well.
<mrvn> Time for a good book and then bed.
alp_ has quit [Client Quit]
Alpounet has joined #ocaml
tarbo2 has quit [Client Quit]
tarbo2 has joined #ocaml
_andre has quit ["Lost terminal"]
onigiri has joined #ocaml
ttamttam has joined #ocaml
cognacc has joined #ocaml
jcaose_ has joined #ocaml
jcaose has quit [Read error: 60 (Operation timed out)]
albacker is now known as edon
edon has quit [Remote closed the connection]
albacker has joined #ocaml
ygrek has quit [Remote closed the connection]
jcaose_ has quit [Read error: 54 (Connection reset by peer)]
rwmjones_lptp has left #ocaml []
albacker has quit ["Leaving"]
bohanlon has quit [Remote closed the connection]
ttamttam has quit ["Leaving."]
Nepomuk has quit ["Leaving"]
seanmcl has joined #ocaml
bohanlon has joined #ocaml
seanmcl has quit []
slash_ has quit [Client Quit]
seanmcl has joined #ocaml
ikaros has quit ["Leave the magic to Houdini"]
_unK has quit [Remote closed the connection]
sramsay has joined #ocaml
sramsay has quit [Client Quit]