Skip to content

Commit

Permalink
Revise tutorial.
Browse files Browse the repository at this point in the history
  • Loading branch information
rgleichman committed Dec 29, 2016
1 parent 7873645 commit 6c5663d
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 50 deletions.
94 changes: 47 additions & 47 deletions examples/tutorial.hs
Expand Up @@ -26,7 +26,7 @@ y = 3 * 5
{-You might be thinking that so far it looks like Glance has just decorated
the program text with some boxes, lines, triangles and circles. Don't worry,
it will start looking much stranger from here on. Keep in mind that the design
of the icons by themselves does not have much meaning. In fact, as long as the
of the icons does not have much meaning. In fact, as long as the
icons (the non-text parts) are distinguishable from each other, how they are drawn,
even if they are rotated, reflected, squashed or squished does not matter.
The meaning of Glance is entirely in how the icons are connected to each other.
Expand All @@ -46,19 +46,12 @@ f x = 3 * x
box which indicates that it is bound to the result. Now look at the
function application. It looks like 3 is being multiplied by something, but what?
There is a line connecting the second argument of * to the dot in the green icon,
so the second line probably originates from the dot in the green icon.
so the second argument probably comes from the dot in the green icon.
The result of the function application is also connected to the blue square
in the green icon. So the green icon represents a relationship between the
overall result f, the second argument to *, and the result of the multiplication.
Let's think of some possibilities.
Might it be
f = 3 * f?
Let's see what that looks like:
-}
f = 3 * f
{-Nope, no green icon. The recursion of f is just indicated by a line from f to
the argument. What construct in Haskell has three ingredients: a name, a variable,
What construct in Haskell has three ingredients: a name, a variable,
and a result that derives from the variable? Here's a hint.
y has a value of 21.
-}
Expand Down Expand Up @@ -86,8 +79,8 @@ y = (\x -> 3 * x) 7
y = (\x -> 3 * x) 7

{-A more complex example:
-f x y = let q = ((f (x + y - 40) x) * 2) in
-- max (2 * y) q
f x y = max (2 * y) (1 + x)
If you have some drawing implements handy, you might want to try drawing this
yourself before scrolling down. One place to start is to figure out how functions
with "multiple parameters" are defined (which is of course syntactic sugar since
Expand Down Expand Up @@ -132,13 +125,11 @@ Drawing below:
-
-
-
-f x y = let q = ((f (x + y - 40) x) * 2) in
-- max (2 * y) q
f x y = max (2 * y) (1 + x)
-}
f x y = let q = ((f (x + y - 40) x) * 2) in
max (2 * y) q
f x y = max (2 * y) (1 + x)

{-Something different about Glance is that Glance does not have any code regions.
{-Something different about Glance is that Glance does not have any rigid code regions.
In other visual programming languages, the icons inside the body of a function
would be restricted to a rectangle. In Glance, all icons are on the same level.
Theoretically, Glance's flat layout should allow more compact drawings since space
Expand All @@ -151,28 +142,28 @@ f1 = (\x1 -> (\x2 -> (\x3 -> sum [x1, x2, x3])))
{-In most other visual languages, the above code would require three nested
regions.
Regions however can still be useful to tell at what level, or in other words, in
which function a parameter is used. In the code below for example, it would
probably take some time to figure out that x is only being used in an inner
function. To address this, I hope to have Glance draw a perimeter around all
icons inside a function (including the function's lambda icon). This would occur
Without regions however, it can be difficult to see in which function a parameter
is used. In the code below for example, it would probably take some time to
figure out that x is only being used in an inner function. To address this, I hope
to have Glance draw a perimeter around all icons inside a function. This would occur
after layout so it would not make the drawing any larger.
f1 x y = (\z -> x + z) y
-}
f1 x y = (\z -> x + z) y

{-Lets go back to the function apply icon. If you are used to other graphical
visual programming languages, you may be thinking that this does not look very
graphical. Here graphical is referring to a graph topology,
{-
Let's go back to the function apply icon. If you are used to other graphical
programming languages, you may be thinking that drawing below
does not look very graphical. Here graphical is referring to a graph topology,
and no it does not look graphical. The core idea is that nested function
application has a tree topology, not a graph topology. The result of each
sub-expression is only used once. Glance takes advantage of this tree topology
to make its drawings more compact.
y = foo (3 + (baz 2)) (8* (baz 2))
y = foo (3 + (baz 2)) (8 * (baz 2))
-}
y = foo (3 + (baz 2)) (8* (baz 2))
y = foo (3 + (baz 2)) (8 * (baz 2))

{-As soon as an expression is used more than once, the tree topology is lost,
and Glance extracts the sub-expression into a separate (non-nested) icon.
Expand All @@ -196,36 +187,33 @@ y = (((2 + 4 * 4) - (7+ 2 + baz)*8)/21)
(Just x) = Just 3

{-
Since constructors are functions, the match icon has a same shape similar
to the apply icon. The match icon is magenta to help distinguish
it from the apply icon. In a future iteration of the Glance icons, the match and
apply icons should be made more dissimilar so that they can not be confused with
each other, even when displaying Glance drawings in black and white.
Since constructors are functions, the match icon has a topology similar to
the apply icon.
Now that you are familiar with matches, here's a simple case expression.
--y = case maybeInt of
-- Just x -> x + 1
-- Nothing -> 0
-- Just x -> x + 1
-}
y = case maybeInt of
Just x -> x + 1
Nothing -> 0
Just x -> x + 1

{-The case icon is the magenta icon with three yellow circles next to it.
The matches (the textual part left of the arrow) connect to the triangles,
and the result for each match (the textual part to the right of the arrow) is
indicated with the yellow circle. The result for the second match (Nothing -> 0)
indicated with the yellow circle.
The result for the first match (Nothing -> 0)
connects to the circle on the case icon since the right hand side (0) does not
use any value from the pattern (Nothing). For the first match, since the result
(x + 1) is topologically connected to its pattern (Just x), Glance can connect
the result to a new yellow circle. If the result always had to be connected to
use any value from the pattern (Nothing). For the second match, since the result
(x + 1) is connected to its pattern (Just x), Glance can connect
the result to a new yellow circle.
If the result always had to be connected to
the yellow result circle on the case icon, this would create many cycles in the
graph, making the layout much messier.
On a side note, the lambda icon also creates a cycle, but it only creates one cycle
as opposed to the case icon which would create many cycles if remote result circles
were not allowed.
Guards and if expressions look like this:
--y | x == 0 = 1
--- | otherwise = x + 1
Expand All @@ -234,13 +222,12 @@ y | x == 0 = 1
| otherwise = x + 1

{-The Boolean expressions (e.g. x == 0) connect to the orange Ls, and the
corresponding result expressions (e.g. x + 1) connect to the triangle on the
corresponding result expressions (e.g. x + 1) connect to the triangles on the
other side of the mid-line. The overall result that the guard is bound to connects
to either the top or bottom of the mid-line.
to the bottom of the mid-line.
Currently, the guard icon and the case icon look similar since they have similar
topology (number of connections = 1 + 2 * n), but they should look less similar
in better icon versions.
topology, but they should look less similar in better icon versions.
"If" expressions are rendered the same as a guard with only one Boolean.
Expand All @@ -265,9 +252,19 @@ to a composition of functions.
For example:
y = f (g x)
which is the same as
y = (f . g) x
-}
y = f (g x)

{-
With a composition of three functions:
y = f (g (h x))
which is the same as
y = (f . g . h) x
-}
y = f (g (h x))

{-
Glance figures out automatically when to use the compose icon in order to
reduce the nesting depth.
Expand All @@ -280,7 +277,10 @@ factorial (x - 1) * x
to
x * factorial (x - 1)
Notice that the nesting level has been reduced from 3 to 2.
Glance essentially rewrites the second expression as:
(x *) . factorial . (x -) $ 1
Notice that the nesting depth has been reduced from 3 to 2.
--factorial x =
-- if x == 0
Expand Down
4 changes: 1 addition & 3 deletions todo.md
@@ -1,12 +1,10 @@
# Todo

## Todo Now
* Remove parameter from getUniqueName

* Consider adding binding variable names to the lambda icon and match icon. Don't display the name if it is only one character.

## Todo Later
* Add wiki pages discussing: Why a visual language?, Glance design goals, History of Glance, FAQ's, How to contribute, Code guide [code style, ...], Related projects etc..
* Add wiki pages discussing: Why a visual language?, Glance design goals, History of Glance, FAQ's, How to contribute, Code guide [code style, ...], Related projects, examples demonstrating the utility of Glance etc..

### Testing todos
* Fix the arrowheads being too big for SyntaxGraph drawings.
Expand Down

0 comments on commit 6c5663d

Please sign in to comment.