* Re: automatic construction of mli files
2000-07-24 5:34 Julian Assange
@ 2000-07-24 20:48 ` Olivier Andrieu
2000-07-26 16:03 ` John Max Skaller
2000-07-24 22:02 ` Jean-Christophe Filliatre
` (5 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Olivier Andrieu @ 2000-07-24 20:48 UTC (permalink / raw)
To: caml-list
Julian Assange wrote:
>
> .mli files are highly redundant. Almost without exception all, or at
> the vast majority of .mli information can be generated from the
> underlying .ml implementation. We have programming languages to reduce
> redundancy, not increase it. Keeping mli and ml files in-sync is not
> only a waste of time, but error-prone and from my survey often not
> performed correctly, particularly where consistency is not enforced by
> the compiler (e.g comments describing functions and types). While
> exactly the same problem exists in a number of other
> separate-compilation language implementations, we, as camlers, should
> strive for something better.
Urmpf. Well, it's still about type abstraction and name hiding isn't it
? The compiler can't decide for you what you want to keep in the
interface and what should be hidden.
But it's quite easy to generate an mli file with everything in it :
ocamlc -i -c mycode.ml > mycode.mli
You could even use a Makefile rule :
%.mli : %.ml
$(OCAMLC) -i -c $^ > $@
Olivier.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: automatic construction of mli files
2000-07-24 20:48 ` Olivier Andrieu
@ 2000-07-26 16:03 ` John Max Skaller
0 siblings, 0 replies; 16+ messages in thread
From: John Max Skaller @ 2000-07-26 16:03 UTC (permalink / raw)
To: andrieu; +Cc: caml-list
Olivier Andrieu wrote:
>
> Julian Assange wrote:
> >
> > .mli files are highly redundant. Almost without exception all, or at
> > the vast majority of .mli information can be generated from the
> > underlying .ml implementation. We have programming languages to reduce
> > redundancy, not increase it. Keeping mli and ml files in-sync is not
> > only a waste of time, but error-prone and from my survey often not
> > performed correctly, particularly where consistency is not enforced by
> > the compiler (e.g comments describing functions and types). While
> > exactly the same problem exists in a number of other
> > separate-compilation language implementations, we, as camlers, should
> > strive for something better.
>
> Urmpf. Well, it's still about type abstraction and name hiding isn't it
> ? The compiler can't decide for you what you want to keep in the
> interface and what should be hidden.
Perhaps not, but sometimes I think it might be easier if the
interface specification was consolidated with the implementation.
When no .mli file is specified, ocaml generates an interface
-- with all symbols becoming public -- anyhow.
> But it's quite easy to generate an mli file with everything in it :
> ocamlc -i -c mycode.ml > mycode.mli
The problem is that subsequent refinements are lost
when the implementation file is extended to include symbols:
now you're committed to hand management of the .mli file.
But if you stick with the generated .mli file
the same interface is generated if the file
is simply omitted. So the main use is to make the interface
more compact by physically hiding hiden implementation details.
--
John (Max) Skaller, mailto:skaller@maxtal.com.au
10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850
checkout Vyper http://Vyper.sourceforge.net
download Interscript http://Interscript.sourceforge.net
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: automatic construction of mli files
2000-07-24 5:34 Julian Assange
2000-07-24 20:48 ` Olivier Andrieu
@ 2000-07-24 22:02 ` Jean-Christophe Filliatre
2000-07-26 16:09 ` John Max Skaller
2000-07-24 22:09 ` John Prevost
` (4 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Jean-Christophe Filliatre @ 2000-07-24 22:02 UTC (permalink / raw)
To: Julian Assange; +Cc: caml-list
> .mli files are highly redundant. Almost without exception all, or at
> the vast majority of .mli information can be generated from the
> underlying .ml implementation. We have programming languages to reduce
> redundancy, not increase it. [...]
We probably don't use interfaces (.mli files) in the same way.
Personally, I write the interface *before* the code. It clarifies the
design of an implementation, helping you focusing first on the
features of the module, independently of the way you will write it.
Therefore, there is no way of generating the .mli from the .ml, since
it comes first. Moreover, I don't put the same kind of documentation
in the interface and in the code: in the interface I put
specifications, mainly, and in the code I put implementation details.
In the extreme situation where there is no real need for writing an
interface, you can either simply not write one (this is not mandatory)
or generate it from the code with "ocamlc -c -i".
But writing an interface is always a good idea, since it encourages
you to abstract data types and to provide only small and orthogonal
sets of functions, which cannot be done automatically in most cases.
--
Jean-Christophe Filliatre
Computer Science Laboratory Phone (650) 859-5173
SRI International FAX (650) 859-2844
333 Ravenswood Ave. email filliatr@csl.sri.com
Menlo Park, CA 94025, USA web http://www.csl.sri.com/~filliatr
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: automatic construction of mli files
2000-07-24 22:02 ` Jean-Christophe Filliatre
@ 2000-07-26 16:09 ` John Max Skaller
0 siblings, 0 replies; 16+ messages in thread
From: John Max Skaller @ 2000-07-26 16:09 UTC (permalink / raw)
To: Jean-Christophe Filliatre; +Cc: Julian Assange, caml-list
Jean-Christophe Filliatre wrote:
[discussion of programming techniques]
> But writing an interface is always a good idea, since it encourages
> you to abstract data types and to provide only small and orthogonal
> sets of functions, which cannot be done automatically in most cases.
On the other hand, writing the interface _first_ is not always
appropriate when you want to rapidly prototype experimental code
where you don't actually know what the interface is going to turn
out to be until you experiment.
I often do this, _then_ write an interface, then reimplement
the code cleanly according to this interface. Using this methodology,
I often write the implementation first -- an 'abstraction' of the
interface being in my head: an easier medium to 'edit' rapidly
than a text file :-)
--
John (Max) Skaller, mailto:skaller@maxtal.com.au
10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850
checkout Vyper http://Vyper.sourceforge.net
download Interscript http://Interscript.sourceforge.net
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: automatic construction of mli files
2000-07-24 5:34 Julian Assange
2000-07-24 20:48 ` Olivier Andrieu
2000-07-24 22:02 ` Jean-Christophe Filliatre
@ 2000-07-24 22:09 ` John Prevost
2000-07-24 23:14 ` David Brown
` (3 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: John Prevost @ 2000-07-24 22:09 UTC (permalink / raw)
To: Julian Assange; +Cc: caml-list
>>>>> "ja" == Julian Assange <proff@iq.org> writes:
ja> .mli files are highly redundant. Almost without exception all,
ja> or at the vast majority of .mli information can be generated
ja> from the underlying .ml implementation. We have programming
ja> languages to reduce redundancy, not increase it. Keeping mli
ja> and ml files in-sync is not only a waste of time, but
ja> error-prone and from my survey often not performed correctly,
ja> particularly where consistency is not enforced by the compiler
ja> (e.g comments describing functions and types). While exactly
ja> the same problem exists in a number of other
ja> separate-compilation language implementations, we, as camlers,
ja> should strive for something better.
I disagree. .mli files are not at all redundant. For one thing, if
you do not desire to use .mli files, you do not need to write them at
all--the system works perfectly well if you use only .ml files.
What .mli files are *for* is to restrict the type of a top-level
module. Within the language we may write:
module Foo =
(struct
type t = int
let foo x = x
let bar x = x + 1
let baz x = x
end : sig
type t
val foo : int -> t
val bar : t -> t
val baz : t -> int
end)
in order to restrict the visibility of types. But using top-level
modules, there's no declaration which may be wrapped in a type
constraint. .mli serves exactly this purpose.
Now--what if the language were changed to annotate such things
in-line? I argue that it would not, in fact, become a better
language. For the above, we might write:
EXTERN opaque
type t = int
EXTERN int -> t
let foo x = x
EXTERN t -> t
let bar x = x + 1
EXTERN t -> int
let baz x = x
Note that I don't actually recommend this syntax, I'm just trying to
point out what information has to be provided.
The first thing to note is that each top-level declaration must be
annotated with the type you wish to export, if you want to export
anything at all. I'm of two minds about this. On the one level,
there are good arguments for doing it that way: the type constraints
are near the code they go with. When I look at foo, I see that it's
actually meant to turn an int into a t.
On the other hand, it really breaks things up. When I see:
type t
val foo : int -> t
val bar : t -> t
val baz : t -> int
it's very easy to see what basic types and operations on those types
are provided by the module. If I want to change what information is
revealed, it's pretty easy to do.
And things get even hairier when you want to restrict things down
more from more complex types.
I personally think that making type constraints an aspect of the
module-level language, and hence not supporting inline declarations of
this sort of thing is good. If you want things to be transparent,
don't use .mli files. In general, if you want to hide anything, I
think you usually want to hide enough to make inline constraints more
confusing than not.
John.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: automatic construction of mli files
2000-07-24 5:34 Julian Assange
` (2 preceding siblings ...)
2000-07-24 22:09 ` John Prevost
@ 2000-07-24 23:14 ` David Brown
2000-07-25 1:13 ` Jacques Garrigue
` (2 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: David Brown @ 2000-07-24 23:14 UTC (permalink / raw)
To: Julian Assange; +Cc: caml-list
On Mon, Jul 24, 2000 at 03:34:22PM +1000, Julian Assange wrote:
> .mli files are highly redundant. Almost without exception all, or at
> the vast majority of .mli information can be generated from the
> underlying .ml implementation. We have programming languages to reduce
> redundancy, not increase it.
The redundancy is intentional, though. There are two differing
philosophies concerning the information in the mli file. One attitude,
taken by languages such as Eiffel, is that there should be no specification
file. The source contains markers to determine what is "public" and what
is "private". The compiler provides tools to generate specs for
documentation use.
The other attitude, taken by Ada, and sort of, but not really, by C, is
that the spec file is a document of the interface to the module. The
implementation is independent from the spec. The developer should feel
free to implement the spec as needed, as long as it complies with that
interface.
Both methods have advantages and disadvantages.
- The single file approach is easier for the programmer to create,
especially when doing rapid prototyping.
- The single file approach makes it less obvious if a given change is going
to change the interface. A separate spec can be checked against to
verify that the developer didn't change the interface.
- The separate spec is usually difficult for those first learning the
language. Ocaml helps here by not requiring the spec to be written, and
even generating it for you.
There are very strong arguments by big names for both sides. Ocaml, like
it does in many areas, leaves the choice up to the developer.
If you wish to have a single file, don't write a .mli file at all. Modules
will export all symbols by default if there is no spec. If you want to
make a spec when you are done, compile the modules with -i, and redirect
the output to the spec file. Feel free to comment it, and delete the
symbols you didn't really want to export.
For those who wish to use a more "structured" approach to development, the
spec can be written first. Then the compiler will verify that the code
written corresponds with the spec.
The challenge, then is to figure out which methodology I prefer :-).
Dave Brown
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: automatic construction of mli files
2000-07-24 5:34 Julian Assange
` (3 preceding siblings ...)
2000-07-24 23:14 ` David Brown
@ 2000-07-25 1:13 ` Jacques Garrigue
2000-08-01 11:22 ` Anton Moscal
2000-07-25 11:48 ` Hendrik Tews
2000-07-26 10:16 ` David Delahaye
6 siblings, 1 reply; 16+ messages in thread
From: Jacques Garrigue @ 2000-07-25 1:13 UTC (permalink / raw)
To: proff; +Cc: caml-list
From: Julian Assange <proff@iq.org>
> .mli files are highly redundant. Almost without exception all, or at
> the vast majority of .mli information can be generated from the
> underlying .ml implementation. We have programming languages to reduce
> redundancy, not increase it. Keeping mli and ml files in-sync is not
> only a waste of time, but error-prone and from my survey often not
> performed correctly, particularly where consistency is not enforced by
> the compiler (e.g comments describing functions and types). While
> exactly the same problem exists in a number of other
> separate-compilation language implementations, we, as camlers, should
> strive for something better.
I know the argument against .h files.
However I'm not sure it applies to .mli, which in my view have a role
rather different of C headers.
One first point is that they are optional. If you don't like the
burden of writing them (which is much simplified by the -i option of
the compiler), you can just avoid them. A tool like ocamlbrowser still
allows you to browse the contents of the .cmi file, thus giving access
to all type information. The only capacity you loose is export
control, but in many cases this doesn't really matter anyway.
So why do people write .mli files ? Just because it is nice to cleanly
separate interface and implementation. This goes completely against
some ideas in the OO community, particularly concerned by the close
relationship between specification and implementation, but thanks to a
more powerful type system, a larger part of the specification is
verifiable. A verifiable redundancy can be profitable, in fact all the
ML type system is about getting enough redundancy to your code to
detect errors.
Not to say that the current situation is perfect. The fact you have to
duplicate all type definitions is not so nice for instance. But for
people used to the .ml/.mli dichotomy, having both kind of information
united in a single file does not seem very attractive.
Practically what I usally do when I start a new project in Caml is
start without .mli files, until my project gets structured enough so
that I know what needs to be exported from each module. Then I
generate .mli's with the -i option of the compiler, trim definitions
to keep only the ones I need, and eventually add comments to
definitions (I'm often happy enough with labels only, but I know it's
not Good). From there on changes to the .mli are small enough, and
actually I want to know when the interface is changed, since this may
influence other modules.
Regards,
---------------------------------------------------------------------------
Jacques Garrigue Kyoto University garrigue at kurims.kyoto-u.ac.jp
<A HREF=http://wwwfun.kurims.kyoto-u.ac.jp/~garrigue/>JG</A>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: automatic construction of mli files
2000-07-25 1:13 ` Jacques Garrigue
@ 2000-08-01 11:22 ` Anton Moscal
2000-08-02 12:03 ` Dmitri Lomov
2000-08-02 14:13 ` Gerard Huet
0 siblings, 2 replies; 16+ messages in thread
From: Anton Moscal @ 2000-08-01 11:22 UTC (permalink / raw)
To: Jacques Garrigue; +Cc: caml-list
On Tue, 25 Jul 2000, Jacques Garrigue wrote:
> Not to say that the current situation is perfect. The fact you have to
> duplicate all type definitions is not so nice for instance. But for
> people used to the .ml/.mli dichotomy, having both kind of information
> united in a single file does not seem very attractive.
I think, SML `local' is a good alternative to interfaces in the many
cases: `local' allows to hide definitions from the module interface
without explicit signature specification.
Regards,
Anton Moscal
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: automatic construction of mli files
2000-08-01 11:22 ` Anton Moscal
@ 2000-08-02 12:03 ` Dmitri Lomov
2000-08-02 14:13 ` Gerard Huet
1 sibling, 0 replies; 16+ messages in thread
From: Dmitri Lomov @ 2000-08-02 12:03 UTC (permalink / raw)
To: caml-list
I have lot of experience with Java, where there is no
explicit signatures present.
'public' in Java is like the EXPORT keyword that was proposed.
This makes any Java class a total mess of interface and
implementation. If you look at Java class you cannot figure out
the interface, because implementation pokes out everywhere.
Usually, if I need to understand some Java class, I have to
javadoc it, and then look at the resulting html. IMHO, that's awful.
Even C++ headers are better than this.
>From my point of view, OCaml .ml/.mli treatment is very good.
There are some things that I DO NOT like about OCaml .mli/.ml files, however.
1) I have to duplicate type definitions in .mli and in .ml files.
I think every ocamler knows how tedious is keeping consistency here.
Most of the time, you just change the definition in one of the files,
compile, get an error message, and (with curses ;)) copy definition to another
file. I suppose complier can do this work for the user.
Maybe there is some hidden philosophy behind this... I will be happy
if someone explaint it to me
2) Just one little thing I could not figure how to do...
Suppose I have a module, called Eval, implementation of which
differs for bytecode and native-code generation.
What I wanted to do was:
- create an eval.mli in the root directory of my project
- create bytecode/eval.ml: bytecode implementation of eval.mli
- create i386/eval.ml: implementation of eval.mli for i386
- create alpha/eval.ml: implementation of eval.mli for Alpha &c
- compile versions of my program as follows:
ocamlc -o program bytecode/eval.cmo program.ml
ocamlopt -o program.opt i386/eval.cmx program.ml
You see here, that inside of program.ml I need not to know what versio I
compile (for bytecode or for i386 or for Alpha)
But this trick didn't do, because I was unable to compille eval.cmo and eval.cmx
When I did (in bytecode/)
ocamlc -c -I .. eval.ml
I got eval.cmi and eval.cmo (so ocamlc did not look eval.cmi in a root directory).
Can anybody suggest how to do this trick with OCaml?
Regards,
Dmitri
Anton Moscal wrote:
>
> On Tue, 25 Jul 2000, Jacques Garrigue wrote:
>
> > Not to say that the current situation is perfect. The fact you have to
> > duplicate all type definitions is not so nice for instance. But for
> > people used to the .ml/.mli dichotomy, having both kind of information
> > united in a single file does not seem very attractive.
>
> I think, SML `local' is a good alternative to interfaces in the many
> cases: `local' allows to hide definitions from the module interface
> without explicit signature specification.
>
> Regards,
> Anton Moscal
--
_________________________________________________________________
Dmitri S. Lomov
mailto:dsl@tepkom.ru ICQ#: 20524819 (Rusty)
+7 (812) 428-46-57 (b) +7 (812) 295-94-15 (h)
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: automatic construction of mli files
2000-08-01 11:22 ` Anton Moscal
2000-08-02 12:03 ` Dmitri Lomov
@ 2000-08-02 14:13 ` Gerard Huet
1 sibling, 0 replies; 16+ messages in thread
From: Gerard Huet @ 2000-08-02 14:13 UTC (permalink / raw)
To: dsl, caml-list
At 16:03 02/08/00 +0400, Dmitri Lomov wrote:
>There are some things that I DO NOT like about OCaml .mli/.ml files, however.
>1) I have to duplicate type definitions in .mli and in .ml files.
> I think every ocamler knows how tedious is keeping consistency here.
> Most of the time, you just change the definition in one of the files,
> compile, get an error message, and (with curses ;)) copy definition to
another
> file. I suppose complier can do this work for the user.
> Maybe there is some hidden philosophy behind this... I will be happy
> if someone explaint it to me
Just to add my 2 cents to this rambling discussion on interfaces. I used to
gripe myself about this duplication problem. But one day I realised that a
lot of this duplication could be avoided, because often the interfaces can
be designed as pieces of data structures definitions (DTDs), which consist
entirely of type declarations AND WHICH DO NOT NEED AN IMPLEMENTATION FILE
AT ALL, and pieces of method/exceptions descriptions, for which a .mli and
a .ml file share some redundancy, but where the programmer has the
opportunity to think carefully about what is visible from outside and at
what level of abstraction.
Furthermore it is essential that we provide the possibility of designing
the interface BEFORE the code gets written, in order to do team work and
top-down design. For a large project, dummy implementations will typically
give a debugging environment to test your module, but here we want to check
the type consistency of these debugging dummies with respect to the master
.mli, as opposed to generate the .mli specs from them.
I am currently working on a linguistic data base, where the data base
format is a BIG .mli describing the abstract syntax of my data base,
thinking about it as a DTD. This format is used as interface both to the
parser which reads in the data, and to the various processors, extractors,
and printers of the data base. This .mli file has no implementation
associated with it, and thus there is not any redundancy in terms of source
code.
Of course, it is useful to have the facility to get the .mli from the .ml
for quick-and-dirty bottom-up programming. But as your program gets large,
and your modules become parametric functors, you really want to keep
separate your interface specs and your code, and the redundancy is slight.
Gérard
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: automatic construction of mli files
2000-07-24 5:34 Julian Assange
` (4 preceding siblings ...)
2000-07-25 1:13 ` Jacques Garrigue
@ 2000-07-25 11:48 ` Hendrik Tews
2000-07-26 10:16 ` David Delahaye
6 siblings, 0 replies; 16+ messages in thread
From: Hendrik Tews @ 2000-07-25 11:48 UTC (permalink / raw)
To: caml-list
Julian Assange writes:
From: Julian Assange <proff@iq.org>
Date: 24 Jul 2000 15:34:22 +1000
Subject: automatic construction of mli files
.mli files are highly redundant. Almost without exception all, or at
the vast majority of .mli information can be generated from the
underlying .ml implementation. We have programming languages to reduce
redundancy, not increase it. Keeping mli and ml files in-sync is not
only a waste of time, but error-prone and from my survey often not
performed correctly, particularly where consistency is not enforced by
the compiler (e.g comments describing functions and types). While
exactly the same problem exists in a number of other
separate-compilation language implementations, we, as camlers, should
strive for something better.
I don't share your point of view. We have a big project (>100
files, approx 60000 lines of ocaml code). And the policy
regarding mli files is quite simple: If the mli file could be
generated from the source code, then, don't write one! The ocaml
compiler (together with ocamldep) will recognize its absence and
compile the ml file into both a cmo and a cmi file.
If, on the other side, you really want to hide some type
information, then you provide an mli file and in this case it
cannot be generated from the ml file. In our project we have 26
mli files for 63 ml files. The rest is generated by the compiler.
Moreover I don't think redundancy is that bad. Redundancy helps
you to catch errors. I often write mli files even if they contain
only the information that would be infered by the comiler
automatically. But this redundant mli file helps me to catch
programming errors.
Bye,
Hendrik
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: automatic construction of mli files
2000-07-24 5:34 Julian Assange
` (5 preceding siblings ...)
2000-07-25 11:48 ` Hendrik Tews
@ 2000-07-26 10:16 ` David Delahaye
6 siblings, 0 replies; 16+ messages in thread
From: David Delahaye @ 2000-07-26 10:16 UTC (permalink / raw)
To: Julian Assange; +Cc: caml-list
> .mli files are highly redundant. Almost without exception all, or at
> the vast majority of .mli information can be generated from the
> underlying .ml implementation. We have programming languages to reduce
> redundancy, not increase it. Keeping mli and ml files in-sync is not
> only a waste of time, but error-prone and from my survey often not
> performed correctly, particularly where consistency is not enforced by
> the compiler (e.g comments describing functions and types). While
> exactly the same problem exists in a number of other
> separate-compilation language implementations, we, as camlers, should
> strive for something better.
I don't think that .mli are redundant. They essentially contain type
information and, in a strongly typed system, it is quite relevant and
especially useful. Moreover, with .mli, you can build abstract data types,
which are, in general, greatly used. So, to keep .mli and .ml files in-sync is
not a waste of time but a way to ensure that your .ml file is an implementation
of your specification. If you have errors during this verification then it
could be explained by (semantical) errors in your code, you wouldn't have seen
without this check. Of course, it could also be due to the .mli file which must
be changed but, again, it is not a waste of time and it should be have been
done before changing the implementation. Personally, I don't like .ml files
without .mli because you don't have any type information and even if I want to
export everything in an .ml file, I generate the .mli automatically.
Regards.
David.
===============================================================================
David Delahaye <Email>: David.Delahaye@inria.fr
<Laboratory>: The Coq Project <Domain>: Proofs
<Adress>: INRIA-Rocquencourt Domaine de Voluceau BP105 78153 Le Chesnay Cedex
FRANCE
<Tel>: (33)-(0)1 39 63 57 53
<Fax>: (33)-(0)1 39 63 56 84
<Url>: http://pauillac.inria.fr/~delahaye
===============================================================================
[If you have time to waste, you can have a look on my proof that 2 = 1. We know
that, for -1 < x <= 1:
ln(1 + x) = x - 1/2(x^2) + 1/3(x^3) - 1/4(x^4) + ...
Let x = 1:
ln(2) = 1 - 1/2 + 1/3 - 1/4 + 1/5 - 1/6 + 1/7 - 1/8 + 1/9 - ...
Let multiply the two members by 2:
2ln(2) = 2 - 2/2 + 2/3 - 2/4 + 2/5 - 2/6 + 2/7 - 2/8 + 2/9 - ...
2ln(2) = 2 - 1 + 2/3 - 1/2 + 2/5 - 1/3 + 2/7 - 1/4 + 2/9 - ...
Let sum the terms with the same denominator:
2ln(2) = 1 - 1/2 + 1/3 - 1/4 + 1/5 - 1/6 + 1/7 - ...
2ln(2) = ln(2)
Finally, 2 = 1.]
^ permalink raw reply [flat|nested] 16+ messages in thread