Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

DZone's Guide to

# Destructuring CoffeeScript One Sip at a Time

· Web Dev Zone ·
Free Resource

Comment (0)

Save
{{ articles[0].views | formatCount}} Views

Building real-time chat? Enroll in a Free Course on Mobile Chat Development.

Originally authored by Alberto Pose

TL;DR? Don’t worry, (: You can see the code running here.

# Introduction

Destructuring in Coffeescript is an elegant feature that makes the language feel closer to pure functional languages such as Haskell. Let’s see an example of that.

# Show me the code

We will start by creating two types of tree objects:

class Leaf then constructor: (@value) ->
class Node then constructor: (@nodes...) ->

Leaf, as the name suggests, will be the tree nodes that contain values. On the other hand, Nodes will be the objects that will glue the tree together.

Let’s look at some structures in order to see how the tree will look:

#  / \
# 5  / \
#   9   7

new Node(new Leaf(5), new Node(new Leaf(9), new Leaf(7)))

#    /
#   /
#  /
# 7

new Node(new Node(new Node(new Leaf(7))))
Now that we know how some of the trees will look, we can start thinking about how we can iterate them. We can use the constructor property to distinguish whether we have a Node or a Leaf.
five = new Leaf(5)
node = new Node(new Leaf(2))
node2 = new Node(new Node(new Leaf(1)))

# [Function: Leaf]
five.constructor

# [Function: Node]
node.constructor

# true
node2.constructor == node.constructor

# false
node.constructor == five.constructor
Let’s write a function that will add all the Leaf nodes of a given tree.
sumTree = (tree) ->
switch tree.constructor
when Leaf
{value} = tree
value
when Node
{nodes} = tree
f = (accum, node) -> accum + sumTree(node)
nodes.reduce f, 0

# returns 5
sumTree new Node(new Leaf(3), new Leaf(2))

A couple of things to notice from the previous example:

• switchwhen is versatile and can receive functions as the content to be matched.
• In CoffeeScript, everything is an expression (as much as possible). That means that the last evaluated statement of a function will be the return value. In the Leaf branch, it returns value and in the Node branch the returned value is the result of nodes.reduce f, 0
• Last but not least, by doing {value} = tree and {nodes} = tree we are destructuring the objects. This feature simplifies code and improves readability.

From the last code snippet, we can generalize some parts and get a functional way (fold function) to transverse the data structure:

reduceTree = (fLeaf, fNode, valueNode, tree) ->
switch tree.constructor
when Leaf
{value} = tree
fLeaf(value)
when Node
{nodes} = tree
f = (accum, node) -> fNode(accum, reduceTree(fLeaf, fNode, valueNode, node))
nodes.reduce f, valueNode

The arguments of the function are:

• fLeaf: Function to reduce to each of the Leaf nodes
• fNode: Function to reduce to each of the Nodes
• valueNode: Initial value

We can express sumTree using reduceTree in the following way:

# Conclusion

Coffeescript syntax sugar allows some algorithms to be codified in an elegant fashion, especially when they involve destructuring. In the RAML Grammar project, where we describe RAML Grammar for providing suggestions and autocomplete to the API Designer, we extensively use trees and easily transverse them thanks to the nature of the language.

Power realtime chat, IoT and messaging apps at scale. Pubsub realtime messaging, functions, chat, presence, push, notifications, blocks catalog and more.

Topics:

Comment (0)

Save
{{ articles[0].views | formatCount}} Views

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.