First, I'd like to fix grouping within the if/then/else construct. This
is parsed fine:
if y=1 then
let z = 2 in
print_int y;
print_int z;
else
print_string "not one"
But the following isn't accepted:
if y=1 then
print_int y;
print_int 2;
else
print_string "not one"
I understand that the let statement groups the following compound
expression into one statement for the then-clause, so it's a precedence
problem. Would it really be enough to raise the precedence of ; higher
than that of if/then? Is there any reason this hasn't been done already?
Second, I have some ideas of things to do with Atomic Variants (sounds
like they could be a monster in a sci-fi movie). First thing is to
somehow allow the use of a type composed of all Atomic (non-polymorphic)
Variants as an integer type. One thing I want to do is index arrays
with them. Yes, I could use records, but then I couldn't iterate across
the structure.
Thanks for listening, and tune in next time for more crazy ideas.
E.
_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs
Hm... instead of having
type food = Carrot | Apple | Pizza | Coke | Sushi
let in_supply = Array.create 5 0
in_supply.(Coke) <- 20
you could do it like this instead
let carrot, apple, pizza, coke, sushi = 0, 1, 2, 3, 4
let in_supple = Array.create 5 0
in_supply.(coke) <- 20
What do you think?
- Tom
It may be useful to note that some people might want to write code like:
foo ;
x <- if y then a else b ;
bar ;
In that example bar is really meant to be outside the if-then-else.
OCaml has no such thing as statements, but only expressions. But let
me use these words: you want a statement-level if-then-else with lower
precedence than ";", it cannot be the same as this expression-level
if-then-else with higher precedence than ";". If you're bored with
begin/end a good solution might be to define a new construct using
camlp4 instead of hacking the compiler. It's the good advice in
general for syntax problems.
my_if condition my_then
foo ;
x <- if y then a else b ;
bar ;
my_else
etc
Of course one wants better keywords than this. Finally, I'd made the
closing of that new if mandatory, it seems clearer.
Hope that helps.
--
David
On 1/13/07, Edgar Friendly <thele...@gmail.com> wrote:
> Would it really be enough to raise the precedence of ; higher
> than that of if/then? Is there any reason this hasn't been done already?
and
On 1/13/07, David Baelde <david....@gmail.com> wrote:
> It may be useful to note that some people might want to write code like:
>
> foo ;
> x <- if y then a else b ;
> bar ;
>
> In that example bar is really meant to be outside the if-then-else.
I think the biggest consern is that the else clause is optional. So
you can write code like this:
if condition then do_something (); (* no trailing else clause *)
do_something_else (); (* this is outside the if expression ')
...etc...
I think this is the uncommon case, and deserves the parentheses:
x <- (if y then a else b) ;
> > OCaml has no such thing as statements, but only expressions. But let
> > me use these words: you want a statement-level if-then-else with lower
> > precedence than ";", it cannot be the same as this expression-level
> > if-then-else with higher precedence than ";".
I think I'm arguing that the precedence of if/then/else is too high, and
maybe should be lowered. Of course this isn't a reasonable thing to
ask, because it'll likely break existing code. Anyone with a way to
have my cake and eat it too?
> > If you're bored with
> > begin/end a good solution might be to define a new construct using
> > camlp4 instead of hacking the compiler. It's the good advice in
> > general for syntax problems.
Writing things in camlp4 could help me, but won't improve the world of
ocaml. I want to compare the situation to TeX / LaTeX -- since you can
customize it so much, people fix what they don't like on their local
copy, but these improvements never make it upstream to improve the
situation for the world.
I will agree that I am too eager to "fix" the compiler, and appreciate
the community's help in tempering my inexperience. But I'd like to help
ocaml become a better language, and this seems like a reasonable small
step to start on.
E.
What you really want is a mapping from a variant type to elements of
data. We already have the Map and Hashtbl modules for that. Although
it would be nice with some syntactic sugar for dealing with them.
There seems to be an old syntax extension for hashtables here:
http://www.bononia.it/~zack/stuff/hashtbl_ext.ml
E.
Not in a functional language, like OCaml, where you're composing expressions
into programs. If you want to make a fair comparison you should at least
start by quantifying how common each is, and whether or not your proposed
change has knock on effects (e.g. cyclic precedences).
> I think I'm arguing that the precedence of if/then/else is too high, and
> maybe should be lowered. Of course this isn't a reasonable thing to
> ask, because it'll likely break existing code. Anyone with a way to
> have my cake and eat it too?
Use camlp4 to create some more revised syntaxes.
> > > If you're bored with
> > > begin/end a good solution might be to define a new construct using
> > > camlp4 instead of hacking the compiler. It's the good advice in
> > > general for syntax problems.
>
> Writing things in camlp4 could help me, but won't improve the world of
> ocaml.
It will if you do something more productive with camlp4, like try...finally
or ...
> I want to compare the situation to TeX / LaTeX -- since you can
> customize it so much, people fix what they don't like on their local
> copy, but these improvements never make it upstream to improve the
> situation for the world.
>
> I will agree that I am too eager to "fix" the compiler, and appreciate
> the community's help in tempering my inexperience. But I'd like to help
> ocaml become a better language, and this seems like a reasonable small
> step to start on.
I wouldn't call changing the precedence of "if" a small step...
On a related note, current precedences dictate that this:
string1^string2 :: list
is parsed as:
string1^(string2 :: list)
which is useless.
--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists
You should at least measure the overhead of using a hash table before trying
to address the overhead...
--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists
_______________________________________________
and create lots of different syntax which make the code unsharable at
the end (each one using different syntaxes).
I think camlp4 is the not the proper way to extends the language, and is
definitevely *NOT* going to improve the world of OCaml.
--
Vincent Hanquez
Although I disagree with this first step, I think OCaml need a hand in
becoming more mainstream. unfortunately, it seems that INRIA is not really
interested in making this happened, maybe tweaking syntax and extending the
libraries [1].
At the moment, every one seems to have their own standard libraries to extends
the deficiency/problems/lacks of the common one, and also a bunch a
syntax extensions, that are also incompatible/redundant with each other
for most of them.
[1] I would certainly prefer to be dead wrong here, but at the moment
I'm conforted in this idea.
Cheers,
--
Vincent Hanquez
>> I think I'm arguing that the precedence of if/then/else is too high, and
>> maybe should be lowered. Of course this isn't a reasonable thing to
>> ask, because it'll likely break existing code. Anyone with a way to
>> have my cake and eat it too?
>
> Use camlp4 to create some more revised syntaxes.
>
I was thinking more along the lines of some parsing trick that would
look for the 'else' without the user having to use a 'let' binding as
the then-expression.
hmm, maybe it'd suffice to change
| if /expr/ then /expr/ [ else /expr/ ]
to
| if /expr-high-priority-semi/ then /expr-high-priority-semi/ [ else
/expr-high-priority-semi/ ]
>> I want to compare the situation to TeX / LaTeX -- since you can
>> customize it so much, people fix what they don't like on their local
>> copy, but these improvements never make it upstream to improve the
>> situation for the world.
>>
Does this make sense? It's like every user having their own forked
system. Without someone collecting, filtering, editing, integrating
improvements, improvements stay scattered and of little use to the
community.
E.
It's not the uncommon case... It's what's the ?: operator for C++ and Java.
I guess it's very common indeed.
I think I'm arguing that the precedence of if/then/else is too high, and
> maybe should be lowered. Of course this isn't a reasonable thing to
> ask, because it'll likely break existing code. Anyone with a way to
> have my cake and eat it too?
>
>
Look at nemerle [1], I believe they have the if/then/else construct with the
else clause mandatory, and for cases where in OCaml it is ommited, they
would use the when keyword. This solves your problem:
if y=1 then
print_int y;
print_int 2;
else
print_string "not one"
is same as
if y=1 then
( print_int y;
print_int 2; )
else
print_string "not one"
but
when y=1 then
print_int y;
print_int 2;
would be (in OCaml)
(if y=1 then print_int y); print_int 2
Does it make code unsharable or can you apply multiple camlp4 macros to one
piece of code?
> I think camlp4 is the not the proper way to extends the language, and is
> definitevely *NOT* going to improve the world of OCaml.
Camlp4 may be the best we have. I can't wait to see the next generation...
Playing with Haskell and F# has opened my eyes a bit. F#'s operator
overloading and active patterns will make my code much nicer. Being lazier
can simplify things until you have to optimise, in which case it suddenly
becomes really complicated and error prone.
--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists
_______________________________________________
I've been considering commercialising the replacement OCaml stdlib that I
developed. Are you still using it? Would anyone else be interested?
Lots can be done to improve upon the reliability and performance of OCaml's
stdlib...
--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists
_______________________________________________
What do you mean exactly in this last sentence ? I agree OCaml should
evolve but what kind of "laziness" are you referring to ?
Sincerely,
--
Gabriel Kerneis
What I meant, is when you need to read code that used camlp4 you need to
learn almost a new language. It obviously depends of the changes, but
it's not pure OCaml.
I can trivially find a lots of different incompatible syntax doing a 5s
search, that's the problem.
The common syntax "extensions" should come with OCaml so that everyone
that use OCaml use the same language. I'm not saying camlp4 has no use,
but it should be limited to very specific use.
--
Vincent Hanquez
That won't help to make OCaml a mainstream language.
The ones which are going to buy this, if there's anyone, will have a
different code than the one that are not going to buy it. it just
balkenized a bit more the situation.
It's not really complex to have a replacement stdlib anyway, everybody
can do it, and a lots of people have already put some freely-available
on the internet.
> Are you still using it?
It has been heavily stripped.
--
Vincent Hanquez
Lazy (as opposed to eager) computation. OCaml is very eager. Using laziness
more can speed things up in some simple cases, e.g. nested maps and folds.
> > I think camlp4 is the not the proper way to extends the language, and is
> > definitevely *NOT* going to improve the world of OCaml.
>
> Camlp4 may be the best we have. I can't wait to see the next generation...
>
> Playing with Haskell and F# has opened my eyes a bit. F#'s operator
> overloading and active patterns will make my code much nicer.
Felix has 'user defined syntax' which includes infix operators,
outfix operators (brackets), and arbitrary statements. Arbitrary
extensions to expressions aren't supported yet.
However the system isn't really as good as Camlp4: if user
grammar productions are overloaded, then because the system
uses recursive descent parsing error handling is weak
(an unoverloaded production is handled as a special case,
so left factoring is recommended). Caml p4 allows almost arbitrary
intervention in the grammar, and the action rules are arbitrary
Ocaml -- felix only allows syntax macros (which are Turing complete
but macros just don't cut it compared to explicit code generation
for complex cases).
Of course, Felix has function overloading (which subsumes
operator overloading).
I'm curious what active patterns are. Is that using RTTI to
decode expressions at run time? Like a strong form of
C++ 'dynamic cast'? (or, an extension of variant decoding,
which after all is also using a variant tag for run time
decoding).
BTW: the *major* problem with all code generators is error handling.
It's very easy to add 'sugar' to a language in the form of rewrite
rules .. it is much harder to handle errors, because they might
occur either in the desugaring OR in subsequent processing
(eg type checking). Since the subsequent processing uses the
desugared form of the code, it is hard to refer properly
to the location of the error.
Mind you .. HM type inference has this problem too.
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
> The common syntax "extensions" should come with OCaml so that everyone
> that use OCaml use the same language. I'm not saying camlp4 has no use,
> but it should be limited to very specific use.
Conditional compilation is one of those uses I think.
There is little need for it in Ocaml, compared to C, but it
is still occasionally useful.
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
This is not clear. Laziness can be very fast if well optimised,
but optimisation is hard in general. The trivial case of nested maps
and folds can be optimised by hand in Ocaml.
It also isn't really true Ocaml is 'eager' in 'general'.
Almost all constructions in all languages are in fact lazy:
indeed procedural/imperative programming is ultimately lazy.
A simple example: Ocaml match is lazy:
match x with | true -> t | false -> f
evaluates t or f lazily .. in general this is obviously
necessary since any pattern variables (not exhibited in
this case) are not known until the match is done.
At best you can say function application in Ocaml is eager,
and even that isn't true: wherever you use a reference,
you're passing a pointer, and that's lazy evaluation,
until you 'eagerify' it by dereferencing the pointer.
Similarly when you pass a mutable data structure as an argument,
evaluation is actually lazy .. operations on it are done
*inside* the function body.
So actually, in an imperative language like Ocaml, there is no
real need for lazy evaluation of function arguments .. there
is already plenty of control over evaluation time. The main
downside is that the programmer needs to exert this control
manually .. and that is also the main upside, compared to
say Haskell, where you really don't know how good a job
the optimiser is doing precisely because of the lazy semantics.
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
Although remind you that a property of camlp4 syntaxes is that you can
trivially convert an input source in plain (indented) OCaml code. This
is done using the Pr_o module, an OCaml pretty printer.
Thus, you can share it.
$ camlp4 some_strange_syntax.cmo pr_o.cmo foo.ml -o foo_ocaml.ml
--
Nicolas Pouillard
Hmmm .. changing the precedence of operators to avoid two parentheses ...
I don't think that's good.
if y=1 then (
let z = 2 in
print_int y;
print_int z;
) else
print_string "not one"
I will however add my own pet wish: a 'return' statement! It doesn't
have to break type safety -- you should only be allowed to 'return' a
type compatible with the ordinary return type of the function. The
alternative (using exceptions to jump out of code) is ugly, slow and
unsafe.
Rich.
--
Richard Jones
Red Hat UK Limited
I agree, I cannot think of a bad way to use it, and it would be more
useful than having one more nested if then else or an exception mechanism.
(the only problem I'm seeing if that people will use this return
statement at the end of function)
Xavier, if somebody does a patch to do that or some other useful feature,
would that be considered for entering CAML's CVS ?
(i.e. what are the rules for accepting a patch ?)
Cheers,
--
Vincent Hanquez
> On 1/14/07, Vincent Hanquez <t...@snarc.org> wrote:
> > and create lots of different syntax which make the code unsharable at
> > the end (each one using different syntaxes).
> >
> > I think camlp4 is the not the proper way to extends the language, and is
> > definitevely *NOT* going to improve the world of OCaml.
> >
>
> Although remind you that a property of camlp4 syntaxes is that you can
> trivially convert an input source in plain (indented) OCaml code. This
> is done using the Pr_o module, an OCaml pretty printer.
>
> Thus, you can share it.
>
> $ camlp4 some_strange_syntax.cmo pr_o.cmo foo.ml -o foo_ocaml.ml
Getting standard OCaml code doesn't guarantee that you can do something
with it: in the case of syntax extensions, the result will be most likely
unreadable. But the real problem is that there is no way of reverting
back to the original source code. So if you write your programs in the
revised syntax, all patches must be written in the revised syntax.
Martin
--
Martin Jambon
http://martin.jambon.free.fr
> On Mon, 15 Jan 2007, Nicolas Pouillard wrote:
>
>> On 1/14/07, Vincent Hanquez <t...@snarc.org> wrote:
>> > and create lots of different syntax which make the code unsharable at
>> > the end (each one using different syntaxes).
>> >
>> > I think camlp4 is the not the proper way to extends the language, and is
>> > definitevely *NOT* going to improve the world of OCaml.
>> >
>>
>> Although remind you that a property of camlp4 syntaxes is that you can
>> trivially convert an input source in plain (indented) OCaml code. This
>> is done using the Pr_o module, an OCaml pretty printer.
>>
>> Thus, you can share it.
>>
>> $ camlp4 some_strange_syntax.cmo pr_o.cmo foo.ml -o foo_ocaml.ml
>
> Getting standard OCaml code doesn't guarantee that you can do something
> with it: in the case of syntax extensions, the result will be most likely
> unreadable. But the real problem is that there is no way of reverting
> back to the original source code. So if you write your programs in the
> revised syntax, all patches must be written in the revised syntax.
Yes.
And the worst thing is, that your "original" source will only be
usable as long as the syntax extension is being maintained by
someone. You might even have to take over maintenance yourself at the
end. That might be a big cost for a bit of syntactic sugar in the long
run.
Regards -- Markus
> On Sun, Jan 14, 2007 at 08:49:57PM +0000, Jon Harrop wrote:
> > Does it make code unsharable or can you apply multiple camlp4 macros to one
> > piece of code?
>
> What I meant, is when you need to read code that used camlp4 you need to
> learn almost a new language. It obviously depends of the changes, but
> it's not pure OCaml.
>
> I can trivially find a lots of different incompatible syntax doing a 5s
> search, that's the problem.
>
> The common syntax "extensions" should come with OCaml so that everyone
> that use OCaml use the same language. I'm not saying camlp4 has no use,
> but it should be limited to very specific use.
OCaml is well-enough designed so that there is no "common" syntax
extension. The problem is that people use it for a variety of things, and
each domain may benefit from particular enhancements of the syntax.
Either you incorporate all those extensions into the standard syntax,
which is totally insane, or you consider them just as libraries. Loading
a library is no big deal, whether it provides more functions or more
syntax.
IMHO the problem is more that writing camlp4 syntax extensions is very
different from writing everyday OCaml code. In other words,
it is inaccessible to beginners, and most other people think it's too
complicated anyway. It requires too much expertise and only few people are
able to maintain such code.
Here is a list of things that I suggest if one ever wants to have a
standard and widely use way of extending the syntax in OCaml:
* implement a 2-stage (2, not n) compilation so that syntax extensions can
be defined in standard OCaml modules.
* each "macro" has a name and is provided as a module item.
* there should a standard syntax for macro expansions, so that external
readers know that a special syntax is being used. E.g.
<:Mymodule.mymacro< blabla >>
where blabla is parsed using the standard OCaml lexer, and the custom
"mymacro" parser provided by module "Mymodule" (as opposed to current
quotations where the content is parsed with any lexer).
* defining a syntax extension should be done with some code which looks as
much as possible like standard Ocaml.
Here is an example. There are three new keywords "macro", "quote" and
"pragma", plus some special syntax for writing the parser.
"macro" is used to introduce the definition of a syntax extension.
"quote" is used to represent the OCaml syntax tree and is available only
in macro definitions. It would be a standard replacement for
<:expr< ... >>, <:patt< ... >>, etc. Its type (expr, patt, str_item, ...)
should be figured out automatically.
"pragma" would introduce normal OCaml code which must be compiled during
the first stage of the compilation (not shown in the example).
macro cond stream =
let subst e1 e2 e3 = (* could be defined externally using "pragma" *)
match e1 with
quote true -> e2
| quote false -> e3
| _ -> quote (if $e1 then $e2 else $e3) in
parse stream with (* equivalent of an EXTEND statement with a single,
new entry *)
[ [ e1 = Ocaml.expr; e2 = Ocaml.expr; e3 = Ocaml.expr -> subst e1 e2 e3
| e1 = Ocaml.expr; e2 = Ocaml.expr -> subst e1 e2 (quote ()) ] ]
(* same program, continuing *)
let test_cond x y z =
<:cond< (x + y = z) (z + 1) 0 >>
(* is equivalent to:
let test_cond x y z =
if (x + y = z) then (z + 1) else 0
*)
OK, there are many issues to solve, and it may not look as simple as
advertised, but I am sure it can be done.
Martin
--
Martin Jambon
http://martin.jambon.free.fr
_______________________________________________
The camlp4-based syntax extension for lazy stream parsing could be considered
a "common" extension because it is bundled with OCaml and is used by lots of
people.
I used it in several of the tutorial papers on our site simply because it is
the most succinct approach to parsing:
http://www.ffconsultancy.com/free/ocaml/parsing.html
http://www.ffconsultancy.com/free/ocaml/interpreter.html
It may be superceded by active patterns but I'd still like to see this syntax
incorporated into OCaml itself.
> The problem is that people use it for a variety of things, and
> each domain may benefit from particular enhancements of the syntax.
try ... finally is another syntax extension that I think would be welcomed by
all.
> Either you incorporate all those extensions into the standard syntax,
> which is totally insane, or you consider them just as libraries.
I think there are several camlp4 syntax extensions that are sufficiently
useful that we would all benefit from them being incorporated into the
language.
> IMHO the problem is more that writing camlp4 syntax extensions is very
> different from writing everyday OCaml code. In other words,
> it is inaccessible to beginners,
I highly recommend this web page by some guy called Martin Jambon: ;-)
http://martin.jambon.free.fr/extend-ocaml-syntax.html
Your page is really the only resource on the web that aims to elucidate
camlp4. It is very good, but I still failed to write the syntax extension
that I wanted (symbolic expressions as patterns).
> OK, there are many issues to solve, and it may not look as simple as
> advertised, but I am sure it can be done.
All good ideas.
--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists
_______________________________________________
> try ... finally is another syntax extension that I think would be
> welcomed by
> all.
A less invasive alternative would be to add something like this to
pervasives (taken from Leroy and Rémy's unix course [1]) :
let apply f x ~finally y =
let res = try f x with exn -> finally y; raise exn in
finally y;
res
The only quirk is that when you need to introduce a local or
anonymous function for the blocks, but I don't really care about that.
However I'm tired of copying this function over and over in my io
intensive sources.
Best,
Daniel
[1] <http://pauillac.inria.fr/~remy/poly/system/camlunix/index.html>
There ARE common syntax extensions.
how many people miss a try-except-finally construct ?
how many people miss a return statement to break the flow of a function.
etc ..
I'm not talking about weird extensions that ease the life of grammar
writter or lambda calculus , etc .. but really the basic one.
I still think camlp4 is a good idea for limited use like this.
> The problem is that people use it for a variety of things, and
> each domain may benefit from particular enhancements of the syntax.
> Either you incorporate all those extensions into the standard syntax,
> which is totally insane, or you consider them just as libraries. Loading
> a library is no big deal, whether it provides more functions or more
> syntax.
I'm especially not talking about all extensions, but obviously the ones
that everybody can use, whatever they works on.
> IMHO the problem is more that writing camlp4 syntax extensions is very
> different from writing everyday OCaml code. In other words,
> it is inaccessible to beginners, and most other people think it's too
> complicated anyway. It requires too much expertise and only few people are
> able to maintain such code.
What about the beginners then ?
All what you suggest below doesn't really help making it more accessible
I think.
> Here is a list of things that I suggest if one ever wants to have a
> standard and widely use way of extending the syntax in OCaml:
> [snip]
I like this special "macro" keyword and this should also be part of the
language. So does some specific construction like try-finally.
--
Vincent Hanquez
This is exactly my point.
I have this kind of trivial function spread over and over again.
and lots of people have this function as well, maybe a bit different,
slightly imcompatible with each other.
Coding with OCaml would be some much easier if all those trivia would
come directly with the STANDARD distribution. and it would be much more
consistant across 2 differents developers as well.
Cheers,
--
Vincent Hanquez
> On Mon, Jan 15, 2007 at 11:13:58PM +0100, Daniel Bünzli wrote:
>> A less invasive alternative would be to add something like this to
>> pervasives (taken from Leroy and Rémy's unix course [1]) :
>>
>> let apply f x ~finally y =
>> let res = try f x with exn -> finally y; raise exn in
>> finally y;
>> res
>>
>> The only quirk is that when you need to introduce a local or
>> anonymous function for the blocks, but I don't really care about
>> that.
>>
>> However I'm tired of copying this function over and over in my io
>> intensive sources.
>
> This is exactly my point.
>
> I have this kind of trivial function spread over and over again.
> and lots of people have this function as well, maybe a bit different,
> slightly imcompatible with each other.
>
> Coding with OCaml would be some much easier if all those trivia would
> come directly with the STANDARD distribution. and it would be much
> more
> consistant across 2 differents developers as well.
I don't know for the other trivial functions, but this apply function
looks like
Std.finally from extlib.
I hardly miss any trivial functions when using extlib, mileage might
vary.
--
Best Regards,
Quôc
extlib is not the only standard extension library that exists.
I can easily count 3 of them widely available on internet.
and, agreed that's a good start (if that's would be directly available
in pervasives), it's not as good has having a:
try
...
finally
...
directly in the language.
Cheers,
--
Vincent Hanquez
I don't miss any of those things .. the point being they're
not so 'common' as you might think.
I'm a Python programmer too, and I never use 'finally' ..
I've never found any use for it.
Felix has return statement .. but then Felix has *statements*:
executable Ocaml is all expressions, so a return statement would
seem out of place.
> I'm not talking about weird extensions that ease the life of grammar
> writter or lambda calculus , etc .. but really the basic one.
One man's nice extensions are weird to another. Many parts of
Ocaml are weird (IMHO :) but at least its a shared weirdness.
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
try ... finally is useful when closing file handles.
However, simply trying to read a file as a list of strings is a sticking point
for many newbies because the obvious functional implementations aren't
robust:
let rec read ch = try input_line ch :: read ch with End_of_file -> []
Elegant but not tail recursive. Conventional transformation into tail
recursive form using an accumulator:
let rec read ?(t=[]) ch =
try read ~t:(input_line ch::t) ch with End_of_file -> t
Still not tail recursive because tail calls inside a try block are not
optimised, so it still segfaults when the file has >100,000 lines on a 64-bit
machine.
Solution is to box and unbox, moving the tail-recursive call outside the try
block:
let rec read ?(t=[]) ch =
match try Some(input_line ch) with End_of_file -> None with
| Some h -> read ~t:(h::t)
| None -> t
Inelegant.
We really want a File.fold function to fold over the lines of the file, and a
cons function:
File.fold cons ch []
I have a much bigger wish list for functions than I do for syntax. I'd like
the stdlib functions to be tail recursive, more comprehensive and faster...
--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists
_______________________________________________
> I have a much bigger wish list for functions than I do for syntax. I'd like
> the stdlib functions to be tail recursive, more comprehensive and faster...
>
Should we start another thread to put improved/needed stdlib functions?
I imagine some discussion (and postings of code) related to this matter
could be productive.
E.
correct me if i am wrong,
you want this to work like it currently does:
if cond then bla;
bla_outside_if;
and this to work like you describe it:
if cond then bla;
bla_inside_if;
else
inside_else;
what_about_this; (* ? *)
appart from the what_about_this expression, consider this:
if cond then
bla;
bla; if cond2 then bla;
bla;
bla;
else ... (* which if do this belong to? *)
allthough it is straitforward to say that else always belongs to the
"if" it is closest to, it does add a whole new elemnt of confusion.
Just pretend parentheses are compulsory :). (What would happen in C
if we left the braces out anyway! Go and change C instead, this will
affect far more people!)
BTW, learning a language by saying you want to change it (before you
even did any interesting programming in it) is not IMHO the most
beneficial attitude. It is really kind of you to want to help us to
"improve the world of ocaml" but shouldn't you learn the language
inside out and write two or three projects in it first ?
My 2^(-10)€ (with or without parentheses),
C.
I would suggest using some other name than 'end' (maybe 'endif'?)
since end is allready used to terminate a lot of other structures, if
'end' might or might not follow an if it would mess those other
structures up big time :)
> try ... finally is useful when closing file handles.
[]
> Solution is to box and unbox, moving the tail-recursive call outside the try
> block:
>
> let rec read ?(t=[]) ch =
> match try Some(input_line ch) with End_of_file -> None with
> | Some h -> read ~t:(h::t)
> | None -> t
>
> Inelegant.
But what I do all the time to eliminate exceptions, which in general
I dislike. In my context
let entry = try Some (Hasthtbl.find tbl key) with Not_found -> None in
match entry with
| Some v ->
| None ->
No issue of recursion here. Of course, it is easy to just define
the first line as a function, encapsulating the inelegance at
the expense of readers needing to know what an undocumented
function does.
But is it the job of a language to provide syntax for everything?
Usually languages provide syntax which spans the primitives
and a bit more covering really common idioms .. and leaves
the rest to the library.
A too rich syntax is harder to learn IMHO, for example
Ocaml classes are hard to learn. I've been writing Ocaml
for a while and still have no idea what the difference
between a method interface in a class type and a virtual
method is.
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
> Should we start another thread to put improved/needed stdlib functions?
> I imagine some discussion (and postings of code) related to this matter
> could be productive.
It would be more productive, IMHO, to join with a developer
team such as that of extlib and contribute to an existing
library, wouldn't it?
Alternatively, you can put a feature request in the
official Ocaml bugtracker.
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
> No, I want to make the following code legal:
>
> if y = 1 then
> print_int y;
> print_int z;
> else
> print_string "not one"
>
>
> It's just an unnecessary stumbling block for programmers coming from
> other languages.
So is your syntax:
if cond1 then e1
elif cond2 then e2
..
else el
endif
is THE correct, unambiguous, formulation, and what Felix uses <g>.
For procedural code:
if cond do ..
elif ..
..
else ..
done
These forms were decided by Wirth after the Pascal ambiguities,
and his next attempt, Modula, uses them.
Felix also uses
match .. with .. endmatch
but strangely has an open
let .. in ...
whereas Standard ML uses
let .. in .. end
Ocaml uses a closed form here:
for .. do .. done
Felix, like C++, also has ; as a statement terminator
not a separator. Research was done on this (no I can't
cite it). Terminators are known to be better :)
Closed forms are precedence free, allow an unambiguous
grammar, and support easy cut and paste: all in all,
these syntaxen obey an important rule: the substitution
principle.
However, they lead to excess terminators, and so most languages
close some forms and leave others open. IMHO Ocaml leaves
too many open, but this is just a minor taste issue: what
really interested me is the semantics.
BTW: Python solves the excess terminator problem by using indentation,
which is generally quite nice, IMHO, though it makes code containing
long quoted strings very ugly.
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
Of course, the correct® ugly alternative is to manually CPS-transform your code.
If functions don't return, you don't need no steenkin' return statements :-).
Yours, Florian.
Xavier, if somebody does a patch to do that or some other useful feature,
would that be considered for entering CAML's CVS ?
(i.e. what are the rules for accepting a patch ?)
Last time this question came up the answer was submit the patch
as feature wish to the bug tracking system and pray. See
http://caml.inria.fr/pub/ml-archives/caml-list/2001/10/4bad397017270c62b70852840f37ad61.en.html
But perhaps the position of the Ocaml team has changed?
Bye,
Hendrik
It's totally common to to do some action despite that an exception has
been raised or not to cleanup stuff (like file descriptor is the obvious
example).
At the moment in OCaml you need to multiple layer or try/with to be able
to express this. it would be much nicer to allow this construction as a
proper idiom, not ad-hoc.
> I'm a Python programmer too, and I never use 'finally' ..
> I've never found any use for it.
You probably don't write/read much python code then.
( I found 2 use of finally in felix's python code )
> Felix has return statement .. but then Felix has *statements*:
> executable Ocaml is all expressions, so a return statement would
> seem out of place.
OCaml is a functional language, however it also contains imperative feature.
It doesn't seems so inappropriate to have a return statement, as long
it's not abused.
--
Vincent Hanquez
Well, seeing that the very useful native exception backtrace patch has been
sitting idle (acknowledged) for more than a year, I think that's not
working it out too well :\
Seeing the number of people monitoring the issue, I think lots of people
are waiting it.
I'm not saying the patch is perfect, but at least if somebody in the
ocaml team would say something about it, we could improve it.
http://caml.inria.fr/mantis/view.php?id=3885
--
Vincent Hanquez
>However, simply trying to read a file as a list of strings is a sticking point
>for many newbies because the obvious functional implementations aren't
>robust:
>
>
>
Exceptions are evil.
Brian
No it isn't. First, I don't use exceptions like that: I usually
wrap them. Second, this technique isn't that useful in a language
with garbage collection: this is not C++. A thirdly, in my own
language Felix there ARE no exceptions .. so it can hardly
be 'common'.
The Felix compiler (an Ocaml program) throws exceptions
in three circumstances:
(a) Errors: no cleanup is required.
(b) Library functions: either it is a program error
or I map the exception to a variant: no cleanup is
required.
(c) Exiting a deep recursion: in no case is any
cleanup required.
So actually in a 60Kloc program, no cleanup is done
anywhere for any reason. It just isn't necessary.
> > I'm a Python programmer too, and I never use 'finally' ..
> > I've never found any use for it.
>
> You probably don't write/read much python code then.
Actually I'm a Python ex-guru, I have two major pieces
of software written in it, and I've even *implemented*
a Python interpreter .. in Ocaml :)
> ( I found 2 use of finally in felix's python code )
Probably written by Erick not me :)
> > Felix has return statement .. but then Felix has *statements*:
> > executable Ocaml is all expressions, so a return statement would
> > seem out of place.
>
> OCaml is a functional language, however it also contains imperative feature.
>
> It doesn't seems so inappropriate to have a return statement, as long
> it's not abused.
If I recall, the revised syntax also has a return statement.
I'm simply trying to show that the only way to really substantiate
a claim something is common is to do a real survey of code.
I have not analysed all the Ocaml code out there but it is
my guess most Ocaml programmers would have no real use for
a return expression.
Many may agree exception handling is not so good, but many
would probably favour another proposal for restructuring
exceptions, rather than adding a finally clause.
I forget the URL of the proposal, which is a kind of
let/try construction, perhaps someone can fill that in?
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
Does you felix program have threads ? or lots of file descriptor ? or
has to stay up for a long period of time ? or use side effect quite
extensively ?
Absolutely not, it's a compiler that doesn't need much of these stuff.
And even then, you can most of the time just rely on exit(3) to cleanup
since it's a short live service.
What about a server now ? add threads in the mix where all mutex need to
be properly unlocked, add also function with weird side effects that
don't have any representation variable at the OCaml level (thus cannot be
garbage collected), etc...
So please don't generalise your situation which is quite specific
(compiler) to the whole world of OCaml and open your mind to the fact
that people has different need/expectation.
(and that Felix doesn't have exceptions, I couldn't care less. OCaml
does and there are no going away, so live with it.)
> Actually I'm a Python ex-guru, I have two major pieces
> of software written in it, and I've even *implemented*
> a Python interpreter .. in Ocaml :)
Good for you. (interpreter still fall in the compiler category btw)
Cheers,
--
Vincent Hanquez
> Does you felix program have threads ? or lots of file descriptor ? or
> has to stay up for a long period of time ? or use side effect quite
> extensively ?
>
> Absolutely not, it's a compiler that doesn't need much of these stuff.
> And even then, you can most of the time just rely on exit(3) to cleanup
> since it's a short live service.
Correct.
> What about a server now ? add threads in the mix where all mutex need to
> be properly unlocked, add also function with weird side effects that
> don't have any representation variable at the OCaml level (thus cannot be
> garbage collected), etc...
What about it? C manages to handle all that .. and has no exceptions.
> So please don't generalise your situation which is quite specific
> (compiler) to the whole world of OCaml and open your mind to the fact
> that people has different need/expectation.
Try not to make assumptions about what people know.
I've been programming for three decades. My mind isn't
closed .. you just don't seem to get that what YOU think
is common practice may actually not be.
> (and that Felix doesn't have exceptions, I couldn't care less. OCaml
> does and there are no going away, so live with it.)
You missed the point. Neither C nor Felix have exceptions, and Ocaml
can be programmed the same way. There's no need for finally
if you program in an 'exception free' style.
It may be convenient but your claim was that the need was 'common'.
I doubt this.
I DO agree exceptions, as structured now, are not so good.
They're clumsy, hard to use, and dangerous (if not downright evil).
But adding 'finally' may not be the best solution,
the try/let construction looks better to me.
> > Actually I'm a Python ex-guru, I have two major pieces
> > of software written in it, and I've even *implemented*
> > a Python interpreter .. in Ocaml :)
>
> Good for you. (interpreter still fall in the compiler category btw)
The interpreter actually needed finalisation, since it used
Ocaml GC instead of Python reference counting. In fact Ocaml
finalisers were more or less added to Ocaml *because* my
project provided a solid use case.
In fact I have used Ocaml in a telco environment .. using
the nice Event module, with many threads, services,
and clients interacting in (soft) real time. That was some
time ago so I can't say if I would have used 'finally'
in that context or not. But typically I do that kind of
thing the C way, which is generally the Ocaml way too:
you propagate return codes from functions using variants
up call chains.
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
E.
> But adding 'finally' may not be the best solution,
> the try/let construction looks better to me.
>
I can't find an example of this. Something about doing variable binding
as part of the try statement, and then finalizing how?
> But typically I do that kind of
> thing the C way, which is generally the Ocaml way too:
> you propagate return codes from functions using variants
> up call chains.
>
The OCaml standard library seems to be programmed using exceptions over
variants. I'll have to say I don't like or use exceptions much, but I'm
forced to by the standard libraries.
E.
Choosing boxing and unboxing over exceptions is fine if you have that choice
and are willing to endure the performance degredation and added verbosity.
However, you only have that choice if your code is self-contained. If you're
writing a library where users can raise exceptions, you must be careful to
undo state changes. In OpenGL, for example:
let transform m k x =
GlMat.push();
GlMat.mult m;
try
k x;
GlMat.pop()
with e ->
GlMat.pop();
raise e
could be rewritten:
let transform m k x =
GlMat.push();
GlMat.mult m;
try k x finally
GlMat.pop()
Handling user-raised exceptions in this way is likely if you're using
higher-order functions.
--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists
_______________________________________________
Not directly. You could use IF .. THEN .. ENDIF and have both.
Or perhaps you could add
if .. do .. done
to Ocaml -- "if .. then .. " and "if .. do .. " are both
supported in Felix which uses Ocamlyacc to parse it,
I think indicating LALR1 can distinguish these two cases?
However camlp4 is recursive descent isn't it?
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
That is a reasonable argument to examine: but I'm not sure
finally is actually all that useful. If you're thinking of:
try maybe_throw X; do something
finally -> cleanup done
then it can be coded in Ocaml like:
begin try maybe_throw X; do something; cleanup
with x -> cleanup; throw x end
Now you can argue the repetition of 'cleanup' is a bad,
and I would agree, BUT in Ocaml this is no big deal:
begin let cleanup = .. in try ... end
In Java and other brain dead languages without lexical scoping
you cannot do this.
So Java really NEEDS finally, whereas in Ocaml the utility
is less. I note C++ can use RAII:
class file {
FILE * f; file(string x) : f(open(x)) {}
~file() { close(f); }
};
..
{
file f(name); maybe throw ..
}
and here needs no finally, but in general in C++ you have
the same problem as Java: no lexical scoping.
> > But adding 'finally' may not be the best solution,
> > the try/let construction looks better to me.
> >
> I can't find an example of this. Something about doing variable binding
> as part of the try statement, and then finalizing how?
I have lost the URL, sorry. But the problem is localisation:
the only sane way to use exceptions is like:
let result = try Some (open f) with Error -> None in
match result with None -> ... Some ....
If you try to do it like:
try
before
open f
middle
close f
after
with _ -> close f
then you have all sorts of problems if a different exception
is thrown in the before or after parts. Using type information
to distinguish the kind of exception is clearly a hack:
what if you're opening two files?
So roughly, this structure is not amenable to composition.
Adding 'finally' doesn't solve that problem, and that
problem is far worse than the lack of finally.
[Sorry this is a really bad explanation ..]
> > But typically I do that kind of
> > thing the C way, which is generally the Ocaml way too:
> > you propagate return codes from functions using variants
> > up call chains.
> >
> The OCaml standard library seems to be programmed using exceptions over
> variants. I'll have to say I don't like or use exceptions much, but I'm
> forced to by the standard libraries.
Yes, but you can do what many people do: map the exceptions into
variants like:
let hfind x y =
try Some(Hashtbl.find x y)
with Not_found -> None
religiously, eliminating the exceptions. And you can convert
to exceptions from variants like:
let efind x y =
match hfind x y with
| Some r -> r
| None -> raise Not_found
So really the library gives one of two cases, and allows you
to code the other easily. You aren't forced to use "long throw"
handlers, i.e. handlers which are a long way from the point
of the throwing code lexically.
The wrapper above eliminates any need for a finally clause
since ordinary conditionals and matches can be used instead --
in the case you're converting to variants.
It still leaves open the case of "long throw" exceptions
where you want to use exceptions: that may well benefit
from a finally clause but you see now the number of use
cases is reduced because the wrapper technique will be
appropriate in some cases.
IN FACT the problem is not entirely an issue with exceptions!
Examining the 'exception free' case using fopen below
we have the SAME problem:
let fopen f lock = try Some (open f) with Error -> None in
let lck = mutex () in lock mutex;
let f = fopen name lck in
match f with
| Some file -> ... close, release lck
| None -> release lck
WOOPS! Again we had to repeat the cleanup code.
Releasing the mutex AFTER the whole code works, but
if we want separate control flows for the two cases
we have to test the variant again:
begin match f with .. end; release lck;
match f with .. (* fork again *)
So actually, you could use a 'finally' here too: the problem
doesn't appear to be special to exception handling, but rather
a case where you have a control fork and want some code done in
the middle of both branches of the fork.
Roughly .. block structure (nesting) can't handle interleaved
execution very cleanly: you can minimise the impact with
lexically scoped subroutine call, but you still need to call
it twice.
Whereas with 'finally' clause you don't, the problem is
that you're restricted to the balanced (block) structure so the
code location of the 'finally' clause is right for both
branches. In complex cases .. the finally clause isn't
useful because it imposes too much nested structure
that turns out to be wrong anyhow: you have a state machine
which just can't be represented with a pushdown stack,
not even one that supports a second control path via
stack unwinding.
Please note again I'm not arguing against adding finally
(though I might do so!) I'm arguing the need for it isn't
as common as you might think in Ocaml, and part of the need
is only a symptom of a wider problem.
Some other languages provide continuations instead
of exceptions, and it is much easier to manage control
flow in such a language, since in effect 'goto' targets
are first class (can be stored in variables). I guess
it is also easier to *lose* control too :)
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
> Choosing boxing and unboxing over exceptions is fine if you have that choice
> and are willing to endure the performance degredation and added verbosity.
> However, you only have that choice if your code is self-contained. If you're
> writing a library where users can raise exceptions, you must be careful to
> undo state changes. In OpenGL, for example:
>
> let transform m k x =
> GlMat.push();
> GlMat.mult m;
> try
> k x;
> GlMat.pop()
> with e ->
> GlMat.pop();
> raise e
>
> could be rewritten:
>
> let transform m k x =
> GlMat.push();
> GlMat.mult m;
> try k x finally
> GlMat.pop()
>
> Handling user-raised exceptions in this way is likely if you're using
> higher-order functions.
Of course any specific example has a work around:
let finally u f = try u () with e -> f (); raise e in
let u () = GlMat.push(); GlMat.mult m in
let f () = GlMat.pop() in
finally u f
This would, however, be a mess if the push/pop things were
nested (which is likely I guess). Felix provides the syntax
{ code here }
meaning Ocaml's
(fun () -> code here)
which is very convenient for this idiom:
finally { push GlMat; mult GlMat m; } { pop GlMat; };
More generally you can write:
let f = new thing in
let finally () = close f in
try ... finally()
with e -> finally(); raise e
which all gets very messy when you have to repeat the
exercise in the 'try' block for some other exception AND
in the 'new thing' code as well .. and it's a nightmare
if your 'finally()' code can ALSO raise an exception.. ;(
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
It would be more convincing if you hadn't made the trivial mistake to
put the first cleanup function in the try.
if for a really weird reason cleanup raises an exception, cleanup is done twice.
the correct OCaml code is:
let r = try maybe_throw X; do something; with exn -> cleanup; raise exn in
cleanup;
r
the point is not it's hard to do, it's annoything to duplicate here and
there, and doing the inline code lose the higher level view we can have
with a syntaxic sugar like try-finally.
> try
> before
> open f
> middle
> close f
> after
> with _ -> close f
>
> then you have all sorts of problems if a different exception
> is thrown in the before or after parts. Using type information
> to distinguish the kind of exception is clearly a hack:
> what if you're opening two files?
The thing is you don't do this with a flat block. If you need to unwind
a complex state you do:
before
try
let fd = open fd
try
middle
finally
close fd
finally
after
> Yes, but you can do what many people do: map the exceptions into
> variants like:
>
> let hfind x y =
> try Some(Hashtbl.find x y)
> with Not_found -> None
I'm not arguing against this method. You do it the way you want,
but when you use exception, having a finally is very handy for a lots of
case. Nothing more, nothing less.
> let fopen f lock = try Some (open f) with Error -> None in
> let lck = mutex () in lock mutex;
> let f = fopen name lck in
> match f with
> | Some file -> ... close, release lck
> | None -> release lck
>
> WOOPS! Again we had to repeat the cleanup code.
> Releasing the mutex AFTER the whole code works, but
> if we want separate control flows for the two cases
> we have to test the variant again:
>
> begin match f with .. end; release lck;
> match f with .. (* fork again *)
>
> So actually, you could use a 'finally' here too:
seems that you *finally* understand it ;)
--
Vincent Hanquez
Again, it would more convincing if the code you wrote was correct.
Here the f function doesn't get call if u didn't raise an exception.
We want the f function to be called in ALL case.
> This would, however, be a mess if the push/pop things were
> nested (which is likely I guess). Felix provides the syntax
This is not about Felix.
> which is very convenient for this idiom:
>
> finally { push GlMat; mult GlMat m; } { pop GlMat; };
And I would wrote it in OCaml with the abstraction function I have:
finally (fun () -> push GlMat; mult GlMat m) (fun () -> pop GlMat);
See, you can also show what you want to show without talking about
language X on language Y's ML, and thus been more on topic.
Cheers,
--
Vincent Hanquez
that's not clear-cut ; it depends on the cleanup function. For
instance, concerning I/O channels in the standard library, you have
close_out and close_out_noerr. They do not have the same behavior, and
you should rather use the _no_err one in the with exn part.
> the point is not it's hard to do, it's annoything to duplicate here and
> there, and doing the inline code lose the higher level view we can have
> with a syntaxic sugar like try-finally.
Just use a higher-order function: it won't duplicate code, it's
high-level and it doesn't require any syntactic sugar.
let with_file_out fname f =
let oc = open_out fname in
try let r = f oc in close_out oc ; r
with exn -> close_out_noerr oc ; raise exn
let with_mat m f =
GlMat.push () ;
let r =
try GlMat.mult m ; f ()
with exn -> GlMat.pop () ; raise exn in
GlMat.pop () ;
r
You're right it's not clear-cut, but I'm talking about generic code.
Some function doesn't have the opportunity to not raise something
(without bracing them in try fct () with _ -> ()) and sometimes you also
want to propagate the cleanup's fct exception .. because something went
very wrong.
> >the point is not it's hard to do, it's annoything to duplicate here and
> >there, and doing the inline code lose the higher level view we can have
> >with a syntaxic sugar like try-finally.
>
> Just use a higher-order function: it won't duplicate code, it's
> high-level and it doesn't require any syntactic sugar.
Please read what I wrote before replying. The higher order function is
what I do now, because there's no other way for the code I use. It's *not*
hard to do and I already have lots of code that just look like your
example functions.
That said, it's just would be *easier* to express the "concept" with
appropriate keyword, not *emulated* through try-with.
> let with_file_out fname f =
> let oc = open_out fname in
> try let r = f oc in close_out oc ; r
> with exn -> close_out_noerr oc ; raise exn
This one doesn't have equivalent with finally, but that's fine
it cannot cover everything.
But *most* of the time the cleanup function is similar in both case.
> let with_mat m f =
> GlMat.push () ;
> let r =
> try GlMat.mult m ; f ()
> with exn -> GlMat.pop () ; raise exn in
> GlMat.pop () ;
> r
This become:
let with_mat m f =
GlMat.push ();
try GlMat.mult m ; f (); finally GlMat.pop ()
I can see in a jiffie what the second function does.
It's not as clear with the first one, I need to read a bit more to see
what it does (and GlMat.pop has been duplicated)
Cheers,
--
Vincent Hanquez
My code lacks generality, in that it assumed the expression
returned the unit. I see no difference whether the cleanup
is in the try or not: did I miss something?
[Well yes .. if the cleanup can raise an exception .. :]
> the point is not it's hard to do, it's annoything to duplicate here and
> there, and doing the inline code lose the higher level view we can have
> with a syntaxic sugar like try-finally.
I don't dispute these claims. However the same is true for many
features. We don't want to implement them all, so how do we choose?
The C++ committee basically chose features which either:
(a) were extremely common
(b) were so complex many people would get it wrong
(c) couldn't be done any other way
In addition, the C++ committee had limited time and couldn't
do everything. So a choice of a few features had to be made.
Some were accepted simply because they met the criteria and
were easy to implement, and others, although harder, provided
great benefit.
Given all these factors .. would you REALLY chose 'finally' as
a feature?
If I gave you just three features you could add .. would you
REALLY waste one of your wishes on 'finally'?
> seems that you *finally* understand it ;)
Lol! I have no trouble understanding it. See above.
My issue is with whether it is really that useful and common
it really should be part of an already over rich language.
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
The most important changes are compatible with OCaml's stdlib. I've just made
it faster and more robust.
> it just balkenized a bit more the situation.
I see no alternative.
> It's not really complex to have a replacement stdlib anyway, everybody
> can do it, and a lots of people have already put some freely-available
> on the internet.
Depends what features you want.
--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
Objective CAML for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists
_______________________________________________
> > It's not really complex to have a replacement stdlib anyway, everybody
> > can do it, and a lots of people have already put some freely-available
> > on the internet.
>
> Depends what features you want.
And on the licence ;(
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
_______________________________________________
> Well, seeing that the very useful native exception backtrace patch has
been
> sitting idle (acknowledged) for more than a year, I think that's not
> working it out too well :\
Like elephants, I'm slow, but never forget :-) You'll be pleased to
learn that I've been working recently on exception backtraces for
ocamlopt. The code (nearly finished) currently sits in the
"opt_backtrace" branch of the repository and should be part of
release 3.10.
It implements an exception backtrace mechanism similar to that already
available in bytecode, but different from Markus Mottl's call backtrace.
The two kinds of backtraces are incomparable in general, but while
Markus's solution is quite low overhead already, mine has even lower
overhead, especially in terms of code size.
Native-code backtraces will be available initially for the following
back-ends: i386, amd64 and powerpc, both for Unix-like OS and for
Windows. Ports to other back-ends will be considered if there is
sufficient demand.
- Xavier Leroy
Le Sun, 21 Jan 2007 18:07:04 +0100, Xavier Leroy <Xavier...@inria.fr> a écrit :
> You'll be pleased to
> learn that I've been working recently on exception backtraces for
> ocamlopt. The code (nearly finished) currently sits in the
> "opt_backtrace" branch of the repository and should be part of
> release 3.10.
Now, that's an excellent news!
Will backtraces still be only available to uncaught exceptions ?
Sometimes it'd be useful to have backtraces in other cases, to
understand what's going on.
Not to get backtraces for all exceptions! Since exceptions have many
uses in OCaml, that would be uselessly painful :)
But maybe something like Printexc.to_string_with_backtrace (or
Printexec.to_string ~backtrace:true ?), so that debugging code could
decide to report, or log, backtraces of chosen exceptions...
Best regards,
Pierre.