Blogged by Ujihisa. Standard methods of programming and thoughts including Clojure, Vim, LLVM, Haskell, Ruby and Mathematics written by a Japanese programmer. github/ujihisa

Wednesday, December 30, 2009

Trying Out Bundler In 1 Minute

Let's write an application which uses the gem library "g" without installing it globally.

Mise En Place

Install bundler to make the application easily.

gem install bundler

And if you already have g, uninstall it to make sure the application you'll make doesn't use the globally installed g.

gem uninstall g

Getting Started

$ mkdir ggg; cd ggg
$ vim Gemfile
gem 'g'
gem 'ruby-growl'

$ gem bundle
$ vim app.rb
require 'vendor/gems/environment'
require 'g'
g 'success!!!'

$ ruby app.rb

That's all!

For your information:

$ tree
.
|-- Gemfile
|-- app.rb
|-- bin
|   `-- growl
`-- vendor
    `-- gems
        |-- cache
        |   |-- g-1.3.0.gem
        |   `-- ruby-growl-1.0.1.gem
        |-- doc
        |-- environment.rb
        |-- gems
        |   |-- g-1.3.0
        |   |   |-- README.markdown
        |   |   |-- Rakefile
        |   |   |-- VERSION
        |   |   |-- g.gemspec
        |   |   |-- lib
        |   |   |   `-- g.rb
        |   |   `-- spec
        |   |       `-- g_spec.rb
        |   `-- ruby-growl-1.0.1
        |       |-- LICENSE
        |       |-- Manifest.txt
        |       |-- Rakefile
        |       |-- bin
        |       |   `-- growl
        |       |-- lib
        |       |   `-- ruby-growl.rb
        |       `-- test
        |           `-- test_ruby-growl.rb
        `-- specifications
            |-- g-1.3.0.gemspec
            `-- ruby-growl-1.0.1.gemspec

14 directories, 20 files

Monday, December 28, 2009

Usually Something, But If...

Which do you prefer to write in Ruby?

if boundary_condition
  code_for_the_extreme_case
else
  code_for_the_typical_case
  ...
end

Or

unless boundary_condition # `if !boundary_condition` as well.
  code_for_the_typical_case
  ...
else
  code_for_the_extreme_case
end

In such cases, first I try to use guards. This is straightforward.

return code_for_the_extreme_case if boundary_condition
code_for_the_typical_case
...

But sometimes I cannot use such notation in cases where not to use return or break.

Solution

I made a DSL for this problem.

class UsuallyPending
  instance_methods.map {|i| i.to_s }.
    reject {|i| /__/ =~ i }.
    each {|m| undef_method m }

  def initialize(b1)
    @b1 = b1
  end

  def but_if(cond, &b2)
    if cond
      b2.call
    else
      @b1.call
    end
  end
end

def usually(&b1)
  UsuallyPending.new(b1)
end

usually do
  p ARGV
  p 'hello!'
end.but_if ARGV.empty? do
  p 'Give me arguments!'
end

This is a straightforward expansion of postpositive if with block instead of a value.

Sunday, December 27, 2009

BFC: Brainf\*\*k Compilers

Today I released BFC 1.0!

BFC: Brainf**k Compilers http://github.com/ujihisa/bfc

bfc.rb is a compiler written in Ruby, which can compile BF code to Ruby, C, Haskell, Scheme and LLVM.

BFC Shot

USAGE OF BFC

$ ./bfc.rb --help
$ ./bfc.rb [-v|--version]

$ ./bfc.rb [-r|--ruby]    helloworld.bf > helloworld.rb
$ ./bfc.rb [-c|--c]       helloworld.bf > helloworld.c
$ ./bfc.rb [-h|--haskell] helloworld.bf > helloworld.hs
$ ./bfc.rb [-l|--llvm]    helloworld.bf > helloworld.ll
$ ./bfc.rb [-s|--scheme]  helloworld.bf > helloworld.scm

$ cat helloworld.bf | ./bfc.rb --ruby
$ ./bfc.rb [-r|--ruby|-c|--c|-h|--haskell|-l|--llvm] helloworld.bf --run
$ ./bfc.rb [-c|--c] helloworld.bf --without-while > helloworld.c
$ spec ./bfc.rb

THE BRAINF**K LANGUAGE

According to Wikipedia, the programming language Brainf**k has the following 8 tokens that each have semantics. Here is the equivalent transformation from Brainf**k to C.

table

The bfc.rb converts BF codes to each languages mostly based on the table.

C Translation Table in bfc.rb:

',' => '*h=getchar();',
'.' => 'putchar(*h);',
'-' => '--*h;',
'+' => '++*h;',
'<' => '--h;',
'>' => '++h;',
'[' => 'while(*h){',
']' => '}'

Ruby Translation Table in bfc.rb:

',' => 'a[i]=STDIN.getc.ord',
'.' => 'STDOUT.putc(a[i])',
'-' => 'a[i]-=1',
'+' => 'a[i]+=1',
'<' => 'i-=1',
'>' => 'i+=1',
'[' => 'while a[i]!=0',
']' => 'end'

They are straightforward enough not to be explained the detail.

In the same way, we can write translation tables for most programming languages except special languages including Haskell and Assembly languages.

TRANSLATING TO HASKELL

Translating BF to Haskell needs two tricks. Haskell was difficult to handle BF because:

  • Variables in Haskell are not allowed to be re-assigned
    • ++h is impossible
  • There's no feature like while statement

So I used IO Monad with biding same-name variables, and defined while function.

Haskell Translation Table in bfc.rb:

',' => 'tmp <- getChar; h <- return $ update (\_ -> ord tmp) i h;',
'.' => 'putChar $ chr $ h !! i;',
'-' => 'h <- return $ update (subtract 1) i h;',
'+' => 'h <- return $ update (+ 1) i h;',
'<' => 'i <- return $ i - 1;',
'>' => 'i <- return $ i + 1;',
'[' => '(h, i) <- while (\(h, i) -> (h !! i) /= 0) (\(h, i) -> do {',
']' => 'return (h, i);}) (h, i);'

And the definition of while is:

while cond action x
 cond x    = action x >>= while cond action
 otherwise = return x

This is short, but can handle loop with changing the value with larger scope like C's.

TRANSLATING TO C WITHOUT WHILE STATEMENTS

Unlike the effort on Haskell, it is impossible to write simple translation table for C when I can use only goto for control flows instead of while statements. So I made the compile to have label counters to make labels for goto a lot.

Excerpt from bfc.c:

when ','; '*h=getchar();'
when '.'; 'putchar(*h);'
when '-'; '--*h;'
when '+'; '++*h;'
when '<'; '--h;'
when '>'; '++h;'
when '['; "do#{counter += 1}:"
when ']'
  "if (*h != 0) goto do#{counter}; else goto end#{counter};" <<
  "end#{counter}:"
end

TRANSLATING TO LLVM

LLVM Assembly language is similar to Haskell to the extent of the prohibition of re-assignments, and not similar to Haskell to the extend of having do syntax for Monad. So I decided to use pointers to store values. Also, LLVM needs many temporary variables which cannot be re-assigned, so I used counters again to use temporary constants.

The translation table with counters is too big to paste here, so I'll just show the definition of '+' which means '++h' in C.

when '+'
  a = tc += 1; b = tc += 1; c = tc += 1; d = tc += 1
  "%tmp#{a} = load i32* %i, align 4\n" <<
  "%tmp#{b} = getelementptr [1024 x i8]* %h, i32 0, i32 %tmp#{a}\n" <<
  "%tmp#{c} = load i8* %tmp#{b}, align 1\n" <<
  "%tmp#{d} = add i8 1, %tmp#{c}\n" <<
  "store i8 %tmp#{d}, i8* %tmp#{b}, align 1\n"

(where tc is the abbreviation of tmp counter.)

One more thing. LLVM is famous for its aggressive optimizations. For example, the result of the conversion from helloworld.bf to LLVM Assembly Language is very long.

$ ./bfc.rb --llvm ./helloworld.bf | wc -l
2842

But once you optimize the assembly by opt command of LLVM, the line of code will become shorter and more succinct.

SUMMARY

BFC supports compiling BF to the following language.

  • Ruby
  • C
  • Haskell
  • LLVM Assembly Language
  • Scheme

In some languages it was easy to write the translator, but Haskell and LLVM was tough for me.

If I have a plenty of time, I'd like to try these challenges:

  • Compiling to Erlang
  • Compiling to IA-32 Assembly Language
  • Compiling to LLVM Bitcode
  • More Spec!
  • Benchmark Suite

Anyway, I recommend you to take a look at the BFC. Enjoy!

Saturday, December 26, 2009

LLVM For Starters

Installation of LLVM Compiler and Runtime

See the previous post.

Overview of LLVM

To write a helloworld application, you can choose a path where to start. The typical path is,

  1. Write a code in LLVM Assembly Language (.ll)
    • $ vim sample.ll
  2. Compile it to LLVM Bytecode (.bc)
    • $ llvm-as sample.ll
  3. Run it on LLVM interpreter
    • $ lli sample.bc

Or,

  1. ditto
  2. ditto
  3. Compile it to Executable Binary File
    • $ llc sample.bc
  4. Run it!
    • $ ./sample

In this post, I'll explaing about the first step "LLVM Assembly Language".

Helloworld in LLVM Assembly Language

LLVM is not a stack machine but a register machine.

tableoftype

tableoftype

(This table is from wikipedia)

Let's write helloworld application. Before that, I'll show the equivalent code in C.

int main() {
  puts("Hello, world!");
  return 0;
}

In LLVM Assembly Language, the code will be written as below.

@str = internal constant [14 x i8] c"Hello, world!\00"
declare i32 @puts(i8*)
define i32 @main()
{
  call i32 @puts( i8* getelementptr ([14 x i8]* @str, i32 0,i32 0))
  ret i32 0
}

This code suggests the following notices:

  • We can write an integer number directly in the assembly code, on the other hand, we cannot write a string directly.
  • The long name getelementptr seems to be * in C.

If I write helloworld in C like the LLVM Assembly code, it is like:

char str[14] = "Hello, world!";
int main() {
  puts((char *)str);
  return 0;
}

Fibonacci in in LLVM Assembly Language

Nanki wrote Fibonacci in LLVM Assembly Language.

@str = internal constant [4 x i8] c"%d\0A\00"

define void @main() nounwind {
init:
  br label %loop
loop:
  %i = phi i32 [0, %init], [%i.next, %loop]
  %fib = call i32 @fib(i32 %i)

  call i32 (i8*, ...)* @printf( i8* getelementptr ([4 x i8]* @str, i32 0, i32 0), i32 %fib)

  %i.next = add i32 %i, 1

  %cond = icmp ult i32 %i.next, 30
  br i1 %cond, label %loop, label %exit

exit:
  ret void
}

define i32 @fib(i32 %n) nounwind {
  %cond = icmp ult i32 %n, 2
  br i1 %cond, label %c1, label %c2

c1:
  ret i32 1
c2:
  %n1 = sub i32 %n, 1
  %n2 = sub i32 %n, 2

  %fib1 = call i32 @fib(i32 %n1)
  %fib2 = call i32 @fib(i32 %n2)

  %r = add i32 %fib1, %fib2
  ret i32 %r
}

declare i32 (i8*, ...)* @printf(i8*, ...) nounwind

To understand the code deeper, let me write back the code in C.

#include<stdio.h>
int fibonacci(int n);

int main() {
  int i, i_next, fib;
init:
  i = 0, i_next = 0;
loop:
  i = i_next;
  fib = fibonacci(i);
  printf("%d\n", fib);
  i_next = i + 1;
  if (i_next < 30) {
    goto loop;
  } else {
    goto exit;
  }
exit:
  return 0;
}

int fibonacci(int n) {
  int cond, n1, n2, fib1, fib2, r;
  cond = n < 2;
  if (cond) {
    goto c1;
  } else {
    goto c2;
  }
c1:
  return 1;
c2:
  n1 = n - 1;
  n2 = n - 2;
  fib1 = fibonacci(n1);
  fib2 = fibonacci(n2);
  r = fib1 + fib2;
  return r;
}
  • LLVM Assembly Language enables us to use the same name both for a variable and a function because of the existence of prefix
  • LLVM Assembly Language cannot handle many calculation at the same time like return fib(n-2) + fib(n-1).

Tuesday, December 22, 2009

Let's Try LLVM

Mac OS X has LLVM compiler, but doesn't have LLVM Assembler. Let's start installing the trunk LLVM on your Mac.

According to http://llvm.org/docs/GettingStarted.html#checkout,

$ cd ~/src
$ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
$ cd llvm

In the directory there is /docs directory which contains many html files. Check them.

$ ./configure --prefix=/Users/ujihisa/src/llvm/usr
$ gmake -k |& tee gnumake.out

It took long time. After the build process, I found an interesting note.

...
gmake[1]: Leaving directory `/Users/ujihisa/src/llvm/bindings'
llvm[0]: ***** Completed Debug Build
llvm[0]: ***** Note: Debug build can be 10 times slower than an
llvm[0]: ***** optimized build. Use make ENABLE_OPTIMIZED=1 to
llvm[0]: ***** make an optimized build. Alternatively you can
llvm[0]: ***** configure with --enable-optimized.

I should have set --enable-optimized.

Anyway, let the installation finish.

$ gmake install

It also took time.

Don't forget to make path to the ./usr/bin/. There are many llvm-related executable files.

Hello, world!

Let's write hello world on LLVM!

I referred this page. The sample code contains a small mistakes, so I fixed.

Write the following code on a.ll (not a.11):

@str = internal constant [13 x i8] c"hello world\0A\00"

define void @main() nounwind
{
  %temp = call i32 @printf( i8* getelementptr ([13 x i8]* @str, i32 0,i32 0))
  ret void;
}

declare i32 @printf(i8*, ...) nounwind

Assemble it:

$ llvm-as -f a.ll
$ lli a.bc
hello world

Yay!

The generated file a.bc is a binary file.

Vim

Fortunately the svn repository contains a vim script for llvm named llvm.vim. You should install it if you're a vimmer.

(To be continued...)

Monday, December 21, 2009

Today's RubySpec (Dec 21, 2009)

I succeeded in fixing RubySpec to pass all String specs both in Ruby 1.8.7 and Ruby 1.9.2. yay!

$ /usr/bin/ruby ../mspec/bin/mspec ./core/string/*.rb -t ~/rubies/bin/ruby192
ruby 1.9.2dev (2009-12-21 trunk 26145) [i386-darwin9.8.0]
.............................................................................................

Finished in 0.559929 seconds

93 files, 1083 examples, 6132 expectations, 0 failures, 0 errors
$ /usr/bin/ruby ../mspec/bin/mspec ./core/string/*.rb -t ~/rubies/bin/ruby187
ruby 1.8.7 (2009-07-30 patchlevel 192) [i686-darwin9.7.0]
.............................................................................................

Finished in 0.483685 seconds

93 files, 889 examples, 5620 expectations, 0 failures, 0 errors

New knowledges for me

  • String#squeeze, #count and #delete receive string sequence like "a-c". In Ruby 1.8, an invalid sequence like "c-a" is just regarded as empty sequence. On the other hand, in Ruby 1.9, it raises an ArgumentError.
  • "\u0085" is NEL: Next Line in utf-8. On my Terminal, it looks like "\n". But actually "n" and NEL are completely different characters.
  • String#% Differs Between Ruby 1.8 and 1.9 (the previous blog post)

`String#%` Differs Between Ruby 1.8 and 1.9

Try the following code on your ruby.

p('%-03d' % -5)

The result on ruby 1.8.* is "-05" while the result on ruby 1.9.* is "-5 ".

So, which behavior is correct? The answer is the latter.

  • String#% is subject to be equivalent to sprintf(3)
  • "-" means "left-align"
  • "0" means "completing the spaces with 0" when the alignment is right-align

So, "-0" is equivalent to mere "-". According to the principle, the behavior on ruby 1.8 is wrong.

(I think that the reason why ruby core developers don't change the 1.8's behavior is that the change may break existing codes.)

Sunday, December 20, 2009

Efficient Software-Based Fault Isolation

Paper(pdf): http://crypto.stanford.edu/cs155/papers/sfi.pdf

Discussion: http://papersincomputerscience.org/2009/12/19/efficient-software-based-fault-isolation/

Citation: Wahbe, R., Lucco, S., Anderson, T. E., and Graham, S. L. 1993. Efficient software-based fault isolation. In Proceedings of the Fourteenth ACM Symposium on Operating Systems Principles (Asheville, North Carolina, United States, December 05 – 08, 1993). SOSP ‘93. ACM, New York, NY, 203-216. (PS) (PDF)

This paper is in December 1993; 16 years ago. This paper discusses how to isolate a system failure without using any special hardwares. For example, how to impound a bug within the process is important because nobody expects that a bug of a game which is working on a system causes the whole system to crash.

This paper explains the approach with the following subsections.

  • Segment Matching
  • Address Sandboxing
  • Optimizations
  • Process Resources
  • Data Sharing
  • Implementation and Verification

Yacc, JavaCC and Racc

To compare the three parser generators, here I'll show an easy sample written in them.

Target Syntax

The following codes are accepted.

  • "1+2"
  • "23423423432 + 923401"
  • "23432 + 2"

The compiler will calculate the single addition and shows the value.

The following codes aren't accepted.

  • "1+2+3"
  • "1-2"
  • "1+"

JavaCC

The following code is from Standard Compiler by Minero Aoki.

The filename is A.jj.

PARSER_BEGIN(A)
import java.io.*;

class A {
  static public void main(String[] args) {
    for (String arg : args) {
      try {
        System.out.println(evaluate(arg));
      }
      catch (ParseException ex) {
        System.err.println(ex.getMessage());
      }
    }
  }

  static public long evaluate(String src) throws ParseException {
    Reader reader = new StringReader(src);
    return new A(reader).expr();
  }
}
PARSER_END(A)

SKIP: { <[" ", "\t", "\r", "\n"]> }

TOKEN: {
  <INTEGER: (["0"-"9"])+>
}

long expr():
{
  Token x, y;
}
{
  x=<INTEGER> "+" y=<INTEGER> <EOF>
    {
      return Long.parseLong(x.image) + Long.parseLong(y.image);
    }
}

To run this, type the following commends

$ javacc A.jj
$ javac A.java
$ java A '1 +  3'
4

This build process produces the following files automatically.

  • A.class
  • A.java
  • AConstants.class
  • AConstants.java
  • ATokenManager.class
  • ATokenManager.java
  • ParseException.class
  • ParseException.java
  • SimpleCharStream.class
  • SimpleCharStream.java
  • Token.class
  • Token.java
  • TokenMgrError.class
  • TokenMgrError.java

Yacc and Lex

a.y

%token NUMBER

%%

expr : NUMBER '+' NUMBER { printf("%d", $1 + $3); }

%%
#include <stdio.h>
#include "lex.yy.c"

a.l

%{
#include "a.tab.h"
%}
%%
[0-9]+    {sscanf(yytext,"%d",&yylval); return(NUMBER);}
[ \r\n\t]   ;
.         return(yytext[0]);
%%
#ifndef yywrap
yywrap() { return 1; }
#endif

run

$ bison -d a.y && lex a.l
$ gcc a.tab.c -ly -ll
$ ./a.out

files automatically generated

  • a.out
  • a.tab.c
  • a.tab.h
  • lex.yy.c

Racc

I referred this blog entry http://d.hatena.ne.jp/morphine57/20090824/1251129740

a.racc

class A
  token NUM
rule
   expr : NUM '+' NUM { result = val[0] + val[2] }
end
---- header
require 'strscan'
---- inner
  def parse(str)
    @tokens = []
    s = StringScanner.new(str)
    until s.eos?
      case
      when s.scan(/[0-9]+/)
        @tokens << [:NUM, s[0].to_i]
      when s.skip(/[ \t\r\n]/)
      else
        @tokens << [s.getch, nil]
      end
    end
    do_parse()
  end

  def next_token
    @tokens.shift
  end

And runs

$ racc a.racc
$ ruby192 -r ./a.tab.rb -e 'p A.new.parse "1+ 2"'
3

Files automatically generated

  • a.tab.rb

Statistics

The lines of code which I have to write by myself:

  • JavaCC: 39
  • Yacc: 9 + 11
  • Racc: 26

The lines of code which are automatically generated:

  • JavaCC: 1446
  • Yacc: 3280
  • Racc: 117 (assuming the gem library racc is already installed)

Friday, December 18, 2009

Trying to Install JavaCC (Java Compiler Compiler)

$ sudo port install javacc
--->  Computing dependencies for readline
--->  Fetching readline
--->  Attempting to fetch readline-6.0.tar.gz from http://mirrors.ibiblio.org/pub/mirrors/gnu/ftp/gnu/readline
--->  Verifying checksum(s) for readline
--->  Extracting readline
--->  Applying patches to readline
--->  Configuring readline
--->  Building readline
--->  Staging readline into destroot
--->  Deactivating readline @6.0.000_1
--->  Computing dependencies for readline
--->  Installing readline @6.0.000_2+darwin
--->  Activating readline @6.0.000_2+darwin
--->  Cleaning readline
--->  Computing dependencies for sqlite3
--->  Fetching sqlite3
--->  Attempting to fetch sqlite-3.6.21.tar.gz from http://www.sqlite.org/
--->  Verifying checksum(s) for sqlite3
--->  Extracting sqlite3
--->  Configuring sqlite3
--->  Building sqlite3
--->  Staging sqlite3 into destroot
--->  Deactivating sqlite3 @3.6.16_0
--->  Computing dependencies for sqlite3
--->  Installing sqlite3 @3.6.21_0
--->  Activating sqlite3 @3.6.21_0
--->  Cleaning sqlite3
--->  Computing dependencies for javasqlite
--->  Fetching javasqlite
--->  Attempting to fetch javasqlite-20060714.tar.gz from http://www.ch-werner.de/javasqlite/
--->  Verifying checksum(s) for javasqlite
--->  Extracting javasqlite
--->  Applying patches to javasqlite
--->  Configuring javasqlite
--->  Building javasqlite
Error: Target org.macports.build returned: shell command " cd "/opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_java_javasqlite/work/javasqlite-20060714" && /usr/bin/make -j1 all " returned error 2
Command output: /usr/bin/javac -nowarn  SQLite/Authorizer.java
/usr/bin/javac -nowarn  SQLite/BusyHandler.java
/usr/bin/javac -nowarn  SQLite/Callback.java
/usr/bin/javac -nowarn  SQLite/Database.java
Note: ./SQLite/TableResult.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
/usr/bin/javac -nowarn  SQLite/Shell.java
./libtool /usr/bin/gcc-4.0 -I/opt/local/include -I/opt/local/include \
            -DHAVE_SQLITE2=1 -DHAVE_SQLITE3=1 \
            -o native/mkconst native/mkconst.c /opt/local/lib/libsqlite.la /opt/local/lib/libsqlite3.la
libtool: warning: cannot infer operation mode from `/usr/bin/gcc-4.0'
libtool: you must specify a MODE
Try `libtool --help' for more information.
make: *** [native/mkconst] Error 1

Error: Status 1 encountered during processing.
/opt/local/var/macports/sources/rsync.macports.org/release/ports

readline, sqlite3, javasqlite... What was happening? I just wanted to install JavaCC...

RubyConf 2009 Was Great

I had been staying in Burlingame, California to attend RubyConf 2009 and JRubyConf 2009.

rooms matz keynote breakfast aisle people by tmaedax Matz eatz breakfast alone

I made two presentations there in English.

"Hacking parse.y"

First, I made 45 minutes presentation in English there.

I talked about the parser part of MRI (Matz Ruby Implementation) with demonstrations including adding new syntaxes.

(I wouldn't like to say something negative, but I have to say that my presentation wasn't as well as I expected. I think the reasons were that I was sick at the time and I needed more safety nets of my demonstration.)

"Termtter the ultimate twitter client"

Second, I made 5 minutes short talk there.

This slides were made by jugyo. He tried to make presentation, but he was so afraid of his English that he asked me to make it instead. So I did.

LT; photo taken by kakutani

My roommates.

roommates; Photo taken by kakutani

JRubyConf 2009

I also attended JRubyConf 2009 the day after RubyConf 2009. I really wanted to attend all sessions, but I couldn't because my body condition was worst at the time.

1 2

My Personal Impression

Small But Important Events

I went to Engine Yard twice. I went to eat lunch and dinner with great programmers. I talked a lot. I gave some presents to some people, and I got great things by them as well.

rubyspec conf; photo taken by tmaedax

the Last Supper

English

I was surprised to notice that I was starting to feel as comfortable with English as with Japanese. A few years ago, English was kind of cryptic language for me. To use English, I had to think a lot like calculating. I had to think and translate before I could understand what I was listening to.

When I lived in Canada, I didn't notice that I had stopped doing that. Maybe because my improvement was too gradual to be noticed. My one month stay in Japan made me realize this fact.

It's exciting. Even though I still can't speak English fluently or listen to English without having difficulties, but at least, now I don't feel like using English is so difficult.

Transit at Salt Lake City

Links

stanford

Left Hand Values in Ruby

Local variables, Constants, Instance variables, Class variables and global variables

a = 1
A = 1
@a = 1
@@a = 1
$a = 1

Arefs and Attributes

a[:b] = 1
# a.[](:b, 1)

a.b = 1
a::b = 1

Combine

a, A, @a, @@a, $a, a[:b], a.b =
  1, 1, 1, 1, 1, 1, 1

Opassign

a += 1
# a, b += 1, 2  raises Syntax Error!

The only one syntax which allows to write expression in left hand sides is aref. For example, a[random(10)] = 1 is accepted. Also, I can write such codes:

alias []= instance_variable_set
alias [] instance_variable_get

a = Object.new
a['@a'] = 1
p a['@a'] #=> 1
p a #=> #<Object:0x40afb0 @a=1>

Thursday, December 3, 2009

Termtter Installs New Gem Libraries Automatically

I wrote a new termtter plugin.

http://github.com/jugyo/termtter/blob/dbbd3d1b16933a205470125982f03a3444de3d07/lib/plugins/gem_install.rb

Once you use this plugin by plug gem_install, your termtter will install arbitrary gem libraries when they appeared on your timeline, replies or anything on your termtter. How useful it is. If you already have g, the automatic installation will be announced on your Growl.

The plugin needs more fixes and spec.

Tuesday, December 1, 2009

Write Implementation and Spec on the Same File

-- For http://atnd.org/events/2351 day 1

Sometimes it would be preferable to write the implementation and the specific on the same single file because of the reasons including ease of maintenance and ease of distribution. The following snippet will be helpful for the purpose.

#!/usr/bin/env ruby

{implementation}

case $0
when __FILE__
  {command line interface of the implementation}
when /spec[^/]*$/
  {spec of the implementation}
end

For example, assuming a.rb is that you've written with using the template,

  • ruby a.rb runs {implementation} and {command line interface of the implementation}
  • ./a.rb runs {implementation} and {command line interface of the implementation}
  • spec a.rb runs {implementation} and {spec of the implementation} with RSpec
  • require 'a' in other scripts runs only {implementation}.

Saturday, November 28, 2009

Trying Stomp and Stompserver on Ruby

STOMP: Streaming Text Orientated Messaging Protocol is getting important, particularly for web programmers who need to think scalability. There are Ruby implementations of STOMP, called stomp and stompserver. Here is the brief introduction of them.

INSTALL

$ gem install stomp
$ gem install stompserver

Currently it is reported that stompserver cannot be installed well on ruby 1.9. I don't know why so far.

HELLO, WORLD

Get three terminals ready.

[Terminal 1]$ mkdir tmp && cd tmp
[Terminal 1]$ stompserver

[Terminal 2]$ irb -rubygems
> require 'stomp'
> Stomp::Client.new.subscribe('/a/b') {|m| p m.body }

[Terminal 3]$ irb -rubygems
> require 'stomp'
> Stomp::Client.new.send('/a/b', 'Hello, world!')

And then check your terminal 2.

stompserver creates etc and log directories on the current directly and opens port 61613.

Thursday, November 19, 2009

I'm Attending RubyConf 2009

Now I'm staying at a hotel near San Francisco Airport where RubyConf 2009 will be held on Nov 19 to 21 and JRubyConf on Nov 22 as well.

As an attendee

This is my first time to attend a conference not in Japan. I had lived in Vancouver, Canada for a half year, so now I can speak and listen English better than last year, but I still feel difficulty in using English, particularly in listening. Also, I'm shy and nervous.

If you find such person, feel free to talk to him. It's me. I may have a nameplate that is written "ujihisa".

As a speaker

I'll talk about Ruby's parser. The presentation will be not for a great Ruby hacker, but for an ordinary programmer.

If you are interested in my presentation, I highly recommend you to build the Ruby trunk in advance. It's easy but takes long time.

$ mkdir ~/rubies
$ svn co (ruby trunk)
$ cd (the directory)
$ ./configure --prefix=$HOME/rubies
$ make
$ make install

As a Japanese

If you are interested in Japanese culture, feel free to ask me about it as well as about Ruby.

Contact

http://twitter.com/ujm

Wednesday, November 18, 2009

Playing with JRuby's Parser

Apply this patch to JRuby.

diff --git a/src/org/jruby/lexer/yacc/RubyYaccLexer.java b/src/org/jruby/lexer/yacc/RubyYaccLexer.java
index dd1733e..dc591a2 100644
--- a/src/org/jruby/lexer/yacc/RubyYaccLexer.java
+++ b/src/org/jruby/lexer/yacc/RubyYaccLexer.java
@@ -1208,6 +1208,12 @@ public class RubyYaccLexer {
     private int colon(boolean spaceSeen) throws IOException {
         int c = src.read();

+        if (c == '-' && src.peek(')')) {
+          src.read();
+          lex_state = LexState.EXPR_BEG;
+          yaccValue = new Token("=>", getPosition());
+          return Tokens.tASSOC;
+        }
         if (c == ':') {
             if (isBEG() || lex_state == LexState.EXPR_CLASS || (isARG() && spaceSeen)) {
                 lex_state = LexState.EXPR_BEG;

Now you can write :-) as => in braces as Hash literals.

$ ./bin/jruby ./bin/jirb
> {1 => 2}
=> {1=>2}
> {1 :-) 2}
=> {1=>2}
> {:aaa => :bbb}
=> {:aaa=>:bbb}
> {:aaa:-):bbb}
=> {:aaa=>:bbb}

This patch is almost same as my previous patch to MRI.

diff --git a/parse.y b/parse.y
index b8d9b59..a592aed 100644
--- a/parse.y
+++ b/parse.y
@@ -7125,6 +7125,11 @@ parser_yylex(struct parser_params *parser)

       case ':':
         c = nextc();
+        if (c == '-' && peek(')') {
+            nextc();
+            lex_state = EXPR_BEG;
+            return tASSOC;
+        }
         if (c == ':') {
             if (IS_BEG() ||
                 lex_state == EXPR_CLASS || (IS_ARG() && space_seen)) {

One Month In Japan

I had been in Japan for a month until yesterday. I went to my parents' home, did things related to my admission to the graduate universities, attended some conferences and workshops, and met many friends.

List of workshops I attended:

  • uuuu

  • Kansai Ruby Workshop #38

  • Vim Workshop #4

  • LiveCoing#7

  • Kansai Ruby Kaigi #2 at Kansai Open Forum 2009

  • "Working Effectively with Legacy Code" Study Group

  • Golang Hackathon

  • xUnit Workshop

  • Tokyo Rails Workshop #45

I made presentations at the workshops, mostly about parse.y of Ruby.

Other events:

  • Professor Konami and his students
  • Big Buddha
  • Hoso Hackathon
  • SVTour Alumni Party
  • Teppan lunch
  • ujihkn
  • Ramen Hackathon
  • Todai Hackathon
  • ujihkn

My Sincerely Friends

I feel too thankful for my sincerely friends to say thank you. I proud them. May luck with you!

Thursday, November 12, 2009

RubyConf 2009 Schedule

shot

My talk "Hacking parse.y" will be on Thursday Nov. 18 which is the first day of RubyConf 2009.

http://rubyconf.org/pages/schedule

Wednesday, November 4, 2009

Accepting Both Get And Post Method in Sinatra

Whe you would like to accept both GET and POST request with the same block, use the following get_or_post method.

[Before]

require 'rubygems'
require 'sinatra'

get '/' do
  'hi'
end

post '/' do
  'hi'
end

[AFTER]

require 'rubygems'
require 'sinatra'

def get_or_post(path, opts={}, &block)
  get(path, opts, &block)
  post(path, opts, &block)
end

get_or_post '/' do
  'hi'
end

Sunday, November 1, 2009

4th Vim Workshop at Osaka

http://atnd.org/events/1797

Today I attended a workshop about Vim. Originally I started the workshop, and kozo_ni took over from the workshop and the soul.

The number of the attendees were 10, including a person from far Yokohama.

Presentations of the workshop were broadcast on ustream. Some presentations were recorded.

Friday, October 30, 2009

38th Kansai Ruby Workshop

http://jp.rubyist.net/?KansaiWorkshop38 (in Japanese)

I attended 38th Kansai Ruby Workshop today and make a presentation there. The workshop was ustreamed.

My Presentation "Hacking parse.y"

I have made the same title presentation in Vancouver.rb so far. I also have two other opportunities to make the same title presentation in Kansai Open Forum and RubyConf2009. All presentations are different because of the difference audience. Kansai Ruby Workshop is the most casual place of them, so my presentation today was be the most casual one.

The agenda was the following:

  • Brief self introduction
  • What is Ruby Core
  • What is Ruby's parser
  • Understanding colons
  • Adding literal
  • (cont.)

Note that this presentation isn't for super Ruby programmers. I think all ruby commitors already know all of what I'll talk tomorrow.

Slides, Handouts and Record

Slides are available here(slideshare).

Handouts are availabble here(pdf).

Record is available here(ustream). (in Japanese)

Wednesday, October 14, 2009

GRE Exam

Today I took the GRE exam.

The result was too crazy to write here. I think something must be going wrong.

Thursday, October 8, 2009

RubyGems on Ruby 1.9

This blog post is a note of a report about the current RubyGems 1.3.5 on Ruby 1.9 for myself (including both 1.9.1 and 1.9.2) without any good reproductions or the solutions.

When I did rake192 spec on a directory which contains a Rakefile that uses jeweler, I met an enormous errors (The suffix means the Ruby version on my machine.) I've heard that anyhow gem192 uninstall update-rubygems can solve the problem, so I did it. But after that, the rake192 started to cause segfault!

The segfault is caused by a 1.9.2 marshal's bug which is already reported but not fixed yet. I gave up using 1.9.2, and then I decided to use 1.9.1 instead.

On 1.9.1 the results were exactly same except that it didn't cause a SEGV.

Downgrading RubyGems (failed!)

According to baroquebobcat,

$ gem uninstall rubygems-update
$ gem install -v x.x.x rubygems-update
$ sudo update_rubygems

does downgrade rubygems itself. So I did them with some trivial changes, but it failed again. The following is the result:

$ update_rubygems191
<internal:gem_prelude>:344:in `method_missing': undefined method `bin_path' for Gem:Module (NoMethodError)
        from /Users/ujihisa/rubies/bin/update_rubygems191:19:in `<main>'

hmm...

Friday, October 2, 2009

What's Your View?

When I was a student, my supervisor often asked me the question. It confused me, which meant that I didn't understand what I was talking.

Although the relationship between understanding the contents and grasping the view is bi-directionally, it is worth trying to grasp the view of a given research first, then understand the remains. This strategy is easier, particularly for me. Never forget to look for the author's viewpoint. Ask myself: "What's the view of the research?" Now I must be able to find the goal of the research easily.

Programming Language as Human Interface

5 Reasons Why People Use This Language

There are a lot of programming languages both in the real world and in the academic experimental world. Everybody knows the common function which Professor Turing defined among the languages. Although almost all programming languages which are used as a production can be ultimately written in a single language, we tend to use specific languages for some reasons.

  1. Our project has used this language.
  2. Our project needs a specific library written in this language.
  3. We're excel at this language.
  4. A specific functionality of this language is absolutely effective on our project.
  5. The syntax of this language is good.

This order means the order of impact. Yes, unfortunately the syntax matters the least.

Note that only (3) and (5) are independent on a specific project, and (3) can be said a consequence of (5). Therefore it is deducted that (5) is worth studying.

Human Computer Interaction

According to wikipedia, human computer interaction, also known as the study of human interface, is defined as the study of interaction between people and computers. In other words, human computer interaction is the combination of computer science, behavioral sciences, design and several other fields of study. The goal of HCI (Human Computer Interaction) is to improve the interactions between users and computers by making computers more usable and receptive to the user's needs.

I think that the biggest challenge of this field is how to evaluate the goodness of a given hypothesis. We cannot deductively prove the new theory certainly makes a system more usable easily. We cannot numerically measure how the new theory certainly improved the usability easily.

Programming Language as Human Computer Interaction

Remember the conclusion of the reason why we use a specific programming language, which is previously described: "because the syntax of this language is good." Here we have to consider how to evaluate the goodness of the language. It is difficult for language designers and users to objectively explain how good their language syntax is. This circumstance is highly similar to the issue of HCI.

For example, some people agree the following example: Ruby is better than Java because of the simple "Hello, world!" sample obviously.

# Ruby
puts 'Hello, world!'

/* Java */
class HelloWorld {
  public static void main(String argv) {
    System.out.println("Hello, world!");
  }
}

It is easy for me to disagree the opinion. I don't think I have to declare the reasons here because you can presume easily.

So, how can we evaluate the goodness of language syntax without any controversial counterargument? What points of view are desirable for the purpose? This issue is worth studying.

Conclusion

Programming language has aspects of the study of human computer interaction. I showed only the importance of syntax as one of aspects, but there are some other features include being able to complete by editors and type system for human aid. It turns out that it is good to improve it with the similar ways of previously used in HCI studies.

Other Miscellaneous Comments

According to ACM, HCI is defined as "a discipline concerned with the design, evaluation and implementation of interactive computing systems for human use and with the study of major phenomena surrounding them." In short, HCI is for implementation of interactive computing system. Whereas my view on this entry is for implementation of implementation of interactive computing system. It can be said as higher order HCI.

Thursday, October 1, 2009

Google Earth In Canada

Google Maps in Canada is sometimes insufficient. Information on the map in Canada isn't as rich as in Japan or in the US. The satellite is outdated.

Today I installed Google Earth on my MacBook Air and viewed my neighborhood. I surprised that Google Earth is absolutely greater than Google Maps regarding to the contents.

vpl1

http://home.graffiti.net/rec_images01:graffiti.net/nutcrew/7th20/Vancouver_public_library_vancouver_british_columbia.jpg

This is my nearest public library.

In Google Earth,

vpl

It's amazingly real.

Monday, September 21, 2009

Beautiful and Functional English Writing Software

These days I am concentrated in improving my English skill; particularly in listening and writing. Actually now I'm under increasing pressure because the score of the result of my last TOEFL exam was bad rather than insufficient. So I decided not to code programs too much as my hobby, but to write English essays more and more. I have less time to do all things what I like than usual.

To write English essays more efficiently, I wish such editors:

  • Beautiful rendering with proportional fonts
  • Rich functionalities

When I mentioned about "rich functionalities" in the context of text editing, it stands for Vim. But unfortunately Vim doesn't support proportional fonts but supports only monospaced fonts. Monospaced fonts are beautiful in programming languages, but in natural English language, they aren't.

So I wrote a patch for supporting proportional fonts on MacVim.

1

Building MacVim with my patch

First of all, fetch the MacVim source and build plain Vim.

$ git clone git://repo.or.cz/MacVim.git MacVimUjihisa
$ cd MacVimUjihisa/src
$ ./configure --enable-gui=macvim
$ make

Create the following patch file on a.patch:

diff --git a/src/MacVim/MMTextStorage.m b/src/MacVim/MMTextStorage.m
index 0d272b2..0327a8f 100644
--- a/src/MacVim/MMTextStorage.m
+++ b/src/MacVim/MMTextStorage.m
@@ -656,12 +656,8 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
         cellSize.width = ceilf(em * cellWidthMultiplier);

         float pointSize = [newFont pointSize];
-        NSDictionary *dict = [NSDictionary
-            dictionaryWithObject:[NSNumber numberWithFloat:cellSize.width]
-                          forKey:NSFontFixedAdvanceAttribute];

         NSFontDescriptor *desc = [newFont fontDescriptor];
-        desc = [desc fontDescriptorByAddingAttributes:dict];
         font = [NSFont fontWithDescriptor:desc size:pointSize];
         [font retain];

@@ -680,21 +676,18 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";
         boldFont = [[NSFontManager sharedFontManager]
             convertFont:font toHaveTrait:NSBoldFontMask];
         desc = [boldFont fontDescriptor];
-        desc = [desc fontDescriptorByAddingAttributes:dict];
         boldFont = [NSFont fontWithDescriptor:desc size:pointSize];
         [boldFont retain];

         italicFont = [[NSFontManager sharedFontManager]
             convertFont:font toHaveTrait:NSItalicFontMask];
         desc = [italicFont fontDescriptor];
-        desc = [desc fontDescriptorByAddingAttributes:dict];
         italicFont = [NSFont fontWithDescriptor:desc size:pointSize];
         [italicFont retain];

         boldItalicFont = [[NSFontManager sharedFontManager]
             convertFont:italicFont toHaveTrait:NSBoldFontMask];
         desc = [boldItalicFont fontDescriptor];
-        desc = [desc fontDescriptorByAddingAttributes:dict];
         boldItalicFont = [NSFont fontWithDescriptor:desc size:pointSize];
         [boldItalicFont retain];
     }
@@ -714,32 +707,25 @@ static NSString *MMWideCharacterAttributeName = @"MMWideChar";

         float pointSize = [newFont pointSize];
         NSFontDescriptor *desc = [newFont fontDescriptor];
-        NSDictionary *dictWide = [NSDictionary
-            dictionaryWithObject:[NSNumber numberWithFloat:2*cellSize.width]
-                          forKey:NSFontFixedAdvanceAttribute];

-        desc = [desc fontDescriptorByAddingAttributes:dictWide];
         fontWide = [NSFont fontWithDescriptor:desc size:pointSize];
         [fontWide retain];

         boldFontWide = [[NSFontManager sharedFontManager]
             convertFont:fontWide toHaveTrait:NSBoldFontMask];
         desc = [boldFontWide fontDescriptor];
-        desc = [desc fontDescriptorByAddingAttributes:dictWide];
         boldFontWide = [NSFont fontWithDescriptor:desc size:pointSize];
         [boldFontWide retain];

         italicFontWide = [[NSFontManager sharedFontManager]
             convertFont:fontWide toHaveTrait:NSItalicFontMask];
         desc = [italicFontWide fontDescriptor];
-        desc = [desc fontDescriptorByAddingAttributes:dictWide];
         italicFontWide = [NSFont fontWithDescriptor:desc size:pointSize];
         [italicFontWide retain];

         boldItalicFontWide = [[NSFontManager sharedFontManager]
             convertFont:italicFontWide toHaveTrait:NSBoldFontMask];
         desc = [boldItalicFontWide fontDescriptor];
-        desc = [desc fontDescriptorByAddingAttributes:dictWide];
         boldItalicFontWide = [NSFont fontWithDescriptor:desc size:pointSize];
         [boldItalicFontWide retain];
   }

Then apply it:

$ patch -p2 < a.patch
$ xcodebuild

Then run it:

$ open build/Release/MacVim.app

Then fix its font config.

Known Bugs

  • In insert mode, the location of cursor is far from correct location.
    • a
  • Vertical split is broken.
    • b
  • Handling screenwidth. Now Vim wraps in a strange position.

Now I don't have time to fix the problems.

What's the Difference Between Rip and Bundler?

In the Rip mailing list, defunkt says:

Bundler is for installing gems. Rip is for managing your load path and installed packages.

Rip isn't yet ready to manage your deployments, whereas I think bundler is.

This short answer could be helpful.

Sunday, September 20, 2009

How To Skim Long Sentences Quickly

How can non-English speaking people skim long sentences quickly? Today I saw the light with the hack:

One way to increase your comprehension is to ignore all the extra words in a sentence -- trim the fat.

-- Cracking the TOEFL iBT 2008 edition

It could applied for only formal sentences.

To examine how it works, let me demo with the following sentences:

The Leland Stanford Junior University, commonly referred to as Stanford University or Stanford, is a private research university located in Stanford, California, United States. The university was founded in 1885 by United States Senator and former California governor Leland Stanford and his wife, Jane Lathrop Stanford, as a memorial to their son Leland Stanford Jr., who died of typhoid in Italy a few weeks before his 16th birthday. The Stanfords used their farm lands in Palo Alto to establish the university hoping to create a large institution of higher education in California.

Stanford enrolls about 6,700 undergraduate and about 8,000 graduate students from the United States and around the world every year. The university is divided into a number of schools such as the Stanford Business School, Stanford Law School, Stanford School of Medicine, and Stanford School of Engineering. The university is in Silicon Valley, and its alumni have founded companies including Nike, Hewlett-Packard, Electronic Arts, Sun Microsystems, Nvidia, Yahoo!, Cisco Systems, Silicon Graphics and Google.

The USNWR ranked Stanford's undergraduate program fourth in the nation, and Stanford is consistently ranked high in other college and university rankings. Stanford is one of two private universities that compete in the Pacific-10 Conference. Stanford's main athletic rival is Cal, and the two schools meet annually in the Big Game, a football game in which the winner is awarded the Stanford Axe.

-- http://en.wikipedia.org/wiki/Stanford_University

They become the followings:

  • The Leland Stanford Junior University is a private research university. The university was founded. The Stanfords used their farm lands.
  • Stanford enrolls. The university is divided. The university is. Its alumni have founded companies.
  • The USNWR ranked. Stanford is ranked. Stanford is one of two private universities. Stanford's main athletic rival is Cal.

Of course the fat part which is eliminated is also important for understanding what the sentences are stating, but it doesn't base the structure.

I thought skimming English sentences meant that just see each word flatly and quickly, but it was wrong. It is important for particularly non-English speaking people to catch only the important parts, in this case which are Subject, Verb and Object in each sentences.

Saturday, September 19, 2009

Integrative Biology 131 - Lecture 01: Organization of Body

Integrative Biology 131 - Lecture 01: Organization of Body by Professor Merian Diamond

http://www.youtube.com/watch?v=S9WtBRNydso

Story

  1. She likes starting her class with the phrase "Good morning!" because of the words' positive thought for nervous systems.
  2. Did you introspect? Learn who you are. Be healthy.
  3. First question: how many of you know the structural and functional unit of the lung?
  4. Second question: how many of you know the structural and functional unit of the compact bone?
  5. Third question: how many of you know the structural and functional unit of the most complex part in the earth?
    • A: Human brains
  6. Remember the names of the people who are sitting next to you within 2 minutes.
  7. Every week I pick two students randomly to go to lunch with.
  8. General information (Office hours, books and etc.)
  9. Biology terminologies are mostly from Greek or Latin
  10. Anatomy: Greek; up dissent
  11. Genitals: bird
  12. Carotid: in neck take blood to brain - stupor
  13. Uterus: hysteria
  14. Femur: thigh
  15. Penis: tail
  16. Once you know you never forget them
  17. Techniques to study: gross anatomy c naked eyes ("c" is an abbreviation of "with")
  18. In past we could research dead tissues but these days we can research living tissues with NMR.
  19. Muscles and bones are growing up

Wednesday, September 16, 2009

rubyconf japanese attendee skype public chat room

http://tinyurl.com/klx3ap

Mac OS X Desktop Application Development with Ruby

takao7 published a book "Mac OS X Desktop Application Development with Ruby" (『RubyによるMac OS Xデスクトップアプリケーション開発入門』) I am interested in developing OS X local applications with Ruby very much. #RHCBK

This book is written in Japanese, but I think somebody will translate it to English.

I'm also interested the abbreviation name of this book's title RHC. The title reminds rubyists the Ruby Bible RHG: Ruby Hacking Guide by Minero Aoki.

Monday, September 14, 2009

Git Lessons Learned For Speedup

TOPIC: To know whether we can push or not without doing pull.

git status isn't reliable for this purpose. Even if the result was the following, it doesn't mean we can push without pull. The current branch may be outdated with origin's.

# On branch master
nothing to commit (working directory clean)

git ls-remote origin master is also not. Once we committed, the sha1 is already changed, therefore we cannot compare it to remote's.

So, although this has side effects, git fetch is the best solution for this problem. Doing git fetch periodically on background, and then checking git status is fast and easy way.

In short,

$ ruby -e 'loop { `git fetch` }'

In another shell.

Thursday, September 10, 2009

I Will Speak At RubyConf 2009

rubyconf2009

http://rubyconf.org/

I got an email from Ruby Central this morning.

Thank you for submitting a proposal to speak at RubyConf 2009. We're happy to let you know that your proposal, "Hacking parse.y", has been selected for inclusion in the program.

(snip)

The talks are 45 minutes long, including any Q&A you want to do.

Victoryy!

[Fri Sep 11 19:35:10 PDT 2009 Added]

Wednesday, September 9, 2009

RubyKaigi2009 Best Shots

Do you remember RubyKaigi this year in Japan? Here I'll pick some photos up. They are from Flickr CC Search. (If you don't want to show some of them, feel free to ask me).

http://www.flickr.com/photos/recompile_net/3732360065/

Jugyo the Termtter Founder

http://www.flickr.com/photos/koichiroo/3739822729/

"Java is just a shit" by kitaj (The person is not kitaj but kazuhiko.)

http://www.flickr.com/photos/koichiroo/3740461484/

Higeno Yamaotoko and Ninja of mystery

http://www.flickr.com/photos/recompile_net/3732368117/

RubyKaigi2009 great Staff

http://www.flickr.com/photos/recompile_net/3735212805/

Very young rubyist with "Enterprise Rails"

http://www.flickr.com/photos/33304338@N05/3738447946/

"Why" in Japanese

http://www.flickr.com/photos/kakutani/3745964866/

Council of War

http://www.flickr.com/photos/koichiroo/3739567849/ http://www.flickr.com/photos/koichiroo/3740339276/

TermtterKaigi2009

http://www.flickr.com/photos/darashi/3757919788/

<3

http://www.flickr.com/photos/recompile_net/3732288679/

Kakutani The Ruby Evangelist

http://www.flickr.com/photos/33304338@N05/3732661890/

Typical Programming Style

http://www.flickr.com/photos/koichiroo/3731962457/

Arton and me

http://www.flickr.com/photos/koichiroo/3732781410/

Matz (next to me!)

http://www.flickr.com/photos/iogi/3752528300/

Emobile Hacks

Wednesday, September 2, 2009

Summary: Haskell in the Real World

I read a paper.

Curt Sampson "Experience Report: Haskell in the Real World Writing a Commercial Program in Haskell", draft of submission to ICFP 2009

This paper is not for theoretical purpose but for practical one even though the title includes the purely functional language Haskell.

I have been using Haskell for 3 years, but for draft or experimental one, not for actual production. In contrast Curt Sampson, the author of the paper, used Haskell for production code int the real world.

The paper in short

  • Curt Sampson is an experienced Java programmer, who knows C and Ruby as well.

  • He got interested in functional programming languages due to Paul Graham indirectly.

  • He wrote a financial application in Haskell for his client in the spring of 2008, instead of in Java.

  • "We explained that, for us, switching languages every few years was a normal technology upgrade,"

  • He looked for a language which provides concise yet expressive code, so that his client can read and modify them.

  • It's important not to have to change his tool for new language; e.g. Smalltalk needs special environments.

  • He decided to use Haskell instead of OCaml or Scala, because:
    • Once he considered to use OCaml, but the syntax was not clear enough for him; Double semicolons and lack of overloaded functions mattered.
    • Once he considered to use Scala, but he got dissapointed to know that it couldn't run native code.
  • Haskell codes are readable even for non-programmers.

  • He wrote his own parser library, to offer stateful parsing with ByteString in contrary to the standard library Parsec.

  • Haskell needs fewer lines of test code than Ruby.

  • Haskell is more portable than C++ even when his application involved interfacing with the Microsoft products. GHC has a good FFI.

  • Lazy evaluation causes two problems, threads and space leaks. GHC's profiler helps solving the problems, but not enough.

Conclusion: Haskell is the ultimate language.

Tuesday, September 1, 2009

Installing JHC Via Cabal on Haskell Platform

Haskell Platform may make us happier. I tried to install jhc the haskell compiler via cabal of my haskell platform.

$ cabal install jhc -v
/usr/bin/ghc --numeric-version
looking for package tool: ghc-pkg near compiler in /usr/bin
found package tool in /usr/bin/ghc-pkg
/usr/bin/ghc-pkg --version
/usr/bin/ghc --supported-languages
Reading installed packages...
/usr/bin/ghc-pkg dump --global
/usr/bin/ghc-pkg dump --user
Reading available packages...
Resolving dependencies...
selecting jhc-0.5.20081118.3 (hackage) and discarding jhc-0.5.20081118,
0.5.20081118.1 and 0.5.20081118.2
selecting base-3.0.3.1 (installed) and 4.1.0.0 (installed) and discarding
syb-0.1.0.0 and 0.1.0.1
selecting ghc-prim-0.1.0.0 (installed)
selecting integer-0.1.0.1 (installed)
selecting rts-1.0 (installed)
selecting syb-0.1.0.1 (installed)
In order, the following would be installed:
jhc-0.5.20081118.3 (new package)
jhc-0.5.20081118.3 has already been downloaded.
Extracting
/Users/ujihisa/.cabal/packages/hackage.haskell.org/jhc/0.5.20081118.3/jhc-0.5.20081118.3.tar.gz
to
/var/folders/Dz/Dz5WpFSZGUaFLA8jp8kT5E+++TM/-Tmp-/jhc-0.5.20081118.342599...
Configuring jhc-0.5.20081118.3...
Dependency base -any && ==3.0.3.1: using base-3.0.3.1
Using Cabal-1.6.0.3 compiled by ghc-6.10
Using compiler: ghc-6.10.3
Using install prefix: /Users/ujihisa/.cabal
Binaries installed in: /Users/ujihisa/.cabal/bin
Libraries installed in:
/Users/ujihisa/.cabal/lib/jhc-0.5.20081118.3/ghc-6.10.3
Private binaries installed in: /Users/ujihisa/.cabal/libexec
Data files installed in: /Users/ujihisa/.cabal/share/jhc-0.5.20081118.3
Documentation installed in: /Users/ujihisa/.cabal/share/doc/jhc-0.5.20081118.3
Using alex version 2.3.1 found on system at: /opt/local/bin/alex
Using ar found on system at: /usr/bin/ar
No c2hs found
No cpphs found
No ffihugs found
Using gcc version 4.0.1 found on system at: /usr/bin/gcc
Using ghc version 6.10.3 found on system at: /usr/bin/ghc
Using ghc-pkg version 6.10.3 found on system at: /usr/bin/ghc-pkg
No greencard found
Using haddock version 2.4.2 found on system at: /usr/bin/haddock
Using happy version 1.18.2 found on system at: /usr/local/bin/happy
No hmake found
Using hsc2hs version 0.67 found on system at: /usr/bin/hsc2hs
No hscolour found
No hugs found
No jhc found
Using ld found on system at: /usr/bin/ld
No nhc98 found
Using pkg-config version 0.23 found on system at: /opt/local/bin/pkg-config
Using ranlib found on system at: /usr/bin/ranlib
Using strip found on system at: /usr/bin/strip
Using tar found on system at: /usr/bin/tar
/usr/bin/gcc /var/folders/Dz/Dz5WpFSZGUaFLA8jp8kT5E+++TM/-Tmp-/42599.c -o /var/folders/Dz/Dz5WpFSZGUaFLA8jp8kT5E+++TM/-Tmp-/42599 -D__GLASGOW_HASKELL__=610 -I. -I/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.3/base-4.1.0.0/include -I/Library/Frameworks/GHC.framework/Versions/610/usr/lib/ghc-6.10.3/include -IPAPI_INCLUDE_DIR
cabal: Package jhc-0.5.20081118.3 can't be built on this system.
cabal: Error: some packages failed to install:
jhc-0.5.20081118.3 failed during the building phase. The exception was:
exit: ExitFailure 1

;-(

So, as blackdog suggested, I decided to build jhc by the source code.

jhc official site explains first I have to get source by darcs, but at the time I didn't have it. Let's install darcs.

$ cabal install darcs
Resolving dependencies...
[1 of 2] Compiling Distribution.ShellHarness ( /var/folders/Dz/Dz5WpFSZGUaFLA8jp8kT5E+++TM/-Tmp-/darcs-2.3.099527/darcs-2.3.0/Distribution/ShellHarness.hs, /var/folders/Dz/Dz5WpFSZGUaFLA8jp8kT5E+++TM/-Tmp-/darcs-2.3.099527/darcs-2.3.0/dist/setup/Distribution/ShellHarness.o )
[2 of 2] Compiling Main             ( /var/folders/Dz/Dz5WpFSZGUaFLA8jp8kT5E+++TM/-Tmp-/darcs-2.3.099527/darcs-2.3.0/Setup.lhs, /var/folders/Dz/Dz5WpFSZGUaFLA8jp8kT5E+++TM/-Tmp-/darcs-2.3.099527/darcs-2.3.0/dist/setup/Main.o )
Linking /var/folders/Dz/Dz5WpFSZGUaFLA8jp8kT5E+++TM/-Tmp-/darcs-2.3.099527/darcs-2.3.0/dist/setup/setup ...
Configuring darcs-2.3.0...
Preprocessing library darcs-2.3.0...
Preprocessing executables for darcs-2.3.0...
Building darcs-2.3.0...

src/Darcs/Commands/Optimize.lhs:26:7:
    Could not find module `Text.Regex':
      There are files missing in the `regex-compat-0.92' package,
      try running 'ghc-pkg check'.
      Use -v to see a list of the files searched for.
cabal: Error: some packages failed to install:
darcs-2.3.0 failed during the building phase. The exception was:
exit: ExitFailure 1

What. OK. I have to do ghc-pkg check. I see.

$ ghc-pkg check
There are problems in package network-2.2.1.4:
  import-dirs: /Users/ujihisa/.cabal/lib/network-2.2.1.4/ghc-6.10.3 doesn't exist or isn't a directory
  library-dirs: /Users/ujihisa/.cabal/lib/network-2.2.1.4/ghc-6.10.3 doesn't exist or isn't a directory
  include-dirs: /Users/ujihisa/.cabal/lib/network-2.2.1.4/ghc-6.10.3/include doesn't exist or isn't a directory
  file Network.hi is missing
  file Network/BSD.hi is missing
  file Network/Socket/Internal.hi is missing
  file Network/Socket.hi is missing
  file Network/URI.hi is missing
  cannot find libHSnetwork-2.2.1.4.a on library path
There are problems in package HTTP-4000.0.7:
  import-dirs: /Users/ujihisa/.cabal/lib/HTTP-4000.0.7/ghc-6.10.3 doesn't exist or isn't a directory
  library-dirs: /Users/ujihisa/.cabal/lib/HTTP-4000.0.7/ghc-6.10.3 doesn't exist or isn't a directory
  file Network/BufferType.hi is missing
  file Network/Stream.hi is missing
  file Network/StreamDebugger.hi is missing
  file Network/StreamSocket.hi is missing
  file Network/TCP.hi is missing
  file Network/HTTP.hi is missing
  file Network/HTTP/Headers.hi is missing
  file Network/HTTP/Base.hi is missing
  file Network/HTTP/Stream.hi is missing
  file Network/HTTP/HandleStream.hi is missing
  file Network/Browser.hi is missing
  file Network/HTTP/Base64.hi is missing
  file Network/HTTP/MD5.hi is missing
  file Network/HTTP/MD5Aux.hi is missing
  file Network/HTTP/Utils.hi is missing
  cannot find libHSHTTP-4000.0.7.a on library path
There are problems in package regex-base-0.93.1:
  import-dirs: /Users/ujihisa/.cabal/lib/regex-base-0.93.1/ghc-6.10.3 doesn't exist or isn't a directory
  library-dirs: /Users/ujihisa/.cabal/lib/regex-base-0.93.1/ghc-6.10.3 doesn't exist or isn't a directory
  file Text/Regex/Base.hi is missing
  file Text/Regex/Base/RegexLike.hi is missing
  file Text/Regex/Base/Context.hi is missing
  file Text/Regex/Base/Impl.hi is missing
  cannot find libHSregex-base-0.93.1.a on library path
There are problems in package regex-posix-0.94.1:
  import-dirs: /Users/ujihisa/.cabal/lib/regex-posix-0.94.1/ghc-6.10.3 doesn't exist or isn't a directory
  library-dirs: /Users/ujihisa/.cabal/lib/regex-posix-0.94.1/ghc-6.10.3 doesn't exist or isn't a directory
  file Text/Regex/Posix.hi is missing
  file Text/Regex/Posix/Wrap.hi is missing
  file Text/Regex/Posix/String.hi is missing
  file Text/Regex/Posix/Sequence.hi is missing
  file Text/Regex/Posix/ByteString.hi is missing
  file Text/Regex/Posix/ByteString/Lazy.hi is missing
  cannot find libHSregex-posix-0.94.1.a on library path
There are problems in package regex-compat-0.92:
  import-dirs: /Users/ujihisa/.cabal/lib/regex-compat-0.92/ghc-6.10.3 doesn't exist or isn't a directory
  library-dirs: /Users/ujihisa/.cabal/lib/regex-compat-0.92/ghc-6.10.3 doesn't exist or isn't a directory
  file Text/Regex.hi is missing
  cannot find libHSregex-compat-0.92.a on library path
There are problems in package time-1.1.4:
  import-dirs: /Users/ujihisa/.cabal/lib/time-1.1.4/ghc-6.10.3 doesn't exist or isn't a directory
  library-dirs: /Users/ujihisa/.cabal/lib/time-1.1.4/ghc-6.10.3 doesn't exist or isn't a directory
  include-dirs: /Users/ujihisa/.cabal/lib/time-1.1.4/ghc-6.10.3/include doesn't exist or isn't a directory
  file Data/Time/Calendar.hi is missing
  file Data/Time/Calendar/MonthDay.hi is missing
  file Data/Time/Calendar/OrdinalDate.hi is missing
  file Data/Time/Calendar/WeekDate.hi is missing
  file Data/Time/Calendar/Julian.hi is missing
  file Data/Time/Calendar/Easter.hi is missing
  file Data/Time/Clock.hi is missing
  file Data/Time/Clock/POSIX.hi is missing
  file Data/Time/Clock/TAI.hi is missing
  file Data/Time/LocalTime.hi is missing
  file Data/Time/Format.hi is missing
  file Data/Time.hi is missing
  file Data/Time/Calendar/Private.hi is missing
  file Data/Time/Calendar/Days.hi is missing
  file Data/Time/Calendar/Gregorian.hi is missing
  file Data/Time/Calendar/JulianYearDay.hi is missing
  file Data/Time/Clock/Scale.hi is missing
  file Data/Time/Clock/UTC.hi is missing
  file Data/Time/Clock/CTimeval.hi is missing
  file Data/Time/Clock/UTCDiff.hi is missing
  file Data/Time/LocalTime/TimeZone.hi is missing
  file Data/Time/LocalTime/TimeOfDay.hi is missing
  file Data/Time/LocalTime/LocalTime.hi is missing
  file Data/Time/Format/Parse.hi is missing
  cannot find libHStime-1.1.4.a on library path
There are problems in package rts-1.0:
  include-dirs: PAPI_INCLUDE_DIR doesn't exist or isn't a directory

The following packages are broken, either because they have a problem
listed above, or because they depend on a broken package.
network-2.2.1.4
HTTP-4000.0.7
regex-base-0.93.1
regex-posix-0.94.1
regex-compat-0.92
time-1.1.4
rts-1.0
binary-0.5.0.1
digest-0.0.0.6
utf8-string-0.3.5
zip-archive-0.1.1.3
Diff-0.1.2
QuickCheck-2.1.0.1
binary-0.5
derive-0.1.4
dlist-0.5
fingertree-0.0.1.0
ghc-paths-0.1.0.5
pureMD5-1.0.0.0
rosezipper-0.1
split-0.1.1
terminfo-0.3.0.2
transformers-0.1.4.0
data-accessor-0.2.0.2
monads-fd-0.0.0.1
data-accessor-monads-fd-0.2
pointedlist-0.3.5
uniplate-1.2.0.3
unix-compat-0.1.2.1
utility-ht-0.0.5.1
data-accessor-template-0.2.1.1
vty-3.1.8.4
language-c-0.3.1.1
haskeline-0.6.1.6
mmap-0.4.1
zlib-0.5.2.0
hashed-storage-0.3.7
haddock-2.4.2
ghc-6.10.3
ghc-prim-0.1.0.0
integer-0.1.0.1
base-4.1.0.0
syb-0.1.0.1
base-3.0.3.1
array-0.2.0.0
packedstring-0.1.0.1
containers-0.2.0.1
bytestring-0.9.1.4
old-locale-1.0.0.1
old-time-1.0.0.2
filepath-1.1.0.2
unix-2.3.2.0
directory-1.0.0.3
process-1.0.1.1
pretty-1.0.1.0
hpc-0.5.0.3
template-haskell-2.3.0.1
Cabal-1.6.0.3
random-1.0.0.1
haskell98-1.0.1.0
extensible-exceptions-0.1.1.0
network-2.2.1
time-1.1.3
dph-base-0.3
dph-prim-interface-0.3
dph-prim-seq-0.3
dph-prim-par-0.3
dph-seq-0.3
dph-par-0.3
OpenGL-2.2.1.1
network-2.2.1.1
haskell-src-1.0.1.3
GLUT-2.1.1.2
regex-base-0.72.0.2
QuickCheck-1.2.0.0
mtl-1.1.0.2
HUnit-1.2.0.3
cgi-3001.1.7.1
html-1.0.1.2
editline-0.2.1.0
stm-2.1.1.2
regex-posix-0.72.0.3
regex-compat-0.71.0.1
parsec-2.1.0.1
parallel-1.1.0.1
HTTP-4000.0.6
fgl-5.4.2.2
zlib-0.5.0.0
xhtml-3000.2.0.1
time-1.1.2.4

?

$ cabal reinstall regex-compat
unrecognised command: reinstall (try --help)
$ cabal install regex-compat --reinstall
Resolving dependencies...
Downloading regex-compat-0.92...
Configuring regex-compat-0.92...
Preprocessing library regex-compat-0.92...
Building regex-compat-0.92...

Text/Regex.hs:35:7:
    Could not find module `Text.Regex.Posix':
      There are files missing in the `regex-posix-0.94.1' package,
      try running 'ghc-pkg check'.
      Use -v to see a list of the files searched for.
cabal: Error: some packages failed to install:
regex-compat-0.92 failed during the building phase. The exception was:
exit: ExitFailure 1

???

OK. I forget them. Let's install by stable tar ball. http://repetae.net/dist/jhc-0.7.2.tar.gz this one.

$ cd src
$ wget http://repetae.net/dist/jhc-0.7.2.tar.gz                                                          [20:35:46]
$ cd jhc-0.7.2
$ ./configure --prefix=`pwd`/jhc
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... ac-macros/install-sh -c -d
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking build system type... i386-apple-darwin9.8.0
checking host system type... i386-apple-darwin9.8.0
checking whether ln -s works... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /usr/bin/grep
checking for egrep... /usr/bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking whether byte ordering is bigendian... no
checking for ghc... /usr/bin/ghc
checking for DrIFT... no
DrIFT not found: using preprocessed files
checking for module Data.Generics.Instances... in package syb
checking for hsc2hs... /usr/bin/hsc2hs
configure: creating ./config.status
config.status: creating Makefile
config.status: creating jhc.spec
config.status: creating src/Version/Config.hs
config.status: creating docs/building.mkd
config.status: creating src/cbits/config.h
$ make && make install
make  all-am
/usr/bin/ghc  -fbang-patterns -O -hide-all-packages -package base -package syb  -W -fno-warn-unused-matches  -fwarn-type-defaults -i -i./drift_processed -i./src  -i./src -odir ./src -hidir ./src -package fgl -package regex-compat -package random -package array -package readline -package directory -package bytestring -package binary -package pretty -package mtl -package containers -package unix  -package haskell98 -package utf8-string  -package zlib -fallow-undecidable-instances  -fglasgow-exts -fallow-overlapping-instances --make src/Main.hs src/StringTable/StringTable_cbits.o  src/cbits/md5sum.o -o jhc

on the commandline:
    Warning: -fbang-patterns is deprecated: use -XBangPatterns or pragma {-# LANGUAGE BangPatterns#-} instead

on the commandline:
    Warning: -fallow-undecidable-instances is deprecated: use -XUndecidableInstances or pragma {-# LANGUAGE UndecidableInstances#-} instead

on the commandline:
    Warning: -fallow-overlapping-instances is deprecated: use -XOverlappingInstances or pragma {-# LANGUAGE OverlappingInstances#-} instead
<command line>: unknown package: readline
make[1]: *** [jhc] Error 1
make: *** [all] Error 2

I gave up.

Thursday, August 20, 2009

Visited Bay Area

It was my fourth visit to Bay Area also known as Silicon Valley. I stayed at my friend rakusai's house.

During the visit, almost all time I had been in Palo Alto.

Palo alto from wikipedia

palo alto facebook

Bay Area in Summer

Actually it was my first time to stay there in a summer season. I was truly surprised how it was cold, particularly in San Francisco. It was colder than in Vancouver, Canada.

summer san francisco

san francisco

I met some great people

First, I went to San Francisco to meet github people. San Francisco is pretty far from Palo Alto, so I had to came back soon. And also unfortunately the meetup place was very crowded and noisy, I had trouble with listening English there but I certainly met them. Thanks Tom, the next time is my turn to treat you to good alcohols.

github

Actually I would like to visit Engine Yard to meet Yahuda again as well, but he seemed to be so busy and I didn't want to bother him, so I couldn't met him this time.

Second, I met some Japanese friends include kenn, nobu and shotbt. I heard that kenn is making something new. Here I'll pass it over in silence.

photo from twitshot

Third, I went to Stanford University to meet a researcher and a professor. I asked the professor if my thought would be suit for your research team or not. I was anxious about it, but the professor answered it's absolutely theirs. I decided where to join a research team at the time if I would be admitted the university.

stanford

Now I'm in a hot country, Vancouver. Now I can see my goal in 2009 and the beginning of 2010. I will keep doing the thing what I should do.

My next visit to Bay Area may be November.


All photos are from flickr CC search.

Tuesday, August 18, 2009

Any Programming Languages Without Their Syntactic Sugars Are Esoteric Languages

Haskell is one of the ultimate programming language. Haskell has user friendly syntax, pragmatic purely functional model and really simple notation. But when it comes to throw the syntactic sugars, Haskell became an esoteric languages like yhara showed.

You can easily imagine how the Ruby programming language without its syntactic sugars is like.

Sunday, August 16, 2009

Try EventMachine

The Ruby library EventMachine makes us easy to write a network server/client software on Ruby.

Here's an echo server described in the EventMachine README.

require 'eventmachine'

module EchoServer
  def post_init
    puts "-- someone connected to the echo server!"
  end

  def receive_data data
    send_data ">>>you sent: #{data}"
    close_connection if data =~ /quit/i
  end

  def unbind
    puts "-- someone disconnected from the echo server!"
  end
end

EventMachine::run {
  EventMachine::start_server "127.0.0.1", 8081, EchoServer
}

Let's try it. Save the code to a.rb and do the command:

$ rake build
$ ruby -Ilib a.rb

Now the echo server started on port 8081. Let me check it on another terminal.

$ telnet localhost 8081
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying fe80::1...
telnet: connect to address fe80::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hi
>>>you sent: hi
hey
>>>you sent: hey

It certainly worked.

Say server

OSX has say command which speaks the given sentence. Now I'll write Say Server to handle notification from a remote machine.

require 'eventmachine'

module SayServer
  def receive_data(data)
    system 'say', data
    close_connection
  end
end

EventMachine::run {
  EventMachine::start_server "127.0.0.1", 8081, SayServer
}

It was too easy to fix it.

Unfortunately I didn't know how to make the server say a word in one line. The following command didn't work like I expected.

$ echo 'hi' | telnet localhost 8081

Spawned Processes

I found an interesting document in docs/SPAWNED_PROCESSES.

Spawned Processes in EventMachine are inspired directly by the "processes" found in the Erlang programming language. EM deliberately borrows much (but not all) of Erlang's terminology. However, EM's spawned processes differ from Erlang's in ways that reflect not only Ruby style, but also the fact that Ruby is not a functional language like Erlang.

Note that the word spawn doesn't mean Kernel.#spawn in ruby 1.9. This EventMachine.spawn generates something like an Erlang's tiny process, which can receive and send a message each other.

Here's sample ping-pong code:

require 'eventmachine'

EM.run {
  pong = EM.spawn {|x, ping|
    sleep 0.1
    puts "Pong received #{x}"
    ping.notify( x-1 )
  }

  ping = EM.spawn {|x|
    if x > 0
      puts "Pinging #{x}"
      pong.notify x, self
    else
      EM.stop
    end
  }

  ping.notify 3
}
p :finished

The result is:

$ ruby -Ilib a.rb
Pinging 3
Pong received 3
Pinging 2
Pong received 2
Pinging 1
Pong received 1
:finished

I expected that the message :finished would appers during the ping-pong, but didn't. I fixed the line 'ping.notify 3' into 'Thread.start { ping.notify 3}', but the result was still same. Even worse, 'fork { ping.notify 3 }' got frozen up.

[Aug 18 Added] Stoyan suggested that EM::Deferrable is suit to be used instead of Thread or spawn. The page he introduced shows the following sample code (I added comments on it a little to show the order of processing)

class Worker
  include EM::Deferrable

  def heavy_lifting
    # (3)
    3.times do |i|
      puts "Lifted #{i}"
      sleep 0.1
    end
    set_deferred_status :succeeded
  end
end

EM.run do
  # (1)
  worker = Worker.new
  worker.callback {
    # (4)
    p "done!"
  }
  Thread.new {
    # (2)
    worker.heavy_lifting
    # (5)
    EM.stop
  }
  # (3)'
  puts "resuming remaining program operations"
end

And the result is

Lifted 0
resuming remaining program operations
Lifted 1
Lifted 2
"done!"

Not Equal Is Not Not And Equal

In Ruby, != is tokenized as tNEQ instead of ! and =. Although the Ruby parser must be able to parse a sequence of ! and = as not-equal operator, it is considered as one token for ease. We cannot write those two symbols separately, but nobody wants to do.

By the way, send suggested that it would be very comprehensible to introduce a new not-equal operator ><. I wrote a patch for it for ruby.

diff --git a/parse.y b/parse.y
index 33660a2..77e6cbe 100644
--- a/parse.y
+++ b/parse.y
@@ -6586,6 +6586,11 @@ parser_yylex(struct parser_params *parser)
         return '<';

       case '>':
+        if ((c = nextc()) == '<' ) {
+            lex_state = EXPR_BEG;
+            return tNEQ;
+        }
+        pushback(c);
         switch (lex_state) {
           case EXPR_FNAME: case EXPR_DOT:
             lex_state = EXPR_ARG; break;

As a result, now we can run such a code.

codeshot

Tuesday, August 4, 2009

Hacking parse.y with me

Yesterday I made my first English presentation.

http://ruby.meetup.com/112/calendar/10614880/

What was the topic?

Since this year I have tried some short hacks with MRI (Matz Ruby Implementation), and showed the results on my blog. This presentation was what and how did I fix ruby. Almost half time of my presentation was demonstration, which includes applying patches and building ruby.

How was the presentation?

I must have spoken in awkward and broken English. I hope attendees could understand what I tried to explain. It was still difficult for me to speak and listen English. Even worse I had a trouble in listinig English. I hope I had answered correctly to questions.

The ruby meetup people were friendly and generous. Thank you very much!

workspace

workspace

workspace

(These photos are not my presentation. It's just for showing how the room was like.)

Blog Archive

Followers