-
Notifications
You must be signed in to change notification settings - Fork 6
Extract Destructuring
See also: Destructuring, Structuring and Restructuring
CaffeineScript supports two destructuring syntaxes:
- Extract:
a extract b
. Extract generally is more capable and uses less syntax. Extract returns the last value extracted. - Assignment: {b} = a`. Assignment-style's return-value follows supports Restructuring.
Assignment-style will feel familiar to JavaScript and CoffeeScript veterans. With the exception of the return-value, assignment-style is identical to JavaScript ES6-style , and is a subset of CoffeeScript-Style-Destructuring. Extract, when complete, will be support everything CoffeeScript supported and more.
CoffeeScript and Javascript, as of EcmaScript6 (ES6), have "destructuring assignment." At first it seems cool and elegant, but after using it for a few years, I've found it awkward and largely ineffective in all but the simplest cases:
- Anything more than trivial [] and {} CoffeeScript/JavaScript-pattern-assignment generally isn't worth it.
- It isn't any more token-efficient than non-pattern assignment.
- It is hard to read, since data flow is going right-to-left initially, and then left-to-right.
- CoffeeScript/JavaScript destructuring returns the object being destructured. I have never found that useful. Instead, I usually want the extracted value returned, usually for testing in an if-statement if it is present.
- It requires a lot of {} and [] bracket-matching.
Introducing extract
. Key features:
- Data-flow direction is always the same direction: left-to-right
- Conditional extraction
- Returns the last value extracted - as long as all values could be extracted.
- Reduced tokens
- Pathed extraction
Example:
# CaffeineScript - 6 tokens
compile() extract compiled extract js
# OR
compile() extract compiled.js
# CoffeeScript - 10 tokens
{compiled:{js}} = compile()
# Or, without pattern assignment, CoffeeScript is actually shorter - 8 tokens
js = compile().compiled.js
# CaffeineScript - 7 tokens
Engine extract Elements extract Base, Bitmap
# Or, 6 tokens
Engine extract Elements extract
Base
Bitmap
# CoffeeScript - 10 tokens
{Elements:{Base, Bitmap}} = Engine
# Or, 12 tokens
{Elements} = Engine
{Base, Bitmap} = Elements
# CaffeineScript - 8 tokens
myArray extract [] a, b, c
# CaffeineScript alt - 6 tokens
myArray extract []
a
b
c
# CoffeeScript - 9 tokens
[a, b, c] = myArray
# CaffeineScript - 3 tokens
Engine extract? Elements
# CoffeeScript - 7 tokens
{Elements} = Engine if Engine
# CaffeineScript - 7 tokens
Engine extract? Elements extract? Base, Bitmap
# CoffeeScript - 15 tokens
{Elements:{Base, Bitmap}} = Engine if Engine?.Elements
The old way isn't too bad if you are just pathing the input object:
# CaffeineScript - 5 tokens
Engine.Elements extract Base
# CoffeeScript - 7 tokens
{Base} = Engine.Elements
But when you get just a little more complex, the extract Syntax remains elegant while CoffeeScript/JavaScript starts to get ugly.
# CaffeineScript - 7 tokens
Engine extract Core, Elements.Base
# CoffeeScript - 10 tokens
{Core, Elements:{Base}} = Engine
Consider two lines of CaffeineScript vs CoffeeScript. Each pair is logically the same before/after of a simple refactor. The CaffeineScript refactor effort is trivial, while the CoffeeScript effort is complex and error prone. The goal of the refactor is to extract Core from Engine in addition to the Elements.
# CaffeineScript
Engine.Elements extract Base, Bitmap # before
Engine extract Core, Elements extract Base, Bitmap # after
# CoffeeScript
{Base, Bitmap} = Engine.Elements # before
{Core, Elements:{Base, Bitmap}} = Engine # after
# CaffeineScript - 10 tokens
Engine extract? Elements extract?
Base = default1
Bitmap = default2
# CoffeeScript - 19 tokens
{Elements:{Base = default1, Bitmap = default2}} = Engine if Engine?.Elements
# CaffeineScript - 7 tokens
(extract? a, b) ->
# CoffeeScript - 13 tokens
(options = {}) ->
{a, b} = options
A constant frustration of mine with CoffeeScript is I want to extract some values from an argument, but I also need access to that argument later. There is no good way to do this in CoffeeScript or JavaScript. By separating 'extract' from normal assignment, there is no longer a syntax ambiguity when we want to end up with defaults, extraction and named arguments:
# CaffeineScript - 14 tokens
(options = {} extract a = 1, b = 2) ->
# OR 12 tokens
(options extract? a = 1, b = 2) ->
# CoffeeScript - 17 tokens
(options = {}) ->
{a = 1, b = 2} = options
Used in an expression, extract returns all the extracted values &&ed together in order. Effectively:
- if all values could be extracted, it returns the last one
- else it returns the first false-ish value
# CafScript
if MyLib extract foo bar baz
foo bar baz()
else throw new Error "Expected MyLib to have foo, bar and baz!"
# CafScript
if MyLib?.foo extract? boo
boo()
else throw new Error "Failed to find MyLib.foo.boo!"
Works like other binary operators
# CaffeineScript - 4 tokens
... # long, complex expression
extract a, b
# CoffeeScript - 6 tokens
{a, b} = ... # long, complex expression
- Home
- Get Started
- Benefits
- Highlights
- Productivity by Design
- CaffeineScript Design
- What is CaffeineScript Good For?
- Get the most out of JavaScript
- Language Comparison
- CHANGELOG
- Blocks Instead of Brackets
- Binary Line-Starts
- Everything Returns a Value
- Streamlined Modules
- Scopes and Variables
- Optional Commas
- Semantics
- Ambiguities