List Info

Thread: Re: "ocaml_beginners"::[] Learning camlp4




Re: "ocaml_beginners"::[] Learning camlp4
country flaguser name
United Kingdom
2007-05-21 06:05:46

On Monday 21 May 2007 11:18:59 dmitry grebeniuk wrote:
> Shalom, Richard.
>
>; >> I learned revised syntax when tried to learn camlp4.
> >> I wanted to use camlp4 for fixing some unsafe issues in
> >> original syntax, but I've found that revised syntax already
> >> fixed these issues.
>
> RJ> What are these 'unsafe issues' in the original syntax?
>
> I'll cite from
>; http://caml.inria.fr/pub/docs/tutorial-camlp4/tutorial005.html
>
> ============================================================
> The declaration of a global variable is introduced by the
> keyword ``value'', ``let'' being reserved to the
> construction ``let..in'':
>
> OCaml Revised
> let x = 23;; value x = 23;
> let x = 23 in x + 7;; let x = 23 in x + 7;
> ============================================================
>
> In revised syntax if I write "value x = 23;" I sure that
>; I can never add " in ..." at the end and this binding won't
> be hidden by construction like
>; "let x = 23 in x + 7".

This is a bad idea, IMHO. OCaml has no notion of "global" scope, just a
progression from outer to levels of nested scope.

F# has a better "#light" syntax that uses indentation to replace the "in"
keyword, allowing you to move code with adding or replacing keywords:

let () =
let n = 1000
for i=0 to n
...
done

to:

let n = 1000

let () =
for i=0 to n
...
done

The variable "n" is now visible in the outer scope.

Moreover, you can evaluate parts of a function body in the outer-scope of a
top-level during testing, allowing you to follow the flow of execution.

> From computational point of view, the difference between
> top-level values and other values is great: top-level values
> will be computed when program runs, but values in "let ..
> in" will be computed only when program needs them.

That is not true. Currying of functions and functors delays evaluation
arbitrarily but the simplest counter-example is the (very common):

let () =
let n = 1000 in
...

that I just used. The value of "n" is computed immediately even though in
appears inside a "let ... in" rather than an outer "let".

> So, "value () = print_string "qwen";" will output string
> once and independent of another functions, but
> "value f x = let () = print_string "qwen" in x;" will
>; output string only when "f x" is computed. So I have
>; guarantee that "value x = expr;"; will be computed always
> (if program don't quit before "value x = expr;";, of course)

Yes. The evaluation semantics will never be trivial and introducing new
keywords unnecessarily does not make things better, IMHO.

> List constructor ("[h::t]") is bracketed, so I always know
>; where it ends without need to remember priority of
> operators.

Superfluous parentheses.

>; Most of constructions are closed:

More superfluous parentheses.

>; match ... with
>; case1 ->
> match ... with
>; case11 -> ...
>
> | case12 -> ...
> |
> | case2 -> ...
>
> is wrongly interpreted:

Not if indentation is used (F#).

OCaml offers incredible brevity precisely because these constructs are not
closed:

http://www.ffconsultancy.com/languages/ray_tracer/

otherwise it would be Standard ML.

> to obtain what you want, you need to
> use parentheses or begin..end to close the internal match
> construct. There is a same problem with the if construct,
> because of the optional else (see further).

Again, this is improves the language for smart people who know precedence.

> The declaration of a data constructor with several
> parameters is done by separating the types with ``and''. In
> expressions and patterns, this constructor parameters must
>; be currified:
>
> OCaml Revised
> type t = C of t1 * t2;; type t = [ C of t1 and t2 ];
> C (x, y);; C x y;

This might be a good idea but I don't mind writing a constructor in curried
for:

let c x y = C(x, y)

> I think it's good to have strong distinction between
> type t = C of t1 * t2
> and
> type t = C of (t1 * t2)

I think it would be better to optimise this away transparently.

> Motivation for the currified syntax for constructors
>
> This reflects the actual semantics. There are indeed two
> cases, and the values in the two cases are implemented
> differently. The arity of constructors are more clear.
>
> In normal syntax, it is difficult to understand (and to
> explain) why if C is a constructor with two parameters, this
>; is accepted:
>
> fun C (x, y) -> (x, y)
>
> but not that:
>
> fun C x -> x
>
> In revised syntax you have to write:
>
> fun [ C x y -> (x, y) ]
>
> The revised syntax reflects the fact that the two parameters
> of the constructor C cannot be considered as a tuple.

This logic is upside-down, IMHO. Constructor arguments should be available as
a tuple if they are written as a tuple.

Also, what happens with polymorphic variants in revised syntax, where the
arguments really are a tuple?

fun (`C x : [`C of 'a * 'a]) -> x;;

> The ``else'' is mandatory in the ``if'' statement:
>
> OCaml Revised
> if a then b if a then b else ()

More unnecessary verbosity.

> I think there is no need to explain why mandatory "else"
> is more safe than optional "else".

Diverging from all mainstream programming languages and bloating the language
requires a lot of justification, IMHO. Given that I have never had a problem
with a dangling "if" in OCaml, I can see absolutely no justification for
worsening the syntax of the whole language.

If you really want to improve this, tweak the compiler so that it checks that
the indentation of the code agrees with the interpretation.

> At first glance, I cited the features that are most
>; important for safe ocaml programming in revised syntax.

I completely disagree. The revised syntax is very old and is deliberately not
used by the majority of OCaml programmers because it simply isn't
significantly better. I don't know of a single significant project that uses
the revised syntax outside of camlp4. Indeed, there is even a project to
allow you to use ordinary syntax inside camlp4.

I think F# does a vastly better job of addressing the serious concerns, like
operator overloading. If anyone implemented an F# front end for OCaml then I
would switch to it immediately.

--
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
The F#.NET Journal
http://www.ffconsultancy.com/products/fsharp_journal/?e

__._,_.___
.

__,_._,___
Re: "ocaml_beginners"::[] Learning camlp4
country flaguser name
United States
2007-05-21 06:36:24

--- In ocaml_beginners%40yahoogroups.com">ocaml_beginnersyahoogroups.com, Jon Harrop <jon...> wrote:
&gt; (...)
&gt;
> I completely disagree. The revised syntax is very old and is deliberately not
> used by the majority of OCaml programmers because it simply isn't
> significantly better. I don't know of a single significant project that uses
> the revised syntax outside of camlp4. Indeed, there is even a project to
> allow you to use ordinary syntax inside camlp4.
>
> I think F# does a vastly better job of addressing the serious concerns, like
> operator overloading. If anyone implemented an F# front end for OCaml then I
> would switch to it immediately.
>
> --
> Dr Jon D Harrop, Flying Frog Consultancy Ltd.
>; The F#.NET Journal
> http://www.ffconsultancy.com/products/fsharp_journal/?e
&gt;

(*

message from Jon Harrop => F#
message from Skaller => Felix
(not a rebuke, just an amusing constatation, it's very good to see what
other languages do)
*)

By the way, to my mind the only real syntax issue is the imbricated
matches, that you adresses with the indentation (and that the revised
syntax does not adresses properly IMHO).

About this, do you use the "whitespace thing"; in OCaml ? Is it worth it ? (tell me if this
should be a new topic)

Vincent

__._,_.___
.

__,_._,___
Re Learning camlp4
country flaguser name
Moldova, Republic of
2007-05-21 08:19:44

Shalom, Jon.

>> In revised syntax if I write "value x = 23;" I sure that
>> I can never add " in ..." at the end and this binding won't
>> be hidden by construction like
>> "let x = 23 in x + 7".

JH> This is a bad idea, IMHO. OCaml has no notion of
JH>; "global" scope, just a progression from outer to levels
JH> of nested scope.

It has global scope. Every value that should be visible
to other modules should be declared in "global" scope (in
&quot;top level";).
let () = let n = 1000 in <expr&gt; declares nothing and
can't be exported.
let n = 1000
let () = <expr&gt;
declares n as top-level value and makes some side-effect.
Both n and <expr&gt; will be evaluated.
So keyword "value" is here especially to note what will be
evaluated at program's run and what can be exported from
this module.
And one more thing: when I see
value x = <expr&gt;;
I know I can refer to value x anywhere after its
declaration. But when I see
let x = <expr&gt;
in original syntax, I should go many lines down the source
to see if there is " .. in .. " continuation, and some lines
up to see if it is a construction like
let top_level_value =
let some_other_value =
...
in
let x = <expr&gt;
in
...

JH&gt; F# has a better "#light" syntax that uses indentation to
JH>; replace the "in&quot; keyword, allowing you to move code with
JH&gt; adding or replacing keywords:

The use of indentation as the part of language is a bit of
perversion, I think. It requires IDE to write code without
too much pain.

>> From computational point of view, the difference between
>> top-level values and other values is great: top-level values
>> will be computed when program runs, but values in "let ..
>> in" will be computed only when program needs them.
JH> That is not true. Currying of functions and functors
JH> delays evaluation arbitrarily but the simplest
JH> counter-example is the (very common):

Yes, but the difference between
value () = ...
and
value f x = ...
can be seen easily.

JH> Superfluous parentheses.

JH&gt; More superfluous parentheses.

Parentheses help programmer to see the beginning and the end
of expression, like indentation in F#. It doesn't mean that
one of them is a better way to structure code than another.

JH> OCaml offers incredible brevity precisely because these
JH> constructs are not closed:

I prefer disambiguity to brevity.

JH> otherwise it would be Standard ML.

Standart ML has no polymorphic variants, no objects, no
private types, no other cool features that present in OCaml.
OCaml wouldn't be a Standart ML.
But some people thought about syntax extension to allow
SML syntax...

>&gt; to obtain what you want, you need to
>> use parentheses or begin..end to close the internal match
>> construct. There is a same problem with the if construct,
>> because of the optional else (see further).

JH> Again, this is improves the language for smart people
JH> who know precedence.

Some other smart people prefer not to think about extra
details when compiler can think for them much better.

>> I think it's good to have strong distinction between
>> type t = C of t1 * t2
>> and
>> type t = C of (t1 * t2)

JH> I think it would be better to optimise this away
JH&gt; transparently.

Extra complexity. For example, think about
&quot;Some (1, 2)" as a value of type "option 'a". There
should be code that will understand that "if block has
length more than 1, then this is a tuple";. And code like
match opt_val with [None -> .. | Some x -> x]
will be much more slower when it will be constructing value
&quot;x".
Constructor's arity and type of constructor's argument
should not interfere because of polymorphism.

&gt;> This reflects the actual semantics. There are indeed two
>> cases, and the values in the two cases are implemented
>> differently. The arity of constructors are more clear.

JH> This logic is upside-down, IMHO. Constructor arguments
JH> should be available as a tuple if they are written as a
JH> tuple.

Exactly. So in revised syntax you are not writing
arguments as tuple. You write "C x y", not "C (x, y)". And
when matching you write "match .. with [ C x y -> .. ]".
I think here everything is ok.

JH> Also, what happens with polymorphic variants in revised
JH> syntax, where the arguments really are a tuple?
JH>
JH&gt; fun (`C x : [`C of 'a * 'a]) -> x;;

Both variants are available: "`C 1 2" and "`C (1, 2)".

>&gt; The ``else'' is mandatory in the ``if'' statement:
>>
>> OCaml Revised
>> if a then b if a then b else ()

JH> More unnecessary verbosity.

But there won't appear type error when ocaml adds
implicit "else ()".
This "else ()" is useful when you write imperative code.
In my practice there were much more cases when I wrote
functional code and "else ()" tried to force the type of
";then"-expression to unit. When there are many mutually
recursive functions, it's hard to catch missing else.

>> At first glance, I cited the features that are most
>> important for safe ocaml programming in revised syntax.

JH> I completely disagree. The revised syntax is very old
JH&gt; and is deliberately not used by the majority of OCaml
JH> programmers because it simply isn't significantly
JH>; better. I don't know of a single significant project
JH> that uses the revised syntax outside of camlp4. Indeed,
JH> there is even a project to allow you to use ordinary
JH> syntax inside camlp4.

Classical "appeal to authority&quot;: "majority", "significant
project";.
Most of people use C/C++/Java/C# and most of software
(for now) is written in these languages, so will I say that
these languages are better than others?

--
WBR,
dmitry mailto: gds-mlsts%40moldavcable.com">gds-mlstsmoldavcable.com

__._,_.___
.

__,_._,___
[1-3]

about | contact  Other archives ( Real Estate discussion Medical topics )