<MegaWatS>
let make_mistake (x : foo error) = x.(0) <- (new baz :> foo);;
<MegaWatS>
so far it compiles and works
<MegaWatS>
whoops typo
<MegaWatS>
that should read:
<MegaWatS>
let make_mistake (x : foo array) = x.(0) <- (new baz :> foo);;
<MegaWatS>
of course :)
<MegaWatS>
ok
<mrvn_>
guessed that
<MegaWatS>
now if ocaml allowed you to cast a bar array into a foo array
<MegaWatS>
you could now do the following:
<MegaWatS>
let m = Array.create (new bar) 10 in
<MegaWatS>
make_mistake (m :> foo array);
<MegaWatS>
m.(0)
<MegaWatS>
now m.(0) contains a baz, even though it is statically typed not to
<MegaWatS>
but ocaml won't allow the bolded part
<mrvn_>
same with lists
<MegaWatS>
of course, I didn't even for a minute expect that it would :)
<MegaWatS>
no, lists are immutable
<mrvn_>
you can setbang them
<MegaWatS>
not in ocaml
<mrvn_>
not? hmm. ok
<MegaWatS>
if you could, of course, then lists wouldn't be immutable anymore, and to allow it would be an error again
<MegaWatS>
but what's really nice about the way ocaml handles this is that, it figures out by itself whether the structure you use is mutable or not
<mrvn_>
You can do a simple List.iter (fun x -> x :> foo) foo_list
<MegaWatS>
of course but that doesn't do anything
<mrvn_>
That gives you a new list with casted objects.
<MegaWatS>
you mean List.map
<MegaWatS>
of course
<mrvn_>
Which wrks for arrays too.
<MegaWatS>
but, so what?
<MegaWatS>
yes
<mrvn_>
How doesocam figure out if something is mutable?
<mrvn_>
s/ocam/ ocaml/
<MegaWatS>
well by the definition
<MegaWatS>
I did, for example, as an experiment, define my own list datatype:
<MegaWatS>
type 'a my_list = Cons of ('a * 'a my_list) | Nil;;
<mrvn_>
everything is thats not a reference or class?
<MegaWatS>
which is immutable
<MegaWatS>
and ocaml allowed it
<MegaWatS>
basically, yes
<MegaWatS>
everything that's not a (mutable) record or class
<mrvn_>
java is even worse with casts. Most conainers accept any object. If you need a typesafe container you have to duplicate the code for each type.
mrvn_ is now known as mrvn
<MegaWatS>
yeah
<MegaWatS>
java sucks :/
<mrvn>
Do you have an idea how to write enums in ocaml?
<MegaWatS>
erm :)
<MegaWatS>
type foo = Bar | Baz | Qux;;
<MegaWatS>
that`s really the easiest thing in the world in ocaml
<mrvn>
I need a mapping from type foo = Bar | Baz | Qux;; to 0,2,3
<mrvn>
01,2
<mrvn>
args, 0,1,2
<MegaWatS>
let to_int = function Bar -> 0 | Baz -> 1 | Qux -> 2;;
<MegaWatS>
or you work with constants and abstract types
<mrvn>
something that works magically.
<MegaWatS>
there isn't anything I'm aware of ...
<mrvn>
something that generates the to_int function for a given type.
<MegaWatS>
you have to remeber, enum types in ocaml are a bit more complicated than in C because they are, at the same time, unions
<mrvn>
ocaml internaly must use some mapping to int in the object. Couldn't one marshal it and read that field from the string?
<MegaWatS>
module AnEnum : sig type abstract val make : int -> abstract val take : abstract -> take end = struct type abstract = int let take n = n let make n = if n >= min and n <= max then n else fail_with "blahblah" end;;
<MegaWatS>
well ocaml sometimes needs to box constructor values, when they contain arguments
<MegaWatS>
so no, it's not quite exactly the same thing as an int
<MegaWatS>
what's the problem with writing a
<MegaWatS>
conversion function?
<mrvn>
extra work.
<MegaWatS>
hm
<MegaWatS>
well but not much I guess :)
<MegaWatS>
what do you need it to be converted into an int for?
<mrvn>
at least the compiler warns if you miss one or mistpye one.
<mrvn>
mldonkey, network protocol.
<MegaWatS>
theoretically, you COULD use Obj.magic for that, but I would advise against it
<MegaWatS>
at least, with a hand-written conversion function it is safe
<mrvn>
Problem is I would need an instance of the type to get the int of it.
<MegaWatS>
?
<MegaWatS>
what do you want to do?
<MegaWatS>
brb
<mrvn>
For incoming data I have the int and need to match that with the number of the constructor.
<mrvn>
2 -> read_REQUEST_from_socket socket
<mrvn>
something like that.
<mrvn>
number(Request) -> read_REQUEST_from_socket socket would be nicer.
<mrvn>
But to make a Request for number to convert to int I would need dummy data for the Request.
<mrvn>
It would be better to have a const for each possible Constructor.
<mrvn>
let requestID = 2 and queryID = 3 and ... in
<mrvn>
But then its not safe anymore.
<MegaWatS>
you can hide the implementation with the module signature
<MegaWatS>
and make the type abstract
<MegaWatS>
i.e.
<MegaWatS>
module AbstractT : sig
<MegaWatS>
type t
<MegaWatS>
val foo : t
<MegaWatS>
val bar : t
<MegaWatS>
...
<MegaWatS>
val baz : t
<MegaWatS>
val of_int : int -> t
<MegaWatS>
val to_int : t -> int
<MegaWatS>
end = struct
TachYon25 has quit ["bez ki³y nie ma zaliczenia (z prawd studentek AM)"]
<MegaWatS>
type t = int
<MegaWatS>
let foo = 1 and bar = 2 and ... and baz = N
<MegaWatS>
let of_int n = if n>=1 && n<=baz then n else invalid_arg "of_int"
<MegaWatS>
let to_int n = n
<MegaWatS>
end
<mrvn>
but then you can still have foo=1 bar=1 and baz=1
<MegaWatS>
not if you don't do that in your module
<MegaWatS>
why you would want to, I don't know
<mrvn>
someone has to write up the numbers and he can get it worng.
<mrvn>
wrong
<MegaWatS>
hmm
<mrvn>
The problem is mainly to prevent different people from using the same numbers.
<MegaWatS>
I don't think that's really a problem
<MegaWatS>
hmm
<MegaWatS>
oh that's of course a protocol problem
<MegaWatS>
it has nothing to do with the language
<MegaWatS>
in C you could still have different peopkle start with eg an enum like
<mrvn>
no, but ocaml doesn't have a way to prevent it as enums have in C.
<MegaWatS>
enum enum1 { foo, bar, baz };;
<MegaWatS>
and then person 1 changes the source to look like
<mrvn>
Of cause you can only have one enum.
<MegaWatS>
enum enum1 { foo, bar, baz, qux };;
<MegaWatS>
and person 2 to
<MegaWatS>
enum enum1 { foo, bar, baz, quoz, barax };;
<mrvn>
That would be alright.
<MegaWatS>
well then, what`'s the problem?
<MegaWatS>
in both cases, you have to assign unique numbers to each constructor
<mrvn>
In your case the person would compile both client and gui and they would use the same numbers.
<MegaWatS>
yes, of course
<MegaWatS>
because they use the same module
<MegaWatS>
as posted above
<mrvn>
The problem comes when person 1 and 2 merge their code and forget that they have overlaps in their numbers.
<mrvn>
With a single enum the numbers would change but be uniq.
<MegaWatS>
erm... yes? :)
<MegaWatS>
so, what's different in ocaml?
<mrvn>
you can't let the compiler generate uniq numbers.
<MegaWatS>
oh
<MegaWatS>
well you simply do let foo = 1 let bar = foo + 1 etc
<mrvn>
I was hoping to do something more magic.
<MegaWatS>
hm well the compiler can't do EVERYTHING :)
<MegaWatS>
YOU have to choose some sort of external representation if you want to do a network protocol
<mrvn>
Is the mashaling datastream defined somewhere?
<MegaWatS>
or you simply use marshalling
<MegaWatS>
I think it's supposed to be abstract
<MegaWatS>
but I guess you could look at the sources of the module
<mrvn>
unless they change it with the next ocaml version.
<mrvn>
I think I will write a protocolNumbers.ml and hope that everyone can count.
<MegaWatS>
no I think it's supposed to be stable, as it is supposed to be used to exchange ocaml data
<MegaWatS>
yeah you do that :)
<MegaWatS>
I don't honestly see where problems are supposed to come into it
<MegaWatS>
simply hide everything behind an appropriate signature, and when it needs extension do that inside that module; the outside shouldn't even be concerned with that then
<mrvn>
Do you have an idea whats the best way to notify a client about changes in the servers datastructures at regular intervals (but not every change, just from time to time)
<mrvn>
Atm it send changes out far too often.
<MegaWatS>
well that's not my area of expertise, but naively I would do it with a buffer which accumulates changes, and when it overflows they are sent out and the buffer os cleared
<fabian2>
perhaps you can answer anyway, what i have is a small program which can be compiled and parses command line argumets, i now want to run it in ocaml and therefore have to call main
<fabian2>
but i couldnt figure out how to call it with arguments
<fabian2>
i always get something like this
<fabian2>
This expression has type string but is here used with type unit
<MegaWatS>
?
<fabian2>
and i couldnt find a description of unit
<MegaWatS>
usually you access the command line arguments via
<MegaWatS>
Sys.argv
<fabian2>
yes that works
<MegaWatS>
unit is the type which consists only of a single value, ()
<fabian2>
but only if i compile it
<MegaWatS>
it is the default return type for statements and procedures
<MegaWatS>
usually you should do it something like
<MegaWatS>
let main args = ...
<MegaWatS>
let _ = main Sys.argv
<MegaWatS>
and then, when you want to test it from the toplevel
<MegaWatS>
you canb simply call main [| put your arguments here |]
<fabian2>
with the | ?
<MegaWatS>
can you post the expression where the error occurs?
<MegaWatS>
yes
<MegaWatS>
[ a; b; ..; z ] is a list
<MegaWatS>
[| a; b; ...; z |] is an array
<MegaWatS>
(a,b,c,...,z) is a touple
<MegaWatS>
{ a=a; b=b; ...; z=z } is a record
<MegaWatS>
etc :)
<fabian2>
may i post the program? its 10 lines
gl has quit [Read error: 113 (No route to host)]
<MegaWatS>
just post the line where the error occurs
<MegaWatS>
that should suffice
<fabian2>
main [| "test"; |];;
<fabian2>
e.g.
<MegaWatS>
without the semicolon
<MegaWatS>
ie main [| "test" |]
<fabian2>
main [| "test" |];;
<fabian2>
This expression has type string array but is here used with type unit
<MegaWatS>
well then main takes a unit as argument I guess
<MegaWatS>
I thinkj you defined main as
<MegaWatS>
let main () =...
<MegaWatS>
?
<MegaWatS>
because [| "test" |] is a string array :)
<fabian2>
yes, and this works if comoiled
<fabian2>
so ./a.out test1 test2 gets passed as arguments
<MegaWatS>
of course it works if compiled, as I guess you nowhere have the line main [| "test" |] in it
<fabian2>
yes
<MegaWatS>
so what is it you want to do?
<MegaWatS>
you want to test it in the toplevel?
<MegaWatS>
then you'll have to change it a bit
<MegaWatS>
so that your "main" function gets the command line arguments passed as an argument
<fabian2>
i want a program which can be compiled and parses arguments also be able to run in ocaml and there call it with main arg1, arg2...
<MegaWatS>
well then define main to take this argument
<MegaWatS>
ie
<MegaWatS>
let main args = ...
<MegaWatS>
let _ = main Sys.argv
<MegaWatS>
and then use args to access the arguments
<MegaWatS>
then, you cann call main [| "blah"; "Bleh" |] in the toplevel ...
<fabian2>
hmm thats bad i would rather prefer something like set args ... like in gdb
<fabian2>
else i would always have to change the program when i compile it or use it in the interpreter
<MegaWatS>
why?
<MegaWatS>
no?
<MegaWatS>
you simply do a
<MegaWatS>
let _ = main Sys.argv
<MegaWatS>
to call it with teh command line arguments :)
<MegaWatS>
you see Sys.argv is the array of the command-line arguments
<MegaWatS>
main is a function
<MegaWatS>
if you define main like this:
<MegaWatS>
let main args = ...
<MegaWatS>
then you can call it either like this:
<MegaWatS>
main [| "blah" |]
<MegaWatS>
or like this:
<MegaWatS>
main Sys.argv
<fabian2>
ohh i see let me try
<fabian2>
hmm what is the cwd when run inside of ocaml?
<MegaWatS>
wherever you started ocaml from? :|
<fabian2>
hmm i get
<fabian2>
# main [| "a.out" |];;
<fabian2>
Enter file name
<fabian2>
- : unit = ()
<fabian2>
ohh wait
<fabian2>
i think i have it
<fabian2>
no dodnt work
<MegaWatS>
?
<MegaWatS>
what do you want to do?
<MegaWatS>
I think you wanted to give it command line arguments
<MegaWatS>
try
<fabian2>
just test if the file which is given as arg exist and print out something
<MegaWatS>
main [| ""; "a.out" |]
<fabian2>
yes but if i test it in ocaml i have to give it parameters onj my own
<MegaWatS>
Sys.argv.(0) is usually not used, or rather, contains the application binary :)
<fabian2>
yes thats what i thought was the error if run as program it has as first parameter the filename itself
<fabian2>
okay if you search for expressions you find it soon
<fabian2>
thanks
<MegaWatS>
np
<fabian2>
hmm well not quite done :) this one i should find out by myself but the first steps are hard
<MegaWatS>
they always are
<fabian2>
if run from shell it has argv 0 as program name and when run in ocaml i want to give it only the list of arguments so the solution would be to do main Sys.arv(1)...end
<fabian2>
hope you got what i mean, my loop runs from 0 to length -1 so I have to cut of the first paramater
<MegaWatS>
Array.sub
<MegaWatS>
Array.sub arr 1 (Array.length arr - 1)
<MegaWatS>
Array.sub array low count returns the first count elements from array arr , starting at index low, as a new array
<MegaWatS>
so for example
<MegaWatS>
main (Array.sub Sys.argv 1 (Array.length Sys.argv - 1))
<fabian2>
kay thanks a lot, I will now try to do the next steps on my own