jsigbiz / spec

JavaScript signature notation
130 stars 6 forks source link

Added examples & updated README with my variantion #13

Closed Raynos closed 11 years ago

Raynos commented 11 years ago

This is a discussion issue. I will list all the changes I made and then we can battle it out.

Examples folder

I added an examples folder which the majority of my type definitions so far. The examples folder does contain constructs that I have not defined in the README yet.

Grammar

I've added the start of a grammar definition which is far from complete.

name := <type>

I don't allow anonymous type declarations. I allow two types of declarations. The first one is saying name := <type> which generally means a lexical variable name has the type <type>. I also use name to mean reference to name in npm.

Example (npm name):

continuable/map := (Continuable<A>, (A) => B) => Continuable<B>

Example (local name):

xhr := (XhrOptions, Callback<HTTPResponse>) => HTTPRequest

Removal of dot notation

I think I've removed it from the README because it's not needed. You can actually define the type of a lexical variable to just be an object

consistent optional types

Optional types is now done purely through String? and (opts?: Object) is invalid and should be replaced with (opts: Object?)

Introduce explicit type declarations

The second type of declaration is declaring a named type. Named types are not related to the npm namespace or the lexical variables in your program. Named types are purely defined and reference in other type signatures.

An example would be

type Callback<T> := (err: Error, value: T) => void
type Continuable<T> := (callback: Callback<T>) => void

Rename Value to Any

I've basically renamed the usage of Value to mean "any" type to usage of Any to mean "any" type

Compound function types

Instead of defining the same lexical variable multiple times, one for each function signature you can use a compound signature

getOrSet := 
    (Object, String) => T &
    (Object, String, T) => void

Replacing the notion of "named paramters" with "labelled types"

Instead of saying that we can name paramters, I've changed the wording to say that you can label any type.

Example:

add := (left: Number, right: Number) => result: Number

Introducing the enum type

Enum is like the or type but more human readable. For example type: "create" | "update" | "delete" can be expressed as type: Enum("create", "update", "delete")

Example:

type Delta := {
  id: String,
  type: Enum("create", "update", "delete"),
  changes: Object
}
junosuarez commented 11 years ago

:= symbol

I'm still ambivalent about this versus just : - it adds symbols that don't exist elsewhere in jsig or JavaScript. If no one else objects to it, however, I could be convinced.

removal of dot notation

In the earlier draft, dot notation was actually just implicit lexical symbols, rather than a feature of jsig. I support removing it from the examples in favor of clarity and the implicit lexical notation introduced elsewhere in your changes.

consistent optional types

The distinction between foo?: T and foo: T? was intending to capture the difference between foo being a property with a value of undefined and foo not being a property at all. JavaScript is a bit warty (and casual!) that way. I was attempting to defer to the language in terms of describing semantics. This distinction matters more in describing objects than arguments, eg {} would satisfy {foo?: String} but not {foo: String?}, while {foo: undefined} would satisfy the second but not the first. The somewhat bizarre annotation of {foo?: String?} would be satisfied by both.

Having a consistent way to express optionality is great - is it worth the cost of reduced expressivity than the underlying language? I could be convinced of this, but it wasn't my first inclination in the earlier draft.

Rename Value to Any

I'm good with this. Several other languages use Any. I took Value from the ES5 grammar, but I think Any reads better (and has the benefit of being more concise!)

Compound function types

In my mind & intention, this was already supported. I appreciate the effort to clarify that :)

Labeled types

:+1:

Enum

:+1:

Raynos commented 11 years ago

:= symbol

I use this to differentiate the PascalCase new types and the lexical symbols in the programs from labels.

Labels are there purely for human readable words and you can re-use the same label name as many times as you want. The := definitions have to be unique

consistent optional types

I was thinking of { foo?: X } I'm not too sure it can be completely removed

robotlolita commented 11 years ago

Compound function types

Here I believe the disjoint union would be better, since & implies that the preceding type is extended by the following type. So:

getOrSet := (Object, String) => T
          | (Object, String, T) => void
Raynos commented 11 years ago

@killdream I think of | as meaning that getOrSet is either function A or function B. I think of & as meaning that getOrSetis both function A AND function B. it's a function that complies with both signatures.

Raynos commented 11 years ago

@jden

I take back "consistent optional types". You need ? on the tag for things like

foo := (opts?: { key: String }) => Any

for types where placing a ? on the end looks silly basically

Raynos commented 11 years ago

@jden I want to break this PR into individual small features and PR & discuss them one by one.

I want to start with ones that can just be landed like:

junosuarez commented 11 years ago

@Raynos sounds good. I had asked @thlorenz to comment on some of these as well. I'll close this for now. I'm also going to go ahead and stick a version number on the current spec as 0.1.0, so we can go from there.

junosuarez commented 11 years ago

Would also love a separate PR for the grammar you started working up, maybe with a note that it is not (yet) normative