<Swynndla>
so the function is ok ... I mean no real criticisms? ... no faster way of doing it?
<smkl>
Swynndla: don't use append, reverse the list at end
<liralen>
swyn - actually, here, just use cons.
<Swynndla>
why ... is it faster?
<liralen>
swyn - and reverse the list at end =)
<liralen>
swyn - complexity.
<Swynndla>
ok ...
<Swynndla>
the way I've done it ... is it tail recursion?
<liralen>
no, you don't have a tail recursive function.
<smkl>
actually you can do it so that you don't have to reverse, and it could be tail recursive, too
<Swynndla>
smkl, oh??
<liralen>
swyn - notice that you wait for s2l to return before the '@' operator can complete. You can use an accumulator to get a tail-recursive function.
reltuk has joined #ocaml
<Swynndla>
hmmm ... I'm not sure how to use an accumulator ... I'm still trying to learn this stuff :)
<Swynndla>
can you give me a hint?
<liralen>
let recurse lst = let rec aux l acc = match l with [] -> acc | (h::t) -> aux t (h::acc) in aux lst [];;
<liralen>
er, also, 'reverse'.
<liralen>
Sorry, I need to go to sleep.
<Swynndla>
:)
<liralen>
anyway, does that help?
<Swynndla>
let me think about that ...
Kinners has left #ocaml []
<Swynndla>
so that would give me the list backwards? ... but I want it forwards? (am I misunderstanding it?)
<liralen>
yes, hence the name 'reverse'.
<liralen>
That function uses an accumulator and has tail-recursivity.
<Swynndla>
ok ...
<liralen>
good night.
<Swynndla>
nite
<Swynndla>
thx liralen
<Swynndla>
so then why shouldn't I use cons in my eg above to get a reverse list ... why is an accumulator better?
<liralen>
er, I used cons in there. You didn't use cons. You used @.
<liralen>
(not really here)
<Swynndla>
:)
<Swynndla>
why isn't this as good:
<Swynndla>
let list_of_string s =
<Swynndla>
let n = String.length s in
<Swynndla>
let rec s2l s = function
<Swynndla>
0 -> []
<Swynndla>
| n -> [s.[n-1]] :: s2l s (n-1)
<Swynndla>
in
<Swynndla>
s2l s n
<Swynndla>
;;
<Swynndla>
and then I could reverse the list?
<Swynndla>
(speaking to anyone that's really here :) )
blueshoe has joined #ocaml
<Swynndla>
hangon ... I'm missing something here
<Swynndla>
hey blueshoe :P
<liralen>
yes, you miss a tail-recursive function.
<blueshoe>
hey
<liralen>
but good that you get the use-cons-and-then-reverse.
<Swynndla>
:)
<Swynndla>
why shouldn't I use List.rev ?
<liralen>
huh? You can use List.reverse if you like.
<Swynndla>
oic .. u r saying that I can use the accumulator example to come up with a solution to my above function all in one go!
<Swynndla>
blueshoe, I wrong a function to turn a string to a list ... but it wasn't tail recursion
<blueshoe>
but does it work?
<Swynndla>
yup
<blueshoe>
cool :)
<Banana>
hello evryone.
<Swynndla>
hey Banana
<blueshoe>
hey
<Banana>
use tail recursion when you can.
<Swynndla>
but blueshoe on big strings, I'd overflow the stack I guess
<Swynndla>
blue .. can I show you what I came up with?
<blueshoe>
tail recursion is certainly an important concept to understand
<blueshoe>
sure
<Swynndla>
I read that the ocaml compiler turns tail recursive functions into the equivalent of 'while' loops ... and use the same amount of stack throughout the run
<Swynndla>
let list_of_string s =
<Swynndla>
let n = String.length s in
<Swynndla>
let rec s2l s = function
<Swynndla>
0 -> []
<Swynndla>
| n -> s2l s (n-1) @ [s.[n-1]]
<Swynndla>
in
thornber has joined #ocaml
<Swynndla>
s2l s n
<Swynndla>
;;
<thornber>
do many people use the revised syntax provided by the camlp4 pre-processor ?
<blueshoe>
i don't think so, thornber
<thornber>
thx
thornber is now known as ejt_
<Swynndla>
blueshoe, I could use this instead: | n -> [s.[n-1]] :: s2l s (n-1) and then I could use List.rev
<Banana>
Swynndla: the second solution is better.
<Swynndla>
blueshoe, but liralen was giving me a few hints about doing it with tail recursion *and* not having to reverse the list at the end
<Swynndla>
by using an accumulator
<Banana>
yes.
The-Fixer has joined #ocaml
<Swynndla>
oic
<Swynndla>
I just have to get my head aroung it Banana :)
<Banana>
;)
<blueshoe>
do you understand what tail recursion is, swynndla?
<Swynndla>
if the recursion is the last thing the function does
<Swynndla>
then it's tail recursion?
<Banana>
not the last...
<blueshoe>
there must also be no recursion within the function body
<Banana>
the only.
<ejt_>
the function must just _return_ the result of the recursion, ie. not use it in a further calculation
<Banana>
thus your result should be available in the non-recursive branch.
<Swynndla>
gotcha
<blueshoe>
and you should also try to understand why that's important
<Swynndla>
ocaml seems to encourage using a lot of small functions and not one big one
<blueshoe>
yes
<Swynndla>
blueshoe, i guess I don't understand why
<Banana>
you should take the factorial exemple.
<Swynndla>
ok
<blueshoe>
have you written a factorial function, swynndla?
<Swynndla>
um .... no .. let me try ... (should be too hard) ...
<blueshoe>
yeah, it's a good idea to tackle and fully understand that before going on to concepts like tail recursion
<Swynndla>
let rec fact n = match n with
<Swynndla>
1 -> 1
<Swynndla>
| _ -> n * fact (n-1)
<Swynndla>
;;
<Banana>
Swynndla: quite ;)
<Banana>
you can put 0 -> 1
<Swynndla>
:)
<Swynndla>
is 0 -> 1 better?
<Banana>
0! is 1 by definition so...
<Swynndla>
oic
<Swynndla>
yes
<Swynndla>
more complete
<Banana>
yes.
<Banana>
so this is the not tail recursive one.
<Banana>
try fact 100000
<Swynndla>
it
<Swynndla>
it's not?
<Banana>
non it isn't.
<Banana>
no.
<Swynndla>
oh ... I got a stack overflow :/
<Banana>
wanna see why it isn't ?
<blueshoe>
try to write out what happens when you do a factorial of 4
<Maddas>
Swynndla: Your last operation is the multiplication, not the call fact (n-1)
<Swynndla>
but ... the recursion is the only thing it does ... isn't it????
<Maddas>
not all recursion is tail recursion!
<Banana>
no as Maddas pointed out it does the multiplication at last.
<Swynndla>
oic
<blueshoe>
apart from trying to make this tail recursive, swynndla, i suggest trying to understand what happens with your call stack with fact 4
<Maddas>
Sorry if I spoiled anything :)
<Swynndla>
Maddas, no that's fine :)
<Swynndla>
blueshoe, yes I think I understand why that is using up the stack
<blueshoe>
not just using
<blueshoe>
what happens to it
<blueshoe>
the "shape" of the recursion
<Swynndla>
it needs to expand it all before it can do any of the muliplication?
<blueshoe>
right
<Swynndla>
shape?
<blueshoe>
just write out what happens with fact 4 by hand
<Swynndla>
ok
<blueshoe>
also, you might want to check out the structure and interpretation of computer programs (sicp)
<blueshoe>
they go through all of this, with scheme
<ejt_>
you should stick to doing explicit recursion until your comfortable with it
<ejt_>
s/your/you're/
<Banana>
Swynndla: the s2l function is embedded into list_of_string so you can name it as you want, you can't call it from outside.
<Swynndla>
oic
<Swynndla>
ejt: gotcha
<Maddas>
ejt_: nice :)
<Banana>
ejt_ function is a bit less efficient but much more elegant.
Kinners has quit [Read error: 104 (Connection reset by peer)]
Kinners has joined #ocaml
ott has quit [Remote closed the connection]
<Banana>
got to go.
<Banana>
see you, everyone.
<ejt_>
bye
Banana is now known as Banana[AFK]
<Kinners>
Swynndla: got the explode function sorted out?
<Swynndla>
Kinners, yup I think so now :)
pattern has quit [Connection timed out]
<Swynndla>
any bigger than fact 12 and the numbers wrap around
<ejt_>
there is a big num library (I've not used it)
<Swynndla>
ahh ic
<Swynndla>
ahhhhh ... I just did fact_float instead :P
<ejt_>
hmm
<ejt_>
Swynndla: are you doing this for a class ?
<Swynndla>
nope ... hobby
<ejt_>
then you may find haskell a better environment to learn functional programming (/me waits for the flames)
<Swynndla>
lol
<Swynndla>
why haskell?
<ejt_>
ocaml mixes up imperative and functional styles, I don't think it's clear to the beginner which is which
wazze has joined #ocaml
<ejt_>
just my opinion, ocaml is good
<Swynndla>
hehe ...
<Swynndla>
http://merjis.com/richj/computers/ocaml/tutorial/ch5/ says ... "Haskell, another functional language, is pure functional. OCaml is therefore more practical because writing impure functions is sometimes useful."
<Swynndla>
so more practical but doesn't teach functional styles as well :)
<Maddas>
I doubt you can say it's "more practical"
<Maddas>
At least not just because it is impure
<Swynndla>
gotcha ...
<Swynndla>
and #haskell has more people in it! ... that's more practical for me? :)
<Swynndla>
but then ... you all are so nice to me
* Maddas
shrugs
<ejt_>
I had great problems with memory useage in haskell programs due to the lazy eval
<Maddas>
Easiest way to find out which you prefer is to learn both :-)
<ejt_>
Swynndla: talk to shapr on #haskell
<Swynndla>
hehe
<ejt_>
he's helpful
<Swynndla>
oic
<Swynndla>
I have to go though ...
<Swynndla>
next time I will
<Swynndla>
oh ... I see you all are in #haskell anyway :P
<Swynndla>
I'm trying to learn C as well ... I was going to just learn C but someone told me not to bother and that I'd save program time and frustration by learning ocaml
<Swynndla>
I know a tiny bit of c .. but more perl ...
<ejt_>
it depends what you want to do
<Swynndla>
try
<Swynndla>
true
<Swynndla>
ocaml is interesting ... in a mathematical way :)
<ejt_>
you'll probably be programming more quickly with ocaml
<Swynndla>
and it looks nice lol
<Swynndla>
perl is quick though
<Swynndla>
I mean quick to throw something together
<Demitar>
More importantly, maintenance takes a lot less effort. :)
<mellum>
Quicker. Easier. More seductive.
<Swynndla>
lol
<Swynndla>
Demitar, mellum ... both of you sound as if you are talking about a cheap date :)
<Swynndla>
well, I better leave before my jokes get any worse ... bye
<Swynndla>
and thx
Swynndla has quit ["Leaving"]
<mellum>
Yet to learn he has about the Dark Side.
<Maddas>
haha
Nutssh has quit ["Client exiting"]
_JusSx_ has joined #ocaml
pattern has joined #ocaml
<Maddas>
Hm
<Maddas>
I would like to make a server that can listen to multiple connections in a non-blocking way, is there any specific library you can recommend or should I stick to the Unix module?
<Kinners>
maybe camlserv.sf.net might have something?
<Maddas>
I'll check, thanks :)
Kinners has left #ocaml []
cjohnson has joined #ocaml
reltuk has quit ["leaving"]
Vjaz_ has quit [Read error: 110 (Connection timed out)]
Nutssh has joined #ocaml
The-Fixer has quit [Read error: 110 (Connection timed out)]
ejt_ is now known as ejt
The-Fixer has joined #ocaml
The-Fixer has quit ["Goodbye"]
Nutssh has quit ["Client exiting"]
cjohnson has quit ["Drawn beyond the lines of reason"]
Vjaz has joined #ocaml
The-Fixer has joined #ocaml
Hipo has joined #ocaml
The-Fixer has quit ["Goodbye"]
owell has left #ocaml []
The-Fixer has joined #ocaml
azimuth has joined #ocaml
azimuth has left #ocaml []
buggs^z is now known as buggs
_JusSx_ has quit ["BitchX: now with 42 percent more random quit messages!"]
_JusSx_ has joined #ocaml
cjohnson has joined #ocaml
Vincenz has joined #ocaml
Vincenz has left #ocaml []
owll has joined #ocaml
owll has left #ocaml []
The-Fixer has quit ["Goodbye"]
The-Fixer has joined #ocaml
HackerMaster has joined #ocaml
<HackerMaster>
Hello
<smkl>
hey
<HackerMaster>
hi
HackerMaster is now known as DS-paintballer
<DS-paintballer>
how are you?
<smkl>
DS-paintballer: are you interested in OCaml?
<DS-paintballer>
well its a place to talk right
<smkl>
DS-paintballer: do you have a cell phone with java support?
<DS-paintballer>
no
ejt has left #ocaml []
<DS-paintballer>
why?
<smkl>
i want somebody to test my application
<DS-paintballer>
is it js or j
<DS-paintballer>
java or javascript
<smkl>
java ... most phones only have WMLScript, not javascript
<DS-paintballer>
i know
<DS-paintballer>
sory I dont have a java encoder
DS-paintballer has left #ocaml []
LittleDan has joined #ocaml
<LittleDan>
I'm not trying to be a troll, but why doesn't OCaml overload infix operators?
<Maddas>
LittleDan: Type interference
<Maddas>
That's one reason, I guess, and other reasons others surely know better than me
<Riastradh>
OCaml has no typeclasses.
<LittleDan>
Riastradh: So it's impossible to overload them?
<Riastradh>
Yes.
<LittleDan>
Riastradh: and generic functions can't work with different types?
<Riastradh>
OCaml has no method of type dispatch. (unless you count the [horrid] object system)
<Riastradh>
...run-time type dispatch, that is.
<LittleDan>
Where can I find an explanation of OCaml's type system? The type inference doesn't make sense from the tutorial I'm reading.
<Riastradh>
What about it doesn't make sense?
<LittleDan>
How everything is automatically infered
<LittleDan>
even for user-defined types, it seems
<Riastradh>
With a type inferencer.
<LittleDan>
Does it find the types lazily?
<Riastradh>
?
<LittleDan>
When does it look for what type it is?
<LittleDan>
does it check what type it is when the variable is created or when the type is requested?
<Riastradh>
What do you mean 'when the type is requested?'
<Maddas>
LittleDan: Do you want to know if the interference is done at compile-time or at run-time?
<LittleDan>
I'm not sure how OCaml's type system works. Is there a reference for it?
<LittleDan>
maddas: No, I mean lazily or eagerly, but I'm probably using that wrong.
<Maddas>
All types are inferred at compile-time, so I'm not sure if what you ask makes sense (I don't know too much either, though.)
<LittleDan>
Maddas: Is there a reference?
<Demitar>
LittleDan, the manual might answer your questions. But what is the difference between eager and lazy type evaluation_
<LittleDan>
Demitar: I'm not sure
<LittleDan>
sorry for my ignorance
<Demitar>
So you're asking a question whose answer you wouldn't know how to interpret? =)
<LittleDan>
Demitar: Some languages you don't care about the type much unless you do something like somevariable.type()
<LittleDan>
but I guess the type has already been infered by then
<Demitar>
Are you perhaps talking about static and dynamic typing?
<LittleDan>
Demitar: kindof
<Demitar>
Well OCaml is statically typed.
<LittleDan>
Demitar: I know, but types are infered and I don't really understand how
<LittleDan>
I don't understand user-defined types, specifically.
<Demitar>
Well say you have a union like this: type foo = Foo | Bar | Baz
<LittleDan>
But then what if you do later type conflicting = Foo | Nothing
<Demitar>
Now whenever you create an object using the Foo constructor or match against it the type system knows it's of type foo since the constructors are unique.
<Demitar>
LittleDan, you can't do that inside the same module.
<LittleDan>
Demitar: Do you ahve to explicitly reference teh constructor?
<Demitar>
How else would you suggest the object would be created?
<Maddas>
LittleDan: Dynamic and static typing are independent of lazy and eager evaluation.
<LittleDan>
In Python, if you have a user-defined type, you have to explicitly create it with a constructor function.
<LittleDan>
Maddas: I know; I thought things in OCaml might have been multiple types or something weird.
<Maddas>
Maybe you should keep on reading for now :)
<Demitar>
Yes, but that's quite a bit different since python is dynamically typed.
<LittleDan>
I'm reading the section on making types and they don't explain it
<Maddas>
What are you reading?
<LittleDan>
The tutorial referenced on the subject bar of this channel (but I found it from Google, not here_
<LittleDan>
)
<Maddas>
The one on merjis.com?
<LittleDan>
yes
<Demitar>
It means the (python-) object can behave in various ways regardless of the actual implemented type. It's really an object with methods with a different syntax.
<LittleDan>
Demitar: Since version 2.2, they are actually the same, except one is implemented in C. They're as equivalent as builtin functions are to other functions.
<Maddas>
Which chapter are you reading?
<LittleDan>
3
<Maddas>
Which example are you having problems with in perticular?
<LittleDan>
nothing, I was just trying to understand it completely
<Maddas>
particular, even
<Demitar>
LittleDan, in OCaml however all type information (oo is a slight bit different, message passing) is discarded at compile time.
<LittleDan>
Demitar: Now I'm completely confused
<Riastradh>
There is no type information after compile-time.
<LittleDan>
Demitar: I almost understood it for a second
<Maddas>
If that confused you, you didn't understand it properly :-)
<LittleDan>
Do you just mean that the ones and zeros don't use OCaml's type system?
<Riastradh>
The compiler figures out all types at compile-time (or not, in which case it complains to you about type errors) and then eliminates any type information before run-time occurs.
<LittleDan>
Oh, I already knew that (you just explained it weirdly); that comes with static typing, right?
<Riastradh>
And rather than having the programmer write out the type of every single expression, the compiler figures out the types.
Kinners has joined #ocaml
<LittleDan>
That's type inference, right? I just didn't understand how conflicting types worked.
<LittleDan>
and I think it's that it doesn't compile
<Riastradh>
They don't work. If there is a type conflict, the compiler complains and stops compiling.
<LittleDan>
What if types are defined in a module?
<Riastradh>
?
<LittleDan>
OCaml has a module system, right?
<Riastradh>
It does.
<LittleDan>
Can OCaml modules contain code defining types?
<Riastradh>
Yes.
<LittleDan>
How can you use those types? Just the same way? What if different modules have types defined differently?
<Riastradh>
Just the same way. I don't understand the last question.
<Demitar>
LittleDan, a module works as a namespace.
<Demitar>
For both types and values.
<Riastradh>
Namespaces simply allow for organizing _names_; the _types_ are independent of the modules: it's just their _names_ that are organized.
<LittleDan>
Let's say in module a I have type x = Foo | Bar and in module b I have type y = Bar | Baz. How will that work?
<LittleDan>
if I import both
<Riastradh>
That depends on the signatures of the two modules.
<mellum>
I suppose you can't.
<Riastradh>
If they define x & y as abstract types, then the constructors won't be imported and there will be no name clashes.
<Riastradh>
If a exports Foo and b exports Bar, then there will also be no name clashes (and vice versa).
<Riastradh>
If they both export Foo or they both export Bar, then you have a problem, and you should be using qualified names.
<mellum>
I never import anything, IMHO this makes it a lot easier to see where identifiers are coming from...
<Maddas>
mellum: I agree.
<Demitar>
LittleDan, you don't need to open a module to use it. A.Bar and B.Bar.
<LittleDan>
You don't need an explicit open statement?
<Maddas>
No
<Demitar>
Consider open A;; to be the from A import * and the import A is implicit in A.*
<Maddas>
LittleDan: Maybe you should read on :)
<LittleDan>
they showed examples of using modules; it looked like open left it in a namespace
<Demitar>
LittleDan, the trick here is that module names must start with an uppercase letter.
<Demitar>
LittleDan, no the open statement imports it into the current namespace.
<Demitar>
(Does that hold true even in an interface?)
_JusSx_ has quit ["BitchX: don't leave home without it!"]
<LittleDan>
is (*) n the same as (* n)?
<LittleDan>
or is that a comment?
<Kinners>
that's a comment
<Kinners>
use ( * )
<LittleDan>
is ( * ) n the same as ( * n)?
<Demitar>
No, ( * ) is a function * is an operator.
<Demitar>
Thus * wants an argument in front of it and one after. While ( * ) merely is int -> int -> int
<LittleDan>
If > and other comparison operators can work on any type in OCaml, what's stopping + from working on different types?
<Demitar>
> is cheating afaik.
<LittleDan>
so there's no way to define something equivalent?
<mattam>
not yet
<Kinners>
and the comparison operators always return the same type (bool)
<mattam>
they're much like python standard methods on classes, but you can't add any
<LittleDan>
mattam: Actually you can now use __slots__ to emulate that
<mattam>
what ?
<LittleDan>
mattam: To emulate the behavior of immutability in classes
<LittleDan>
mattam: It's not special
<mattam>
how is it related to what i said ?
<LittleDan>
mattam: I thought you were saying that it was an exception that affected everything or something like that
<mattam>
oh no
<LittleDan>
Does the OCaml compiler optimize out tree recursion at all?
<Riastradh>
The comparison functions cheat. That's all there is to it.
<Maddas>
Tree recursion? Tail recursion?
<Maddas>
oh, never mind.
<LittleDan>
Maddas: I mean tree recursion. I'm pretty sure it optimizes tail recursion, doesn't it?
<Maddas>
Yes, I just didn't hear of tree recursion before. Google corrected me :)
<LittleDan>
because the tutorial was recommending tree recursion, and I always thought that was too inefficient to be used.
<mattam>
what's tree recursion optimization ?
<Riastradh>
How do you want it to optimize tree recursion? It's rather difficult to generalize a transformation from a tree recursive algorithm to a tail recursive algorithm.
<Riastradh>
Tree recursion isn't inherently inefficient.
<LittleDan>
Riastradh: Doesn't it store too many stack frames?
<Riastradh>
The stack is often a great intermediate accumulator.
<mattam>
its proportional to the max depth of the tree, so it isn't too big usually