忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。


IronScheme + かんたんなEmacsの初期設定 .emacsファイル

前回で括弧にハイライトが付くようになりました。
IronSchemeのような括弧地獄でやっていく第一歩です。

今回は、IDEのように書いた内容をその場で実行できるようにしましょう。

前回書いた.emacsファイルをこう書き換えます。
参考:

.emacs
(show-paren-mode t)

;思わず"\"C:\\Program Files\\IronScheme\\IronScheme.Console\" -emacs"
;としたくなってしまうかもしれませんが、それでは何故かうまくいきません。
;%ProgramFiles%を使ってもダメです。
;きちんと"C:\Program Files\IronScheme"にパスを通して、以下のようにしてください。
;run-schemeの実装に原因があるかもしれません(※)。
;※参考:http://saito.s4.xrea.com/wiliki.cgi?Emacs%3Ascheme-args-to-list
(setq scheme-program-name "IronScheme.Console.exe -emacs")
(run-scheme scheme-program-name)

;エラーの文字化け対策
(modify-coding-system-alist 'process "IronScheme.Console" '(utf-8 . utf-8))


書き換えが終わったら.emacsファイルを保存し、Emacsを実行します。

emacsDefaultPage.jpg

Emacsが動き出したら前回と同じように、*.scmファイルをEmacsの中にドラッグ&ドロップします。
すると内容が表示されます。

そしたら何とか頑張って操作してウィンドウを上下に2分割してください。
私は正式な方法を知りませんが、一番下のボックスをクリックするとなぜか2分割になることを経験的に知っています。

さて2分割にしたら、schemeのコード側のウィンドウでコードを全部選択し、メニューから

Scheme → Evaluate Region

とします。
すると選択された範囲のSchemeが実行されます。
実行結果は*scheme*という所に表示されます。
ウィンドウの下の部分のファイル名っぽい名前が出ているところをマウスをカチカチしていると出てきます。

runSchemeOnEmacs.jpg

ここでは5から初めて0で終わるカウントダウンをしています。

メニューからScheme → Evaluate Last S-expression
なども試してみましょう。




拍手[0回]

PR

Emacsの括弧対応ハイライト 初期設定 (Windows7)

私はVisual StudioやEclipseべったりでそれ以外のエディタはさっぱりです。
しかし頑張ります!

IronSchemeのエディタとしてEmacsなるものを使ってみることを考えます。
OSはWindows7を想定します(というかそれしか使っていませんが…)。

ftp://ftp.gnu.org/gnu/emacs/windows/

最新バージョンはemacs-23.4-bin-ii386.zipのようです。

実行するとこんな画面が表示されます。
emacsDefaultPage.jpg

*.scmなファイルをドラッグ&ドロップするとさっそくLisp系のエディタとして使えます。
でもデフォルトの状態では対応する括弧をハイライトにしないようです。(下図)

emacsNoParenthesesNotification.jpg

これを次のように対応括弧ハイライトにするにはどうすればいいのでしょうか?

emacsParenthesesNotification.jpg

詳しくないのですが、以下のようにすればいいようです。
参考 参考

まず、

C:\Users\ユーザー名\AppData\Roaming

の中に.emacsとういファイルを作ります。
(他のディレクトリを見ると場所間違ってるんじゃないかって言う気もしますが、あってます)
先頭の.を忘れないでください。
もちろんWindowsでは.がはじめに来るファイルは作りにくいです。
そこでまず例えば"test.emacs"というようなファイルを作り、それの名前を後から変えます。

rename test.emacs .emacs

.emacsの中身は一番簡単なこれでいいでしょう:

(show-paren-mode t) 

これは括弧対応を表示するという意味です。
メモ帳か何かで保存してください。
そしてbinの中のrunemacs.exeを実行すると無事、対応括弧ハイライトになったemacsが起動します。

拍手[0回]


IronScheme doで配列を回すと…

doで配列を回す

勉強中のIronSchemeですが、さっそくわかりません!
doという、C#で言うところのforに相当するものがあるのですが、これと配列を組み合わせると不可解な現象が起きます。
(ちなみに、doは真のSchemerは本当は使わないそうです。)

(import (rnrs) (ironscheme clr))

(clr-using System)
(define myArray (clr-new-array Int32 4))


(do ((index 0 (+ index 1)))
	((= index (clr-prop-get Array Length myArray)))
	(clr-indexer-set! Int32[] myArray index index))


(do ((index 0 (+ index 1)))
	((= index (clr-prop-get Int32[] Length myArray)))
	(clr-static-call
		Console
		WriteLine
		(clr-indexer-get Int32[] myArray index)))

(clr-static-call Console ReadLine)

これはC#でいうと以下の様なプログラムに相当します。
(厳密にはC#版は上手く動くので違うのですが)

using System;

class Program
{
    public static int[] myArray = new int[4];

    static void Main()
    {
        for (int index = 0; !(index == myArray.Length); index++)
        {
            myArray[index] = index;
        }

        for (int index = 0; !(index == myArray.Length); index++)
        {
            Console.WriteLine(myArray[index]);
        }

        Console.ReadLine();
    }
}



私がやりたかったのはこういうことです:
長さ4の配列を作り、それを{ 0, 1, 2, 3 } というふうに初期化し、それを出力するのです。

Expected:
0
1
2
3

ですから上のプログラム(IronScheme)を実行して下のような結果を受け取った時には驚きました。

Actual:

36561384
36561408
36561432
36561456

……
!!?

このやけに大きな数字は一体!?
ためしてみると実行するたびにこの数字は変わっていきました。

これではまるで何かのアドレスのようです。
いや.netですからハッシュコードでしょうか。
でもInt32のGetHashCode()はそれ自身を返すはず…
一体どういうことでしょう。

色々やってみる

一つの考えとしてclr-indexer-getかclr-indexer-set!がおかしいのではないかというのが思い浮かびます。
配列への値のセットやゲットが上手くいっていないのです。
そこで次のような単純なIronSchemeを書きます。
(import (rnrs) (ironscheme clr))

(clr-using System)
(define myArray (clr-new-array Int32 1))
(clr-indexer-set! Int32[] myArray 0 42)
(display (clr-indexer-get Int32[] myArray 0))

(clr-static-call Console ReadLine)
C#でいうとこんな感じです:

using System;

class Program
{
    public static int[] myArray = new int[1];

    static void Main()
    {
        myArray[0] = 42;
        Console.Write(myArray[0]);
        Console.ReadLine();
    }
}

これは長さ1の配列を作り、最初に42を代入し、それを表示するプログラムです。
もし配列のゲットやセットがうまくいっていないのなら、ここで42ではない、変な数字が表示されるはずです。
どうなるでしょうか。
(以下IronSchemeの結果を書きます)

42

あれれ…42と出力されました。
配列には42をセットしましたから、これは正常です。
配列の値のセットとゲットは上手く行っているようです。

すると変数が悪いのでしょうか?
変数を使うことによってなにか動的言語に詳しくないプログラマが陥る罠が現れるのでしょうか?
確かめてみましょう。
まずは手軽なグローバル変数を。

(import (rnrs) (ironscheme clr))

(clr-using System)
(define myArray (clr-new-array Int32 1))
(define value 42)
(clr-indexer-set! Int32[] myArray 0 value)
(display (clr-indexer-get Int32[] myArray 0))

(clr-static-call Console ReadLine)

using System;

class Program
{
    public static int[] myArray = new int[1];
    public static int value = 42;

    static void Main()
    {
        myArray[0] = value;
        Console.Write(myArray[0]);
        Console.ReadLine();
    }
}



これは先ほどとほとんど同じプログラムです。
唯一違うのは42という数字を間接的に配列に代入している点です。
間にグローバル変数を挟んでいるのです。
やはり先程と同じく、これが正常に動けば42と表示され、
問題があれば変な42以外の数字が表示されます。
42

42です。
うーん当たり前といえば当たり前です。
ここには問題ありません。
しかし念のためローカル変数も調べてみましょう。

(import (rnrs) (ironscheme clr))

(clr-using System)
(define myArray (clr-new-array Int32 1))
(let 
	((value 42))
	(clr-indexer-set! Int32[] myArray 0 value)
	(clr-static-call Console WriteLine value))
(clr-static-call Console WriteLine (clr-indexer-get Int32[] myArray 0))

(clr-static-call Console ReadLine)

using System;

class Program
{
    public static int[] myArray = new int[1];

    static void Main()
    {
        int value = 42;
        myArray[0] = value;
        Console.Write(myArray[0]);
        Console.ReadLine();
    }
}

結果はどうなるでしょう。(IronScheme版)

42
39708184

……おお!!
あり期待していませんでしたが、問題はここにありました!

どういうわけか数字をConsole.WriteLineは正しく扱っているのに、インデクサはおかしく扱っています。
そういえば配列のインデクサは本当のインデクサではなかった気もします。
関係あるのでしょうか?

なにはともあれ原因はここにあるようです。
さてどうするべきでしょうか。
原因がわかっても解決方法は?

とりあえず、型が関係しているような気がします。
たとえばIronSchemeの数字はInt32ではないとか。
たしかSchemeでは全てが参照型だった気がします。
変数の型を調べてみましょう。

(import (rnrs) (ironscheme clr))

(let ((value 42))
	(clr-static-call 
		System.Console 
		WriteLine 
		"{0} {1}" 
		(clr-call System.Object GetType value)
		value))

(clr-static-call System.Console ReadLine)

class Program
{
    public static int[] myArray = new int[1];

    static void Main()
    {
        int value = 42;
        System.Console.WriteLine("{0} {1}", value.GetType(), value);
        System.Console.ReadLine();
    }
}

このプログラムは変数indexの型と値を表示します。
もし変数の型に問題があるのなら型はSystem.Int32以外が表示されるでしょう。
結果は・・・
System.Int32 42


残念、ここには問題はありませんでした。
indexはちゃんとSystem.Int32の42です。
IronSchemeは謎の数字の型を使っていて、それゆえに変な値が表示されるのでは?
という私の仮説は脆くも崩れ去りました。


解決方法

でも念のため元のコードでキャストしてみましょう。

(import (rnrs) (ironscheme clr))

(clr-using System)
(define myArray (clr-new-array Int32 4))


(do ((index 0 (+ index 1)))
	((= index (clr-prop-get Array Length myArray)))
	(clr-indexer-set! Int32[] myArray index (clr-cast Int32 index)))


(do ((index 0 (+ index 1)))
	((= index (clr-prop-get Int32[] Length myArray)))
	(display (clr-indexer-get Int32[] myArray index))
	(newline))

(clr-static-call Console ReadLine)
C#版:
using System;

class Program
{
    public static int[] myArray = new int[4];

    static void Main()
    {
        for (int index = 0; !(index == myArray.Length); index++)
        {
            myArray[index] = (int)index;
        }

        for (int index = 0; !(index == myArray.Length); index++)
        {
            Console.WriteLine(myArray[index]);
        }

        Console.ReadLine();
    }
}

0
1
2
3
あれ…
上手くいってしまいました。
うーん拍子抜けです。
これは一体何だったのでしょう…

indexをキャストするとうまくいくことから、IronSchemeではindexが何か別のものであった可能性が考えられます。
しかしその可能性は上のサンプルで否定されました。
ますますもってわかりません。

しかし上手く配列を回せたのでOKということにしましょう!

ちなみに

配列を使わない場合はどうなるかというと、こうなります。

(import (rnrs) (ironscheme clr))

(clr-using System)
(define myValue 0)

(let 
	((value 42))
	(set! myValue value)
	(clr-static-call Console WriteLine value))
(clr-static-call Console WriteLine myValue)

(clr-static-call Console ReadLine)

42
42
正常です。

拍手[0回]


IronSchemeでWPFをつかう

先日はお騒がせました。
ちゃんと使えます
IronSchemeでもIron~~な他の言語でもWPFは使えます
前回コメントいただいた通りです。

ただC#のようなストレートな書き方ではなく、ちょっと回りくどくなります。
こうなりました:
(import (rnrs) (ironscheme clr))

(clr-reference PresentationFramework)
(clr-reference PresentationCore)
(clr-reference WindowsBase)

(clr-using System.Windows)
(clr-using System.Threading)

(define 
	runApplication
	(lambda 
		() 
		(define app (clr-new Application))
		(clr-call Application Run app (clr-new Window))))

(define staThread (clr-new Thread runApplication))
(clr-call Thread SetApartmentState staThread 'STA)
(clr-call Thread Start staThread)

IronSchemeWpf.jpg

C#ではこうなるでしょう
(ただし、事前に
PresentationFramework,
PresentationCore,
WindowsBase,
System.Xamlの参照を追加する必要あります):
using System.Windows;
using System.Threading;

class Program
{
    static void runApplication()
    {
        var app = new Application();
        app.Run(new Window());
    }

    static void Main(string[] args)
    {
        var staThread = new Thread(runApplication);
        staThread.SetApartmentState(ApartmentState.STA);
        staThread.Start();
    }
}

そうですね
STAThread属性を付けられないのなら、
別の方法でSTAThreadを走らせてやればよかったんですね。
ApartmentStateプロパティがObsoleteになっていたので勘違いしてしまいました。
(かわりにSetApartmentStateが使えます。)

拍手[0回]


IronSchemeでWPFは使えない??

04/21/2012 訂正:自己解決しました
有益なコメントも頂きました
詳しくはこちら


.netな動的言語については詳しくないのですが
(というかほとんど全然知らないのですが)、
複数のサイトによると(Dynamically Compiling C#IronPythonの特徴
IronPythonは属性をどうも使えないらしいです。

で、どうやらその理由が動的言語であることに由来するらしいのです。
本当かは判断できませんが・・・。

とすると、もしかしてIronSchemeでも属性が使えないのでしょうか?
ぱっと見たところ、属性を付与する命令というか方法はないように見えます(一日中調べました)。

属性が使えないことの何が嫌かというと、もちろん
(上で引用した記事にも書いてあるように)
WCFが上手く使えないということもあるのでしょうが、
WPFも使えないのではないかということです。
ウィンドウを表示してワイワイ賑やかになれないということです。

WPFはSTAThreadで動きます。
なのでMainメソッドにSTAThread属性を与えてやらなければ
InvalidOperationExceptionをスローして強制終了です。
そして動的言語では属性を与えられない(のでしょうか?)。
つまり動的言語は全てWPFを使えないことになってしまうのでしょうか?
(いやでも、ググるとIronPythonでWPFを使っている例が見つかりますね。あれ・・・??)

ちなみに、こんなコードを書いてクラッシュしました:
(import (rnrs) (ironscheme clr))

(clr-reference PresentationFramework)
(clr-reference PresentationCore)
(clr-reference System.Xaml)
(clr-reference WindowsBase)

(clr-using System.Windows)

;[System.STAThread] might be needed.

(define app (clr-new Application))
(clr-call Application Run app (clr-new Window))

で、こちらがエラーです:
Unhandled CLR exception during evaluation:
CLR Exception: System.InvalidOperationException
System.InvalidOperationException: The calling thread must be STA, because many U
I components require this.
   at System.Windows.Input.InputManager..ctor()
   at System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
   at System.Windows.Input.KeyboardNavigation..ctor()
   at System.Windows.FrameworkElement.EnsureFrameworkServices()
   at System.Windows.FrameworkElement..ctor()
   at System.Windows.Controls.Control..ctor()
   at System.Windows.Window..ctor()
   at eval-core(003).$2()
   at #.psyntax.expander::compile-r6rs-top-level#anon#1#2$2505(CodeContext $cont
ext)
   at #.ironscheme.exceptions::dynamic-wind(Object in, Object proc, Object out)
   at #.psyntax.main::load-port#1$2552(CodeContext $context)
   at #.ironscheme.exceptions::dynamic-wind(Object in, Object proc, Object out)
   at IronScheme.Runtime.Builtins.CallWithCurrentContinuation(Object fc1)
   at IronScheme.Runtime.R6RS.Exceptions.WithClrExceptionHandler(Object handler,
 Object thunk)


どなたかご存じの方に教えていただきたいです!

04/21/2012 訂正 : 自己解決しました
有益なコメントも頂きました
詳しくはこちら

拍手[0回]