Created
October 3, 2014 21:03
-
-
Save mystor/c7013abf1cad40b526f0 to your computer and use it in GitHub Desktop.
Proposed Changes to Myst Object Syntax
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- PROBLEM 1: Large objects as arguments | |
react.createClass Obj#{ | |
render: fn -> | |
doSomething! | |
} | |
-- Becomes -- | |
<{ | |
react.createClass Obj#{ | |
render: fn -> | |
<{ doSomething! }> | |
;} -- A semicolon is inserted because of indentation | |
}> | |
-- This can be fixed by a few different mechanisms: | |
-- - Special case } and similar tokens to prevent ; from | |
-- being inserted before them | |
-- - Change the Syntax for objects, such that this doesn't | |
-- happen. | |
-- - Example: <{ => {, }> => } | |
-- object : (Obj|Map) { [property] } | |
-- For the first case, the syntax would be the same as currently | |
-- For the second case, you would be able to do this: | |
react.createClass Obj | |
render: fn -> | |
doSomething! | |
-- The layout engine would consider Obj to be a block-initializer, | |
-- rather than the empty object, and would insert tokens as follows: | |
{react.createClass Obj | |
{render: fn -> | |
{doSomething! | |
}}} | |
-- This also would simplify the problem of where to put the comma | |
react.createClass Obj | |
render: fn -> x | |
getInitialState: fn -> initialState | |
-- becomes -- | |
{react.createClass Obj | |
{render: fn -> {x | |
};getInitialState: fn -> {initialState | |
}}} | |
-- One-line objects would look like: | |
react.DOM.div (Obj id: "myId"; className: "thing") | |
-- becomes -- | |
{react.DOM.div (Obj {id: "myId"; className: "thing"}) | |
} | |
-- Presumably, lists/arrays would be similar | |
map f (Arr a; b; c; d) | |
-- becomes -- | |
{map f (Arr {a; b; c; d}) | |
} | |
-- or -- | |
map f Arr | |
firstElement | |
secondElement | |
thirdElement | |
fourthElement | |
-- becomes -- | |
{map f Arr | |
{firstElement | |
;secondElement | |
;thirdElement | |
;fourthElement | |
}} | |
-- I'm not sold on the token for the block initializer | |
-- Also, this means that the #merge operator may not work as well | |
-- We won't be able to do | |
Map#map_or_object | |
-- to get something as a Map, as Map will be a special token... | |
-- There may be another option of `MapE` for an empty map | |
-- which can be merged into, but it won't be as elegant | |
-- We could probably do lhs binding in map decls too! | |
doSomethingWith Obj | |
methodA x: | |
let y = 20 | |
let z = 30 | |
x + y + z | |
methodB y: if y < 10 | |
then 1 | |
else methodB (y - 1) -- methodB is visible! | |
-- If we want, we can even use = instead of : | |
doSomethingWith Obj | |
methodA x = | |
let y = 20 | |
let z = 30 | |
x + y + z | |
methodB y = if y < 10 | |
then 1 | |
else methodB (y - 1) -- methodB is visible! | |
-- This may produce nice-ish syntax for creating classes | |
mkThingy x y = Obj | |
__constructor__: mkThingy | |
x: x | |
y: y | |
-- or -- | |
mkThingy x y = Obj | |
__proto__: mkThingy.prototype | |
x: x | |
y: y | |
-- Presumably, the optimizer could make this | |
-- actually quite efficient, by detecting the | |
-- special __constructor__ and __proto__ properties | |
-- This brings up the problem of how to handle maps in pattern matches | |
-- This is how it's currently done | |
case x of | |
{a, b, c} -> -- a, b, and c are avaliable here | |
[d, e, f] -> -- elements 0, 1, 2 are bound to d, e, f | |
{a:[1,2]} -> -- Checks if the property a matches [1,2] | |
-- With the new system, for the sake of consistency, | |
-- it would probably look like | |
case x of | |
Map{a; b; c} -> -- a, b, and c are avaliable here | |
Vec{d; e; f} -> -- elements 0, 1, 2 are bound to d,e,f | |
Map{a:Vec{1; 2}} -> -- Checks if the property a matches Vec{1; 2} | |
-- or -- | |
case x of | |
(Map a; b; c) -> -- a, b, and c are avaliable here | |
(Vec d; e; f) -> -- elements 0, 1, 2 are bound to d,e,f | |
(Map a:(Vec 1; 2)) -> -- Checks if the property a matches Vec{1; 2} | |
-- But this actually would have different semantics, as | |
-- the original version matched against map-like things | |
-- (it would also match against objects), while this only | |
-- matches against Maps/Vecs (you could also match vs. objects) | |
-- Maybe there would be a more generic version? | |
case x of | |
(# a; b; c) -> -- hashmap? | |
(.. a; b; c) -> -- list? | |
(# a:(.. 1; 2)) -> -- Looks kinda ugly & weird | |
-- Also splats? | |
case x of | |
(Vec x; ..xs) -> -- Much more verbose than [x, ..xs] | |
-- Use the old syntax for generic cases? | |
case x of | |
(Map a; b) -> -- Map | |
{a; b} -> -- Map -or- Obj | |
(Vec a; b) -> -- Vec | |
[a; b] -> -- Vec or Arr | |
(Set a; b) -> -- Set | |
-- , could be made equivalent to ;, to make the syntax similar? | |
case x of | |
(Map a, b) -> -- Map | |
{a, b} -> -- Map -or -Obj | |
(Vec a, b) -> -- Vec | |
[a, b] -> -- Vec or Arr | |
(Set a, b) -> -- Set | |
-- That could also happen in instantiation | |
fun (Map a: 'b', c: 'd') | |
-- or ; could be dropped entirely for , (make , the statement delimiter) | |
-- Maybe require a # after the name, and allow people to define | |
-- their own object types (some standard interface for instantiation?) | |
case x of | |
(Map#a, b) -> Map# a: b; b: a | |
{a, b} -> Obj# a: b; b: a | |
-- Match vs maybes? | |
(Just# x) -> doSomethingWith x | |
(Nothing#) -> doSomething! | |
-- There would have to be a syntax & type stuff | |
-- Perhaps a class type which represents a constructor? | |
let Just = Class# | |
properties: Vec# x | |
prototype: Obj# | |
isJust: true | |
let Nothing = Class# | |
prototype: Obj# | |
isJust: false | |
-- Creating? | |
let myObject = Just# 10 -- construct from array? | |
-- or? | |
let myObject = Just# x:10 -- construct from map? | |
-- or? | |
let myObject = Just 10 -- function constructor? | |
-- It would be pretty cool if you could instantiate JS objs | |
-- in this way too... | |
let someObjectRequiringNew = Router# apple, pear | |
-- Although, destructuring wouldn't make any sense... | |
-- Another thing which could be nice is arbitrary blocks | |
-- of code which are isolated with variables | |
let x = 10 | |
begin -- (maybe do, but I would like that for pseudo-monads) | |
let x = 20 | |
console:log x -- 20 | |
console:log x -- 10 | |
-- Thanks a ton for reading through this, I really appreciate | |
-- your input :). Do you have any opinions on these syntaxes? | |
-- I find that writing them out helps me realize what I like and | |
-- what I don't like about them. | |
-- I'm not super happy with anything above, and I would love | |
-- your input as to how I could improve the syntax going forward |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment