Friday, March 11, 2011

The i Programming Language - Part 1 - The Concept

Here is my idea for a new programming language. The language is called "i" for Internet, or interactive. The main difference between i  (or IPL) and other languages of today is the dynamic, or even unpredictable nature of i programs. This is achieved by using two key features:

A program written in i, every time it runs, uses:
  1. Different data. Input data is provided by Internet APIs like google search, flickr, youtube, amazon. For example when the program needs a picture of a a car, it grabs it from one of the free repositories on the Internet. Possibly, it grabs a different picture every time it runs. When a program needs encyclopedic information, it gets an article from wikipedia. When it needs a definition of a word: it uses a free dictionary or google's "define: this", when it needs a word translated, it uses translate.google.com and so on. It can use paid services too. It all depends on what libraries are available. And here we come to point 2.
  2. Different algorithms. Algorithms can be provided by libraries or functions found on the Internet. The i runtime engine, if it cannot find a requested library or function locally, starts searching around, maybe looking in a few hinted or well known places, or maybe all over the Internet, again using google search.
It is possible to write functions, or libraries that can be executed by any i program that finds them at runtime. Like the Internet is more than just a collection of web sites, an i program is more than just a collection of functions.

To make the language universal, and quick to accept, it compiles to JavaScript bytecode or is read and executed by an interpreter written in JavaScript. The i program, and the i libraries can be hosted inside regular html web pages. That's how they can be discovered quickly. A regular web search finds them.

The execution flow looks like this:
  1. A user requests a web page from a web server. The web page contains an i program in a native format plus an i interpreter written in JavaScript. Or it contains an i program already converted to JavaScript.
  2. The program starts running on page load event or when the user clicks a button or some other way. The program gets data, finds and calls other i programs using AJAX calls to i runtime engine hosted on a web server within the same domain, which in turn calls various Internet APIs. Note: the primary runtime environment is the browser, but the runtime on the server is needed to get past same origin policy, to make the i interpreter smaller and simpler, and to provide standard i libraries. The program is effectively running inside the user's browser downloading data and pieces of i code as it goes. It can also run code written in any language, executed on web servers, exposed using REST. Details to be defined.
  3. An i program can run forever, and can run simultaneously on an unlimited number of computers by spawning itself from the browser to servers that accept i code for execution.

Wednesday, March 9, 2011

My ruby zoo

Ruby is fun. A lot of fun. It makes programmers smile.  It makes them try crazy things... and those crazy things work.

Thank you Yukihiro Matsumoto!

Here is a little game I wrote with my kids one Saturday afternoon maybe a year ago.
There is an animal.rb and a zoo.rb and there is myzoo.rb which runs all that. I ran it using IronRuby.

animal.rb:
class Animal
  # create accessor methods for reading these properties 
  attr_reader :attractiveness, :upkeep, :name, :age, :dies_at, :cost_to_buy, :current_value, :dead
  
  MAX_ATTRACTIVENESS = 100
  MAX_UPKEEP = 100
  MAX_AGE_WHEN_BUYING = 30
  MAX_YEARS_TO_LIVE_AFTER_BUYING = 30
  MAX_COST_TO_BUY = 100

  ADVERBS = ["Small", "Big", "Smelly", "Cutest", "Sweetest", "Greenish", "Killer", "Harmless", "Angry"]
  NOUNS = ["Croc", "Elephant", "Hippo", "Ant", "Bear", "Mollusk", "Octopus", "Snake", "Snail"]

  def initialize(name)
    @attractiveness = rand(MAX_ATTRACTIVENESS)
    @upkeep = rand(MAX_UPKEEP)
    @name = name
    @age = rand(MAX_AGE_WHEN_BUYING)
    @dies_at = @age + rand(MAX_YEARS_TO_LIVE_AFTER_BUYING)
    @cost_to_buy = rand(MAX_COST_TO_BUY)
    @dead = false
  end

  def Animal.get
    name = ADVERBS[rand(ADVERBS.length)] + " " + NOUNS[rand(NOUNS.length)]  
    return Animal.new(name)
  end

  def make_older
    return if @dead
    if age == @dies_at
       @dead = true
       puts @name + " died of old age."
    else      
       @age += 1
       @attractiveness -= 1
    end
  end

  def show
    puts 
    puts "Name: #{@name}"
    puts "Attractiveness: #{@attractiveness.to_s} max: #{MAX_ATTRACTIVENESS.to_s}"
    puts "Cost to buy: $#{@cost_to_buy.to_s} max: #{MAX_COST_TO_BUY.to_s}"
    puts "Upkeep per year: $#{@upkeep.to_s} max: #{MAX_UPKEEP.to_s}"
    puts "Age: #{@age.to_s} year(s). max: #{MAX_AGE_WHEN_BUYING.to_s}" 
    puts "Dies at: #{@dies_at.to_s} year(s). max: #{(MAX_AGE_WHEN_BUYING + MAX_YEARS_TO_LIVE_AFTER_BUYING).to_s}" 
    puts 
  end
end # class Animal


zoo.rb:
class Zoo
  # ticket price can be set directly
  attr_accessor :ticket_price 
  # other properties are set internally 
  attr_reader :overhead_cost, :seed_money, :animals, :upkeep, :year, :animals_bought, :guests, :revenue, :cash

  def initialize()
    @animals = Array.new
    @upkeep = 0
    @overhead_cost = 100
    @ticket_price = 10
    @guests = 0
    @revenue = 0
    @seed_money = 500
    @cash = @seed_money
    @year = 0
  end

  def show
    puts
    puts "Animals: " + @animals.length.to_s
    puts "Upkeep last year: $" + @upkeep.to_s
    puts "Overhead cost: $" + @overhead_cost.to_s
    puts "Ticket price: $" + @ticket_price.to_s
    puts "Revenue last year: $" + @revenue.to_s
    puts "Guests last year: " + @guests.to_s
    puts "Cash: $" + @cash.to_s
    puts "Year: " + @year.to_s
    puts
  end

  # This defines how we buy animals:
  def buy_animal(animal)
      @cash = @cash - animal.cost_to_buy
      puts "You now have: $" + @cash.to_s
      @animals.push animal
  end

  def next_year
    @upkeep = 0
    @animals.each do |animal|
         animal.make_older
    end

    @animals.delete_if do |animal| 
         animal.dead 
    end

    @animals.each do |animal|
         @upkeep += animal.upkeep
    end

    @guests = 0
    @animals.each do |animal|
        @guests += animal.attractiveness
    end
    
    @guests = (@guests/Math.sqrt(@ticket_price)).to_i
    @revenue =  @guests * @ticket_price
    @cash += @revenue - @overhead_cost - @upkeep
    @year += 1
  end

end #class Zoo


myzoo.rb:
require "zoo.rb"
require "animal.rb"

YEARS_TO_PLAY = 10
CREATE_OR_APPEND_MODE = "a+"
WRITE_MODE = "w"
SCORES_FILE = "scores.txt"

def show_hall_of_fame
  File.open(SCORES_FILE, CREATE_OR_APPEND_MODE) {}
  scores = IO.readlines(SCORES_FILE) 

  puts "Hall of fame: "
  puts "...is waiting for your name" if scores.length == 0
  puts scores if scores.length > 0
end

def update_hall_of_fame (cash, player)
  File.open(SCORES_FILE, CREATE_OR_APPEND_MODE) {}
  scores = IO.readlines(SCORES_FILE) 
  
  scores[scores.length] = format("%10.10s %s", cash.to_s, player) 
  scores.sort!.reverse!
  File.open(SCORES_FILE, WRITE_MODE) {|f| f.write(scores) }
end

       
def show_menu
  puts
  puts "b = Buy Animals"
  puts "s = Sell Animals" 
  puts "p = Set Ticket Price" 
  puts "a = Show Animals" 
  puts "z = Show Zoo" 
  puts "n = Next Year" 
  puts "h = Hall of Fame" 
  puts "q = Quit"
  puts
end

puts "Welcome to MyZoo!"
puts "You manage it. Try to make as much money as you can in #{YEARS_TO_PLAY.to_s} years."

print "What's your name boss? "
player = gets

myzoo = Zoo.new
show_hall_of_fame

puts "You have in the bank: $" + myzoo.cash.to_s

playing = true

while playing and myzoo.year <= YEARS_TO_PLAY do
  show_menu
  print "Enter command:"
  command = gets

  case command
    when "b\n"
      some_animal = Animal.get
      some_animal.show
      print "Do you want to buy this animal? (y/n) "
      answer = gets
      myzoo.buy_animal(some_animal) if answer == "y\n"
  
    when "s\n" 
      if myzoo.animals.length > 0
         puts "Your salesperson has been eaten by #{myzoo.animals[0].name}." 
      else
         puts "There is no fauna in your zoo."
      end

    when "p\n" 
      print "New ticket price: "
      answer = gets
      if answer.to_i > 0
         myzoo.ticket_price = answer.to_i  
      else      
         puts "Sorry, no free tickets this year." 
      end  

    when "a\n" 
        if myzoo.animals.length > 0 
           puts "Your animals: " 
           myzoo.animals.each do |animal|
                animal.show
           end
        else
           puts "Did you buy any? Are they still alive?"
        end

    when "z\n" 
      myzoo.show    

    when "n\n"
      myzoo.next_year
      myzoo.show

    when "h\n"
      show_hall_of_fame

    when "q\n"
      print "Abandoning your enterprise? (y/n)"
      answer = gets
      if answer == "y\n" then 
         puts "Good-bye!"
         playing = false
      end 
  end
end

update_hall_of_fame(myzoo.cash, player) if myzoo.cash > 0
show_hall_of_fame



Tuesday, March 8, 2011

"Marek Edelman. Życie. Po prostu." by Witold Bereś and Krzysztof Burnetko.

I have read this 500 page book in Polish. The English title is "Marek Edelman: Simply A Life". A 30 minute DVD is included with the book. It shows Edelman being interviewed by the authors for the book.

This book is for you if you are looking for a first hand account of what the relations between different groups of Jews and Poles were in pre-war Poland, during the war, and after.

This book tells the story of the first Warsaw uprising - the Ghetto uprising - as it was: without pathos. It is a shocking story, but told without big words or hatred.


This book also tells a more general story. This book is for you if you are looking for inspiration how to live your life. What is important.


A few quotes by Marek Edelman:
"In life, those who let others live, are right."
"In principle, life is most important. And if you live, then the most important thing is freedom. And then you give life for freedom. And then you don't know what is most important."
"I am a Polish Jew, but Ala [wife] and all Jews think that I am a disgusting polonophile, and that I have a character of a Pole. But I think that patriotism is disgusting. I would never say about myself that I am a patriot - I am a patriot of the idea of freedom everywhere."
And finally:
"In life, I like caviar and beautiful girls."

............
2025.05.29 update: 
Marek Edelman is an exemplary person, a hero, but even he had skeletons in his closet. During the interview he said in passing that before the war he too took part in scamming of the farmers coming to Warsaw. The interviewers didn't ask him to explain. 

2025.06.12 update:
Another thing that I remembered in view of the lies that sometimes show up on the internet: Poland did not expel Jews in 1968. The communist party's "anti-Zionist" campaign affected Polish Jews, including Marek Edelman, but it did not forcefully expel them from the country. Instead, many lost their government jobs, including Edelman, and were told they could apply to leave the country. This was completely voluntary. If someone took up that offer, and many people, not only Jews, desperately wanted to leave communist Poland - in 1970 there were 20 attempted hijackings of passenger planes - to escape to the West, they would have to sell their possessions, and they would be given a one-way travel document. Edelman, if I remember correctly, got some other job thanks to a friend, and in less than a year, when the campaign ended, got back his original job at the hospital.

The Associate by John Grisham

Read by: Erik Singer
9CDs

Another story from the world of lawyers. We meet Kyle McAvoy when he is a senior at Yale law school. He is about to graduate and start a career in public law, but someone sinister has other plans for him. What will Kyle do with his life? Will he follow his ideals or will he give in to the dark side?

Monday, March 7, 2011

Language Implementation Patterns by Terrence Parr

Rating: Lot's of information, but poorly presented.

Basic Patterns:
  • Mapping Grammars to Recursive-Descent Recognizers: convert formal language specification (grammar) into a parser.
  • LL(1) Recursive-Descent Lexer: break up character streams into tokens.
  • LL(1) Recursive-Descent Parser: make a parsing decision (choose parsing method) for the current (1) input symbol.
  • LL(k) Recursive-Descent Parser: make a parsing decision (choose parsing method) for up to k next input symbols.
Quotes:
  • "A language is just a set of valid sentences."
  • "To parse, then, is to conjure up a two-dimensional parse tree from a flat token sequence."

Criticism:
This book could have been much better. It suffers from the following problems:
  •  Code examples:
    • Incompleteness - critical functions are missing initially: code which uses match() starts on page 41, but match() implementation is shown on page 55 for the first time.
    • Names of variables and functions are cryptic/not clear and do not follow one convention: 
      • variable names: T, p, c, x, k, i, r, Integer memoI, int memo, FOLLOW_INT_in_point37, _save,
      • function names: LT(), LA(), isSpeculating(), alreadyParsedRule(), _list(), speculate_stat_alt1().
  • Critical terms are used without introduction.
  • Definitions seem chaotic/incomplete.
  • Concepts are introduced in chaotic order.
  • Some concepts seem to change meaning: current token becomes a lookahead token.
  • There is a lot of alternative terminology that is used without introducing it properly: here are my notes on  "lexer":  Lexer: a type of recognizer; aka scanner, aka lexical analyzer, aka tokenizer: reads a stream of characters and yields a stream of tokens aka input symbols, aka vocabulary symbols.

Software Creativity by Robert Glass

Rating: A critical look at formal methods as a solution to all.

By page 19 (and 13 pages of forewords) we learned that there are two opposite views of how software should be developed: disciplined and flexible, and that the author will in the end show us that the middle way is the best.

Author's theory about software practice includes these issues:
  • Discipline vs. flexibility
  • Formal methods vs. heuristics
  • Optimizing vs. satisficing (sic!)
  • Quantitative vs. qualitative
  • Process vs. product
  • Intellectual vs. clerical tasks

On page 268 there is a good list of what academic research should be focusing on, two of which seem especially worthy:
  • issues contrary to commercial interests,
  • unsolved problems.

I think that definition of standards with sample implementations might fall into the "contrary to commercial interests" category. This might prevent the "design by committee" problems that we see in CORBA and IATA CUSS standards.

Chapter 9 contains an interesting discussion of "fun" in software development. The author references a paper by Bruce Blum, who lists the fun/tedium ratio for different phases of SDLC:
  • "selling the concept" phase - pure problem solving/analysis phase: 100% fun - 0% tedium
  • writing down requirements: 50-50
  • top-level design: 40-60
  • detailed design: 33-67
  • programming: 75-25
  • testing: 33-67
  • maintenance: 0-100


Chapter 9.3 mentions another interesting idea for creating projects with higher ratio of fun - the "incremental consensus" technique by Jerry Weinberg: begin with 2 people who want to work in a mutually pleasing manner and succeed on a project, then grow the team in increments of 1 and only when the candidate gets everyone's acceptance.

Chapter 13 lists ideas on how organizations can become more creative:
  • support open sharing of information
  • support risk-taking behaviors
  • create group diversity
  • create highly participative culture
  • create "slack resources"

Chapter 14 lists traits of creative people.

Chapter 15 shows that computer tools can decrease creativity in problem solving.

Chapter 16 explains creativity paradoxes:
  • The more you know about the problem domain, the less creative your solutions are.
  • To come up with creative solutions, you must know how others solved it.


Chapter 17 shows that software life cycle is just an implementation of a universal problem solving algorithm:
  • Identify a problem.
  • Define the requirements of the problem.
  • Design a solution to the problem.
  • Implement the design.
  • Test the implementation.
  • Use the implemented product.

Summary:
What I am missing in this book is the word "pragmatic". It is a simple, elegant, and "to the point" summary of the approach that Robert L. Glass postulates to use for software development.

Rapid Development by Steve McConnell

Rating: Instruction manual for software projects.

Chapter 7 - Lifecycle Planning - has a surprise for those who think that "Agile" and "SCRUM" are new revolutionary concepts. This book was written in 1996 and the Evolutionary Prototyping, Staged Delivery, Design-to-Schedule, and Evolutionary Delivery processes described there look eerily familiar to us.

There is a very interesting table on page 156: Lifecycle Model Strengths and Weaknesses. The Spiral model is a clear winner.

Chapter 9 - Scheduling - explains what the estimated completion date really is. "Developers typically estimate 20 to 30 percent lower than their actual effort. Merely using their normal estimates puts the chance of completing on time below 50%".

Chapter 11 - Motivation - has interesting insights about developers and managers. For example: "Compared to the general population, developers are much more motivated by possibility of growth, personal life, opportunity for technical supervision, and interpersonal relations with their peers. Developers are much less motivated by status, interpersonal relationships with subordinates, responsibility, and recognition."

Percentage of computer professionals who have a preference for:

  • introverted (I) over extroverted (E): 58%... I = interested in ideas rather than people and things,
  • thinking (T) over feeling (F): 80%... T = logical, objective decisions,
  • judging (J) over perceiving (P): 66%... J = live in a planned, orderly way.

Chapter 43 - Voluntary Overtime - shows in a Machiavellian way how to trick developers into producing more without compensation. It's tricky, but it can be done. Other ways DO NOT work. Involuntary or excessive overtime decreases overall productivity. "Trying to motivate developers can be like trying to push on a rope - you'd be better off pulling on the other end."


Key Lessons:

  • Software development can be optimized for schedule, quality, performance, maintainability, usability, cost. Pick one or make trade-offs.
  • To get software on time you must:
    • not make classic mistakes,
    • follow software development fundamentals,
    • manage risk,
    • use schedule-oriented practices.

Summary:
Rapid Development complements Code Complete. It gives team leads and managers knowledge with which they can deliver software projects on time.