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

Friday, June 26, 2009

VimM#4

Yesterday I hosted a Tech Conference VimM#4 at Tokyo, Japan. VimM#4 is the biggest Vim conference in Japan. More than 50 programmers gethered there.

VimM#4 Photo1

VimM#4 Photo2

There were 11 talks. I gave a talk about my blogger.vim. See the datails of all VimM#4 talks in http://vim-users.jp/2009/06/vimm4-ann/(in Japanese). I'll show a brief summary below in English.

Talks

Introduction to Vim Server with bonar

  • Vim as server
  • Demonstration of web server powered by vim(!)

Printing a Source Code with Vim with taku-o

  • How to print a source code with Vim
  • It is important to choose appropriate colorscheme

Extirpation of Mankind with ssig33

  • Dynamic typying programming language Japanese

Blogger.vim with ujihisa

11 Ways to make the shift to Vim from IDE with hagino_3000

  • Use good Key mappings

Vim on Emacs with ubuntu

  • Define what is Vim and what is Emacs

  • Emacs can behave like Vim

The only one document that a person who tries to master Vim with kana

  • kana wrote a systematic document on a magazine "Web+DB Press (Aug. 24)"
  • buy and read it!

Keynote with ujihisa

  • Write your summary on your blog, and trackback here!

My Impression

When I start planning to hold VimM#4 on the beggining of July, I've never imagine that it would become such a big meeting. There are a lot of programmers who use Vim every day.

The meeting was broadcasted on ustream. People in other area of Japan also watched it and gave questions us on IRC. People in Austria also watched us!

Thanks to harajune and Tokyo university people who were glad to provide us a room. Thanks to speakers. Thanks to kana and mickey24 who broadcasted VimM#4 on ustream. Thanks to some attendees gave us a lot of snacks and drinks.

VimM#4 Photo3

VimM#4 Photo4


This entry is also written in Japanese in the planet vim-users.jp.

Monday, June 22, 2009

The First Visit to Japan in the Past 3 Months

I had been in Vancouver, Canada for three months and I've been in Tokyo, Japan since yesterday. Because I have never stayed in foreign country, I came as a fresh reminder that there were some surprising things in Japan.

Air

The air in Japan is so different from Canada or the US.

The different thing I noticed first is smell. Japan smells differently from the US. It is difficult for me to explain that. (The US smells similarly from Canada, differently from the China. China smells differently from Japan. In short, Japan != China != US = Canada. I don't know other countries.)

Humidity level is very high, particularly in the end of June. The time span from the middle of June to the beginning of July is the biggest rainy season in Japan. It is called Baiu or Tsuyu. It will have been cloudy for a month. I came to Japan the very time, and I got baptized with it. Even when I feel the cool wind, I would get sweat inevitably. Our skin can never get dried.

People

People smell human scents. It is not common for Japanese people to use fragrant waters or deodorant compared to Canada or the US, so Japanese people don't smell chemicals but natural organisms, and unfortunately the latter one is bad in hot rain season.

I also found that almost all people are Japanese except in airports. In Canada, I can hear not only English but also Spanish, Korean, Chinese, Japanese and other languages. But in Japan only one language I can hear is Japanese. There certainly exist foreigners, but not many.

Japanese crowd

Foods

The only one word I need to say is: awesome. Eat Japanese foods infinitely in Japan.

Sukiya's Beef Dish and Salmon with rice and pork soup

---- (Images by Flickr CC)

Friday, June 19, 2009

Question About Making Slides

I'm looking for a slide maker for tech talk presentations which satisfy all of those requirements:

  1. Mathematics notation with LaTeX syntax
  2. Generates PDF
  3. Easy notation (like wiki, rdoc or markdown)
  4. Works in OS X
  5. Supports Multi-byte Characters (e.g. Japanese)
  6. Open Source
  7. Easy Image Organize

Those softwares did not satisfy:

  • LaTeX Beamer: Only 1, 2, 4, (5), 6
  • Keynote: Only 2, 4, 5, 7
  • Rabbit: Only 2, 3, 4, 5, 6
  • Vim: Only 2, 3, 4, 5, 6

LaTeX Beamer seems to be better than others, but the software itself is corrupt.

Markdown with LaTeX with Beamer

First of all, I'll show the conclusion. Never use LaTeX via Markdown to make a presentation slide with Beamer.

I have too many reasons why you should not use it to write here. I spent all a day with it, and the only one thing I found was that it was a never ending maze.

Sure, Markdown syntax provides us to simple notation. It may make us happy. But, as a practical matter, it does not help us without we write wrappers for each something forever.

Pandoc the Ultimate Markdown Utility

I installed pandoc by svn trunk source code, because I failed to install the dependency library haddock by MacPorts.

Install (for OS X)

Assume you have already * installed cabal. * have your local bin directory ~/bin

cabal install utf8-string
cabal install zip-archive
svn checkout http://pandoc.googlecode.com/svn/trunk/ pandoc
cd pandoc
CABALOPTS=--user make
make test
PREFIX=~ make install-exec

Note that the environment variable CABALOPTS=--user. I use cabal by normal user, not by super user. In the case we have to explicitly set it. Now you have pandoc commands in your ~/bin.

$ ls ~/bin
hsmarkdown
html2markdown
markdown2pdf
pandoc
(and others already you have...)

Usage

I think I don't have to show the usage of those commands, because those filenames are enough comprehensive. Therefore, I'll show some example input and output below.

$ pandoc -h
pandoc [OPTIONS] [FILES]
Input formats:  native, markdown, markdown+lhs, rst, rst+lhs, html, latex, latex+lhs
Output formats:  native, html, html+lhs, s5, docbook, opendocument, odt, latex, latex+lhs, context, texinfo, man, markdown, markdown+lhs, rst, rst+lhs, mediawiki, rtf
Options:
  -f FORMAT, -r FORMAT  --from=FORMAT, --read=FORMAT                    
  -t FORMAT, -w FORMAT  --to=FORMAT, --write=FORMAT                     
  -s                    --standalone                                    
  -o FILENAME           --output=FILENAME                               
  -p                    --preserve-tabs                                 
                        --tab-stop=TABSTOP                              
                        --strict                                        
                        --reference-links                               
  -R                    --parse-raw                                     
  -S                    --smart                                         
  -m[URL]               --latexmathml[=URL], --asciimathml[=URL]        
                        --mimetex[=URL]                                 
                        --jsmath[=URL]                                  
                        --gladtex                                       
  -i                    --incremental                                   
  -N                    --number-sections                               
                        --no-wrap                                       
                        --sanitize-html                                 
                        --email-obfuscation=none|javascript|references  
                        --toc, --table-of-contents                      
  -c CSS                --css=CSS                                       
  -H FILENAME           --include-in-header=FILENAME                    
  -B FILENAME           --include-before-body=FILENAME                  
  -A FILENAME           --include-after-body=FILENAME                   
  -C FILENAME           --custom-header=FILENAME                        
  -T STRING             --title-prefix=STRING                           
  -D FORMAT             --print-default-header=FORMAT                   
                        --dump-args                                     
                        --ignore-args                                   
  -v                    --version                                       
  -h                    --help                                          

Assume sample.md is below:

## This is a pen
Is this a pen? No, it is Nancy.

    def fib(n)
      rand(n) ** 2
    end

* hara y y hara y?
* y

Then

$ pandoc -t html sample.md
<div id="this-is-a-pen"
><h2
  >This is a pen</h2
  ><p
  >Is this a pen? No, it is Nancy.</p
  ><pre
  ><code
    >def fib(n)
  rand(n) ** 2
end
</code
    ></pre
  ><ul
  ><li
    >hara y y hara y?</li
    ><li
    >y</li
    ></ul
  ></div
>

What a crazy line breaks!

$ pandoc -t html sample.md
\subsection{This is a pen}

Is this a pen? No, it is Nancy.

\begin{verbatim}
def fib(n)
  rand(n) ** 2
end
\end{verbatim}
\begin{itemize}
\item
  hara y y hara y?
\item
  y
\end{itemize}

Yes.

$ echo 'hi' | pandoc -t html
<p
>hi</p
>

Stdin OK.

$ pandoc -t html sample.md | html2markdown
## This is a pen

Is this a pen? No, it is Nancy.

    def fib(n)
      rand(n) ** 2
    end

-   hara y y hara y?
-   y

That's amazing! That's what I've wanted!

I used html2text written in python for my blogger.vim. It can be used for converting markdown from html, but I found a lot of misconversions. I had to write some wrapper for my blogger.vim.

Now I got released from the burden. I decided to switch using this pandoc instead of the python library html2text.

Haddock Install Failed

I tried to install pandoc the markdown utility plus alpha, but I couldn't install the dependent library haddock.

$ sudo port install pandoc
--->  Building haddock
Error: Target org.macports.build returned: shell command "cd /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_devel_haddock/work/haddock-2.4.1 && ./Setup build -v" returned error 1
Command output: Creating dist/build/autogen (and its parents)
Preprocessing library haddock-2.4.1...
Preprocessing executables for haddock-2.4.1...
Building haddock-2.4.1...
Building library...
Creating dist/build (and its parents)
/opt/local/bin/ghc -package-name haddock-2.4.1 --make -hide-all-packages -no-user-package-conf -i -idist/build -isrc -idist/build/autogen -Idist/build/autogen -Idist/build -optP-include -optPdist/build/autogen/cabal_macros.h -odir dist/build -hidir dist/build -stubdir dist/build -package Cabal-1.6.0.3 -package array-0.2.0.0 -package base-4.1.0.0 -package containers-0.2.0.1 -package directory-1.0.0.3 -package filepath-1.1.0.2 -package ghc-6.10.2 -package ghc-paths-0.1.0.5 -package haskell98-1.0.1.0 -package pretty-1.0.1.0 -O -XCPP -XPatternGuards -XDeriveDataTypeable -XScopedTypeVariables -XMagicHash Distribution.Haddock Haddock.Types Haddock.InterfaceFile Haddock.Exception Haddock.Utils

src/Haddock/Utils.hs:1:13:
    Warning: -XPatternSignatures is deprecated: use -XScopedTypeVariables or pragma {-# LANGUAGE ScopedTypeVariables#-} instead
Linking...
/usr/bin/ar q dist/build/libHShaddock-2.4.1.a dist/build/Distribution/Haddock.o dist/build/Haddock/Types.o dist/build/Haddock/InterfaceFile.o dist/build/Haddock/Exception.o dist/build/Haddock/Utils.o
ar: creating archive dist/build/libHShaddock-2.4.1.a
/usr/bin/ld -x -r -o dist/build/HShaddock-2.4.1.o.tmp dist/build/Distribution/Haddock.o dist/build/Haddock/Types.o dist/build/Haddock/InterfaceFile.o dist/build/Haddock/Exception.o dist/build/Haddock/Utils.o
Building executable: haddock...
Creating dist/build/haddock (and its parents)
Creating dist/build/haddock/haddock-tmp (and its parents)
/opt/local/bin/ghc -o dist/build/haddock/haddock --make -hide-all-packages -no-user-package-conf -i -idist/build/haddock/haddock-tmp -isrc -idist/build/autogen -Idist/build/autogen -Idist/build/haddock/haddock-tmp -optP-include -optPdist/build/autogen/cabal_macros.h -odir dist/build/haddock/haddock-tmp -hidir dist/build/haddock/haddock-tmp -stubdir dist/build/haddock/haddock-tmp -package Cabal-1.6.0.3 -package array-0.2.0.0 -package base-4.1.0.0 -package containers-0.2.0.1 -package directory-1.0.0.3 -package filepath-1.1.0.2 -package ghc-6.10.2 -package ghc-paths-0.1.0.5 -package haskell98-1.0.1.0 -package pretty-1.0.1.0 -O -funbox-strict-fields -O2 -XCPP -XPatternGuards -XDeriveDataTypeable -XScopedTypeVariables -XMagicHash src/Main.hs

src/Main.hs:1:39:
    Warning: -XPatternSignatures is deprecated: use -XScopedTypeVariables or pragma {-# LANGUAGE ScopedTypeVariables#-} instead

src/Haddock/Utils.hs:1:13:
    Warning: -XPatternSignatures is deprecated: use -XScopedTypeVariables or pragma {-# LANGUAGE ScopedTypeVariables#-} instead
[15 of 24] Compiling Haddock.Interface.AttachInstances ( src/Haddock/Interface/AttachInstances.hs, dist/build/haddock/haddock-tmp/Haddock/Interface/AttachInstances.o )

src/Haddock/Interface/AttachInstances.hs:94:17:
    Ambiguous occurrence `funTyConName'
    It could refer to either `Haddock.Interface.AttachInstances.funTyConName', defined at src/Haddock/Interface/AttachInstances.hs:108:0
                          or `TypeRep.funTyConName', imported from TypeRep at src/Haddock/Interface/AttachInstances.hs:26:0-13

Error: The following dependencies failed to build: haddock
Error: Status 1 encountered during processing.

It is summarized as follows:

src/Haddock/Interface/AttachInstances.hs:94:17:
    Ambiguous occurrence `funTyConName'
    It could refer to either `Haddock.Interface.AttachInstances.funTyConName', defined at src/Haddock/Interface/AttachInstances.hs:108:0
                          or `TypeRep.funTyConName', imported from TypeRep at src/Haddock/Interface/AttachInstances.hs:26:0-13

I don't understand why Haddock developpers have made this mistake.

Sunday, June 14, 2009

One of The Worst Trap with MacBook Air

I got upset. My MacBook Air was suddenly crashed and I had to wait for a long time to boot it again in a cafe.

I had tried to plug an ear phone into my MacBook Air. Look at this figure:

MacBook Air USB Port and Ear Phone

We cannot see these ports without putting up MacBook Air very high. Therefore we have to plug an ear phone into it without seeing there. The worst trap with MacBook Air is that if we plug an ear phone into the very neighbor USB port, the machine will be crashed just at the time. There's no warning nor alert.

Friday, June 12, 2009

A Problem with Skype in a Specific Room

One of my friends found a bug of Skype. Although he cannot write English well, he put his efforts into reporting on the bug to a skype user support forum.

http://www.kanasansoft.com/weblab/2009/06/skyperoom.html (in Japanese)

Hello.

I fond bug of function of "topic".
If "<" is put in the topic, the display becomes amusing.
It is not possible to make remarks with Windows.
In Mac, "&amp;" in topic is evaluated as "&".

His effort is great. Even though there are some awkward expressions, his message may be came across.

I'll show a correct of that report for the couse of his improvement.

> I fond bug of function of "topic".
I love a bug in the topic feature.
> If "<" is put in the topic, the display becomes amusing.
If there's "<" in a topic, the display will get crazy.
> It is not possible to make remarks with Windows.
The bug makes windows users unable to send any messages.
> In Mac, "&amp;" in topic is evaluated as "&".
In Mac, "&amp;" in a topic is displayed as "&".

Notes

  • "fond" is an adjective. "I'm fond" or just "I love" are better.

    • Maybe he had tried to write "found", but the fact that he loves bugs made me assured.
  • This is a bug report, therefore the first "Hello" is OK. If it's an email, he had to write "Dear Skype Developpers,"

You might find some awkward expressions in my correction. I'm glad to see your correction!

Thursday, June 11, 2009

It Is Difficult To Extend Ruby's Syntax of Defining a Method Without End

To define a method in a line, we may write such a code.

def f(x) x + 1 end

I tried to add this new syntax to Ruby.

def: f(x) x + 1

I thought I could add the syntax. It consists of:

  • keyword def (k_def in parse.y)
  • a char ':'
  • function name (fname in parse.y)
  • an expression (expr in parse.y)
  • the end of line (term in parse.y)

To skip the keyword end, I made a restriction of having only one expression in the definition of the new method. I thought it would work, but I found that it couldn't.

I had been struggling to implement it. I'll introduce one of my tries here.

diff --git a/parse.y b/parse.y
index 636f51f..203cd9c 100644
--- a/parse.y
+++ b/parse.y
@@ -2878,6 +2878,40 @@ primary                : literal
                         $$ = dispatch2(module, $2, $4);
                     %*/
                     }
+                | k_def ':' fname
+                    {
+                        $<id>$ = cur_mid;
+                        cur_mid = $3;
+                        in_def++;
+                    /*%%%*/
+                        local_push(0);
+                    /*%
+                    %*/
+                    }
+                  f_arglist
+                  expr
+                  term
+                    {
+                    /*%%%*/
+                        $$ = newline_node($6);
+
+                        void_stmts($$);
+                        fixup_nodes(&deferred_nodes);
+
+                        fixpos($$, $6);
+
+                        NODE *body = remove_begin($6);
+                        reduce_nodes(&body);
+                        $$ = NEW_DEFN($3, $5, body, NOEX_PRIVATE);
+                        fixpos($$, $5);
+                        fixpos($$->nd_defn, $5);
+                        local_pop();
+                    /*%
+                        $$ = dispatch3(defc, $3, $5, $6);
+                    %*/
+                        in_def--;
+                        cur_mid = $<id>4;
+                    }
 k_def fname
                     {
                         $<id>$ = cur_mid;

After applying this patch, a sample code

def: f(x) x + 2
p f(10)

will raise a syntax error:

/var/folders/Dz/Dz5WpFSZGUaFLA8jp8kT5E+++TM/-Tmp-/v705342/390:3: syntax error, unexpected tIDENTIFIER, expecting $end
p f(10)
 ^

This tricky code can work well:

def: f(x) x + 2;;
p f(10) #=> 12

I still need a more work.

My Birthday

Today I turned 25 years old.

Wednesday, June 10, 2009

Default Parameter -- Dynamic Define, Recursive Call

In method parameter, we can write any kind of assignment statements in Ruby.

The most popular default parameter is literals:

def f(a, b = :aaa)
  ...
end

Rarely we can see method calls in default parameter:

def f(a, b = Array.new)
  ...
end

def g(a, b = 1 + 2)
  ...
end

We can refer the other precedent parameters:

def f(a, b = a * 2)
  b
end
p f(10) #=> 20

We can write more complicated code there.

def g(a, b = (def j; end; 1))
  [a, b]
end

This code works tricky. After g was called without the second argument, method j is defined.

We also can write recursive call there.

def fib(n, x = n == 0 ? 0 : n == 1 ? 1 : fib(n-2) + fib(n-1))
  x
end

p fib(10) #=> 55
p fib(10, :hehehe) #=> :hehehe

RubyGems Best Practice

It is unexpectedly difficult To handle RubyGems with multi ruby implementation in one OS. This entry is drawing my best practice of the problem.

Principle: Gem in the User Area

As far as possible, we should install gem libraries in a user area instead of the root area.

You shouldn't run such a command

$ sudo gem install {something}

but

$ gem install {something}

By this way the new library will be installed under ~/.gem/ruby/1.8 if your ruby is ruby1.8.*.

Note that we have to write it on your ~/.zshrc.

export PATH=~/.gem/ruby/1.8/bin:$PATH

Now let's uninstall all your gem libraries on the root area!

$ yes | sudo gem uninstall '' -a

Multi Ruby Implementation

Assume that you have more than four ruby implementations on your OS.

So how to distinguish them?

  • ruby1.8.6: Just Ignore

  • ruby1.8.7: Default

  • ruby1.9.1: Suffix '191' for any commands

  • ruby1.9.2: Suffix '192' for any commands

It is easy to ignore ruby1.8.6 by export PATH=/opt/local/bin:$PATH on your ~/.zshrc.

How can I install a gem library into the specific version of the ruby?

  • ruby1.8.7: gem install {name}

  • ruby1.9.1: gem191 install {name} --format-executable

  • ruby1.9.2: gem192 install {name} --format-executable

Note that there's no 'sudo's.

Where will those commands deploy it?

  • ruby1.8.7: under ~/.gem/ruby/1.8

  • ruby1.9.1: under ~/rubies/lib/ruby/gems/1.9.1

  • ruby1.9.2: under ~/rubies/lib/ruby/gems/1.9.1

The list may surprise you. Yes, it's not typo.

  • When 1.8.7's gem command is called by normal user, first it tries to install under /opt/local/lib/ruby/gems/1.8 and fails, then tries to install under ~/.gem/ruby/1.8 and succeeds. The minor version is ignored automatically.

  • When 1.9.1's gem command is called by normal user, first it tries to install under ~/rubies/lib/ruby/gems/1.9.1 and succeeds (the configure option --prefix=~/rubies matters)

  • 1.9.2 is considered as 1.9.1! Look at it

    $ ruby192 -rrbconfig -e 'p RbConfig::CONFIG["ruby_version"]' "1.9.1"

Therefore, just write it on your ~/.zshrc

export PATH=~/.gem/ruby/1.8/bin:$PATH
export PATH=~/rubies/lib/ruby/gems/1.9.1/bin:$PATH

Easier

It is laborious to type --format-executable everytime. This is where .gemrc comes in. Add this line: 'gem: --no-ri --format-executable'. This also works for ruby1.8.7, but you don't have to care about it because there's no bad side effect.

You may mistype 'sudo gem install ...' someday. In terms of human computer interface, it is better not to do a wrong way by computer supports than by human efforts. Let's prohibit root to do gem! Write below on your ~/.zshrc.

function sudo() {
  if [ $1 = "gem" ]; then
    echo "Use gem without sudo!"
  else
    command sudo $*
  fi
}

References

Monday, June 8, 2009

Defining Instance Method Easily and Viscerally

Motivation

There are two kind of methods in Ruby. One is a class method like File.open, the other is an instance method like Fixnum#to_s.

class A
  def self.f
    ...
  end

  def g
    ...
  end
end

The class A has a class method A.f and an instance method A#g. To call them, you just have to write A.f or A.new.g.

You can define a class method in another way:

# suppose class A is already exist.
def A.f
  ...
end

However, you cannot define an instance method in this way,

# suppose class A is already exist.
def A#g
  ...
end
# !!! This code defines Kernel#A instead of A#g

but in this way,

# suppose class A is already exist.
A.method(:define_method).call(:g) do
  ...
end

or

# suppose class A is already exist.
A.__send__(:define_method, :g) do
  ...
end

Now let's think about good notations of defining an instance method.

Case 1: Add Support Method

def def_(klass, name, &block)
  klass.method(:define_method).call(name, &block)
end

And then

def_ A,:g do
  ...
end

Now you can call A.new.g. The code is a little tricky. If your eyes are a little bad, you can see

  • def_ as def

  • A,:g as A#g

and can ignore do. You can imagine def_ A,:g do is def A#g!

There's only one bad news: when the method A#g has arguments, we have to write it as

def_ A,:g do |x|
  ...
end

That means your eyes must ignore more. We have to think more deeply.

Case 2: Fix parse.y

I succeeded to fix parse.y to be able to handle the notation.

First, I fixed the scanner to suspend to ignore the normal comment notation in a special case. For ease of fix, I compromised that if '#' appears before an alnum in the state EXPR_END, then it won't be considered as a comment in this time. Second, I fixed the parser so as to define an instance method.

Apply this patch to ruby-trunk revision 23651:

diff --git a/parse.y b/parse.y
index 636f51f..ee5fb22 100644
--- a/parse.y
+++ b/parse.y
@@ -2905,6 +2905,35 @@ primary                : literal
      in_def--;
      cur_mid = $<id>3;
        }
+                | k_def cname '#' {lex_state = EXPR_FNAME;} fname
+                    {
+                        $<id>$ = cur_mid;
+                        cur_mid = $5;
+                        in_def++;
+                    /*%%%*/
+                        local_push(0);
+                    /*%
+                    %*/
+                    }
+                  f_arglist
+                  bodystmt
+                  k_end
+                    {
+                    /*%%%*/
+                        NODE *body = remove_begin($8);
+                        reduce_nodes(&body);
+                        $$ = NEW_DEFN($5, $7, body, NOEX_PRIVATE);
+                        fixpos($$, $7);
+                        fixpos($$->nd_defn, $7);
+                        $$ = NEW_CLASS(NEW_COLON3($2), $$, 0);
+                        nd_set_line($$, $<num>6);
+                        local_pop();
+                    /*%
+                        $$ = dispatch4(defi, $2, $5, $7, $8);
+                    %*/
+                        in_def--;
+                        cur_mid = $<id>6;
+                    }
 k_def singleton dot_or_colon {lex_state = EXPR_FNAME;} fname
        {
      in_single++;
@@ -6373,6 +6402,9 @@ parser_yylex(struct parser_params *parser)
  goto retry;

       case '#':                /* it's a comment */
+        c = nextc();
+        pushback(c);
+        if(lex_state == EXPR_END && ISALNUM(c)) return '#';
  /* no magic_comment in shebang line */
  if (!parser_magic_comment(parser, lex_p, lex_pend - lex_p)) {
      if (comment_at_top(parser)) {

Now you can write:

def A#initialize(a)
  @a = a
end

def A#foo
  @a
end

p A.new(10).foo #=> 10

Wonderful!

Note

  • I ignored the concept of singleton methods or singleton classes on purpose to simplify the difference between class methods and instance methods

  • In JavaScript, it's easy to define an instance method.

    // class method A.f = function() { ... };
    // instance method A.prototype.g = function() { ... };
    

Saturday, June 6, 2009

Inescapable Bafflegab in Vim

Assume that your vimrc has the following settings.

set encoding=utf-8
set termencoding=utf-8
set fileencodings=ucs-bom,euc-jp,cp932,iso-2022-jp

If you write the following phrase and save it,

カナサンスゴイ

and then you will see a bafflegab after re-open the file by :e. (You can resolve the bafflegab by :e ++enc=utf8.)

before

after

If there's other good words, for example 'あ', bafflegab will never appear.

Solution

Of course nobody can type :e ++enc=utf8 no matter when open the file. There are two easy solutions.

  • Add BOM. :setl bomb and :w.
  • Add other words if it's possible.

Note that modeline won't help the problem.

Friday, June 5, 2009

The Possibility of Unary Operators

class Symbol
  def -@
    to_s.reverse.to_sym
  end
end

class Fixnum
  def to_proc
    lambda { self }
  end
end

class Regexp
  def -@
    to_s
  end

  def to_proc
    lambda { self }
  end
end

class Array
  def -@
    reverse
  end

  def to_proc
    lambda {|i| self[i] }
  end
end

p -:hello
p [nil].map(&10)
p -/quick/
p [nil].map(&/cool/)
p -[1, 2, 3]
p [0, 1, 1, 2].map(&[:a, :b, :c])

Installing Ruby 1.9.1 By Source Code

I use both stable version and edge version of ruby. The stable one, ruby 1.8.7, is installed by MacPorts. The edge ruby 1.9.2dev is installed by the source from svn trunk via git-svn. While 1.8.7 is in /opt/local/bin/ruby, 1.9.2dev is in a user area ~/git/ruby-trunk/ruby19/bin/ruby.

Today I came across to use ruby 1.9.1 for checking some special cases. I installed it in the following way:

$ mkdir ~/rubies
$ mkdir ~/rubies/src
$ cd ~/rubies/src
$ svn co http://svn.ruby-lang.org/repos/ruby/branches/ruby_1_9_1/
$ cd ruby_1_9_1
$ autoconf
$ ./configure --program-suffix=191 --prefix=/Users/ujihisa/rubies --disable-install-doc

$ make && make install

And then write it on your ~/.zshrc:

export PATH=$PATH:~/rubies/bin

Note that:

  • configure's --prefix option can accept only an absolute path.

You can install other versions of ruby by the almost same procedure, and run by like ruby191.

Thursday, June 4, 2009

(Draft) Extended Markdown for Vim Hacks

This post is for the authors of Vim Hacks.

Markdown syntax supports <code>, <img>, <ul> or other primary html tags. Vim Hacks authors need <kbd> tag besides. And also, it is useful for us to be supported to contain metadata of Vim Hacks in a file. Therefore, I propose Extended Markdown Syntax for Vim Hacks.

  • Extention: ***.mdv
  • <h1> of the first line becomes
  • `|<Cr>|` becomes <kbd>&lt;Cr&gt;</kbd>
  • Author: *** of the last line becomes <author>***</author>

Example:

# Hack #22: Ultra Super Great Vim Plugin | lv2 2009-06-06

## PROBLEM
blah blah blah

## SOLUTION
use [blogger.vim](http://www.vim.org/scripts/script.php?script_id=2638) with
the key mapping `|j|`.

## DISCUSSION
blah blah blah

    nnoremap j :<C-u>1000sl<Cr>
    nnoremap k :<C-u>1000sl<Cr>

blah blah blah. hara y y hara y?

Author: ujihisa

TODO

  • Implement mdv2html and html2mdv
  • Implement mdvlint

Dvorak keymapping for Vim users

Brixen recommended me to switch to use dvorak instead of qwerty. Although I've never tried dvorak, I've often heard that it is very effective to use this layout.

This pdf is the most important reference for a dvorak beginner of vimmer I've ever found: http://boredzo.org/vi_tutorial/vi_tutorial-Dvorak-Color.pdf

vi_tutorial-Dvorak

Brixen also told that those lessons are good for learning dvorak:

I input Japanese by kana-typing input style on my US Keyboard. It's independent with qwerty mapping, so there's no confusion about switching dvorak to qwerty to input ASCII typesets.

Followers