<pattern_>
This expression has type float but is here used with type float ref
<pattern_>
so i need to first "let y = ref 1.0" or something
<pattern_>
and pass that to foo
<pattern_>
# let y = ref 1.0 ;;
<pattern_>
val y : float ref = {contents = 1.}
<pattern_>
# let x = foo y ;;
<pattern_>
val x : float -> float = <fun>
<pattern_>
# x 2.0 ;;
<pattern_>
- : float = 3.
<Kinners>
or just let x = foo (ref 1.0);; but I think they want you to use plain numbers
<pattern_>
no, i think that should work
<pattern_>
all you're doing is allocating space for n
<Kinners>
I'm saying for the conditions of the function foo, take a number in, not a different type
<pattern_>
semantics ;)
<pattern_>
i think the whole requirement that n be mutable is ridiculous anyway, if you're just returning its value
lament has quit [Remote closed the connection]
<Kinners>
it has to be mutable
<pattern_>
it does according to the specs, but not practically
<pattern_>
if the purpose of the function is to return the sum of n and i, then you don't need n to be mutable
<Kinners>
no, that's not the purpose
<pattern_>
technically, no... because he did specify that n must be mutable... but i don't see a reason for it
<Kinners>
what happens when you call x 2.0 again?
<pattern_>
oh, i see
<pattern_>
i was only thinking of it being used once
<pattern_>
but that's an excellent point
<pattern_>
actually, if you called it by: "let x = foo (ref 1.0)" then you could call it twice and have the same result ;)
<Kinners>
what do you mean?
<pattern_>
i mean (ref 1.0) is an anonymous reference
<pattern_>
so calling foo with another anonymous reference a second time won't matter
<pattern_>
it was a lame attempt at humor
<pattern_>
nevermind
<Kinners>
ok :)
<pattern_>
i do see that, since you'll likely be calling foo with a real reference, it does very much matter when you call it more than once
<pattern_>
so i'm going to email this guy http://www.paulgraham.com/accgen.html with the fruits of our labor, so OCaml can take its rightful place on the list of Accumulator Generator languages
<pattern_>
i don't know any of the other languages on there... but i bet some of them didn't stick to the letter of the specifications
<pattern_>
like i see that in the vbscript snippet n is declared "private"
<pattern_>
that'll likely be the equivalent of allowing n to remain immutable in ocaml
<pattern_>
one of them being that the function must take both ints and floats
<Kinners>
the vbscript code looks ok to me, but I don't know vbscript that well, it creates a new instance of the class on each foo() call doesn't it?
<Kinners>
I wondered about that
<pattern_>
i don't know vbscript at all... that was just a guess about n being a local variable, making it practically equivalent to letting n stay immutable in ocaml (since all you'll need to do is return the value of n + i)
<whee>
ensub.html
<pattern_>
as far as the function taking both ints and floats, i guess i'd have to create a new type
<whee>
bah
<Kinners>
palomer: you need to make a function that keeps track of the value of n after each addition
<pattern_>
yes, and that's what the reference is for
<pattern_>
i understand
<pattern_>
i was just saying that the vbscript looked like it wasn't doing that
<pattern_>
but maybe it is... i don't know vbscript
<pattern_>
one extra interesting requirement is that "Doesn't store the accumulated value or the returned functions in a way that could cause them to be inadvertantly modified by other code."
<Kinners>
I think it is, create a new class instance on each foo call with a private n variable
<pattern_>
if n is mutable then there's no way to keep it from being "inadvertanly modified by other code", is there?
<pattern_>
that's the whole point of having an immutable value
<Kinners>
you need some form of closure, so having a private n for each call to foo
<pattern_>
but if it's immutable then there's no way to get a sum of all the values ever passed to the secondary function
<pattern_>
this is actually a kind of interesting problem
<pattern_>
definately not as simple as it first appeared when the solution seemed to be simply: let foo n i = n + i
<Kinners>
time for <cough>Obj.magic</cough>?
<pattern_>
hehe
<pattern_>
i don't even know oo at all
<pattern_>
and i think using an library function would be cheating :)
<pattern_>
how about: "let foo n i = let n' = ref n ; n' := !n' + 1; n!"
<pattern_>
i mean "+ i", not "+ 1"... don't know why i keep typing 1
<whee>
how about a closure of some sort?
<whee>
like the haskell version
<whee>
<-- learning dvorak :D
<pattern_>
nice
<whee>
still typing slow heh
<pattern_>
after dvorak you should tackle boustrophedon
<pattern_>
and then really make your computer unuseable to anyone else ;)
<Kinners>
pattern_: you'd be creating a new ref on each call
<pattern_>
grrr
whee has quit [Remote closed the connection]
<pattern_>
and the syntax was all messed up... fixed it, but you're right
<Kinners>
want the answer?
<pattern_>
ya
<Kinners>
let foo n = let n' = ref n in fun i -> n' := !n' + i; !n';;
<pattern_>
you're da man
<pattern_>
now i have to figure out why it's different from:
<pattern_>
let foo n i = let n' = ref n in n' := !n' +. i ; !n' ;;
<pattern_>
why should where i is input in to the function make a difference?
<pattern_>
let foo n i = let n' = ref n in n' := !n' + i ; !n' ;;
<pattern_>
let foo n = let n' = ref n in fun i -> n' := !n' + i ; !n' ;;
<pattern_>
they look functionally identical to me
<Kinners>
what happens in both cases when you call foo 10?
<pattern_>
a function is returned
<pattern_>
that function has 'n as a local reference containing 10
<pattern_>
that function takes another argument
<Kinners>
not in the first case
<Kinners>
the first case, you just get the curried form (hope I'm not butchering that term) of foo n, so let n' = ref n ... hasn't been executed at that point
<pattern_>
it hasn't?
<pattern_>
then i don't understand how currying works
<Kinners>
no, it's waiting for you to apply the final arguments
<pattern_>
i see
<pattern_>
and in the 2nd case it does assign n to n'
<pattern_>
and only then does it ask for another argument
<pattern_>
makes sense now
<Kinners>
right, it builds a closure and returns the accumulator ready to be used
<pattern_>
it's cool how you can ask for another argument in the middle of a function like that
<pattern_>
i didn't know you caould do that
<pattern_>
now all that's left is to make the function accept both ints and floats
<pattern_>
oooh... listen to this: "I currently believe that you can't write this program in ML and Ocaml (no polymorphism)" !
<Kinners>
benchmarks/comparions are kind of arbitrary
<pattern_>
true.. it's just a toy problem
<Kinners>
for dynamically typed languages
<pattern_>
but still... it's sad that ocaml isn't listed there among the likes of c++, vbscript and javascript
<pattern_>
if they can do it, ocaml should be able to do it
<pattern_>
although i don't know if it can be done withing the same function
<pattern_>
because i think you'd need to define a new type for both ints and floats first
<pattern_>
and even then it could concievably violate his requirement that the function take "exactly one argument"... since you'd need to pass it something like (FloatInt 2.0)
<Kinners>
let make_gen f n = let n' = ref n in fun i -> n' := f !n' i ; !n';; would be what you might do, lets you pass a function
<pattern_>
how would that help?
<Kinners>
let intadd_gen = make_gen (+) or let floatadd_gen = make_gen (+.)
<pattern_>
right, but now we have all of these seperate functions
<Kinners>
or let foobar = make_gen (fun x y -> x + y * x) 10;;
<Kinners>
not as an answer to the question but in the real world :)
<pattern_>
and you have to know which arguments you're passing to it ahead of time in order to use the right function
<Kinners>
you need to do that anyway
<pattern_>
and if you know what arguments you'll be passing, you might as well create a new polymorphic type first, and call "foo (FloatInt 2.0)"
<Kinners>
foo only supports addition
<pattern_>
it does in our present form
<pattern_>
but you can have it pattern match based on the polymorphic type instead
<pattern_>
and then add float or int based on the type
<Kinners>
I'm not talking about foo anyway, I'm just saying if you were writing a real foo function for use in a program, using make_gen instead is much better anyway
<pattern_>
so, you'd actually call it with "foo (Float 2.0)" or "foo (Int 2)", then... not "foo (FloatInt 2.0)"
<pattern_>
yeah, it is better because it allows you to pass an arbitrary function
<pattern_>
i was still talking about the toy problem
<Kinners>
yep
<pattern_>
so i guess the reason that ocaml doesn't allow arguments to be polymorphic is because then it couldn't do compile-time type checking, right?
<Kinners>
something like that, someone did some work on polymorphism though
<Kinners>
using a polymorphic type would be equivalent to the C++ exampe I think
<pattern_>
really?
<pattern_>
then the c++ example must be violating the spec, which says the function must take a single argument of type float or int
<Kinners>
is let accu = foo (Float 2.0) much different from Acc<double> accu(2.0); ?
<pattern_>
i don't know c++, so i can't say
<Kinners>
you have to tell it the type to use, and if you used Acc<int> accu(2) you couldn't add a double to a accu
<pattern_>
hmmm
<Kinners>
an ocaml version would be a little more strict (like no float + integer)
<pattern_>
why not? we can put in conversions for those
<Kinners>
I was thinking in terms of making it close to the C++ one, so only needing to specify the type in the call to foo
<pattern_>
you'd need to specify it in both foo and the secondary function call
<palomer>
:o
<pattern_>
i don't think this is working anyway
<pattern_>
the pattern match seems to be forcing the value of n' to be float (because that's the first match