Loading ...
Sorry, an error occurred while loading the content.

programmer feedback / friendliness

Expand Messages
  • spir
    I realise now that all my questions about a kind of polymorphic (and list) print and string construction are related to a feature now found in all modern
    Message 1 of 9 , Mar 6, 2012
    • 0 Attachment
      I realise now that all my questions about a kind of polymorphic (and
      list) print and string construction are related to a feature now found
      in all "modern" languages, both static and dynamic (python, lua, ruby,
      but also D, Go, freepascal...), which I was searching in OCaml.
      The point is the ability for the programmer to easily get (sensible)
      feedback about any element living in a program. This, without having to
      write specific print and/or string functions for every new type; but
      with the possibility to do it when needed. Such a feature is constantly
      helpful when exploring possible ways of designing or implementing
      program components, and indeed when testing, debugging, controlling
      program behaviour.
      Moreover, designing custom string formats or print funcs for
      higher-level types builds on (builtin or custom) forms of lower-level ones.

      Precisely, in OCaml, type construction feels like an algebraic Lego game
      ;-), which makes such a feature in a sense trivial: constructing a
      string for an element of a given type is recursively deconstructing the
      type; thus, all what is needed is a string pattern for each type
      construction pattern (list, tuple/record, variant,...). But it can
      initially only be provided by the compiler, since it depends on
      knowledge of types. Actually, this feature does exist since OCaml's
      toplevel is able to write out (sensibly) any value of any type, even
      giving its type.
      Why not make it available to the programmer? "string_of x" would just
      return this string, and "print x" write it out. It's basically just an
      automagic string conversion functionality for every possible type; but
      it must be built in the language (the door must be open by the compiler,
      in a static lang, then only can programmers build on it).

      What do you think? (Sure, if I had never programmed with user-friendly
      languages, I would not know I desperately miss this feature; but believe
      me: once you use it everyday, I mean 33 times a day, it is hard to live
      without it ;-)

      Options:
      * A "linguistic method" (string_of_x) would define a custom string form
      for type x, automagically replacing the builtin one.
      * In addition, since OCaml has C-like formats, there could be one for
      this, eg %v for 'value' like in Go.

      Denis

      PS: Note I'm not talking here about strings for and output to
      (end-)users, which is a distinct topic (but would indeed reuse this
      feature).
    • Gabriel Scherer
      This topic has been discussed frequently. There have been several experiments with variants of the OCaml language extended with some kind of ad-hoc
      Message 2 of 9 , Mar 6, 2012
      • 0 Attachment
        This topic has been discussed frequently. There have been several
        experiments with variants of the OCaml language extended with some
        kind of ad-hoc type-dispatch ability. See for example the G'Caml
        research project:
        http://www.yl.is.s.u-tokyo.ac.jp/~furuse/gcaml/

        There have also been practical experiments to hack this into the
        compiler. The latest attempt is Jérémie Dimino's "generic printer
        patch":
        http://www.mail-archive.com/caml-list@.../msg01109.html

        Please feel free to use it if you can afford patching the compiler --
        eg. you don't need to pass your code to other people. Jérémie is an
        excellent OCaml hacker and his patch is certainly of good quality.

        There is no integration in the OCaml language because it's not clear,
        I believe, what is the clean way to integrate such things to a
        language. It's easy for the toplevel which in effect type-checks at
        runtime so has both type and value information available, but it's
        more a hack than an elegant capability. You don't want to put hacks in
        a programming language semantics. Adding runtime type information has
        unacceptable performance costs (as the TIL project found out :
        http://www.cs.cornell.edu/home/jgm/tilt.html ), and there are other
        ways to do this that are probably better, for example Haskell type
        classes permit passing ad-hoc information just to the functions that
        have a need for it.


        Have you looked into Batteries or Extlib's Std.dump function, that do
        best-effort printing of runtime data? As I said, that's by far the
        easiest way to go for debugging, and the result is not that bad.

        On Wed, Mar 7, 2012 at 6:30 AM, spir <denis.spir@...> wrote:
        >
        > I realise now that all my questions about a kind of polymorphic (and
        > list) print and string construction are related to a feature now found
        > in all "modern" languages, both static and dynamic (python, lua, ruby,
        > but also D, Go, freepascal...), which I was searching in OCaml.
        > The point is the ability for the programmer to easily get (sensible)
        > feedback about any element living in a program. This, without having to
        > write specific print and/or string functions for every new type; but
        > with the possibility to do it when needed. Such a feature is constantly
        > helpful when exploring possible ways of designing or implementing
        > program components, and indeed when testing, debugging, controlling
        > program behaviour.
        > Moreover, designing custom string formats or print funcs for
        > higher-level types builds on (builtin or custom) forms of lower-level ones.
        >
        > Precisely, in OCaml, type construction feels like an algebraic Lego game
        > ;-), which makes such a feature in a sense trivial: constructing a
        > string for an element of a given type is recursively deconstructing the
        > type; thus, all what is needed is a string pattern for each type
        > construction pattern (list, tuple/record, variant,...). But it can
        > initially only be provided by the compiler, since it depends on
        > knowledge of types. Actually, this feature does exist since OCaml's
        > toplevel is able to write out (sensibly) any value of any type, even
        > giving its type.
        > Why not make it available to the programmer? "string_of x" would just
        > return this string, and "print x" write it out. It's basically just an
        > automagic string conversion functionality for every possible type; but
        > it must be built in the language (the door must be open by the compiler,
        > in a static lang, then only can programmers build on it).
        >
        > What do you think? (Sure, if I had never programmed with user-friendly
        > languages, I would not know I desperately miss this feature; but believe
        > me: once you use it everyday, I mean 33 times a day, it is hard to live
        > without it ;-)
        >
        > Options:
        > * A "linguistic method" (string_of_x) would define a custom string form
        > for type x, automagically replacing the builtin one.
        > * In addition, since OCaml has C-like formats, there could be one for
        > this, eg %v for 'value' like in Go.
        >
        > Denis
        >
        > PS: Note I'm not talking here about strings for and output to
        > (end-)users, which is a distinct topic (but would indeed reuse this
        > feature).
        >
        >
        >
        > ------------------------------------
        >
        > Archives up to December 31, 2011 are also downloadable at http://www.connettivo.net/cntprojects/ocaml_beginners
        > The archives of the very official ocaml list (the seniors' one) can be found at http://caml.inria.fr
        > Attachments are banned and you're asked to be polite, avoid flames etc.Yahoo! Groups Links
        >
        >
        >
      • spir
        ... Thank you, Gabriel. As I said, for now I m just exploring the bases of the language without using any external tools (which allows me discovering aspects
        Message 3 of 9 , Mar 6, 2012
        • 0 Attachment
          On 03/07/2012 07:07 AM, Gabriel Scherer wrote:
          > Have you looked into Batteries or Extlib's Std.dump function, that do
          > best-effort printing of runtime data? As I said, that's by far the
          > easiest way to go for debugging, and the result is not that bad.

          Thank you, Gabriel. As I said, for now I'm just exploring the bases of
          the language without using any external tools (which allows me
          discovering aspects which else would remain masked by these tools). But
          I will certainly use something use things like Batteries as soon as some
          piece of code grows.

          I'm still wandering around polymorphism and some kind of flexible string
          output (see other post) because (1) I'm so used to it I don't know yet
          how to do without (brain rigidity, certainly!) (2) one project for which
          I'm exploring OCaml (a toy dynamic language) absolutely requires
          something like that. But I will stop soon and probably use printf and
          friends just for familiarity, one less thing to learn for now.

          As for how to implement a basic print_anything or better
          string_of_anything cleanly, I guess so many languages have it that at
          least one must do it nicely ;-) And well, it's just another builtin
          polymorphic operation, isn't it? How does OCaml cope --cleanly-- with
          all others (eg relational ops, or list_of_anything features)?
          (Also, OCaml's powerful type inference system seems to be the right tool
          to tag such features with type info at compile time and/or replace
          generic funcs in source code with specific ones, isn't it? But I have no
          clue how this is actualy done in other langs.)

          Denis
        • Gabriel Scherer
          ... I realize I have been a bit obtuse here; indeed, you pointed out earlier that you don t want to rely on third-party work. Sorry for being pushy. Std.dump
          Message 4 of 9 , Mar 7, 2012
          • 0 Attachment
            > As I said, for now I'm just exploring the bases of the language
            > without using any external tools.

            I realize I have been a bit obtuse here; indeed, you pointed out
            earlier that you don't want to rely on third-party work. Sorry for
            being pushy.

            Std.dump is implemented as a library, using the type-unsafe part of
            the OCaml library that allow to manipulate the value representation
            directly. This is essential knowledge when writing OCaml/C bindings --
            an ugly business -- but is also exposed on the OCaml side for the
            eventual useful hacks. But it is usually not advertised to newcomers,
            because the immediate reaction of people that learn about it is to
            abuse it in all kind of ways, and this result in very bad
            code. Learning *not* to use them is necessary to grow as an OCaml
            programmer; that's why they tend to be relegated to encapsulated hacks
            such as Std.dump, such that we can pretend we don't know what's
            happening.

            You will find:

            - the reference manual on OCaml value representation, terse but
            complete:
            http://caml.inria.fr/pub/docs/manual-ocaml/manual032.html#toc138

            - a more approachable presentation in the online book "Developping
            Applications with Objective Caml", available in both english and
            french:
            http://caml.inria.fr/pub/docs/oreilly-book/html/book-ora115.html
            http://www.pps.jussieu.fr/Livres/ora/DA-OCAML/book-ora116.html
            It contains in particular a small example of generic value printer

            - the source code of Std.dump:
            https://gitorious.org/ocaml-batteries/gasche-batteries/blobs/master/src/batPervasives.ml#line99
            (For the story, the last person to touch it was 'ygrek', who used
            his knowledge of value representations to write a Python script to
            print OCaml values in GDB.)

            To be clear: I do not encourage you to look into those smelly guts. My
            personal opinion is that, if you're an OCaml beginner, you have better
            ways to improve than learning dirty details about tangential ways to
            do fishy things -- for example you could go on with that toy language
            implementation project and learn a lot of things by practice
            alone. But if you insist on a bottom-up approach, there it is, deep in
            the pit.

            > (2) one project for which I'm exploring OCaml (a toy dynamic
            > language) absolutely requires something like that.

            Oh, no, it certainly does require this, and trying to make OCaml
            a dynamic language for the purpose of easier implementation of
            a dynamic language is the *wrong* way to go. Because -- if that was
            possible, which it isn't -- that would amount to reusing the
            capabilities of your host system without learning anything. It's by
            writing a *static* implementation of your dynamic language that you
            will get a good feeling of what dynamic languages really are.

            Dynamic language implementations don't use static typing
            information -- they don't have it. They keep tags/data at runtime,
            along with their values, that represent type information. That can be
            faithfully represented in OCaml with an algebraic data type:

            type dynval =
            | Int of int
            | Float of float
            | Closure of clos_env * clos_code
            (* or Closure of (dynval -> dynval) *)

            With a single 'dynval' type, you need no "polymorphic printing
            function", just a printing function for your type.

            > And well, it's just another builtin
            > polymorphic operation, isn't it? How does OCaml cope --cleanly-- with
            > all others (eg relational ops, or list_of_anything features)?

            The polymorphic comparison operators are implemented without type
            information, as there is none available at runtime. They're
            implemented (in C) by inspection of the runtime OCaml value, whose
            type is unknown and can only be partly approximated from its
            shape/tags/etc. That's quite similar to how `dump` above works.

            > On 03/07/2012 07:07 AM, Gabriel Scherer wrote:
            > > Have you looked into Batteries or Extlib's Std.dump function, that do
            > > best-effort printing of runtime data? As I said, that's by far the
            > > easiest way to go for debugging, and the result is not that bad.
            >
            > Thank you, Gabriel. As I said, for now I'm just exploring the bases of
            > the language without using any external tools (which allows me
            > discovering aspects which else would remain masked by these tools). But
            > I will certainly use something use things like Batteries as soon as some
            > piece of code grows.
            >
            > I'm still wandering around polymorphism and some kind of flexible string
            > output (see other post) because (1) I'm so used to it I don't know yet
            > how to do without (brain rigidity, certainly!) (2) one project for which
            > I'm exploring OCaml (a toy dynamic language) absolutely requires
            > something like that. But I will stop soon and probably use printf and
            > friends just for familiarity, one less thing to learn for now.
            >
            > As for how to implement a basic print_anything or better
            > string_of_anything cleanly, I guess so many languages have it that at
            > least one must do it nicely ;-) And well, it's just another builtin
            > polymorphic operation, isn't it? How does OCaml cope --cleanly-- with
            > all others (eg relational ops, or list_of_anything features)?
            > (Also, OCaml's powerful type inference system seems to be the right tool
            > to tag such features with type info at compile time and/or replace
            > generic funcs in source code with specific ones, isn't it? But I have no
            > clue how this is actualy done in other langs.)
            >
            > Denis


            On 3/7/12, spir <denis.spir@...> wrote:
            > On 03/07/2012 07:07 AM, Gabriel Scherer wrote:
            >> Have you looked into Batteries or Extlib's Std.dump function, that do
            >> best-effort printing of runtime data? As I said, that's by far the
            >> easiest way to go for debugging, and the result is not that bad.
            >
            > Thank you, Gabriel. As I said, for now I'm just exploring the bases of
            > the language without using any external tools (which allows me
            > discovering aspects which else would remain masked by these tools). But
            > I will certainly use something use things like Batteries as soon as some
            > piece of code grows.
            >
            > I'm still wandering around polymorphism and some kind of flexible string
            > output (see other post) because (1) I'm so used to it I don't know yet
            > how to do without (brain rigidity, certainly!) (2) one project for which
            > I'm exploring OCaml (a toy dynamic language) absolutely requires
            > something like that. But I will stop soon and probably use printf and
            > friends just for familiarity, one less thing to learn for now.
            >
            > As for how to implement a basic print_anything or better
            > string_of_anything cleanly, I guess so many languages have it that at
            > least one must do it nicely ;-) And well, it's just another builtin
            > polymorphic operation, isn't it? How does OCaml cope --cleanly-- with
            > all others (eg relational ops, or list_of_anything features)?
            > (Also, OCaml's powerful type inference system seems to be the right tool
            > to tag such features with type info at compile time and/or replace
            > generic funcs in source code with specific ones, isn't it? But I have no
            > clue how this is actualy done in other langs.)
            >
            > Denis
            >
            >
            > ------------------------------------
            >
            > Archives up to December 31, 2011 are also downloadable at
            > http://www.connettivo.net/cntprojects/ocaml_beginners
            > The archives of the very official ocaml list (the seniors' one) can be found
            > at http://caml.inria.fr
            > Attachments are banned and you're asked to be polite, avoid flames
            > etc.Yahoo! Groups Links
            >
            >
            >
            >
          • rixed@happyleptic.org
            -[ Wed, Mar 07, 2012 at 09:19:45AM +0100, Gabriel Scherer ]---- ... And so are not any cleaner than dump, yet they are buildins while dump is not, for some
            Message 5 of 9 , Mar 7, 2012
            • 0 Attachment
              -[ Wed, Mar 07, 2012 at 09:19:45AM +0100, Gabriel Scherer ]----
              > > And well, it's just another builtin
              > > polymorphic operation, isn't it? How does OCaml cope --cleanly-- with
              > > all others (eg relational ops, or list_of_anything features)?
              >
              > The polymorphic comparison operators are implemented without type
              > information, as there is none available at runtime. They're
              > implemented (in C) by inspection of the runtime OCaml value, whose
              > type is unknown and can only be partly approximated from its
              > shape/tags/etc. That's quite similar to how `dump` above works.

              And so are not any "cleaner" than dump, yet they are buildins while
              dump is not, for some other reason.
            • Gabriel Scherer
              ... Well, for a start it s difficult (but possible) to break abstraction and security assumptions using comparison operators, while it s beginning to be quite
              Message 6 of 9 , Mar 7, 2012
              • 0 Attachment
                > And so are not any "cleaner" than dump, yet they are buildins while
                > dump is not, for some other reason.

                Well, for a start it's difficult (but possible) to break abstraction
                and security assumptions using comparison operators, while it's
                beginning to be quite easy with a serialization mechanism...

                (I have heard people advise to encapsulate security-relevant data
                inside closures to make sure that information couldn't leak from
                comparison operators -- that would still be allowed in a sandboxed
                environment forbidding, eg., the Obj module.)

                In any case, "I can add this ugly feature to the language and have it
                kept forever for compatibility reasons because this other feature is
                already present" never was a very good argument. But yes, if you
                suggest removing the unsafe polymorphic operators, you have my support
                -- but that won't happen for very good compatibility reason, and
                because the alternatives are not as convenient.

                On Wed, Mar 7, 2012 at 10:17 AM, <rixed@...> wrote:
                > -[ Wed, Mar 07, 2012 at 09:19:45AM +0100, Gabriel Scherer ]----
                >> > And well, it's just another builtin
                >> > polymorphic operation, isn't it? How does OCaml cope --cleanly-- with
                >> > all others (eg relational ops, or list_of_anything features)?
                >>
                >> The polymorphic comparison operators are implemented without type
                >> information, as there is none available at runtime. They're
                >> implemented (in C) by inspection of the runtime OCaml value, whose
                >> type is unknown and can only be partly approximated from its
                >> shape/tags/etc. That's quite similar to how `dump` above works.
                >
                > And so are not any "cleaner" than dump, yet they are buildins while
                > dump is not, for some other reason.
                >
                >
                >
                > ------------------------------------
                >
                > Archives up to December 31, 2011 are also downloadable at http://www.connettivo.net/cntprojects/ocaml_beginners
                > The archives of the very official ocaml list (the seniors' one) can be found at http://caml.inria.fr
                > Attachments are banned and you're asked to be polite, avoid flames etc.Yahoo! Groups Links
                >
                >
                >
              • spir
                ... Exactly, that s what I had in mind. ... Oh, yes. I don t fully realise yet that here Int/Float/Closure actually are variants of one single type for OCaml;
                Message 7 of 9 , Mar 7, 2012
                • 0 Attachment
                  On 03/07/2012 09:19 AM, Gabriel Scherer wrote:
                  > Dynamic language implementations don't use static typing
                  > information -- they don't have it. They keep tags/data at runtime,
                  > along with their values, that represent type information. That can be
                  > faithfully represented in OCaml with an algebraic data type:
                  >
                  > type dynval =
                  > | Int of int
                  > | Float of float
                  > | Closure of clos_env * clos_code
                  > (* or Closure of (dynval -> dynval) *)

                  Exactly, that's what I had in mind.

                  > With a single 'dynval' type, you need no "polymorphic printing
                  > function", just a printing function for your type.

                  Oh, yes. I don't fully realise yet that here Int/Float/Closure actually
                  are variants of one single type for OCaml; thus I can do kind of
                  type-match (actually constructor-match, if I use OCaml terminology
                  properly) on its variants. This simplifies much, if I understand what
                  you mean correctly: I can for instance directly have a generic string_of
                  for dynval elements, which does not need polymorphism on the OCaml side.
                  Right?

                  Denis
                • Lukasz Stafiniak
                  ... Print for dynval is not generic, it is no different than print for any other type, only that dynval is more complex than most datatypes. This is because
                  Message 8 of 9 , Mar 7, 2012
                  • 0 Attachment
                    On Wed, Mar 7, 2012 at 12:20 PM, spir <denis.spir@...> wrote:
                    >
                    > On 03/07/2012 09:19 AM, Gabriel Scherer wrote:
                    >
                    > > With a single 'dynval' type, you need no "polymorphic printing
                    > > function", just a printing function for your type.
                    >
                    > Oh, yes. I don't fully realise yet that here Int/Float/Closure actually
                    > are variants of one single type for OCaml; thus I can do kind of
                    > type-match (actually constructor-match, if I use OCaml terminology
                    > properly) on its variants. This simplifies much, if I understand what
                    > you mean correctly: I can for instance directly have a generic string_of
                    > for dynval elements, which does not need polymorphism on the OCaml side.
                    > Right?

                    Print for dynval is not generic, it is no different than print for any
                    other type, only that dynval is more complex than most datatypes. This
                    is because dynval is a type-indexed universal type, for abstract-type
                    based universal types things are more difficult. See
                    https://ocaml.janestreet.com/?q=node/18 and
                    https://ocaml.janestreet.com/?q=node/95
                  • Lukasz Stafiniak
                    Also, have a look at: http://code.google.com/p/deriving/wiki/Introduction (someone has just posted the link to the other caml-list.)
                    Message 9 of 9 , Mar 7, 2012
                    • 0 Attachment
                      Also, have a look at:

                      http://code.google.com/p/deriving/wiki/Introduction

                      (someone has just posted the link to the other caml-list.)
                    Your message has been successfully submitted and would be delivered to recipients shortly.