Dylan Introduction

by "Blag" - Senior Developer Evangelist

Return to Geeky Thursday

What is Dylan?


Dynamic (Dy) Language (Lan).


Released on 1992.


Developerd by Apple for the Apple Newton computer.


Multi-paradigm, with support for functional and object-oriented programming.


How to install Dylan


We're going to use Open Dylan...an Open Source implementation.

Here's how to download and install Open Dylan


Pretty much download the file, extract it and add it to your path.

Who uses Dylan?


  • Being an internal Apple prooduct...it didn't really widespread
  • As an Open Source project, it sparks interest, but no so much...
  • Enthusiastic people maintain it and use it...

Starting out...


Dylan doesn't have a REPL :( at least not on Linux

On Windows you can say "dylan-environment" and then "play"

Comments


Comments are very simple

				
// This is a comment


/*This is 
a comment as well*/
				

Printing Output


Comments are very simple

				
format-out("%s", "Hello World");

format-out("%d", 5);
				

Variables


Variables don't need a type, but we can add it to enforce values


= is used to initialize a variable while := is used to update its value


				
//Global variables

define variable *my-var* = 7;

define variable *my-string-var* :: <string> = "Hello";


//Local Variables

define method sandbox()

    let my-var = 3;
	
    my-var := 5;
	
end method sandbox;
				

Conditionals


Dylan provides some interesting additions to the good old If

				
if(condition > 3)

    format-out("%s\n", "Yes");
    
elseif(condition < 1)

    format-out("%s\n", "Nope!");
    
end if;	
				

				
case(condition > 3) => format-out("%s\n", "Yes");

    (condition < 1) => format-out("%s\n", "Nope!");
    
    otherwise => format-out("%s\n","What?!");
    
end case;
				

				
let age = 42;

let var = "";

select(age by \<)

    13 => var := "youngster";
    
    20 => var := "teenager";
    
    60 => var := "adult";
    
    otherwise => var := "senior";
    
end select;

format-out("%s\n", var);
				

The output will be "adult"

Loops

We have "FOR" and "WHILE" available

				
let i = 0;

while(i < 5)

    format-out("%d\n", i);
	
    i := i + 1;
	
end while;
				

				
for(i from 0 below 5)

    format-out("%d\n", i);
    
end for;
				

Methods


Method can return one, multiple or no values

				
define method say-greeting(greeting :: <object>);

    format-out("%s\n", greeting);
	
end method say-greeting;
				

				
define method get-sum(a :: <integer>, b :: <integer>)

=> (sum :: <integer>)

    a + b; 
	
end method get-sum;
				

				
define method get-sum-by(a :: <integer>, b :: <integer>)

=> (sum :: <integer>, by :: <integer>)

    values(a + b, a * b); 
    
end method get-sum-by;



//let (sum, by) = get-sum-by(3, 5);

//format-out("%d%s%d\n", sum, " and ", by);
				

Arrays


Arrays are fixed in size

				
define variable *my-array* = make(<array>, size: 3);


define method arrays()

    *my-array*[0] := "A";
    
    *my-array*[1] := "B";
    
    *my-array*[2] := "C";
    
    format-out("%s\n", *my-array*);
    
end method arrays;
				

Classes


Classes are declared differently from other languages...

				
define variable *person* = make(<people>, age: 42);


define class <people> (<object>)

    slot name :: <string>;
    
    slot age :: <integer>, init-keyword: age:;
    
end class <people>;


define method sandbox()

    *person*.name := "Blag";
    
    format-out("%s%s%s%d%s\n", "My name is ", *person*.name,
    
               " and I'm ", *person*.age, " years old.");
               
end method sandbox;


sandbox();
				

Strings


The aren't too many String functions...

				
    let name = "Blag";
	
    format-out("%d\n", name.size);
	
    format-out("%s\n", name[0]);
				

First, we print how many characters do our String have...

Then we print a substring, which is in this case "B"

Fibonacci list sequence


Finally...we're going to make our first application...


A Dylan is composed of many files...


On the terminal type make-dylan-app fibonacci


Open the file fibonacci.dylan


Before we continue...


Open the file library.dylan and type the following

				
Module: dylan-user


define library fibonacci

  use common-dylan;
  
  use io;
  
end library fibonacci;


define module fibonacci

  use common-dylan;
  
  use format-out;
  
  use standard-io;
  
  use streams;  
  
end module fibonacci;					
				
				
Module: fibonacci 


define method fib

    (num :: <integer>, a :: <integer>, b :: <integer>)
    
    if(a > 0 & num > 1)
    
        format-out("%d ", a + b);
        
        fib(num - 1, a + b, a);
        
    elseif(a = 0)
    
        format-out("%d %d ", a, b);
        
        format-out("%d ", a + b);
        
        fib(num - 1, a + b, b);
        
    end if;
    
end method fib;
				
				
define method fibonacci()

    format-out("Enter a number: ");
    
    force-out();
    
    let num = read-line(*standard-input*);
    
    let (iNum, iNext) = string-to-integer(num,
    
                        base: 10,start: 0, 
                        
                        end: size(num),
                        
                        default: $unsupplied); 
    
    fib(iNum, 0, 1);
    
    format-out("\n");
    
end method fibonacci;


fibonacci();
				

To be able to run it, we need to do the following...


dylan-compiler -build fibonacci.lid

This will create an executable on _build/bin

Making an LCD Number App


This is my favorite application of all time...


Create the app and name it "led-numbers"


Add the same to library.dylan but respect the names


				
Module: led-numbers


define variable *led-table* = make(<table>, size: 10);


*led-table*['0'] := " _  ,| | ,|_| ";

*led-table*['1'] := "  ,| ,| ";

*led-table*['2'] := " _  , _| ,|_  ";

*led-table*['3'] := "_  ,_| ,_| ";

*led-table*['4'] := "    ,|_| ,  | ";

*led-table*['5'] := " _  ,|_  , _| ";

*led-table*['6'] := " _  ,|_  ,|_| ";

*led-table*['7'] := "_   , |  , |  ";

*led-table*['8'] := " _  ,|_| ,|_| ";

*led-table*['9'] := " _  ,|_| , _| ";
				
				
define method led-numbers()

    let i = 0;
    
    let val = "";
    
    let line = "";
    
    let line1 = "";
    
    let line2 = "";
    
    let line3 = "";
    
    format-out("Enter a number: ");
    
    force-out();
    
    let num = read-line(*standard-input*);
    
    while(i < num.size)
    
        line := *led-table*[num[i]];
        
        val := split(line,',');
        
        line1 := concatenate!(line1, val[0]);
				
				        
        line2 := concatenate!(line2, val[1]);
        
        line3 := concatenate!(line3, val[2]);
        
        i := i + 1;
        
    end while;
    
    format-out("%s\n", line1);
    
    format-out("%s\n", line2);
    
    format-out("%s\n\n", line3);
    
end method led-numbers;

 
led-numbers();
				

When we run it we're going to see...

Decimal to Romans


This App will create a Roman Numeral based on a decimal number


Create the app and name it "dec-to-roman"


Add the same to library.dylan but respect the names


				
Module: dec-to-roman


define variable *roman-table* = make(<table>, size: 12);

define variable *keys-array* = make(<array>, size: 12);


*roman-table*[1000] := "M";

*roman-table*[900] := "CM";

*roman-table*[500] := "D";

*roman-table*[400] := "CD";

*roman-table*[100] := "C";

*roman-table*[90] := "XC";

*roman-table*[50] := "L";

*roman-table*[40] := "XL";

*roman-table*[10] := "X";
				
				 
*roman-table*[9] := "IX";

*roman-table*[5] := "V";

*roman-table*[1] := "I";


*keys-array*[0] := 1000;

*keys-array*[1] := 900;

*keys-array*[2] := 500;

*keys-array*[3] := 400;

*keys-array*[4] := 100;

*keys-array*[5] := 90;

*keys-array*[6] := 50;

*keys-array*[7] := 40;

*keys-array*[8] := 10;

*keys-array*[9] := 9;
				
				

*keys-array*[10] := 5;

*keys-array*[11] := 1;


define method dec-to-roman()

    let break = #f;
    
    format-out("Enter a number: ");
    
    force-out();
    
    let num = read-line(*standard-input*);
    
    let (iNum, iNext) = string-to-integer(num,base: 10,
    
                        start: 0, end: size(num),
                        
                        default: $unsupplied);
				
				
    while(iNum > 0)
    
        break := #f;
        
        for(i from 0 below 12)
        
            if(iNum >= *keys-array*[i] & break = #f)
            
                format-out("%s",
                
                *roman-table*[*keys-array*[i]]);
                
                iNum := iNum - *keys-array*[i];
                
                break := #t;
                
            end if;
            
        end for;
        
    end while;
    
    format-out("\n\n");
    
end method dec-to-roman;


dec-to-roman();
				

When we run it we're going to see...

Random Names


This App will generate 100,000 random pseudo-random names using two 16 elements arrays


We will measure the runtime.


While Dylan provides a Random Function...is pseudo...so I'm using my own logic...


Create the app and name it "random-names"


Leave library.dylan the way it is...


				
Module: random-names


define variable *names* = make(<array>, size: 16);

define variable *last-names* = make(<array>, size: 16);

define variable *full-names* = make(<array>, size: 100000);


*names*[0] := "Anne"; *names*[1] := "Gigi";

*names*[2] := "Blag"; *names*[3] := "Juergen";

*names*[4] := "Marek"; *names*[5] := "Ingo";

*names*[6] := "Lars"; *names*[7] := "Julia";

*names*[8] := "Danielle"; *names*[9] := "Rocky";

*names*[10] := "Julien"; *names*[11] := "Uwe";

*names*[12] := "Myles"; *names*[13] := "Mike";

*names*[14] := "Steven"; *names*[15] := "Fanny";
				
				
*last-names*[0] := "Hardy"; 

*last-names*[1] := "Read";

*last-names*[2] := "Tejada"; 

*last-names*[3] := "Schmerder";

*last-names*[4] := "Kowalkiewicz"; 

*last-names*[5] := "Sauerzapf";

*last-names*[6] := "Karg"; 

*last-names*[7] := "Satsuta";

*last-names*[8] := "Keene"; 

*last-names*[9] := "Ongkowidjojo";

*last-names*[10] := "Vayssiere"; 

*last-names*[11] := "Kylau";
				
				
*last-names*[12] := "Fenlon"; 

*last-names*[13] := "Flynn";

*last-names*[14] := "Taylor"; 

*last-names*[15] := "Tan";


define method random-names()

    let counter = 0;
    
    let aux = 0;
    
    let ans = 0;
    
    let aux_ans = 0;
    
    let seed = 0;
    
    let aux_seed = 0;
				
				
    for(i from 0 below 99999)
    
        counter := i;
        
        let (aux,seed) = truncate/(counter, 101);
        
        seed := seed * 7;
        
        let (aux,ans) = truncate/((seed - 1), 15);
        
        ans := ans + 1;
        
        let (aux,aux_seed) = truncate/(counter, 4);
        
        aux_seed := aux_seed * 7;
        
        let (aux,aux_ans) = truncate/((aux_seed - 1), 
        
                            15);
        
        aux_ans := aux_ans + 1;
        
        *full-names*[i] := concatenate(*names*[ans], 
        
                           " ", *last-names*[aux_ans]);
				
				
    end for;
    
end method random-names;


random-names();
				

When we run it we're going to see...


I'm impressed...that was really fast -:)

Even though it was not really random...

Counting Letters


In this example we're going to read a file and count how many time a letter appears...


Name the app count-letters


Create a file called "readme.txt" with the following text...


"This is a text file that we're going to read using Dylan"


Before we continue...


Open the file library.dylan and type the following

				
Module: dylan-user


define library count-letters

  use common-dylan;
  
  use io;
  
  use system;
  
end library count-letters;


define module count-letters

  use common-dylan;
  
  use format-out;
  
  use streams;
  
  use file-system;
  
end module count-letters;					
				
				
Module: count-letters


define variable *key-letters* = make(<array>, size: 57);

define variable *key-values* = make(<array>, size: 57);


define method checkKey(key :: <character>)

=> (index :: <integer>)

    let index = 0;
    
    let break = #f;
    
    for(i from 0 below 56)
    
        if(*key-letters*[i] = key & break = #f)
        
            break := #t;
            
            index := i;
            
        end if;
        
    end for;
				
				
    
    values(index);
    
end method checkKey;


define method count-letters()

    let file-stream = make(<file-stream>, 
    
                      locator: "readme.txt",
                      
                      direction: #"input",
                      
                      element-type: <byte-character>);
                      
    let line = read-line(file-stream);
    
    let index = 0;
    
    for(i from 0 below 56)
    
        index := checkKey(line[i]);
				
				
        if(index > 0)
        
            *key-values*[index] := 
            
            *key-values*[index] + 1;
            
        else
        
            *key-letters*[i] := line[i];
            
            *key-values*[i] := 1;
            
        end if;
        
    end for;
				
				
    for(i from 0 below 56)
    
        if(*key-letters*[i] ~= #f)
        
            format-out("%s%s%s\n", *key-letters*[i], 
            
                       "-->", *key-values*[i]);
            
        end if;
        
    end for;
    

end method count-letters;



count-letters();
				

When we run it we're going to see...


Want to see something awesome?


Carl Gay is working on a Dylan Web Playground


Web Playground


And he actually included a couple of my examples...in a more idiomatic way -;)


That's it for now...


Dylan is a pretty cool language


Not so easy at first buy fun to work with...


And still surprised that I came from Apple...


Contact Information


Blag --> blag@blagarts.com

@Blag on Twitter

Go back home...