<thomas001>
enum.cc:3: invalid conversion from `int' to `foo'
<det>
also
<thomas001>
det: in C++ there is no implicit int -> enum
<det>
switch has all kind of caveat that you can't get with match
<det>
oh :)
<det>
I forget c++ likes to pretend it is type-safe
<lus|wazze>
oh we're talking about c++ - ok thats something different
<lus|wazze>
still you can explicitly cast an int to an enum
<lus|wazze>
with the same results
<Riastradh>
(0 : foo) won't work.
<det>
my main point was dispatching on the variant/ enum anyways
<lus|wazze>
but the most important limitation of enums is that the constructors cant have arguments
mattam has quit [Read error: 60 (Operation timed out)]
<lus|wazze>
in enums
<lus|wazze>
eg like type foo = A of int | B of float | C of string
<lus|wazze>
and consequently you can't use anything like the powerful pattern-matching constructs of ocaml on them
<det>
ocaml will make sure you always match it correctly (cant leave of one of the enums, etc)
<det>
s/of/off/
<thomas001>
when doing type foo=A|B|C;; are A,B,C globally defined symbols?
<Riastradh>
They're defined in the current module; there is nothing that's 'global,' as far as I know, in OCaml.
<det>
lus|wazze: yeah, you need to use union's to achieve that sort of thing, which are most definately NOT type-safe :)
<thomas001>
template<class T> class Enum{public:bool operator==(const Enum<T>& e){return this==&e;}}; class foo:public Enum<foo>{} A,B,C; <-- typesafe enums in C++ ?
* Riastradh
barfs.
<Riastradh>
BURN THE HERETIC!
<Riastradh>
C++ code in #ocaml! Stop the presses! Get the stakes!
<Riastradh>
C++ template code, that is.
<thomas001>
sure it is ;)
<det>
thomas001: you still can't properly match the enum
<thomas001>
det: what do you mean with match?
<det>
thomas001: you need to be able to say, in a type-safe manner, do this for A, this for B and this for C
<thomas001>
not nice,but switch does not work with objects
<det>
that leaves the possibility of forgetting an enum
mattam_ has quit [Read error: 54 (Connection reset by peer)]
<thomas001>
yes
<det>
type foo = A | B | C
<det>
let print_foo f =
<det>
match f with
<det>
A -> print_string "A"
<det>
| B -> print_string "B"
<det>
| C -> print_string "C"
* Riastradh
hides before the equivalent C++ code is pasted.
<thomas001>
det: yes it's nicer in ocaml
<det>
you are guarenteed to cover all cases exactly once in ocaml :)
<det>
not to mention all the nastiness of switch
<det>
basicly just a special goto
<det>
hunger overwhelming
* det
really leaves
<det>
oh, one more thing, it gets even nicer with paramaters to the constructors:
<thomas001>
another thing: type t = C of int * bool | D of (int * bool);; <-- where is the difference ?
<Riastradh>
The constructor is the difference.
<lus|wazze>
C is a constructor which takes two arguments, one of type int ,one of type bool
<lus|wazze>
D is a constructor which takes one argument, a tuple consisting of an int and a bool
<det>
type foo = A of float | B of int * int | C
<det>
let print_foo f =
<det>
match f with
<det>
A(a) -> Printf.printf "A %f" a
<det>
| B(a, b) -> Printf.printf "B %d %d" a b
<det>
| C -> Printf.printf "C"
<Riastradh>
lus|wazze, er, that's the same thing, isn't it?
<thomas001>
i thought int*bool is also a tuple....
<det>
no
<Riastradh>
# type t = C of int * bool | D of (int * bool);;
<Riastradh>
type t = C of int * bool | D of (int * bool)
<Riastradh>
# C (1,true);;
<Riastradh>
- : t = C (1, true)
<Riastradh>
# D (1,true);;
<Riastradh>
- : t = D (1, true)
<thomas001>
so (int*bool) is different from int*bool ?
<det>
thomas001: it's the same as a function that takes 2 arguments compared to a function that takes 1 argument which is a tuple of 2 elements
<lus|wazze>
Riastradh, almost the same thing
<lus|wazze>
but there is a difference when matching
<lus|wazze>
when you do
<lus|wazze>
type foo = C of int * bool
<lus|wazze>
you CAN
<lus|wazze>
't
<lus|wazze>
you CAN't
<lus|wazze>
do
<lus|wazze>
match x : foo with C x -> (* x is a tuple *)
<det>
they are probally represented differently in the bytecode compiler
<det>
and the same with the native
<lus|wazze>
on the other hand, the representation of the type foo is more efficient than that of
<lus|wazze>
type bar = D of (int * bool)
<Riastradh>
Oh, that's silly.
<thomas001>
lus|wazze: fundamental question: do i call a ctor the same way i call a function?
<det>
ctor ?
<Riastradh>
Constructor.
<det>
thomas001: you call a ctor like you call a function in C
<thomas001>
type foo=A of int;; A 1;; <--
<thomas001>
looks like a normal function call
<det>
yeah, hrmph
<det>
maybe I shouldnt talk till I learn ocaml completely :)
<thomas001>
sry i dont see a real logic behind all this
<thomas001>
# type bar=B of int*int;; <-- does B take one argument of type int*int or 2 arguements each of type int ?
<det>
B(1,2)
<Riastradh>
Two arguments, each of type int, it seems.
<thomas001>
but type bar=B of (int*int) would take one tuple ?
<Riastradh>
However, if it were: B of (int * int) it would take one argument, a tuple of two ints.
det has quit [Remote closed the connection]
rox has quit [asimov.freenode.net irc.freenode.net]
rox has joined #ocaml
<thomas001>
why must typenames start with small letters?
* Riastradh
doesn't like the capitalization rules in OCaml either.
<lus|wazze>
because everything except constructor and module names must start with a lowercase letter
<thomas001>
but why?
<lus|wazze>
well they COULD have done it the other way around
<lus|wazze>
but then you would be here asking, "why must typenames start with a capital letter?"
<thomas001>
why capitilization rules at all>
<lus|wazze>
so it can distinguish constructors from identifiers?
<Riastradh>
I see the reason for -having- capitalization rules, but why they are what they are I don't see.
<lus|wazze>
well as i said
<thomas001>
lus|wazze: aren't the names enough to distinguish?
<lus|wazze>
umm no?
<Riastradh>
No.
<lus|wazze>
how should the parser know that foo is a constructor and not an identifier if there were no capitalization rules
<Riastradh>
Not without whole-program analysis.
<lus|wazze>
like, say, in
<lus|wazze>
match x with foo bar -> ...
<Riastradh>
And if you do whole-program analysis, you get compile-times like that of Stalin, which is a Bad Thing.
<Riastradh>
(Stalin the Scheme compiler, that is)
<lus|wazze>
how does it know that foo and bar are not variables to be bound in the matching
<lus|wazze>
instead of constructor names?
Smerdyakov has joined #ocaml
<Riastradh>
match foo with bar (baz, quux, zot) -> ...
<Riastradh>
What could bar be but a constructor?
<lus|wazze>
yes
<lus|wazze>
but what about baz, quux, and zot?
<lus|wazze>
they could be either
<Riastradh>
Indeed.
<Riastradh>
I haven't thought about it much, but I think whole-program analysis might help there.
<Riastradh>
Well, no, it probably wouldn't.
<thomas001>
how should the parser know what foo is? doesn't it keep a list of all identifiers and ctors defined until the line foo appears?
<Riastradh>
foo isn't the problem here.
<Riastradh>
baz, quux, and zot are.
<thomas001>
if baz,... are no ctors and no identifiers they are variables...
<lus|wazze>
umm variables ARE identifiers?
<lus|wazze>
and how does it know, for example , that they are not defined as ctors in some other module
<Riastradh>
Oh, yes, whole-program analysis would work there.
<Riastradh>
But you'd need the whole bloody program, which would suck, since a REPL wouldn't work with it, and you couldn't compile each module individually.
lament has joined #ocaml
<thomas001>
< Riastradh> match foo with bar (baz, quux, zot) -> ... <-- if baz was a ctor, it whould be listed in a list where all ctors are stored... (sry if i annoy you....)
rox has quit [asimov.freenode.net irc.freenode.net]
<Riastradh>
Oh, well, actually...you'd just need the module interfaces.
rox has joined #ocaml
thomas001 has quit [Remote closed the connection]
Smerdyakov has quit ["sleep"]
TachYon has joined #ocaml
mattam has joined #ocaml
lus|wazze has quit ["Quidquid latine dictum sit, altum sonatur."]
lus|wazze has joined #ocaml
reltuk has joined #ocaml
drlion has quit [Read error: 113 (No route to host)]