Style for curv libraries

20 views
Skip to first unread message

Wink Saville

unread,
Jun 18, 2020, 6:43:34 PM6/18/20
to Curv
I couldn't find a coding style guide in the curv repo, if I missed it please point me in the right direction. Otherwise here is a strawman:

This is loosely modeled on Python Docstrings in that the documentation follows the name and parameters but before the body. I tried a more C style with doc before the function signature, but I felt the Python style was better.

External docs start with "///" to differentiate from internal docs which would be "//".

The file starts with a Module level documentation:

/// **********************************************
/// Module docs blah, blah
/// **********************************************

When converting to an document delete the leading /// so turns into:

**********************************************
Module docs blah, blah
**********************************************

For a single line function the entire function remains and the doc follows.

  teIdx af = 0;
      /// Return index of the trailing edge point.



For a multi line function something like this:

 normalize af
     /// Return the normalized airfoil, which I
     /// define as a airfoil section with a chord of 1.0
   = do
   ...
  in
    naf;

Again, the "body" is removed leaving when converted to documentation:

 normalize af
     /// Return the normalized airfoil, which I
     /// define as a airfoil section with a chord of 1.0

And a multi-line function taking a record or array like:

fattenTe {
      naf        /// Normalized af [[x,y], ...] with af[0] == trailing edge
    , tt=1       /// Trailing edge Thickness
    , chord=10   /// Chord length
  }
    /// Fatten Trailing Edge. Not yet implemented just
    /// returns naf.
  = do
    //print "fattenTe naf=$naf tt=$tt chord=$chord NOP";
  in
    naf;


Again the body is removed:

fattenTe {
      naf        /// Normalized af [[x,y], ...] with af[0] == trailing edge
    , tt=1       /// Trailing edge Thickness
    , chord=10   /// Chord length
  }
    /// Fatten Trailing Edge. Not yet implemented just
    /// returns naf.

Here is curv-lib-airfoil as an example. The idea would be to create a simple program which would parse libraries/apps and generate some docs. For now the "function" docs get squashed into a single paragraph so until a cure-doc app is created I just put the functions themselves in a "code" block.

Thoughts/suggestions?

-- wink

Doug Moen

unread,
Jun 19, 2020, 8:43:00 AM6/19/20
to Curv
Hey Wink.  Nobody has built a program for extracting documentation from Curv source code and formatting it as HTML. And there is no official coding style guide, not yet.

It's a cool idea. Your project requires structured, parseable comments. I have had some related ideas about Curv which have the same requirement of structured comments.
  • I want "curvfmt", a program for formatting Curv source code, loosely inspired by gofmt, rustfmt, etc. This program would reformat Curv source code in accordance with an official coding style. It would reflow text (both code and comments) to fit a specified text width, ignoring existing indentation and newlines. This means I need to parse comments, probably as some variant of markdown, but probably with some additional markup structure.
  • I want to improve the way that values are printed on the console. I want to print function values as well formatted source code, using the same algorithm as the curvfmt program proposed above. I want to print nicely formatted data structures (lists and records), with indentation, and newlines inserted in accordance with the current terminal width.
  • I want the ability to automatically extract and display documentation about modules, individual module members, functions, and individual function parameters, and display it to the user, both from the REPL, and from a future IDE. Each of these elements has a short, one line description that fits into 50 characters or less, plus a longer, structured, multi-line description that contains all the details.
--
You received this message because you are subscribed to the Google Groups "Curv" group.
To unsubscribe from this group and stop receiving emails from it, send an email to curv+uns...@googlegroups.com.

Alexandre François Garreau

unread,
Jun 19, 2020, 8:46:38 AM6/19/20
to cu...@googlegroups.com
Why not docstrings? Don’t curv support them yet? These also come from
lisp (as many other curv-y things) and are now in widespread knowledge due
to python. They can easily be used programmatically and the grammar,
being more integrated into the language, make it easy to interoperate
(contrarily to some comment-convention, that is modular and to be used or
not, to the users’ wishes).

Also docstrings resolve the problem of storage, escaping, and encoding, in
a standard way. Comments often are not treated the same way (it is not
uncommon for a source file to be considered “plain-ascii” but use arbitrary
extended codesets in comments, to name authors from various
nationalities).

You may intrigue to add docstrings to modules, that sounds a good thing to
me.

Wink Saville

unread,
Jun 19, 2020, 10:12:41 AM6/19/20
to Alexandre François Garreau, Curv
Docstrings and curvfmt and would be a great additions to curv.

I'd like to be able to write curvfmt in curv, but that leads to making curv a general purpose language.

Doug is that something you want to do?

Alexandre François Garreau

unread,
Jun 19, 2020, 1:29:51 PM6/19/20
to Wink Saville, Curv
Le vendredi 19 juin 2020, 16:12:26 CEST Wink Saville a écrit :
> Docstrings and curvfmt and would be a great additions to curv.
>
> I'd like to be able to write curvfmt in curv, but that leads to making
> curv a general purpose language.

Curv ought to be a compatible addition to some general purpose programming
language it comes from, such as scheme, ML (which also comes from lisp),
or javascript (which also comes from scheme).

But, would be possible by integrating libcurv to any existing programming
language engine (interpreter, VM or compiler), wouldn’t it? I mean it has
already been talked about using libcurv in libfive and vice versa, do I
remember well?

Wink Saville

unread,
Jun 19, 2020, 1:40:06 PM6/19/20
to Alexandre François Garreau, Curv
I find functional languages interesting, but the ones I've run across insist on using "pure functional syntax". What I like about Curv is that it combines imperative and functional syntaxes, which I haven't seen before. So I think it would be interesting to see where it can go.

Alexandre François Garreau

unread,
Jun 19, 2020, 1:59:50 PM6/19/20
to Wink Saville, Curv
Le vendredi 19 juin 2020 19:39:54 CEST, vous avez écrit :
> I find functional languages interesting, but the ones I've run across
> insist on using "pure functional syntax".

Wait wat? which ones? except Haskell, which is the master in this area.

(I’m pretty ignorant in this area, despite being interested in it too)

> What I like about Curv is that
> it combines imperative and functional syntaxes, which I haven't seen
> before. So I think it would be interesting to see where it can go.

Well Curv has indeed some imperative features, but extremely limited, and
this is intended so, and is very nice, because it means within the scope
of the imperative control structure (while, etc.) no side effect will
happen. This is unique to my knowledge. Most notably, it will ease a lot
development for programmers used to imperative programming.

On the other side, “pure functional languages” are really really few… I
only know haskell, and maybe XSLT, and I’m unsure…

On the opposite, afaik, Curv draws much semantic inspiration from the
Scheme programming language (a modern and light dialect of Lisp), and much
syntactic inspiration from ML (which also comes from Lisp, “minus
parentheses, plus types”). Both of these languages are as much imperative
as functional. Like C, javascript, etc. they’re multiparadigm.
Contrarily to C, they allow closures and other high-level functional
features, and unlike javascript, their culture has a strong bias in favor
of functional programming.

More specially, Scheme, and more generally lisp (the actual first
“functional language”), are pretty known for their “macros”. A “killer
feature” that is only useful together with imperative programming. In
fact, it allow to delay, anihilate or replicate side effect at will, in a
manner a bare function application wouldn’t. A purely functional language
such as Haskell or Curv don’t need this because since it is purely
functional, the evaluation strategy may be anything, without impacting the
meaning the program: from “standard application order” to “lazy”; a
“macro” or a “function” would act the same. This makes lisp dialects,
languages from which curv takes great inspiration, essentially based on
combination of both imperative and functional programming. Hence
contrarily to curv, which is purely functional (I develop in another mail
to you).

If you want a general purpose language that combine several approaches,
there are several of much interest in the wild. You may be happy to
discover some of them, and maybe would see the super cool conclusions curv
had taken from them then (and maybe it may also give you more ideas to
propose to curv aknowledgeably) Schemers.org is a good hyper-start for
finding further documentation ;)

Wink Saville

unread,
Jun 19, 2020, 2:23:29 PM6/19/20
to Alexandre François Garreau, Curv
On Fri, Jun 19, 2020 at 10:59 AM Alexandre François Garreau <gale...@galex-713.eu> wrote:
Le vendredi 19 juin 2020 19:39:54 CEST, vous avez écrit :
> I find functional languages interesting, but the ones I've run across
> insist on using "pure functional syntax".

Wait wat? which ones? except Haskell, which is the master in this area.

I've spent a couple weeks learning Haskell, it is also interesting, but the lack of any imperative syntax was off putting. Probably my biggest problem was creating loops with recursion, tough for this old brain.
Thanks for the info, I'll take a look at Schemers.org.

As a side note, I just searched for imperative haskell and from this article:

  In fact Haskell is “imperative programming and more”

So as they say, anything is possible :)

 

Alexandre François Garreau

unread,
Jun 19, 2020, 2:44:28 PM6/19/20
to Wink Saville, Curv
Le vendredi 19 juin 2020, 16:12:26 CEST Wink Saville a écrit :
> Docstrings and curvfmt and would be a great additions to curv.

I’m happy you like the idea of docstrings too :D

> I'd like to be able to write curvfmt in curv, but that leads to making
> curv a general purpose language.

I feel like this “general purpose” thing collides with a fundamental
feature of curv: it is *purely* functional. Unlike other general purpose
programming languages it can draw inspiration from, like Scheme or ML
(which explicitly resort to side-effect as soon as any I/O is needed: and
you soon do).

This characteric usually creates problems as soon as you want to do I/O,
and you usually want to because you usually write programs to interact
with them, or to make stuff in your environment… interacting with files is
an example of that (and it is something you’d need to write curvfmt in
curv).

The smart thing of curv being that with it being a DSL, his *return value*
*is* the I/O. This is a really interesting and beautiful concept.

It could work on files too: imagine a domain-specific functional language
“filer” that take files, or hierarchy of files, as input/arguments, and
returns file(s) or a hierarchy of files as a “return value”… and, not the
“filer” programs, but the engine of it, would open the files and write them,
possibly overwrite… From the “filer language”, in “filer” programs, you
would have nothing to open or write files, but you could read the content
of arguments, and makes new “files” object to return. Then the language
engine “filer” would do the I/O. You could invoke it as “filer program.filer
-i input-file -o output-file” and it would perform what you want, possibly
you could do “-i same-file -o same-file” to overwrite a file hierarchy,
simulating an in-place modification… except it would be implemented using
functional programming.

But a such language wouldn’t be curv anymore. Curv is made so that to
compile to GPU and output shapes, not files. Curv is made to —depending on
what you ask it on command-line interface— automatically open this window
that shows you the curv program return value visually, but is not made to
have an “output file” set from the command-line, to write the return value
to a file (or yes, it has, but it will only write shapes, not ASTs,
strings, curv programs, etc.)… I mean, it has special options to output
other kind of shapes (mesh and voxels), but it’s not the same, is it?

> Doug is that something you want to do?

According me that abids to fundamentally change the language, isn’t it?

I don’t know what Doug may want, but to me, the way curv is designed, if
that changed, it wouldn’t be curv anymore.

At least if it involves adding side-effect I/O operations.

But… maybe extending the curv concept of I/O / return-value to more than
shapes would be an interesting experiment? for strings to begin (it would
be for a single file). That would at least provide functional “output” of
more kinds… then I start wondering if it should be regretted that “file”
and “include” eval their argument, instead of considering it as a string…
because then a separate function “file-as-string” would be needed…

Then for several files, a “separate datatype” (it could as well be a
composition, such as a record of paths) would be needed, and whenever
returned should be written accordingly to the filesystem… how does that
seem to you Doug?

Alexandre François Garreau

unread,
Jun 19, 2020, 2:47:50 PM6/19/20
to Wink Saville, Curv
Okay so I really am not sure anymore of knowing any purely functional
language, beside curv (and maybe xslt: that is, none general purpose, all
DSL).

Anyway note most functional languages do support and doesn’t always warns
against imperative programming. Lisp is the first functional language, and
it supports standard (non recursive) loop forms, GOTOs, etc. And, both
lisp and ML extensivly use imperative programming for drawing, file system
operations, network communication, interactive use, etc.

DSL are an exception there. A nice one.

Doug Moen

unread,
Jun 19, 2020, 3:51:51 PM6/19/20
to Curv
Concerning: Docstrings

In Lisp, the Lisp reader reads a program (or S-expression) and returns a data structure. The Lisp reader discards comments; they aren't preserved in the data structure. Docstrings are a hack to work around this problem: string literals are preserved by the reader. When docstrings were invented, there were already dozens of Lisp implementations, and they needed to find a way to representation documentation that was backward compatible with existing readers. Aside from these backward compatibility requirements, docstrings are just another syntax for comments.

Curv doesn't have the same backward compatibility constraints that the Lisp developers were facing when those languages added docstrings. We don't need a hack; we can just design everything to work correctly from the start.

What's needed is a parser that converts Curv source code to a parse tree, preserving comments and documentation. This parse tree can then be the input to the formatting algorithm. For a curvfmt program, *all* comments need to be preserved in the parse tree, not just "documentation" comments. (The point of docstrings is that they are a special kind of comment that is preserved in the parse tree, but we don't need this distinction.)

Designing the syntax for structured comments and the parse tree data structure is a next step.

Wink Saville

unread,
Jun 19, 2020, 5:56:02 PM6/19/20
to Doug Moen, Curv
Designing the syntax for structured comments and the parse tree data structure is a next step.

After reading the "Comments vs Documentation" section of Documenting Python Code I think it should be trivial for a parser to separate documentation from comments. I think it's desirable to handle multi-line documentation, which Docstrings do well, but off the top of my head another way might be something like /*doc .. doc*/.

As for the syntax of the documentation text I'd go with obvious choices like reStructedText or Markdown. Another thing I'd like to see is for the documentation text to  reference things like filenames, function names and parameter names that reside in the AST. Maybe that is too "wild and crazy" to start with, but being able to write documentation and have it handle some typical refactoring would be really helpful.



Doug Moen

unread,
Jun 19, 2020, 7:28:12 PM6/19/20
to Curv
Concerning: functional programming languages

First, "pure functional languages". Haskell is the most well known. After that, Elm, which is used for programming web applications. The other pure functional languages I know of are research languages for exploring higher order type systems or program verification. For the former, Idris. For the latter, interactive theorum provers such as Coq and Agda.

Next, "functional syntax", which is actually a separate thing. The syntax of Curv is rooted in a lineage of functional languages that began with ML in 1970. ML is actually an impure functional language (it has mutable objects and side effects), but ML introduced the syntax for 'let' expressions, and curried function call syntax: 'f x y'. Modern functional languages that derive from ML include O'Caml, F#, Haskell and Elm.

Next, "general purpose".

Haskell is proof that a pure functional language can also be general purpose. There are even operating systems written in Haskell. If Curv isn't general purpose, it's not because it is a pure functional language.

Curv was always intended to be a domain specific language for graphics programming. It turns out, this covers a lot of ground. Because all graphics primitives are written in Curv itself, Curv will need more support in the future for low level GPU programming, and that's going to drive the addition of new features found in general purpose languages. I'm going to support typed data structures, so that Curv can efficiently manipulate pixel and voxel arrays. I'm going to support interactive animations that respond to external input (eg, mouse and keyboard input, or even webcam input).

But, Curv has security requirements. If you download a 3D model written in Curv and display it, then the Curv program cannot encrypt all your files and display a ransom message. It cannot exfiltrate personal information and upload it to a malware server. That means Curv must continue to be a pure functional language. And I don't think I can add general purpose primitives for file system manipulation and for network programming.

Can "curvfmt" be written in Curv? The basic algorithm, of converting a block of text to another block of text, is a pure function that maps strings onto strings, which could be written in Curv. How that code fits in to the larger framework of how Curv code is executed is something I'll think about some more.

On "macros".

Do Lisp-style macros belong in Curv? It's a reasonable idea, which fits in to the goal of graphics programming. I've considered adding a library for programming L-systems (https://en.wikipedia.org/wiki/L-system), perhaps duplicating the features of the Context Free graphics language (https://www.contextfreeart.org/) in Curv. My first thought is that a macro system would allow me to create a DSL embedded in Curv that corresponds to the syntax of Context Free. Maybe I don't need macros for this; I haven't really worked on the problem yet.

Wink Saville

unread,
Jun 19, 2020, 9:02:54 PM6/19/20
to Doug Moen, Curv
Thanks for the great feedback. I'd like to give my perspective.

I'm not interested in just doing art or graphics per se. I'm a
programmer who'd like to design some 3D things which are
composed of multiple parts. So using an OpenSCAD, Curv or ...
 is a natural direction for me.

Here is a concrete example why I'd like Curv to have I/O capabilities.
Airfoil sections come in various formats and styles and I need to convert
them into a normalized format to make then more universal and easier
to use. Hence, my lib-airfoil.normalize function.

Now I'd like to write a program that takes an airfoil section
xxxx.abc and converts it to a normalized xxxx.curv record file.
I then add the following statement `local xxxx = flie "xxxx.curv"
to my cruv program and all is well.

As it stands now it looks like I need to write the normalization program
in a different language. And of course I also may need to save the normalized
data in a database, in a zip file, out on the Internet or in a local or remote
git repo ....

Bottom line, without a general I/O capability Curv isn't going to work for me
in the long term. That makes me sad.

I totally understand turning Curv into a general purpose programming
language isn't on the horizon but, I'd like you to reconsider. Actually,
I'm sure I could write an "extension" to Curv in C/C++ and teach it to do I/O.
But if it's not what you want, that would be silly.

-- Wink
--
You received this message because you are subscribed to the Google Groups "Curv" group.
To unsubscribe from this group and stop receiving emails from it, send an email to curv+uns...@googlegroups.com.

Doug Moen

unread,
Jun 19, 2020, 10:45:21 PM6/19/20
to Wink Saville, Curv
On Sat, Jun 20, 2020, at 1:02 AM, Wink Saville wrote:
Here is a concrete example why I'd like Curv to have I/O capabilities.
Airfoil sections come in various formats and styles and I need to convert
them into a normalized format to make then more universal and easier
to use. Hence, my lib-airfoil.normalize function.

Now I'd like to write a program that takes an airfoil section
xxxx.abc and converts it to a normalized xxxx.curv record file.
I then add the following statement `local xxxx = flie "xxxx.curv"
to my cruv program and all is well.

Well, importing data from a file is a standard feature of Curv. That's what the "file" command is for. It's just not fully implemented yet. The documentation says that "The Curv ``file`` operation can import data from multiple file formats,
of which the text-based Curv language (``*.curv`` files) is just one example." But only two formats are supported so far.

If you have a text file using some unusual file format that shouldn't be built in to Curv, and you want to import it as a string value, and parse the string, that's a simple extension to the existing 'file' command.

As it stands now it looks like I need to write the normalization program
in a different language. And of course I also may need to save the normalized
data in a database, in a zip file, out on the Internet or in a local or remote
git repo ....

The ability to import from a remote git repo, using a URL, is on my roadmap. The actual feature is a package manager, where you can import packages written by other people, referencing packages using a URL. Remote packages are sandboxed, so they can't use the "file" command to access arbitrary files anywhere on your local machine. Package management is now a considered a necessary feature for any serious programming language, and I want this for the 1.0 release.

Database access is not something that I had previously considered.

Bottom line, without a general I/O capability Curv isn't going to work for me
in the long term. That makes me sad.

You don't need a general I/O capability to do what you described. You just need the ability to create a Curv package that consists of multiple files: some are *.curv source files and some are data. The curv source files can reference data files from the same package.

Wink Saville

unread,
Jun 19, 2020, 11:21:27 PM6/19/20
to Doug Moen, Curv
At this point Curv seems to limiting for what I envision I need in the long term. I'll keep my eye on its progress and hopefully be back in the future.

Thanks,

Wink

Doug Moen

unread,
Jun 20, 2020, 9:43:24 PM6/20/20
to Curv
Hi Wink. If you find a 3D modelling tool that meets your needs better, let me know; I'm curious what you settle on.
You might consider github.com/libfive, since that is based on Guile Scheme, which is a GP language.

All the best,
Doug Moen.
--
You received this message because you are subscribed to the Google Groups "Curv" group.
To unsubscribe from this group and stop receiving emails from it, send an email to curv+uns...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages