Summary of SICP Chapter 1

sicp

The contrast between function and procedure is a reflection of the general distinction between describing properties of things and describing how to do things, or, as it is sometimes referred to, the distinction between declarative knowledge and imperative knowledge. In mathematics we are usually concerned with declarative (what is) descriptions, whereas in computer science we are usually concerned with imperative (how to) descriptions.

SICP is a book by Harold Abelson, Gerald Jay Sussman and Julie Summnan used in introductory course at MIT. I started reading the same book one month before. now completed 1st chapter. i want to share what i learned from it. It was very fun and i enjoyed a lot. I believe lot of its readers also enjoyed a lot. that’s why this book got lot of attention in the past decades. Book was published on 1984. Online version of the book is available at https://mitpress.mit.edu/sicp/full-text/book/book.html and you can download as pdf.

SICP contains 5 chapters:

  1. Building Abstractions with Procedures
  2. Building Abstractions with Data
  3. Modularity, Objects and State
  4. Metalinguistic Abstraction
  5. Computing with Register Machines

I will tell what i learned from first chapter in the this article

I presume that you are familiar with atleast one language. SICP teach with Lisp. Lisp mostly considered as academic language, not a mainstream language. See what book says about the evolution of Lisp:

Lisp was not the product of a concerted design effort. Instead, it evolved informally in an experimental manner in response to user’s needs and to pragmatic implementation considerations

You may wonder if you see the syntax of the  Lisp, it is in a prefix style. let me give an example how we write same expression in C and Lisp

In C :   a = b*5 + c – 6;

In Lisp : (define a (+ (* b 5) (- c 6)))

A quick demo of Lisp syntax will get from http://learnxinyminutes.com/docs/common-lisp/

You will understand how syntax works after do some little programs in Lisp.

Every powerful languages will have the following things:

  • Primitive expression: Which is simplest things we can do with language, as it’s name says.
  • Means of combination: Using the primitive expressions we can create complex entities.
  • Means of Abstraction: Compound entities can be named and manipulated as units.
Sample  primitive expressions in Lisp:

512                     ; a number
(+ 4 3)                 ; adding two numbers
(- 10 5)                ; subrtacting 5 from 10
(* 5 6)
(/ 8 2)

more complex one:

(+ (* 3 (+ (* 2 4) (+ 3 5))) (+ (- 10 7) 6))
 = 3 * ((2 * 4) + 3 + 5)  + 10 - 7 +6
 
for naming an object use "define"

a = 5 can be written in Lisp as (define a 5)
(define pi 3.14)

This chapter insist us to think procedurally.  Lisp interpreter itself use th following procedure to evaluate compound expressions

1. Evaluate the sub expressions of the combination
2. Apply the procedure  that is the value of the left most sub expression(the operator) to the arguments that are the values of other sub expressions(the operands).

in (+ 2 3) left most sub expression is ‘+’ which is operator other two sub expressions ‘2’ and ‘3’ are operand. it is clear that + is a primitive procedure and 2, 3 are primitive data.

Evaluation models is recursive, because it is obvious that one sub expression may other compound expression. we can represent it like a tree. book explain about it very well.

We can define our own procedures.

See an example of cube procedure

(define (cube x) (* x x x))

(cube 2) will return 8.

some of cube of two numbers can found by like (+ (cube 3) (cube 4)).

general form of procedure definition is

(define (<name> <formal parameters>) <body>)

First chapter introduce two types of evaluation model. Normal order and Applicative order.
Normal order: which is fully expand expression until it involves only premitive expression and evaluate
Applicative order: It evaluates arguments first and apply procedure. Interpreter itself using this method.

Authors explain about it very well in the book, read book to understand how those works very well, they demonstrate it with images.

Conditional expressions

Conditional expression is to execute some code block depend on some test. there are two types of conditional structures in lisp
1. if statement perform different operations depend on the result of the test
2. cond statement can be considered as case in many language. we can specify unlimited number of tests and their operations if test is true.

Example

(if (= 1 0)   -> test expression
    (+ 2 4)   -> execute if true
    (- 4 2))  -> execute if false
    
(cond ((> 2 2) (error "wrong!"))
      ((< 2 2) (error "wrong again!"))
      ((= 2 2) 'ok')) ; => 'OK

SICP demonstrating concepts with interesting problems like finding roots with newton’s method and at the end of the each sections there are lot of excersise to do. You can see my solutions to the excersise problems of chapter 1 at https://github.com/faisalp4p/sicp/tree/master/ch1

Procedures as black box Abstraction

Explaining power of procedure is the main goal of this chapter. even name of the chapter is ‘Building Abstractions with Procedures’. Procedures can be considered as a Black box. which will take some parameters as input, process it and produce output. For example sqrt is a procedure which take a number x and produce square root of x. once we build sqrt procedure we don’t need to do the same procedure, instead we can call sqrt procedure  by its name and the number as argument. We can have procedure definitions inside a procedure, that is we can combine as much as functions to produce another procedure. sqrt function is recursive in nature, because same function call itself. this function tell us a lot of interesting things about recursion. see there is no looping statement in Lisp, we do procedures which need loop with recursive calls. and chapter keep explaining about tail recursion and tree recursion. tree recursion explain using a procedure to generate Fibonacci series. Through out the chapter we meet interesting problems.

sqrt procedure:
(define (average x y)
  (/ (+ x y) 2))

(define (good-enough? guess x)
  (< (abs (- (square guess) x)) 0.001))

(define (improve guess x)
   (average guess (/ x guess)))

(define (sqrt-iter guess x)
  (if (good-enough? guess x)
      guess
      (sqrt-iter (improve guess x)
                 x)))

(define (sqrt x)
  (sqrt-iter 1.0 x))

(sqrt 9)
3.00009155413138

Order of Growth

Process consume computational resources. order of growth is one of the notation to describe rate of consumption. You may familiar with Big O notation. this sesion explain details about what is order of growth and how we can measure order of growth of a procedure.

Chapter goes through Exponentiation, Greatest common divisor, primality test etc. different methods to solve problems in such domains and how we can optimize that using different tricks.

Higher order functions

This section describes about abstraction with higher order function. Power of a procedure for abstraction will extend considerably if we can accept a procedure as argument and procedure as return value.

We can pass procedure as argument. consider a situation we need find out sum of square of two numbers. after that we have to compute sum of cube of two numbers. above two procedures are some what similar. consider a procedure which take two numbers and a function as arguments that will return sum of those numbers applied to the function received as argument.

we can create anonymous function using lambda keyword. which helps to produce a procedure without name and pass as arguments or as a return value.

Procedures as return value

Now procedure as return value. we can also retrieve a procedure as a return value and use that function. section explain procedure as return value using newton’s method to find roots of numbers with the help of fixed-point function. and there are lot of problem related to this in the exercise part.

At last chapter says, in Lisp procedure is a first-class object. that is we can consider procedures like other first class objects like numbers and string. that’s why can pass and return procedure like numbers and other primitive types.

Links

SICP index : https://mitpress.mit.edu/sicp/full-text/sicp/book/

My solutions for the exercises : https://github.com/faisalp4p/sicp

Quick reference of Lisp language : http://learnxinyminutes.com/docs/common-lisp/

Why you should write a port of SLANGFOR.NET in any language

Have you ever wondered about how write a compiler? and still you don’t have any idea about it? If your answer is ‘Yes’ this article is for you.
I was also very curious about it and feared reading Dragon books :P. But i met a guy called Praseed Pai(http://praseedp.blogspot.com) who just told me that ‘Compiler is just another program’ :). He started a project in 2010 called SLANGFOR.net which is hosted at codeplex(http://slangfordotnet.codeplex.com). This project is an attempt to teach compiler construction by writing a small compiler. It is written in C#, and documented well to understand. Documentation is orgonized in 7 steps. Initial steps are dealing with arithmetic expressions and following steps play with variable declaration, assignment operations, control structures like conditions and loops and finally function. It will not help you to understand big theories behind compiler construction and all. but i swear at least you will get a confidence to write your own DSL.

Recently i ported SLANGFOR.net to Python. only interpreter part, still need to write a backend. project is hosted on github (https://github.com/faisalp4p/slang-python)
I have leaned lot of things by doing this. such as Lexical Analysis, AST, Recursive Descent Parsing, DSL. I took only six days to port it. may be because of the simplicity of python. After that we discussed about it and he gave some more ideas like how we can change it to support dictionaries and Object Oriented programming.

So i recommend you to port SLANGFOR.net to any language if you want to learn
some lessons in compiler construction.

NoUniversity

I am doing a graduation in “Learn by Sharing” from No University.

wired?

NoUniversity(http://nouniversity.github.io/) is nothing but a group of young technology lovers from Startup Village(http://www.startupvillage.in/). They are gathering every week. what they are doing is “Learn by Sharing”. As of now we had 3 meetings, and it was interesting as expected. Vision of the group is to learn and share what we know and lets contribute to open source community.

In the past meetups we had sessions on Python, Ruby, Git etc.. and we are planned to do some projects to learn open source collaboration.

I will update about what is happening at NoUniversity! Keep an eye on it 🙂

PyQt/PySide – Music Player in 10 minutes

Nowadays creating an application is not a tedious task. everyone can create one with little effort.

I am going to tell you about how i wrote a simple music player in 10 minute using python.

Qt
Qt is a Cross platform C++ application development framework. K Desktop environment (KUBUNTU) is made using Qt. Qt provides interface for GUI Programming, Database, Threading, Networking, OpenGL etc. I never seen such a good cross platform framework. It support both Desktop and Mobile platforms.

Python + Qt = PyQt

We can do Qt application development using Python. Because python is such a language we can extend its feature by binding existing C, C++ libraries. So i am going to tell you how i created a music player with a little time using PySide.

Note :  There is PyQt and PySide. Both are different bindings for Qt framework. No much difference between them. PySide not support Qt5 but PyQt. for the sake of understanding tutorial consider PySide==PyQt.

Requirements:

QtCreator – To create interface (GUI)
PySide – Python package to develop music player
pyside-tools – To convert GUI file(.ui) to .py
pyside-phonon  – Manage audio files

1. Start Desiner Form using QtCreator. Name it ‘musicplayerUI.ui

2. Design a form for the music player. mine was:

snap2

3) Convert musicplayerUI.ui to musicplayerUI.py using the following command:

pyside-uic musicplayerUI.ui > musicplayerUI.py

4) Create a python file called “musicplayer.py” to implement music player, which contains:

import sys
from PySide.QtCore import *
from PySide.QtGui import *
from musicplayerUI import *

from PySide.phonon import Phonon

class AudioPlayer(QMainWindow, Ui_MusicPlayer):

    def __init__(self, parent=None):

        super(AudioPlayer, self).__init__(parent)
        self.setupUi(self)
        self.actionOpen.triggered.connect(self.open)
        self.actionQuit.triggered.connect(self.quite)
        self.horizontalSlider.setValue(0)
        self.horizontalSlider.setEnabled(False)
        self.horizontalSlider.sliderReleased.connect(self.slider_value_change)
        self.button.clicked.connect(self.play_or_pause)
        self.button.setText("Play")
        self.button.setEnabled(False)
        self.media_obj = Phonon.MediaObject(self)
        self.current_time = 0

    def play_or_pause(self):
        if Phonon.State.PlayingState == self.media_obj.state():
            self.media_obj.pause()
            self.button.setText("Play")
        elif Phonon.State.PausedState == self.media_obj.state():
            self.media_obj.play()
            self.button.setText("Pause")

    def slider_value_change(self):
        value = self.horizontalSlider.value()
        print value
        self.media_obj.seek(value)

    def open(self):
        dialog = QFileDialog()
        dialog.setViewMode(QFileDialog.Detail)
        filename = dialog.getOpenFileName(self,
             'Open audio file', '/home',
             "Audio Files (*.mp3 *.wav *.ogg)")[0]
        self.audio_output = Phonon.AudioOutput(Phonon.MusicCategory, self)
        Phonon.createPath(self.media_obj, self.audio_output)
        self.media_obj.setCurrentSource(Phonon.MediaSource(filename))
        self.media_obj.tick.connect(self.time_change)
        self.media_obj.totalTimeChanged.connect(self.total_time_change)
        self.media_obj.play()
        self.button.setEnabled(True)
        self.button.setText("Pause")
        self.horizontalSlider.setEnabled(True)

    def time_change(self, time):
        if not self.horizontalSlider.isSliderDown():
            self.horizontalSlider.setValue(time)

    def total_time_change(self, time):
        self.horizontalSlider.setRange(0, time)

    def quite(self):
        sys.exit()



if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = AudioPlayer()
    window.show()
    sys.exit(app.exec_())

5. Run musicplayer.py file. You can play music. enjoy!

I think program is self explanatory. Leave a comment if you have any queries, may i can help you!

Source : https://github.com/faisalp4p/MusicPlayerDemo

Thanks!

My first android application

Mostly i am a server guy. But i had a dream to learn and write android applications. Fortunately i got a chance to write an application recently. it was for my friend. A single screen application for a demo to open and close gate via Bluetooth.

GateRunnr

He gave me a Bluetooth module and an arduino micro controller for testing.

bm

* Bluetooth module(sunrom.com)

arduino

* Bluetooth module connected to arduino

I learned anroid application development from offical documentaion(http://developer.android.com/training/index.html).
There is a pretty cool Bluetooth interfacing API in android http://developer.android.com/guide/topics/connectivity/bluetooth.html

There is only a single activity, because it was a single screen app. Source code is available on the github (https://github.com/faisalp4p/GateRunnr). Code is self explanatory, i am putting some code here.

public class ControllerActivity extends ActionBarActivity {

    protected BluetoothAdapter ba;
    private Set<BluetoothDevice> pairedDevices;
    private BluetoothSocket sock;
    private OutputStream bt_stream;
    private BluetoothDevice device_to_connect;

    private byte[] OPEN_SIGNAL;
    private byte[] CLOSE_SIGNAL;
    private byte[] STOP_SIGNAL;

    int REQUEST_ENABLE_BT = 0;

    boolean bluetooth_denied = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        device_to_connect = null;
        bt_stream = null;
        sock = null;
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_controller);
        getSupportActionBar().hide();
        Typeface roboto_thin = Typeface.createFromAsset(getAssets(), "fonts/Roboto-Thin.ttf");
        Button open_button = (Button)findViewById(R.id.open_button);
        Button close_button = (Button)findViewById(R.id.close_button);
        Button stop_button = (Button)findViewById(R.id.stop);

        open_button.setTypeface(roboto_thin);
        close_button.setTypeface(roboto_thin);
        stop_button.setTypeface(roboto_thin);

        TextView header = (TextView)findViewById(R.id.header);
        TextView sub_header = (TextView)findViewById(R.id.sub_header);
        Typeface pirulen = Typeface.createFromAsset(getAssets(), "fonts/pirulen.ttf");
        header.setTypeface(pirulen);
        sub_header.setTypeface(pirulen);


        OPEN_SIGNAL = "o".getBytes();
        CLOSE_SIGNAL = "c".getBytes();
        STOP_SIGNAL = "s".getBytes();


    }


    @Override
    public void onResume() {
        super.onResume();
        ba = BluetoothAdapter.getDefaultAdapter(); //getting bluetooth adapter

        if (ba == null) {
            //Device not support bluetooth
            Toast.makeText(getApplication(), "Device not support bluetooth", Toast.LENGTH_LONG).show();
        }

        if (!ba.isEnabled()) {
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
        }
        else {
            if (!bluetooth_denied)
                setupConnection();

        }

    }

    public void setupConnection() {

        pairedDevices = ba.getBondedDevices();
        for(BluetoothDevice bt: pairedDevices) {
            if(bt.getName().equals("linvor")) { // replace "linvor" with your bluetooth name
                device_to_connect = bt;
                System.out.println("Linvor found");
                break;

            }
        }
        if (device_to_connect != null) {
            try {
                sock = device_to_connect.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
            } catch (IOException e) {
                Toast.makeText(getApplication(), "Socket cannot create", Toast.LENGTH_LONG).show();
                System.out.println("Socket creation failed");
                sock = null;
                //sock cannot create
            }
            if (sock != null) {
                ba.cancelDiscovery();
                try {
                    sock.connect();
                    System.out.println("Socket connection established");
                    bt_stream = sock.getOutputStream();
                } catch (IOException e) {
                    System.out.println("Socket connection cannot create");
                    Toast.makeText(getApplication(), "blue tooth connot connect", Toast.LENGTH_LONG).show();
                    System.out.println(e.toString());
                    //hello
                }

            }
        }

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode == REQUEST_ENABLE_BT) {
            if(resultCode == RESULT_OK) {

                setupConnection();

            }
            if(resultCode == RESULT_CANCELED) {
                bluetooth_denied = true;
                Toast.makeText(getApplication(), "Please enable bluetooth", Toast.LENGTH_LONG).show();
                finish();

            }
        }
    }

    @Override
    public void onPause() {
        super.onStop();
        if (sock != null) {
            if (sock.isConnected()) {
                try {
                    sock.close();

                } catch (IOException e) {
                    System.out.println("Socket cannot close " + e.toString());
                }
            }
            bt_stream = null;
        }
    }

    @Override
    public void onStop() {
        super.onStop();
        if (sock != null) {
            if (sock.isConnected()) {
                try {
                    sock.close();

                } catch (IOException e) {
                    System.out.println("Socket cannot close " + e.toString());
                }
            }
            bt_stream = null;
        }
    }

    public void openClicked(View v) {
        if (sock != null) {
            if(sock.isConnected()) {
                try {
                    bt_stream.write(OPEN_SIGNAL);
                    System.out.println("Open signal send");

                } catch (IOException e) {
                    System.out.println("IO error in socket " + e.toString());

                }
            }
        }
        //Toast.makeText(getApplication(), "Open Clicked", Toast.LENGTH_LONG).show();

    }

    public void closeClicked(View v) {
        if (sock != null) {
            if(sock.isConnected()) {
                try {
                    bt_stream.write(CLOSE_SIGNAL);

                } catch (IOException e) {
                    System.out.println("IO error in socket " + e.toString());

                }
            }
        }
    }

    public void onStopSignal(View v) {
        if (sock != null) {
            if(sock.isConnected()) {
                try {
                    bt_stream.write(STOP_SIGNAL);

                } catch (IOException e) {
                    System.out.println("IO error in socket " + e.toString());

                }
            }
        }
    }

}