IronSchemeプラクティス


あなたが「肉」の演奏をやめると確信しています。なぜなら、多くの特別な用語を理解できないという理由だけで、私が今あなたに話すことはあなたにとって非常に興味深いように見えるからです。
ヤロスラフ・ハセク


パート1スキームの概要
パート2スキームの深化
パート3 IronSchemeの練習

練習する


それでは、前の記事の例よりも実際に近いアプリケーションを作成してみましょう。 以前の記事では、哲学的な質問と開発の基礎について検討したため、これは主にコードで構成されます。 コードが読みやすくなることを願っていますので、大量のコメントは提供しません。

まず、IronSchemeから.netクラスにアクセスする方法を見てみましょう。

IronSchemeプログラムは、ライブラリのインポートから始まります。
(import (rnrs) (ironscheme) ) 

CLRとの対話に関数を使用するには、ライブラリ(ironscheme clr)をインポートする必要があります。
 (import (rnrs) (ironscheme) (ironscheme clr) ) 

これで、次の機能を使用できます。
(clr-namespaces)
インポートされたすべての名前空間を返します。

(clr-referenceリファレンス)
たとえば、アセンブリをアプリケーションに接続します(clr-reference System.Web)。

(clrを使用する名前空間)
名前空間をインポートします:(clr-using System.IO)。

(clr-callタイプメソッドインスタンス引数...)
オブジェクトメソッドを呼び出します。

(clr-castタイプexpr)
オブジェクトを指定されたタイプに強制します。

(clr-isタイプexpr)
オブジェクトに指定されたタイプがあるかどうかを確認します。

(clr-new type arg ...)
クラスのインスタンスを作成し、コンストラクターに引数を渡します。

(clr-new-arrayタイプのサイズ)
指定されたタイプとサイズで配列を作成します。

(clr-event-add!タイプのイベントインスタンスハンドラー)
イベントハンドラーを追加します。

(clr-event-remove!タイプのイベントインスタンスハンドラー)
イベントハンドラーを削除します。

(clr-field-get typeフィールドインスタンス)
フィールドの値を取得します。

(clr-field-set!タイプフィールドインスタンスexpr)
フィールドに値を割り当てます。

(clr-prop-get typeプロパティインスタンス)
プロパティの値を取得します。

(clr-prop-set!タイププロパティインスタンスexpr)
プロパティの値を設定します。

(clr-static-callタイプメソッドarg ...)
静的メソッドを呼び出します。

(clr-static-event-add!タイプのイベントハンドラー)
静的イベントのハンドラーを追加します。

(clr-static-event-remove!タイプのイベントハンドラー)
ハンドラーを削除します。

(clr-static-field-get typeフィールド)
静的フィールドの値を返します。

(clr-static-field-set!typeフィールドexpr)
静的フィールドの値を設定します。

(clr-static-prop-get typeプロパティ)
静的プロパティの値を返します。

(clr-static-prop-set!typeプロパティexpr)
静的プロパティの値を設定します。

Hello World 2.0


やってみますか? 内容を含むhello-world-clr.ssファイルを作成します。
 (import (rnrs) (ironscheme) (ironscheme clr) ) (clr-static-call Console WriteLine "Hello, world") 

この例は、System.Consoleクラスの静的WriteLineメソッドの呼び出しを示しています。

ただのタイマー


この例はもっと興味深いものです。タイマーを開始します。

通常どおり、最初にライブラリをインポートします。
 (import (rnrs) (ironscheme) (ironscheme clr) ) 

名前空間をインポートします。
 (clr-using System.Threading) 

使いやすくするために、clr呼び出し用に2つのラッパー関数を作成します。 最初の関数はTimerクラスのオブジェクトを作成し、2番目の関数はタイマーの基本パラメーターを変更します。
 (define (timer-new handler) (clr-new Timer handler) ) (define (timer-change timer due-time period) (clr-call Timer Change timer (clr-cast System.Int32 due-time) (clr-cast System.Int32 period)) ) 


内部IronSchemeビューから.Netタイプにキャストするには、clr呼び出しのキャストが必要です。

プログラムが終了しないように、アプリケーションのメインスレッドをブロックする関数も引き続き役立ちます。
 (define (console-block) (clr-static-call Console WriteLine "Press <Enter> to terminate") (clr-static-call Console ReadLine) ) 

タイマーを使用するには、最初に関数ハンドラーを宣言する必要があります。
 (define (time-handler obj) ;; some code ) 

次に、タイマーオブジェクトを作成します。
 (define timer (timer-new time-handler)) 

そして、期間と遅延を示すタイマーを開始します。
 (timer-change timer delay period) 

これで、この例は操作の数をコンソールに出力します。
タイマーを使用した完全なソースの例
 (import (rnrs) (ironscheme) (ironscheme clr) ) (clr-using System.Threading) ;; *************************************** (define (timer-new handler) (clr-new Timer handler) ) (define (timer-change timer due-time period) (clr-call Timer Change timer (clr-cast System.Int32 due-time) (clr-cast System.Int32 period)) ) (define (console-block) (clr-static-call Console WriteLine "Press <Enter> to terminate") (clr-static-call Console ReadLine) ) ;; *************************************** (define counter 0) (define period 1000) ;;ms (define (time-handler obj) (set! counter (+ counter 1)) (displayln counter) ) (define timer (timer-new time-handler)) (timer-change timer 0 period) (console-block) 



Oracle DBの使用


Orcale DBMSの接続とクエリの例を示します。 読者自身がそれを理解できると信じているので、ここで何が起こっているか、どのように起こっているかを書き留めません。 最初に、プログラムはOracleと連携するための機能を発表し、次に、すでにおなじみのTimer用の機能を発表しました。 次に、データベースへの接続が作成され、タイマーによって要求が行われ、要求の結果がコンソールに表示されます。
この例は、監視に使用される実際のアプリケーションから取られています。 当然のことながら、機密コードのフラグメントは「*****」に置き換えられますが、サンプルを理解したり、例を使用して独自のプログラムを開発したりするためには重要ではありません。

Oracleデータベースでの作業の例
 (import (rnrs) (ironscheme) (ironscheme clr) ) ;; **************** Oracle **************;; (clr-reference System.Data) (clr-reference System.Data.OracleClient) (clr-using System.Data.OracleClient) (define (ora-connection-new connection-string) (clr-new OracleConnection (clr-cast System.String connection-string)) ) (define (ora-connection-open connection) (clr-call OracleConnection Open (clr-cast OracleConnection connection)) ) (define (ora-connection-create connection-string) (define connection (ora-connection-new connection-string)) (ora-connection-open connection) connection ;; return ) (define (ora-command-new connection sql-string) (clr-new OracleCommand (clr-cast System.String sql-string) (clr-cast OracleConnection connection)) ) (define (ora-command-parameter-add command key value) (clr-call OracleParameterCollection Add (clr-prop-get OracleCommand Parameters command) (clr-cast System.String key) (clr-cast System.Object value) ) ) (define (ora-execute-reader command) (clr-call OracleCommand ExecuteReader (clr-cast OracleCommand command)) ) (define (ora-read reader) (clr-call OracleDataReader Read (clr-cast OracleDataReader reader)) ) (define (ora-get-value reader key) (clr-call OracleDataReader GetValue reader (clr-call OracleDataReader GetOrdinal reader key) ) ) (define (ora-get-string reader key) (clr-call Object ToString (ora-get-datetime reader key)) ) (define (ora-get-int32 reader key) (clr-call OracleDataReader GetInt32 reader (clr-call OracleDataReader GetOrdinal reader key) ) ) (define (ora-get-datetime reader key) (clr-call OracleDataReader GetDateTime reader (clr-call OracleDataReader GetOrdinal reader key) ) ) ;;***************************************;; ;; **************** Timer ***************;; (clr-using System.Threading) (define (timer-new handler) (clr-new Timer handler) ) (define (timer-change timer due-time period) (clr-call Timer Change timer (clr-cast System.Int32 due-time) (clr-cast System.Int32 period)) ) (define (console-block) (clr-static-call System.Console WriteLine "Press <Enter> to terminate") (clr-static-call System.Console ReadLine) ) ;;***************************************;; ;;######## GLOBAL #########;; (define connection-string "Data Source=*****;User ID=*****;Password=*****;") ;;#########################;; (define (complect-print reader) (import (srfi :13)) (let loop ((index 1)) (if (ora-read reader) (begin (display " (") (display (string-pad-right (number->string index) 5)) (display (string-pad-right (ora-get-value reader "*****") 15)) (display " ") (display (string-pad-right (ora-get-value reader "*****") 20)) (display " ") (display (ora-get-int32 reader "*****")) (display " ") (display (string-pad-right (ora-get-value reader "*****") 25)) (display " ") (display (ora-get-string reader "*****")) (displayln ")") (loop (+ index 1)) ) ) ) ) (define (complect-display connection status) (define sqlStr "select * from ***** where ***** = :complect_status") (define cmd (ora-command-new connection sqlStr)) (define reader '()) (ora-command-parameter-add cmd "complect_status" status) (set! reader (ora-execute-reader cmd)) (display "(complect-status ") (displayln status) (complect-print reader) (displayln ")") (clr-call OracleDataReader Close reader) ) (define (time-handler obj) (define connection (ora-connection-create connection-string)) (clr-static-call System.Console Clear) (displayln "\n;; ************************************************************************* ;;\n") (complect-display connection 1) (newline) (complect-display connection 2) (newline) (complect-display connection 3) (newline) (complect-display connection 4) (displayln "\n;; ************************************************************************* ;;\n") (clr-call OracleConnection Close connection) ) (define timer (timer-new time-handler)) (timer-change timer 0 3000) (console-block) 



Windowsforms


最後に、ウィンドウアプリケーションの簡単な例を示します。 この例では、.NET呼び出しのラッパーを気にしませんでした。 私にとっては、これが可能であるという原則を実証することが重要でした。 もちろん、呼び出しをラップすると、再利用によりコードサイズが小さくなります。
 (import (rnrs) (ironscheme) (ironscheme clr) ) (clr-reference System.Windows.Forms) (clr-using System.Windows.Forms) (define main-form (clr-new Form)) (clr-prop-set! Form Text main-form "--== Hello, world ==--") (clr-prop-set! Form Size main-form (clr-new System.Drawing.Size 640 480)) (define lbl-message (clr-new Label)) (clr-prop-set! Label Text lbl-message "Message: \"Hello, Windows Forms(IronScheme) World!\"") (clr-prop-set! Label Size lbl-message (clr-new System.Drawing.Size 320 20)) (clr-prop-set! Label Location lbl-message (clr-new System.Drawing.Point 150 200)) (clr-call Form+ControlCollection Add (clr-prop-get Form Controls main-form) lbl-message) (clr-static-call Application Run (clr-cast Form main-form)) 


結論として


この記事では、少なくとも.NET上で実行可能なSchemeには不可能なものは何もないことを実証しようとしました。 これは、使い慣れたC#を削除して、Schemeでコーディングを開始する必要があるという意味ではありません。 もちろん、Schemeプログラミングには一定の利点があります;これは、意識がLispイデオロギーに深く浸透するにつれて明らかになります。 それでも、スタジオであらゆる種類のReSharperを使用してC#をサポートすると、.NET向けの開発用の主要言語としてSchemeが大幅に遅れます。 もちろん、.NETを介したLispのファーストクラスのサポートを実装できますが、明らかにそれ以外の場合は必要ありません。 しかし、Lisp、特にSchemeは、組み込み言語として非常に便利です。 この役割では、他の組み込み言語に比べて特定の利点があります。 Lispを使用すると、読み取り可能で柔軟な構成ファイル、コンソールベースのアプリケーション管理インターフェイス、ネットワークを介したデータ転送などを実装できます。 しかし、これについては後の記事で詳しく説明します。

Source: https://habr.com/ru/post/J267119/


All Articles