Destructuring and Pattern Matching in Functional Programming


Couple of weeks back I presented a introductory session on Destructuring and Pattern Matching at Functional Conference 2018, Bengaluru where I demoed live how Destructuring is different from Pattern Matching by using various Functional Programming languages and other non-FP languages.

Difference Between Destructuring & Pattern Matching

Starting with dynamically typed languages like JavaScript

 
// Destructuring gives us a short-hand way of naming parts of the data-structure.
const list = [1,2,3,4,5,6]
let [first, second, ...rest] = list
console.info("first = ", first);
console.info("second = ", second);
console.info("rest = ", rest);

// Destructuring Object
const name = {first: "Dhaval", last: "Dalal", salutation: 'Mr.'};
const {first: firstName, last: lastName} = name;
console.info(firstName);
console.info(lastName);

// Destructuring Function params
function capitalize({first: firstName, last: lastName}){
  return firstName.toUpperCase() + " " + lastName.toUpperCase();
}
console.info(capitalize(name));

// Destructuring Function params
function distance([x1,y1], [x2,y2]){
  return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}

console.info(distance([0,0], [0,0]))
console.info(distance([3,0], [0,0]))
console.info(distance([0,0], [0,4]))
console.info(distance([3,0], [0,4]))

This is Destructuring. It gives you a short-hand way of naming and getting the innards of the structure. At present (at the time of writing this post), JavaScript does not have Pattern Matching out-of-the-box. So, leaving JavaScript there, I moved to Erlang and then hopped over to statically typed languages like Haskell where I demoed the difference between Destructuring and Pattern Matching.

In Pattern matching, we are not only matching on relative positions of elements in the data-structure, but also trying to dispatch to different definitions (look at the distance function – it has 2 definitions) based on the value inside the data structure. This dispatch is a kind of conditional construct, while in destructuring there is nothing conditional about it.

import Data.Char (toUpper)

data Name = Name { 
  first :: String, 
  last :: String,
  salutation :: String
} deriving (Show)

capitalize :: Name -> String
capitalize (Name fName lName _) = (upper fName) ++ " " ++ (upper lName)
  where
    upper cs = [toUpper c | c  Double -> Double
pythagorean x y = sqrt (square x + square y)
  where
    square n = n ^^ 2

distance :: (Double, Double) -> (Double, Double) -> Double
distance (0,0) (0,0) = 0
distance p1@(x1,y1) p2@(x2,y2)
  | p1 == (0,0) || p2 == (0,0) = (let (x,y) = if p1 == (0,0) then p2 else p1 in pythagorean x y)
  | otherwise = pythagorean (x2 - x1) (y2 - y1)

main :: IO ()
main = do
  let name = Name "Dhaval" "Dalal" "Mr."
  print $ name
  print $ capitalize name
  print $ distance (0,0) (0,0)
  print $ distance (3,0) (0,0)
  print $ distance (0,0) (0,4)
  print $ distance (3,0) (0,4)
  print "DONE"

and finally closing with the same example rendered in Clojure. If this interests you, here is the link for examples in other languages https://github.com/DhavalDalal/destructuring-and-pattern-matching/tree/master/01_languages

Double Dispatch

After that, I demoed the implementation of Double-Dispatch using famous Paper-Scissor-Rock game, starting with Java. The same was then implemented in the above mentioned languages.

; We’ll use record to represent the three choices.
(defrecord Paper [])
(defrecord Scissor [])
(defrecord Rock [])

; Multi-methods can be used to solve this problem
; Here is our dispatch function
(defmulti beats
  (fn [e1 e2] [(class e1) (class e2)]))

(defmethod beats [Paper   Scissor] [e1 e2] "paper loses")
(defmethod beats [Paper   Rock]    [e1 e2] "paper wins")
(defmethod beats [Scissor Paper]   [e1 e2] "scissor wins")
(defmethod beats [Scissor Rock]    [e1 e2] "scissor loses")
(defmethod beats [Rock    Paper]   [e1 e2] "rock loses")
(defmethod beats [Rock    Scissor] [e1 e2] "rock wins")
(defmethod beats :default          [e1 e2] "draw")

(println "paper beats paper = "     (beats (Paper.)   (Paper.)))
(println "paper beats scissor = "   (beats (Paper.)   (Scissor.)))
(println "paper beats rock = "      (beats (Paper.)   (Rock.)))
(println "scissor beats paper = "   (beats (Scissor.) (Paper.)))
(println "scissor beats scissor = " (beats (Scissor.) (Scissor.)))
(println "scissor beats rock = "    (beats (Scissor.) (Rock.)))
(println "rock beats paper = "      (beats (Rock.)    (Paper.)))
(println "rock beats scissor = "    (beats (Rock.)    (Scissor.)))
(println "rock beats rock = "       (beats (Rock.)    (Rock.)))

Below is the link to implementations in Java, Scala, Haskell and Erlang
https://github.com/DhavalDalal/destructuring-and-pattern-matching/tree/master/02_double_dispatch

Subsuming The Visitor Pattern

The session concluded by showing how the (in)famous Visitor Pattern that is usually implemented in languages like Java, C# and C++. Here is the problem statement: How will you enhance this code to include rendering these objects on following platforms?

  • OpenGL
  • SVG

                              +---------------+
	                          |    Shape3d    |
	                          +---------------+
	                          | surfaceArea() |<-------------------------------+
	                          | volume()      |                                |
	                          +---------------+                                |
	                                  ^                                        |
	                                 / \                                       |
	                                  |                                        |
	         +------------------------+-----------------------+                |
	         |                        |                       |                |
	  +---------------+       +---------------+       +---------------+        |
	  |   Cylinder    |       |     Sphere    |       |CompositeShape |        |
	  +---------------+       +---------------+       +---------------+ *      |
	  | surfaceArea() |       | surfaceArea() |       | surfaceArea() |--------+
	  | volume()      |       | volume()      |       | volume()      |
	  +---------------+       +---------------+       +---------------+

Possible Solutions:

  • Solution 1:
    • Introduce renderOpenGL() and renderSVG() methods in Shape3d.
    • We have now made shapes aware of the “drawing platform” specific code. Though they are renderable objects, but how to render would be present inside them.
    • It does not scale to more rendering platforms. We have to add to hierarchy everytime.
  • Solution 2: Use Visitor Pattern
	                      +-----------------+                                    +-----------------+
	                      |     Shape3d     |----------------------------------->|     Visitor     |
	                      +-----------------+                                    +-----------------+
	                      | surfaceArea()   |                                    | visit(Cylinder) |
	                      | volume()        |<-----------------------+           | visit(Sphere)   |
	                      | accept(Visitor) |                        |           +-----------------+   
	                      +-----------------+                        |                    ^    
	                              ^                                  |                   / \
	                             / \                                 |                    |
	                              |                                  |            +--------------------+
	         +--------------------+----------------------+           |            |                    |     
	         |                    |                      |           |   +-----------------+  +-----------------+   
	 +-----------------+  +-----------------+  +-----------------+   |   |  OpenGLVisitor  |  |    SVGVisitor   |   
	 |     Cylinder    |  |      Sphere     |  |  CompositeShape |   |   +-----------------+  +-----------------+   
	 +-----------------+  +-----------------+  +-----------------+ * |   | visit(Cylinder) |  | visit(Cylinder) |   
	 | surfaceArea()   |  | surfaceArea()   |  | surfaceArea()   |---+   | visit(Sphere)   |  | visit(Sphere)   |   
	 | volume()        |  | volume()        |  | volume()        |       +-----------------+  +-----------------+   
	 | accept(Visitor) |  | accept(Visitor) |  | accept(Visitor) |                                               
	 +-----------------+  +-----------------+  +-----------------+ 

Subsumption of this pattern was then demoed in Scala, Haskell, Erlang and Clojure. All these languages provide the facility of Destructuring and Pattern Matching. Below is a Subsumed Visitor implementation in Erlang.

-record (cylinder, {baseRadius = 0, height = 0}).
-record (sphere, {radius = 0}).

volume(#cylinder {baseRadius = BaseRadius, height = Height}) ->
	math:pi() * math:pow(BaseRadius, 2) * Height;
volume(#sphere {radius = Radius}) ->
	4.0 / 3.0 * math:pi() * math:pow(Radius, 3);
volume(List = [_|_]) -> 
  lists:foldl(fun(Shape, Acc) -> Acc + volume(Shape) end, 0, List);
volume([]) -> 0;
volume(_) -> not_ok.

surfaceArea(#cylinder {baseRadius = BaseRadius, height = Height}) ->
  BaseArea = math:pi() * math:pow(BaseRadius, 2),
  BaseCircumference = 2 * math:pi() * BaseRadius,
  2 * BaseArea + BaseCircumference * Height;
surfaceArea(#sphere {radius = Radius}) ->
  4.0 * math:pi() * math:pow(Radius, 2);
surfaceArea(List = [_|_]) -> 
  lists:foldl(fun(Shape, Acc) -> Acc + surfaceArea(Shape) end, 0, List);
surfaceArea([]) -> 0;
surfaceArea(_) -> not_ok.

render(openGL, #cylinder {}) ->
  io:format("~p~n", ["OpenGL: rendering cylinder"]);
render(openGL, #sphere {}) ->
  io:format("~p~n", ["OpenGL: rendering sphere"]);
render(svg, #cylinder {}) ->
  io:format("~p~n", ["SVG: rendering cylinder"]);
render(svg, #sphere {}) ->
  io:format("~p~n", ["SVG: rendering sphere"]);
render(Platform, List = [_|_]) -> 
  io:format("Rendering Composite...~n"),
  lists:foreach(fun(Shape) -> render(Platform, Shape) end, List);
render(_, _) -> not_ok.

main([]) ->
  Cylinder = #cylinder {baseRadius = 10, height = 10},
  Sphere = #sphere {radius = 10},
  Composite = [Cylinder, Sphere],
  io:format("Volume of Cylinder ~p~n", [volume(Cylinder)]),
  io:format("Volume of Sphere ~p~n", [volume(Sphere)]),
  io:format("Volume of Composite ~p~n", [volume(Composite)]),
  % io:format("Volume of 2 ~p~n", [volume(2)]),
  io:format("Surface Area of Cylinder ~p~n", [surfaceArea(Cylinder)]),
  io:format("Surface Area of Sphere ~p~n", [surfaceArea(Sphere)]),
  io:format("Surface Area of Composite ~p~n", [surfaceArea(Composite)]),
  % io:format("Surface Area of 2 ~p~n", [surfaceArea(2)]),
  io:format("~p~n", [render(openGL, Composite)]),
  io:format("~p~n", [render(svg, Composite)]),
  io:format("DONE").

Here is the link to source code https://github.com/DhavalDalal/destructuring-and-pattern-matching/tree/master/03_visitor

Conclusion

  1. Most functional programming languages provide some level of de-structuring. Destructuring gives you a short-hand way of naming and getting the innards of the structure.

  2. The difference between destructuring and pattern matching is that in Pattern matching, we are not only matching on relative positions of elements in the data-structure, but also trying to dispatch to different definitions based on the value inside the data structure. This dispatch is a kind of conditional construct, while in destructuring there is nothing conditional about it. So, Pattern matching is about associating a definition with a particular set of inputs. So, for the same function, we can have many such definitions for inputs that we destructure on.


Note: This is an elaboration of one of the melodies that Ryan Lemmer and myself prepared for the Code Jugalbandi. You can download this Jugalbandi – it appeared in the Healthy Code Magazine in April 2015.

Advertisements

Help yourself by making iTerm2 vivid

Tags


Do you like this vivid iTerm? It shows the host, the time and the current directory, with optional Git branch, all in different colors.

Want one similar to this? Follow the steps below:

  1. Download iTerm themes from https://github.com/mbadolato/iTerm2-Color-Schemes
  2. Go to iTerm2 >> Preferences >> Profiles >> Color Tab. In the Color Tab look for dropdown Color Presets… and select Import… and import the themes.
  3. Choose a theme of your liking
  4. Download Source Code Pro Font from https://github.com/adobe-fonts/source-code-pro
  5. Open the Font Book.app and load these fonts by clicking the ‘+’ button.
  6. Go to iTerm2 >> Preferences >> Profiles >> Text Tab. In the Text Tab, look for Change Font button and change it to Source Code Pro Font.
  7. Finally we can customize the prompt and make it vivid. Go to http://xta.github.io/HalloweenBash/
  8. Play with it, follow the steps and copy-paste the code in your ~/.bash_profile get your prompt customized. Here is how my ~/.bash_profile prompt customization looks like:
    # for iTerm2
    export CLICOLOR=1
    
    function parse_git_branch {
      git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'
    }
    
    # prompt
    # format \[\033[COLOR_CODE_HERE\]PROMPT_ESCAPE_OR_TEXT_HERE\[\033[0m\]
    
    export PS1="\[\033[01;35m\]\h \[\033[01;33m\]\t \[\033[01;32m\]\W \[\033[01;34m\]\$(parse_git_branch)\[\033[0m\] \n \[\033[01;37m\]\# => \[\033[0m\]"
    

How to disable failed discrete-GPU (NVIDIA GeForce GT 650M) for 15″ MacBook-Pro 10,1 (mid-2012) on High Sierra 10.13.4


It all started when my MacBook Pro showed me black screen after waking from sleep. After that, many times I would boot straight into Black Screen, and the only sign that the machine was awake could be just tested by pressing the CAPS LOCK key (turns on the button-light) or connecting an External USB with a indicator light.

I started asking myself why would this happen? Was it due to upgrade to High Sierra 10.13.3 or was it that my machine really developed some hardware problem? I asked a friend of mine what can I do and he suggested SMC Reset followed by PRAM (NVRAM) Reset. I tried all that, but it refused to work. I got my MacBook cleaned and then it booted fine. But as soon as, I started using it, all of a sudden it would show a Black Screen, but CAPS LOCK would still glow green and so I would then reboot it again, only to Black screen. Sometimes, upon restarting the first problem message that I got was GPU panic like the one shown below:

Anonymous UUID:       32BD6DA8-14C2-38AD-E466-F3B6DDCE6F7F

Fri May 18 19:43:24 2018

*** Panic Report ***
panic(cpu 2 caller 0xffffff7f916c29cf): "GPU Panic: mux-regs 4 0 a0 99 0 8 severity 3 WS-ready 1 switch-state 3 IG FBs 1 EG FBs 0:0 power-state 3 3D idle HDA idle : AGC GPU REGISTER RESTORE FAILED : rdar://7254528, VendorID invalid\n"@/BuildRoot/Library/Caches/com.apple.xbs/Sources/AppleGraphicsControl/AppleGraphicsControl-3.18.48/src/AppleMuxControl/kext/GPUPanic.cpp:162
Backtrace (CPU 2), Frame : Return Address
0xffffff81f9073a90 : 0xffffff800e66e166 
0xffffff81f9073ae0 : 0xffffff800e796714 
0xffffff81f9073b20 : 0xffffff800e788a00 
0xffffff81f9073ba0 : 0xffffff800e620180 
0xffffff81f9073bc0 : 0xffffff800e66dbdc 
0xffffff81f9073cf0 : 0xffffff800e66d99c 
0xffffff81f9073d50 : 0xffffff7f916c29cf 
0xffffff81f9073db0 : 0xffffff7f916bf1ae 
0xffffff81f9073df0 : 0xffffff7f916c2443 
0xffffff81f9073e30 : 0xffffff800ec9f71c 
0xffffff81f9073ea0 : 0xffffff800ec9f646 
0xffffff81f9073ed0 : 0xffffff800e6a77e4 
0xffffff81f9073f40 : 0xffffff800e6a7345 
0xffffff81f9073fa0 : 0xffffff800e61f4f7 
      Kernel Extensions in backtrace:
         com.apple.driver.AppleMuxControl(3.18.48)[09DFEF11-0A5B-369B-91C5-FD32B3E62DD3]@0xffffff7f916b4000->0xffffff7f916c6fff
            dependency: com.apple.driver.AppleGraphicsControl(3.18.48)[91D747FB-F341-33F2-BBDD-0CA45A3CC1B2]@0xffffff7f916b1000
            dependency: com.apple.iokit.IOACPIFamily(1.4)[95DA39BB-7C39-3742-A2E5-86C555E21D67]@0xffffff7f8f35a000
            dependency: com.apple.iokit.IOPCIFamily(2.9)[1850E7DA-E707-3027-A3AA-637C80B57219]@0xffffff7f8ef34000
            dependency: com.apple.iokit.IOGraphicsFamily(519.15)[D5F2A20D-CAB0-33B2-91B9-E8755DFC34CB]@0xffffff7f8fdb3000
            dependency: com.apple.AppleGraphicsDeviceControl(3.18.48)[89491182-0B41-3BC3-B16F-D5043425D66F]@0xffffff7f91219000

BSD process name corresponding to current thread: kernel_task
----

So, I started Googling for this GPU Panic problem and found that many laptops had this issue and that many forums said it was all due to a faulty discrete GPU on the logic board. I missed the replacement program (as I was not even aware that it existed until I hit this problem) and now my machine is out of warranty (more than 51/2 years now). The machine is a 15″ MBP 10,1 (mid-2012) with dual GPU system. I thought, if I could get Logic board changed, I should be okay, but in many forums many users who got that done were not still immune from that problem. It had all the possibilities of appearing once more (even after changed GPU). Secondly, Logic board replacement is an expensive affair! Last option, of course, is to get a new MPB, but I wanted to wait till the WWDC June 2018 announcement.

Anyways, I still wanted to make sure that this is indeed the same GPU problem that I was facing. So, I thought may be I should downgrade the OS X to El Capitan or Sierra and rule out my High Sierra upgrade. After checking with both the older OS X, I started getting very frequent GPU panics, like the one pasted above. With laptop in comatose mode 😉 I literally had to resuscitate it using SHIFT + OPT + COMMAND + Power (SMC reset) by counting 10 and then do a CMD+OPT+R+P+POWER (NVRAM Reset) and the wait for sometime and power up again. It all then depended on the spirit to re-enter the machine and bring it to life again :)) Many times, it had barely woken up and slipped into coma again. Then sometimes it would work for 2/3 days straight, until I don’t open up any BIG IDEs like Intellij or any program like Chrome or Firefox that caused a switch to dGPU.

In the Apple forums, I saw people had already disabled the on-board dGPU and they had a working system with only the built-in iGPU. However, it was done for older makes (year 2011) of the MBP. I searched for my particular make with NVIDIA GeForce GT650M Graphics card. I stumbled upon 2 links:

1) https://github.com/mayankk2308/purge-nvda/blob/master/purge-nvda.sh (NVIDIA driver)
2) http://www.javajirawat.com/2018/02/macbook-pro-2012-broken-gpu-work-around.html (AMD driver)

Thanks to them and I combined both their solutions to disable the dGPU on my system.

The Steps:

    I. Sanity Check (find the number of GPUs):

    • You can either go to Apple Menu > About This Mac… > Overview Tab > Press System Report…Under Hardware, look for Graphics/Displays…
    • Or you can type at terminal (and it displays the same information)
      $ system_profiler SPDisplaysDataType 
      
      Built-In GPU (Integrated GPU - iGPU): Intel HD Graphics 4000 1536 MB
         ...
         ...
      Second GPU (Discrete GPU - dGPU): NVIDIA GeForce GT 650M
      gMux Version:	3.2.19 [3.2.8]
         ...
         ...
      Display - Color LCD Resolution - 2880 x 1800 Retina Framebuffer Depth:	24-Bit Color (ARGB8888)
      Metal:	Supported, feature set macOS GPUFamily1 v3
      
  1. II. In Recovery Mode, do the following (Using the Recovery Terminal Utility), do the following:

  2. Boot into Recovery Mode (by holding Command+R while pressing the power button). At terminal prompt, we will disable SIP (System Integrity Protection)
        $ csrutil disable
        System Integrity Protection now disabled.
        
  3. Reboot again in Single User mode.
        $ reboot 
        $ # and then hold Command+S keyboard buttons
        $ # to boot in single user mode.
    
        
  4. III. In Single User Mode, do the following:

  5. Do a Hard disk Check:
     
        $ /sbin/fsck -fy
        $
        
  6. Mount Root file system in Read-Write (uw) mode:
        $ /sbin/mount -uw /
        $
        
  7. Create a backup directory to hold existing GeForce drivers:
        $ mkdir /GeForce_save
        $
        
  8. Move all the GeForce drivers to the backup directory:
        $ mv /System/Library/Extensions/GeForce* /GeForce_save
        $
        
  9. Delete Driver Cache
        $ rm -rf /System/Library/Caches/com.apple.kext.caches/
        $
        
  10. Force refresh of Driver cache:
        $ touch /System/Library/Extensions
        $ kextcache -q -update-volume /
        $
        
  11. Reboot again (into Recovery mode while holding Command+R)
        $ reboot 
    
        
  12. IV. In Recovery Mode, do the following (Using the Recovery Terminal Utility):

  13. Remove Nvda Booting GPU
        $ nvram boot-args="nv_disable=1" 
        # OR append existing boot-args 
        $ nvram boot-args="nv_disable=1 $(nvram boot-args 2>/dev/null | cut -f 2-)"
        $ nvram fa4ce28d-b62f-4c99-9cc3-6815686e30f9:gpu-power-prefs=%01%00%00%00
        $
        
  14. Enable SIP (System Integrity Protection)
        $ csrutil enable
        System Integrity Protection now enabled.
        
  15. Reboot machine in normal mode
        $ reboot
         
        

IMPORTANT NOTE:

  1. By using nvram boot-args=”nv_disable=1″, you will lose brightness control (F1/F2 keys) and sleep mode (clamshell open/close) does not work. When the computer awakes after sleep, it shows a black display. Also, the brightness slider will no longer show up in System Prefs -> Display. However, you can adjust the backlight to a fixed value. For example, I prefer the low backlight-level. In the recovery terminal,
    $ nvram backlight-level="\%00"
    
    

    Various valid values in the increasing order of brightness are: 0%00, C%00, \%00, z%00, %9f%00, %cb%00, %01%01, A%01, %8c%01, %e6%01, P%02, %d2%02, \%03, %ff%03.

  2. Once you use this patch, you won’t be able to connect to external displays and project on that screen (as MacBook-Pro routes to external ports – HDMI and thunderbolt using the dGPU)
  3. When the computer after sleep, it shows a black display but the machine is still running the OS. To get the screen back, I need to turn the machine off. But this means, its improper shutdown when you have processes running. One solution is that you can remote desktop into the system by using Screen Sharing or VNC. Using this you can get back into the machine, and work like usual until the process completes and then shutdown the machine. Also, while using Screen Sharing, you can project the shared screen on an external display from that client machine.

Update: After this I applied the Security Update 2018-001 and it went fine. I could boot back into my Mac and work with it just like before. I have not yet updated to High Sierra 10.13.5 yet. Once I am able to get that done as well, I’ll share my findings on this post. Stay tuned!

Improvised Tasks.tmbundle for TextMate

Tags


I added commands to the following commands to the Tasks bundle.

  1. Skip a task (toggle)
  2. Expire Skipped tasks

Items marked in cross – ‘X’ change colour to yellow indicate skipped tasks. This is how it looks:

Improvised-Todo-With-Skip-Task

If you want to use it please follow these steps so that you can use it for your presentations/workshops etc…

  1. Git clone: 
    $ git clone git@github.com:DhavalDalal/textmate-bundles.git
    
  2. Change the working dir to:
    $ cd textmate-bundles/
    $ git branch --list
    * master
    

    We need to checkout to the branch – skipped. However, if you notice, its not being shown as a local branch.

  3. So, lets check all the remote branches:
    $ git branch -a
    * master
      remotes/origin/HEAD -> origin/master
      remotes/origin/master
      remotes/origin/skipped
    

    Though the ‘skipped’ branch is there on the remote, we need to track it locally like the master.

  4. Track all remote branches:
    $ git branch -r | grep -v '\->' | while read remote; do git branch --track "${remote#origin/}" "$remote"; done
    
  5. Verify all our locals for the remotes are created:
    $ git branch --list
    * master
      skipped
    
  6. Update local branches that the track remote branches:
    $ git pull --all
    Fetching origin
    
  7. Switch to Skipped branch:
    $ git checkout skipped
    Switched to branch 'skipped'
    Your branch is up-to-date with 'origin/skipped'.
    
  8. Go to:
    $ cd Review/Bundles
    

    In here, you will find the directory – Tasks.tmbundle

  9. Copy this entire directory to the place where Textmate2 stores its bundles (Usually this is ~/Library/Application\ Support/TextMate/Bundles):
    $ cp -r Tasks.tmbundle/ ~/Library/Application\ Support/TextMate/Bundles/Tasks.tmbundle/
    
  10. Finally, restart TextMate and create a todo list.
  11. Use ⌘K to Skip the task and the same to toggle back to unskip. If no text is selected, the task on the current line is toggled: if it’s pending, it’s marked as skipped and vice versa. If text is selected, every task in the selection is toggled in batch: if any of the tasks are pending, all are marked as skipped; if all are completed, they’re marked as pending.
  12. Press ⌘E to remove skipped tasks in the selection or else the entire document.

Sri Aurobindo’s Integral Education Principles


At the outset, I would not like to distinguish between a mentor, a coach, a trainer and an instructor.  To me this is pedantic.  An educationist is anyone who is educating the other person.   Sri Aurobindo has very beautifully given these 3 principles of Integral education.

  1. Nothing can be taught.
  2. The mind has to be consulted in its growth.
  3. To work from the near to the far.

I use these whenever, I’m coaching – technical coaching or agile coaching, consulting, mentoring or even while playing with kids.    While refactoring, I use the 3rd principle all the times – to work from the near to the far.  What I’ve observed that all these principles are extremely relevant in life (whether you dissect it as personal and professional – it does not matter), not just in education.

During consulting, its extremely helpful to understand the nature and rhythm at which the work and the people (and their temperaments) that i’m involved with and how to go from one level to the next with minimal friction.

For details you can refer to the slides below:

How is Homeopathy is near to Yoga?

Tags


Homeopathy-The-Science-And-Art-Of-Healing

Today I attended the Inaugural function of this book – Homeopathy – The Science and Art of Healing.  Last year Dr. Sharad Shah (I call him Uncle lovingly as the doctor-patient relationship over more than 3 decades has become a personal bond) wrote the book and got it published.  I was happy to receive my personal copy from him.  I started reading it – and what I liked about the book was – he has made the topic of Homeopathy within the grasp of a layman.  I particularly liked the logical build-up of the topics that he has done while weaving it with his personal conflict and history of homeopathy along with detailing the law of similars, and finally the symptoms and prescriptions helpful for anyone.

While reading the Chapter 8 on Concept of Vital Force and in particular Uncle’s bulleted points on elements of Human Life and pointing to Dr. Hahneman’s definition of Vital force wherein he uses the words – spirit, vital force, material body, gifted mind and higher purpose of existence.  When I read these words, I could just connect them to Yoga and told myself – this is how yogic lore looks at the mechanism that we call – human.  I continued reading further without putting any “yoga lens”.   But as I read further, I met sentences like – “uninterrupted flow of vital energy”, “disturbance in vital force causes mal-development”, and the line “disease is a dynamic expression of disturbed vital force” hit me hard.  I could not help but put the “yoga lens”.  I generally read the works of Sri Aurobindo and The Mother.  So, my inquisitiveness led me to Google on what Sri Aurobindo had to say about this?  I found Questions and Answers which Sri Aurobindo had with his personal doctor Dr. Nirodbaran and others in the Ashram.  These were published in the NAMAH journal (Vol 20, Issue 2, 15th July 2012)  by Sri Aurobindo Society. [5]  And in that…to my surprise he says that – “Homeopathy is near to Yoga”.   Now that I had Sri Aurobindo’s words to confirm my finding, I started to read the book again in light of Yoga and what Sri Aurobindo had to say on this.  So in this post, I’ll share with you my findings and present a rational connection between Homeopathy and Yoga – esp. Hathayoga and Mantra Yoga. 

 

Modern Psychology and The Yogic Model

When we look at modern psychology, we find that it puts all thoughts, emotions, impulses, instincts and consciousness into one basket called the “mind”.  However, from psychology of yoga, man’s subjective nature is made up of parts.  Each part has its own awareness or consciousness and thus has its own characteristic attitudes.  At a very broad level, there are 2 divisions in human being – the outer beingconstituting personality of the being (personality derived from the latin word “persona” means mask) and the inner beingthe actual Person using the outer mask.  Ordinarily, we identify ourselves with the outer being and regard it as ourself.[1]  From yogic perspective – this outer being has 3 parts – you can imagine – onion rings – starting with The Physical Body or AnnamayaKosha – अन्नमयकोश, going inwards The Vital Body or PranmayaKosha – प्राणमयकोश and further in – The Mental Body (mind is also a body) or ManomayaKosha – मनोमयकोश.  There are other bodies, but these 3 will suffice our purpose

  • AnnamayaKosha – अन्नमयकोश or food body also called the gross body or स्थूल शरीर.  The food that we eat, gets digested and then assimilated and thus becomes a part of the body…in other words, this physical body is built by accumulation of food and hence the name अन्नमयकोश or the food body. [6]  As I’m a computer engineer, I’ll use the computer as a metaphor –  in that the body is the “hardware” of the human mechanism.   
  • ManomayaKosha – मनोमयकोश or Mental body has to do with facts, thoughts, and knowledge.  Medically, mind and brain are treated the same and consciousness is the outcome of brain activity.  Yogic perspective says that mind and brain are different.  According to Sri Aurobindo the brain is not the seat of thinking.  It is the mind that thinks and the brain is only a communicating channel.   ManomayaKosha is the “software” of the human mechanism.
  • PranmayaKosha – प्राणमयकोश  or Pranic or Vital Body is in between the physical and the mental bodies.  The word vital comes from the latin word – vita or “life”.  Just as there are nerves in the physical body, there is a parallel structure of “Nadis” (नाडी) or nerve-channels or energy pathways exist in the subtle body.  Life-force or Vital force or Prana flows through these Nadis.  We can neither see these Nadis with physical eyes, nor with electron microscope.  These Nadis meet at various junctions and re-distribute again.    So, Pranic body or Vital body is like the electricity that powers the “hardware” and the “software”.  Without this power, neither the physical nor the mental can function or develop further.   It is the means of existence in the material body.

From the psychology of Yoga, each of the Koshas have their own consciousness.

  • Generally,  we look at the body that is something  mechanical.  But the body has its own consciousness and intelligence.  We all know that the heart beats, the liver and kidneys function and the lungs breathe even without our active participation.  In case of illness or injury it will heal itself.  So the body acts from this consciousness and intelligence, all without our mental will or even against it.  The characteristic attitude of physical consciousness is one that of narrowness, rigidity, conservatism, slowness to change, boredom and its habitual modes of action and reaction.
  • Whereas, the vital body is made up of Life-force, desires, emotions, sensations like pleasure, pain etc…, instincts and impulses like anger, fear, lust etc…  The vital consciousness is characterised by attitudes of likes and dislikes, search for pleasure and enjoyment, avoidance of pain and discomfort, desire to possess and accumulate, seeks perpetual variety and change, attachment and repulsion, ambitiousness, aggression, fear and impulsiveness.
  • Whereas Mental is guided by that which is consistent with reason that which is deemed to be true or good.  When mental consciousness is pre-dominant in an individual, the attitude is characterised by rational outlook and it is based on moral and intellectual principles. [1]

In Homeopathy too, when a homeopath takes the case, they study the patient by looking at the physicals, emotional and behavioural traits, mental patterns etc…to arrive at a personality – coincidently these 3 are also the levels which psychology of yoga also concerns itself with.

Mapping-Homeopathic-Miasm-And-Attitudes-of-Consciousness

There are many yogic methods to reach the Ultimate.  Each yoga selects different types of Koshas to reach the highest-level of consciousness.  Hathayoga selects physical body and the vital body as its instruments.  Raja-Yoga selects the mental being as its starting point.

Hathayoga

Hathayoga to me, appears quite nearer to Homeopathy.  Hathayoga uses Physical body as a point of departure to reach the Ultimate, but it does not view it with an eye of a physiologist or an anatomist.  According to Sri Aurobindo – It aims at the conquest of the body and Vital Force (Life-Force  or Prana).   It achieves this using 2 instruments and in 3 steps –

The 2 instruments:

  1. Aasanas – They develop in the body certain attitudes of immobility.  If the body is restless, it cannot hold the Pranic energy that enters or is generated within the system.  So aasanas deal with more material part of the physical totality, but it needs assistance of Pranayamas.
    • First aim is to get the body rid of its restlessness (establish control by physical immobility) and
    • Second aim is to force the body to hold the Pranic energy instead of squandering or dissipating it (develops power by immobility).
  2. Pranayamas – Deals directly with the subtler vital parts – the nervous system.  प्राणायम = प्राण (Life-force or Vital energy) + यम (yama means control).  It refers to the control of Life-force.  Pranayamas do the regulated direction and arrestation of vital force in the body.  It achieves this by control of breath – that includes inhalation/exhalation and varieties of rhythmic patterns, inholding and outholding the breath, bandhas or locks.  When the breath is held, the energy within is also held, this holding of energy causes pressure build up and with the release of breath, the blocked energy is unleashed and during the release process, it removes the energy blockages.
    • First aim of Pranayama is to purify the nervous system, to circulate life-force through all nadis without obstruction, disorder or irregularity and
    • Second to acquire complete control of its functionings.   This is done so that mind and soul do not become subject to body or vital or their combined limitations.

In 3 steps:

  1. Purification – Removal of aberrations, obstructions, disorders brought about by mixed and irregular action of the energy in our physical, moral and mental system.
  2. Concentration – Bringing to its full intensity, the mastered and self-directed use of vital energy.
  3. Liberation – Release our being from the painful knots of individualised energy in a limited play, so that union with the Divine is achieved.[3]

How is Homeopathy near to Yoga?

If we observe carefully, in Homeopathy the medicinal remedy removes obstructions and re-establishes vital energy balance in the system.  Whereas in Hathayoga, Asanas and Pranayamas remove interruptions, obstructions, disorders and re-balance vital energy in the system.   In Homeopathy, the effectuation is on the vital body and then changes are seen in the physical body.  In Hathayoga, effectuations are on the physical and the vital body.  Homeopath gathers insights from individual’s personality as a window to peep within and then select the remedy based on law of similars.  In Hathayoga, there is no such need to gather such insights.  It  is beneficial to whoever practices.  Homeopathy and Hathayoga complement each other and can be used simultaneously.

Mantra Yoga

Now let’s turn the attention to Mantra and Mantra Yoga.  In the word Mantra (मंत्र), the root sound is Man (मन) मन means to think, to understand, to contemplate, to perceive, to comprehend and the suffix – त्र (Tra) is used in the sense of instrumentality, meaning as Instrument.  Therefore, the word mantra means Instrument for contemplation, meditation, perception, comprehension, thinking etc…  Just as asanas serve as an instrument to bring the power of immobility in the material body, mantra is an instrument that arrests the restlessness of the mind and makes it still.  So, it is just the parallel of Aasanas, but for mind.  When mind is noisy, disturbed, opinionated, critical, reactive, or simply addicted to sensory sources of stimulation and entertainment, it squanders and dissipates lot of vital energy generating lot of negative thought and emotional patterns of fear, perverted desires, hatred etc…in the mental field.  All of these ultimately affect the circulation of Prana.  Just like aasanas, Mantra practice gradually calms the mind and eventually stills the mind.  Once the composure is achieved, the mind becomes silent, concentrated and reflective.  This naturally leads to meditation, and gives us focus and energy to go beyond the mind.[4]  This is Mantra Yoga.  All yogic methods – Hathayoga, Jnana Yoga, Bhakti Yoga etc… employ Mantras to prepare the mind for deeper practices.

My Personal Observations

  • So, one of the things that I found strikingly similar between Homeopathy, Hathayoga and Mantrayoga is that all address the vital force to remove obstruction and ensure freely circulating Prana.
  • Another thing that I observed is that what we call resonance in physics, the Mantras are also based on resonance to remove vital-force disturbances, the अंगस्पर्श (Angasparsha – touching different parts of body – See section Aspirated in this post) of Tantra yoga and  Homeopathy is based on Law of Similars to remove vital-energy disturbances caused by the disease-energy, to me this is also a form of resonance…so I’m wondering whether the inner movement behind external forms of resonance are similar?  That is a topic of my personal interest and research…

References

  1. Looking from Within –  A seeker’s Guide to Attitudes for Mastery and Inner Growth. Ed. A. S. Dalal
  2. Homeopathy – The Science and Art of Healing – Dr. Sharad Shah.
  3. The Synthesis of Yoga – Chapter XXVII – Hathayoga pp 506-513, Sri Aurobindo
  4. Mantra Yoga and Primal Sounds – Dr. David Frawley (Pt. Vamadeva Shastri)
  5. NAMAH Journal, Vol. 20, Issue 2, 15th July 2012.  Sri Aurobindo Society.
  6. Three Truths of Well-Being – Sadhguru

Agile India 2018 Conference


Announcing the 14th edition of Agile India Conference with brand new themes and a fabulous lineup of speakers. Agile India is Asia’s Largest & Premier International conference on Leading Edge Software Development Methods.

Meet:

  • Alan Cooper – The Father of Visual Basic, Creator of Goal-directed Design methodology and inventor of the Persona concept
  • Steve Denning – Author of several books on Management, Leadership, Innovation and Organizational Storytelling
  • Linda Rising – Author of four books, most recently the Fearless Change
  • Gregor Hohpe – Author of Enterprise Integration Patterns. Technical Director at Google Cloud Computing
  • James Stewart – Co-founder of the Government Digital Service and x-Deputy CTO of the UK Government
  • Bjarte Bogsnes – Author of Implementing Beyond Budgeting, Chairman of Beyond Budgeting Roundtable and Senior Advisor Performance Framework at Statoil
  • Dr. Denis Bauer – Team Leader and Research Scientist in Cloud Computing in Transformational Bioinformatics at CSIRO
  • Jeff Patton – Author of User Story Mapping and the person responsible for bringing user-centered design thinking to Agile world
  • And 70 more thought leaders from 14 countries

The program spreads across 8 days (March 5-11th 2018, Bengaluru) with two pre-conference plus two post-conference workshop days and four days of conferences in between:

  • March 4-5th: Pre-Conference Workshops from our international experts
  • March 6th: Business Agility Day – Hosted by Agile Alliance
  • March 7th: Design Innovation Day – Hosted by Cooper
  • March 8th: Digital Transformation Day
  • March 9th: DevOps and Continuous Delivery Day – Hosted by Red Hat
  • March 10-11th: Post-Conference Workshops from our international experts

Schedule: Check out conference schedule for the lineup of workshops and speakers.

Tickets: Conference registration is now open and Smart Price offers are going away soon. Register now for best deals!!

Check out the exciting offers for bulk registrationshttps://2018.agileindia.org/agile-india-2018-bulk-booking-offers/.

Sponsors: We thank Scrum.org, AddTeq/Atlassian, Scaled Agile, ICAgile and Scrum Alliance for sponsoring the conference.

If your organization wants to support this non-profit, volunteer-run conference, please check out sponsorship options.

Look forward to meeting you at the conference!!

Paradigms CodeJugalbandi


This year at Functional Conf 2017, Morten Kromberg, CXO of Dyalog Ltd. and myself presented CodeJugalbandi again. The theme was about exploring paradigms. We looked at Object-Oriented, Functional Programming and Array-Oriented Paradigms solving the same problem statement. Given the 45 mins time-frame, we were able to Jugalbandi first 2 melodies. Conversations between two artists can be viewed by clicking the links below, or you can simple watch the embedded Youtube video herein.

Melody Name Paradigms Explored Languages Used
Control Flow and Data-Driven Imperative, Functional Programming and Array-Oriented Paradigms Haskell and APL
Abstractions and Transparency Object-Oriented, Functional Programming and Array-Oriented Paradigms JavaScript and APL
Macro and Micro Functional Programming and Array-Oriented Paradigms Scala and APL

 

 

Slides are simply an index to the melodies.

Functional Conf 2017 – Last Chance to Register – Bangalore – Nov 16-19


Functional Conf is a premier conference on Functional Programming. Since its origin, back in 2014, this event has been a melting-pot for functional programmers from around the world. Currently, functional programming is at the heart of every new generation programming technology and diverse companies are employing functional programming to actuate more effective, robust, and flexible software development. This has given birth to an extremely vibrant community of functional programmers. We are thrilled to partner with GreyOrange, Go-Jek, Erlang Solutions and Dyalog, who share our vision and enthusiasm to foster a community of functional programmers.

This 4th edition of Functional Conf will see participation from 137+ Companies from 13 countries. The conference program contains 45 sessions from 37 speakers covering functional programming in 17 languages – apl, csharp, elixir, elm, erlang, eta, fsharp, haskell, idris, java, javascript, ocaml, php, purescript, rust, scala and swift.

Register at https://confengine.com/functional-conf-2017/register

Agenda:

  • Nov 16th – Pre-Conference workshops
  • Nov 17th – Erlang and Elixir Factory Lite India (First time in India)
  • Nov 18th – Functional Conf
  • Nov 19th – Post-Conference workshops

Pre/Post Conference Workshops:

Nov 16th:

Nov 19th:

Full conference schedule: https://confengine.com/functional-conf-2017/schedule

Dots and Boxes Game in Erlang


I remember playing this pencil and paper game as a kid and it served as a good past-time.

The rules for this game are very simple. The game is very well described here, but I have jotted them here for inline view

  • game begins with empty grid of dots
  • players take turns at adding a horizontal or vertical line between two un-joined adjacent dots
  • a player who completes the fourth side of a 1×1 box earns a point, writes their initials in the box and gets another turn.
  • game is over when there are no more lines that can be placed
  • winner is the player with most boxes
  • the board can be of any size 2×2, 5×5 works well for experts

I’ve coded this game in Erlang, both Sequential and Concurrent. Below is the game output resulting from auto play.

1> dots_and_boxes:auto_play(["foo", "bar"],3,3).
+   +   +

+   +   +

+   +   +

"foo" playing...
+   +   +

+   +   +

+   +---+

"bar" playing...
+   +   +
        |
+   +   +

+   +---+

"foo" playing...
+   +   +
|       |
+   +   +

+   +---+

"bar" playing...
+   +   +
|       |
+---+   +

+   +---+

...
...
...

"bar" playing...
+---+---+
|foo|foo|
+---+---+
|bar|bar|
+---+---+

*** Game Over ***
Game has Drawn!!
Detailed Results: [{"foo",2},{"bar",2}]

Implementation in Sequential Erlang

The entire module is broken down into following groups of functions:

  1. Core functions related to actual playing of the game: Set-up the game and players. Play one player at a time, manually. Functions used for manual play are: dots/2, boxes/1, join/4. In case you want to render the game on screen, use draw/1.
    -module (dots_and_boxes).
    -export ([dots/2, boxes/1, join/4, draw/1, auto_play/3]).
    
    -type point() :: {integer(),integer()}.
    -type line() :: {atom(), point(), point(), boolean()}.
    -type dots() :: [point()].
    -type box() :: {atom(), [line()], string()}.
    -type grid() :: [box()].
    
    -spec dots(integer(), integer()) -> dots().
    dots(XDots, YDots) ->
      [{X,Y} || X <- lists:seq(0, XDots - 1), Y <- lists:seq(0, YDots - 1)].
    
    -spec boxes(dots()) -> [box()].
    boxes([]) -> [];
    boxes(Ds) -> boxes(Ds, 1, length(Ds), []).
      
    boxes(Dots, Begin, End, Bs) when Begin =< End ->
      Dot = lists:nth(Begin, Dots),
      BoxPts = box_points_for(Dot),
      case all_present(BoxPts, Dots) of
        true -> 
          B = {box, lines(BoxPts), []},
          boxes(Dots, Begin + 1, End, [B | Bs]);
        false -> 
          boxes(Dots, Begin + 1, End, Bs)
      end;
      
    boxes(_,_,_,Bs) -> lists:sort(Bs).
      
    all_present(BoxPts, Pts) -> BoxPts -- Pts == [].
      
    box_points_for(BottomLeft) ->
      {X1, Y1} = BottomLeft,
      BoxSize = 1,
      X2 = X1 + BoxSize, Y2 = Y1 + 1,
      BottomRight = {X2, Y1},
      TopRight = {X2,Y2},
      TopLeft = {X1,Y2},
      [BottomLeft,TopLeft,TopRight,BottomRight].
    
    lines([BottomLeft,TopLeft,TopRight,BottomRight]) ->
      %clockwise lines in a box
      [{line,BottomLeft,TopLeft,false}, 
       {line,TopLeft,TopRight,false}, 
       {line,TopRight,BottomRight,false}, 
       {line,BottomRight,BottomLeft,false}].  
      
    -spec join(point(),point(),string(),grid()) -> {grid(), boolean()}.
    % return pair contains a boolean to indicate
    % take another turn for the last player.
    join(D1, D2, Player, Grid) ->
      NextG = [mark_box(B,D1,D2,Player) || B <- Grid],
      {NextG, was_box_signed(Grid, NextG)}.
    
    was_box_signed(PrevG, NextG) ->
      PPs = [B || B <- PrevG, signed_box(B)],
      NPs = [B || B <- NextG, signed_box(B)],
      length(NPs) - length(PPs) == 1. 
    
    signed_box({box,_,P}) -> P /= [].
    
    % 4 arg mark_box
    mark_box(B = {box,Lines,[]}, D1, D2, Player) ->
      PlayerLine = {line,D1,D2,false},
      case contains(PlayerLine, Lines) of
        true -> signBox(mark_box(D1,D2,B), Player);
        false -> B
      end;
      
    mark_box(Box,_,_,_) -> Box.
    
    signBox(MBox = {box,MLines,_}, Player) ->
      case fourth_side_complete(MBox) of
        true -> {box,MLines,Player};
        false -> MBox  
      end.
    
    % 3 arg mark_box
    mark_box(D1, D2, {box,Lines,[]}) ->
      MLines = lists:map(fun 
        ({line,A,B,false}) when ((A==D1) and (B==D2)) -> join_dots(D1, D2);
        ({line,A,B,false}) when ((A==D2) and (B==D1)) -> join_dots(D2, D1); 
        (Line) -> Line
      end, Lines),
      {box,MLines,[]}.
    
    contains(_, []) -> false;
    
    contains(Line = {line,A,B,false}, [L|Ls]) ->
      case L of 
        Line -> true;
        {line,P,Q,false} when (A==Q) and (B==P) -> true;
        _ -> contains(Line, Ls)
      end.
      
    fourth_side_complete({box,Lines,_}) ->
      lists:all(fun({line,_,_,Marked}) -> Marked == true end, Lines).
      
    join_dots({X,Y1}, {X,Y2}) when abs(Y2-Y1) == 1 -> 
      {line,{X,Y1},{X,Y2},true};
    join_dots({X1,Y}, {X2,Y}) when abs(X2-X1) == 1 -> 
      {line,{X1,Y},{X2,Y},true};
    join_dots(_, _) ->
      badarg.
    
  2. Auto-play functions: Set-up the grid and players, call auto_play/3 and watch the game run to completion. auto_play/3 uses draw/1 function.
  3. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
    % All Auto Play related functions
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
    
    -spec auto_play([atom()], integer(), integer()) -> [any()].
    auto_play(Players, XDots, YDots) when (XDots >= 2) and (YDots >= 2) and (length(Players) >= 2) ->
      Grid = boxes(dots(XDots, YDots)),
      % io:format("Initial Grid = ~p~n", [Grid]),
      draw(Grid),
      play(Players, Grid, fun() -> rand_dots_pair(XDots, YDots) end);
    
    auto_play(_, _, _) ->
      io:format("Choose more than 2 players and have number of dots in X and Y direction as atleast 2!~n").
        
    play(Players, Grid, RandF) ->
      case game_over(Grid) of
        true -> show_results(Grid);
        false -> continue_play(Players, Grid, RandF)
      end.
      
    continue_play(Players = [P|Ps], G, RandF) -> 
      io:format("~p playing...~n", [P]),
      {NextG, SamePlayerTurn} = turn(P, G, RandF),
      draw(NextG), 
      case SamePlayerTurn of 
        true -> 
          io:format("~p taking another turn!~n", [P]),
          play(Players, NextG, RandF);
        false -> 
          play(lists:append(Ps,[P]), NextG, RandF)
      end.
    
    show_results(Grid) ->
      All = [{Winner, Score}|Losers] = results(Grid),
      io:format("*** Game Over ***~n"),
      case lists:keymember(Score, 2, Losers) of
        true -> io:format("Game has Drawn!!~n");
        false -> io:format("Winner => ~p~n", [Winner])
      end,
      io:format("Detailed Results: ~p~n", [All]).
    
    results(Grid) ->
      Ps = [P || {box,_,P} <- Grid],
      Rs = frequency(Ps),
      lists:reverse(lists:keysort(2, Rs)).
        
    game_over(Grid) -> 
      lists:all(fun signed_box/1, Grid).
      
    frequency(Xs) -> frequency(Xs, []).
    frequency([], Acc) -> Acc;
    frequency(Xs = [X|_], Acc) -> 
      {Ys,Ns} = lists:partition(fun(E) -> E == X end, Xs),
      frequency(Ns, [{hd(Ys),length(Ys)} | Acc]).
      
    turn(Player, Grid, RandomF) ->
      {D1,D2} = RandomF(),
      case line_not_exists(D1, D2, Grid) of
        true -> join(D1, D2, Player, Grid);
        false -> turn(Player, Grid, RandomF)
      end.
    
    line_not_exists(D1, D2, Grid) ->
      Line = {line,D1,D2,false},
      GLines = lists:foldr(fun({box, Lines, _}, A) -> lists:append(A, Lines) end, [], Grid),
      contains(Line, GLines).
      
    rand_dots_pair(XDots, YDots) ->
      D1 = rand_dot(XDots,YDots),
      D2 = rand_dot(XDots,YDots),
      case distance(D1, D2) == 1 of
        true -> {D1,D2};
        false -> rand_dots_pair(XDots, YDots)
      end.
    
    distance({X1,Y1}, {X2,Y2}) -> 
      math:sqrt((X2-X1)*(X2-X1)+(Y2-Y1)*(Y2-Y1)).
      
    rand_dot(XDots,YDots) -> {rand(XDots),rand(YDots)}.
      
    rand(N) when N >= 2 -> rand:uniform(N) - 1.
    
  4. ASCII drawing related functions: This is the main function draw/1 which consumes the grid to be drawn. The way it does this is by creating raster lines from grid data and renders it on screen as ASCII art. Game lines are partitioned as horizontal lines and vertical lines. For example – In a box, a horizontal line is one that joins two dots horizontally and a vertical line is on that joins two dots vertically. Rasterize renders the game with alternating horizontal and vertical lines. In the process, it also renders player initials (first 3-letters) inside a box, if that box belongs to the player.
  5. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % All drawing related functions
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    rasterize(Grid) ->
      GridLines = lists:flatmap(fun(B) ->
         annotate_lines(B) 
      end, Grid),
      Lines = lists:filter(fun({_,Aligned,_}) ->
        Aligned /= vertical_left_ignore
      end, GridLines),
      {HLines,VLines} = lists:partition(fun({_, Aligned, _}) -> Aligned == horizontal end, Lines),
      SortedHLines = lists:usort(HLines),
      {{_,_,{X,Y},_},_,_} = lists:last(SortedHLines),
      rasterize([], 0, 0, X, Y, SortedHLines, VLines).
    
    rasterize(Acc, _, _, _, _, [], []) -> Acc;
    
    rasterize(Acc, _, _, _, _, HLines, []) -> 
      lists:append(Acc, [[HLines,[]]]);
    
    rasterize(Acc, X, Y, XMax, YMax, HLines, VLines) when (X =&lt; XMax) or (Y =
      {Hs,HLs} = lists:partition(
        fun({{_,{_,Y1},{_,Y2},_},_,_}) -> 
          (Y1 == Y) and (Y2 == Y) 
        end, HLines),
      {Vs, VLs} = lists:partition(
        fun({{_,{_,Y1},{_,Y2},_},_,_}) -> 
          (Y == Y1) and (Y2 == (Y + 1)) 
        end, VLines),
      NewAcc = lists:append(Acc,[[Hs,lists:sort(Vs)]]),
      rasterize(NewAcc,X+1,Y+1,XMax,YMax,HLs,VLs).
      
    -spec annotate_lines(box()) -> [any()].
    annotate_lines(B) ->
      {box,[VLeft,HUpper,VRight,HLower],TakenBy} = B,
      [
        {sort_line(HLower),horizontal, []},
        {sort_line(VRight),vertical_right, TakenBy},
        {sort_line(HUpper),horizontal, []},
        case VLeft of
          {line, {0, _}, {0, _}, _} -> 
            {sort_line(VLeft),vertical_first_col, []};
          _ ->
            {sort_line(VLeft),vertical_left_ignore, []}
        end
      ].
      
    sort_line({line, D1, D2, Present}) when D1 > D2 ->
      {line, D2, D1, Present};
    sort_line(L) -> L.
        
    draw(Grid) ->
      % io:format("Grid = ~p~n", [Grid]),
      RasterLines = rasterize(Grid),
      % io:format("RasterLines = ~p~n", [RasterLines]),
      lists:foreach(fun([RLines, CLines]) ->
        draw_row_lines(RLines),
        draw_col_lines(CLines)
      end, RasterLines).
    
    draw_row_lines(Lines) ->
      lists:foreach(fun(Line) -> 
        case align(Line) of
          horizontal -> io:format("+---");
          horizontal_blank -> io:format("+   ")
        end 
      end, Lines),
      io:format("+~n").
                     
    draw_col_lines(Lines) ->
      lists:foreach(fun(Line) -> 
        case align(Line) of
          {vertical_blank, first_column} ->     
            io:format(" ");
          {vertical, first_column} -> 
            io:format("|");
          vertical_blank -> 
            io:format("    ");
          vertical -> 
            io:format("   |");
          {vertical, TakenBy} -> 
            io:format("~3s|", [TakenBy])
        end
      end, Lines),
      io:format("~n").
      
    align({Line, vertical_first_col, _}) ->
      case Line of
        {line,_,_,false} ->
          {vertical_blank, first_column};
        {line,_,_,true} ->
          {vertical, first_column}
      end;
    
    align(LInfo = {_, vertical_right, TakenBy}) ->
      case LInfo of 
        {{line,_,_,false},_,_} -> vertical_blank;
        {{line,_,_,true},_,[]} -> vertical;
        {{line,_,_,true},_,TakenBy} -> {vertical, TakenBy}
      end;
    
    align({Line, horizontal, _}) -> 
      case Line of
        {line,_,_,false} -> horizontal_blank;
        {line,_,_,true} -> horizontal
      end.
    
  6. Generic functions: zip two lists using a function, transpose a matrix and find index of an item
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Generic functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

zipwith(F, Xs, Ys) ->
  zipwith(F, [], Xs, Ys).

zipwith(_F, Acc, [], []) -> Acc;  
zipwith(_F, Acc, _Xs, []) -> Acc;  
zipwith(_F, Acc, [], _Ys) -> Acc;    
zipwith(F, Acc, [X|Xs], [Y|Ys]) ->
  zipwith(F, lists:append(Acc, [F(X,Y)]), Xs, Ys).

transpose([[]|_]) -> [];
transpose(M) ->
  [lists:map(fun hd/1, M) | transpose(lists:map(fun tl/1, M))].
    
index_of(Item, List) -> 
  index_of(Item, List, 1).

index_of(_, [], _) -> not_found;
index_of(Item, [Item|_], Index) -> Index;
index_of(Item, [_|Tl], Index) -> index_of(Item, Tl, Index + 1).

All the Erlang code is available in this repository https://github.com/DhavalDalal/Dots-And-Boxes-Erlang

Implementation in Concurrent Erlang

The activities of playing a game and rendering are completely different and can happen in different processes. To that end, there are two server processes, one for playing the game, a.k.a. game_server and another for rendering the game as a text ui, a.k.a render_server.

These are both supervised using a game_supervisor. Game client(s) talk to the supervisor. The supervisor routes the request either to the game server or the render server appropriately.

             
                      +-------------------------------+
                      |                               |
                      |                          +----------+ 
                      V                         /|  Render  |
+--------+      +----------+                   / |  Server  |
|  Game  |----->|   Dots   |      +----------+/  +----------+
| Client |      |   And    |----->|   Game   |
|  1..n  |<-----|  Boxes   |      |Supervisor|    
+--------+      +----------+      +----------+\  +----------+
                 Game ^             Router     \ |   Game   |   
                      |                         \|  Server  |  
                      |                          +----------+ 
                      |                               |
                      +-------------------------------+

In case any of the servers die, they are restarted by the supervisor. If a game_server dies all the clients associated with it die too (as the game server maintains games for all the clients and is thus carries state). However, if a render_server dies, no clients are affected and is also restarted by the supervisor.

Note: I’ve done Custom Server implementation, and next is Gen Server implementation that I plan to do next.