If the goal is to emulate (to some extent) the English-like nature of script in our handler names, then I think it is instructive to look at the syntactic forms employed in the current syntax that exists. I can think of the following general forms:

   - properties:
       the X
       the X of Y

   - chunks (part access):
       item X of Y

   - predicates:
       X is [ not ] <something>
       there exists <something>

   - functions (in the mathematical sense):
       average(X, Y)
       sin(Z)

   - commands:
       encrypt X with Y using password Z
       import snapshot

A property is something which encapsulates a piece of state. Sometimes they are constants; sometimes they are read-only and reflect state that changes over time; sometimes they reflect something about the content of something, or an attribute of something and only change when explicitly set. Getting properties never have any side-effects; setting properties only has side-effects within their domain of concern (whether it be a library, or an object).

A chunk is something which allows access to a part of something. Again, sometimes they are read-only, sometimes settable. Getting chunks never have side-effects; setting chunks only have side-effects within their domain of concern.

A predicate is a test which returns true or false, and is to test for a particular condition. They never have side-effects.

A function (in the mathematical sense) takes inputs, and uses those inputs to generate output. If we want to be completely pure, then they should never have side-effects - they should be used for computational devices... i.e. Things which synthesize a result based on input values and related state.

A command is something which actually *does* something. Commands can and do have side-effects.

I'd perhaps further suggest that evaluating functions, predicates, chunks and properties should *not* be able to fail apart from due to mis-use (e.g. asking for an object which doesn't exist, trying to convert "ZOO" from base 10 to base 16). I think this is generally true in the engine, the most prominent exception which comes to mind being the 'url' chunk.

[ As a slight aside...

This latter sitation (functions being able to fail when it is not due to mis-use) is why we have the odd situation with functions being able to return two values (the result, and the actual return value). The reason this is actually not ideal is that you can easily write code which is not and cannot be made correct except by separating out onto multiple lines. e.g.

  processMyTwoBitsOfData url X, url Y

Here, if fetching url X fails, then the command will receive empty, and still get executed which is technically wrong in pretty much any scenario (after all, one of the url's could actually be empty by intent and so you the receiving function cannot tell the difference between a failure in fetching one of its arguments, and the argument actually being empty). In order to write this correctly you need to do:

  local tX, tY
  put url X into tX
  if the result is not empty then throw "fetching X failed"
  put url Y into tY
  if the result is not empty then throw "fetching Y failed"
  processMyTwoBitsOfData tX, tY

Of course, this might just suggest that the url chunk should throw an error in the case of failure; but that then violates the principal that things you cannot predict failure of *must* be explicitly checked for success. Unfortunately, however, the world is not perfect. ]

In contrast, commands (as they are performing an action, rather than a computation) can and do fail in ways you cannot predict. This is typically indicated by returning a non-empty result; with any actual returned value from a command being placed in it (in the case the command didn't fail). [ Note: Script now has the ability to set either the result or it from a command handler - by using return for value, and return for error ].

So, if the goal is to reflect English-like ness in our library function naming (in lieu of being able to actually define our own syntax directly in one of the above forms) then the following seem reasonable:

   - property-like things: The<property>[Of<thing>]

   - chunk-like things: <Chunk>Of<Thing> / TheNumberOf<Chunk>sOf<Thing>

   - predicates: Is[Not]<Adjective> / ThereIs(A|An)<Noun>

   - functions: <Noun> (with potential suffixes describing inputs)

   - commands: <Verb> (with potential suffixes describing inputs)

I realize here function/command are a little too general - they are difficult to abstract in a reasonable pattern as their naming will largely depend on what they are doing.

The case in question was a MIME library with the following parts:

- a function which returns the version of MIME to use in the MIME header - MIMEVersion

- a function which returns the mime type for a given extension - MIMETypeForExtension

- a function which returns the list of extensions matching a wildcarded mime pattern - MIMETypeExtensions

- a command which encodes the input in a MIME transfer encoding - MIMEEncode

- a command which creates a MIME multipart document from an array of pieces - MIMECreateMultipartContent

- a command which creates a MIME multipart document from a field - MIMECreateMultipartContentFromField

- a command which creates a MIME multipart email from a pre-encoding multipart document and attachments - MIMECreateEmail

A naming scheme consistent with the above 'english-like' forms could be something along these lines:

The MIMEVersion is actually a read-only property:

    syntax: the MIMEVersion

    function form: mimeTheMIMEVersion

The MIMETypeForExtension is essentially a parameterized read-only property, or chunk:

    syntax: the MIMEType of extension <ext>

    function form: mimeTheMIMETypeOfExtension(<extension>)

The MIMETypeExtensions as currently posed is either a direct constant lookup, or a 'map' over a list of constants. I think it is reasonable in this case to consider a 'MIMEType' as either being a fixed string, or wild-carded string (at least restricted wild-carded - e.g. text/* but not t*t/plain):

    syntax: the extensions of MIMEType <mimetype>

    function form: mimeTheExtensionsOfMIMEType(<mimetype>)

THe MIMEEncode command is actually a pure function - it takes an input and produces an output entirely based on the input, it cannot fail:

    syntax: <data> encoded for <transfer-encoding> MIME transfer

function form: mimeEncodeForMIMETransfer(<data>, <transfer-encoding>)

('for' suggested here because the transformation is *for* a purpose, not an end state)

The MIMECreateMultipartContent is again a pure function - it encodes a sequence of transfer-encoded parts into a multipart document:

syntax: <parts> encoded as MIME multipart document <type> [ with <params> ]

function form: mimeEncodeAsMIMEMultipartDocument(<parts>, <multi-part type>, <params>)

('as' suggested here because the transformation produces something which is an end state - a multipart document)

The MIMECreateMultipartContentFromField, again a pure function - it encodes the content of a field as a mime multipart document:

    syntax: <field chunk> encoded for MIME multipart document

    function form: mimeEncodeFieldAsMIMEMultipartDocument(<field id>)

The MIMECreateEmail is not truly a pure function as it can fail - it has to potentially load data from files in the attachment arrays. It also has quite a long argument list so is probably better considered a command:

syntax: encode <body> as MIME email with subject <subject> from <sender> to <recipient> [cc <cc>] attaching <attachments> [ into <container> ]

command form: mimeEncodeAsMIMEEmail pBody, pSubject, pSender, pRecipient, pCC, pAttachments

Are these names any better than the ones already used in the library? It is hard to say - naming preferences are highly subjective!

However, one thing which I think is useful to consider in mind is that difficulty in naming things can (in many cases) indicate that the design is of the API is perhaps not quite right. I did the above reimagining of the current names in the library without considering whether there was a better way to 'slice and dice' the functionality. (For example, would it be better to have the concept of a 'mime email object' which you use setters and getters to configure?).

Just my two pence.

Mark.

--
Mark Waddingham ~ m...@livecode.com ~ http://www.livecode.com/
LiveCode: Everyone can create apps


_______________________________________________
use-livecode mailing list
use-livecode@lists.runrev.com
Please visit this url to subscribe, unsubscribe and manage your subscription 
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode

Reply via email to