よくある質問と回答 (FAQ)¶
第三のプログラミング言語 (YAPL) は必要か?¶
Ring は自然言語プログラミング、宣言型プログラミングへの対応が優れています。 最先端のオブジェクト指向プログラミング、関数型プログラミングの実用的な新規技法により、 パラダイムへの対応は画期的です。 Ring はコンパイラと構文解析などの事前知識を必要とせずに、自然言語、あるいは Supernova や QML などの宣言型言語の構築でプログラマが求めるツールを提供します。 さらに、短時間でドメイン特化言語を作成、構築できる言語構成要素を標準装備しています。
プログラミング言語 Supernova では「I want window and the window title is hello world.」と入力すると “Hello, World!” のウィンドウタイトルで GUI ウィンドウを作成できます。 自然言語コードにより「英語のように制限なく使用でき、 プログラミングで人間の言語能力を使用できる」ことを発見しましたが、 実装には新しいプログラミング言語が必要です。
- 汎用性
- 実用性
- 非常に手軽な方法で自然言語プログラムの作成ができます。
よって、使いやすく生産性を最大限まで押し上げることができるシステムを享受できます。
この目的を達成する最良の方法として Ring を作成しました。
Supernova はアイディアの検証であり、どのような利点と欠点があるかについての見識を得るために役に立ちました。 新しいアイディアの検証後に実用的なものを提供しています。 Supernova の後に Ring があります。 ABC の後に Python が存在するのと類似する物語です。 Python は ABC の問題を回避していますが ABC の利点をもたらします。 Ring は Ruby と Ruby on Rails (ROR) の伝説を学んでいます。 プログラミング言語の実力は、汎用プログラミング言語の直接的な用法による優れたフレームワークに最も現れます。 また Ring には明確な目的と動機である「次世代版 Programming Without Coding Technology (PWCT) ソフトウェアの開発」があり、 C 言語で Unix オペレーティングシステムが設計されたことについても学んでいます。 言い換えれば、各々の設計判断で決定する目標があります。
Ring で問題を解決すると意思決定の価値が理解できます。 さて、質問です。計算機プログラミングの概念に関する知識を持たずに、非常に強力なソフトウェアを製作できますか? 科学的な答えは「ビジュアル・プログラミング」と「自然言語プログラミング」です。 実際には、ほかに問題をもたらすことなく、パラダイムを切り替えることはありません。
Ring (コンパイラ + 仮想計算機) の設計と開発、および C コードの生成では、 ビジュアル・プログラミング言語「Programming Without Coding Technology (PWCT)」を 100% 使用しています (一行たりとも手作業でのコーディングはしていません)。
Programming Without Coding Technology (PWCT) の利点は?
- 高速化になります。
- シンタックスエラーとは無縁となります。
- 高度な抽象化水準となるためコードの理解と管理は容易になります。
- コードの記述はすべて管理できるため致命的な欠点はなくなります。
上述のアイディアへの対応、パラダイム切り替え時に発生する問題の解決、強力なビジュアル・プログラミングツールの開発、実用的手法による自然言語プログラミングの提供、多種多様な方法での問題解決、および画期的かつ問題解決方法に関するアイディアの支援。そして、C, C++, C#, Lua, PHP, Python, Ruby, Harbour, Basic と Supernova などのプログラミング言語の豊富な経験とビジュアル・プログラミング (使用経験十年)、および自然言語プログラミング (使用経験五年) の長期研究の集大成として、現役プログラマの認識へ変革をもたらし実用プログラミング言語の新天地と成るべく Ring を設計・開発しました。
プログラミング言語もそうですが、どのような分野・用途のソフトウェアであろうとプログラマ、または開発者は意見や批評をする自由があります。 Ring も例外ではなく、プログラマによく知られており、新規性がないと評価・判断を誤る豊富な機能があります。それは誤解です。背景にあるアイディアを見落しているだけです。
設計段階から実装段階へ移行後に、新たに自然言語インタフェースの実装を行ってから、 ソフトウェアを言葉で表現することにより、プログラミングを開始します (筆者としては、アイジャル・メソッドは自由であり、 移行段階や移行時期についての決定は行いません)。
Ring は新しいプログラミング言語であるため、選択肢は三つあります:
- 今は気にしません。
- Ring の将来について考え、プログラミング言語に関する考えを理解して貢献したいのでしたら、ご支援をお願いします。
- 数年待ってから、使用するために将来復帰してください。
まとめ¶
- Programming Without Coding Technology (PWCT) 2.0 の完成後は Ring で高品質の大規模ソフトウェア開発ができるようになります。
- 宣言型と自然言語パラダイムを段階的に押し進めていきます。
- 次の公開版では、ネットワーク・プログラミングと平行性のために、新しいパラダイムを提供する計画があります。去年、簡易試作品で新しいパラダイムを検証しました。なお、将来の公開版で Ring と統合する予定です。
Ring で弱い型付けを採用する理由は?¶
これは最初の目標で重要なことです。 高速化のためであり、より自然になるからです。 最初の規則: 最初のデータ型は最後の結果に影響します。 例えば “Print : ” + 5 を入力すると、最初に文字列の 5 が表示された後に 5 は文字列へ変換されます。 そして 5 + “10” と入力すると最初に数値の “10” が表示された後に “10” は 10 へ変換されます。 これは同じ演算子を使用して数値と文字列との間で、すばやく変換するのに大いに役に立ちます。 変換を防ぎたい場合は (変換を防ぐコードを記述します)、コードの記述量がより少ない (さらに削除可能) ことに気付くと思います。
弱い型付け = 自動変換と 自動 は 優れたもの であり、 正しく使用されている場合は 手動 より優れています。
Lisp や Smalltalk よりも Ring を使用する利点は?¶
Smalltalk と Lisp は、すばらしいプログラミング言語であり、背景にある様々な概念を気に入っています。 しかし、問題に基づいて適切なプログラミング言語を選択した後であれば、問題を定義できると確信しています。 筆者には解決したい問題があり、この問題において、前述のすばらしいプログラミング言語は理想的ではなかったので Ring を設計しました。
新しいプログラミング言語を設計するとき、過去から学ぶことができますが、 将来を見据えて未来へ向かって進まなくてダメなのです。おそらく、 読者は自然言語プログラミングの知識に関して、古典的知識に基づいていることは筆者も同意しますが、 別技法の実践により、これを実務に取り入れることができることを確認しています。 自然言語に関して読者が誤解していることは 文脈依存 です。 つまり、アイディアの表現方法に関して色々と考えることで使用できるようになります。
用例 : I want window contains 3 buttons.
一文で四つのオブジェクト (ウィンドウと三つのボタン) の作成を行い、ウィンドウへボタンを追加しました。 このような様々な物事を取り入れるのが、自然言語プログラミングの考えかたです。
Ring でユーザインタフェースの作成を最重視する理由は?¶
ビジュアル・プログラミングツールの開発用に設計されているため、 ユーザインタフェースの作成は言語機能のなかで最重要機能の一つです。 Ring は問題に基づきプログラミングパラダイムの選択ができるマルチパラダイム言語でもあります。
ある意味で Ring は PHP の改良版では?¶
Ring は PHP, Lua や Smalltalk の代用品として設計されていません。 Ring の宣言型プログラミングと自然言語プログラミングへの対応は非常に画期的であり、 手続き型、オブジェクト指向、および関数型言語を使い続けるよりも最良です。 Ring には、未来のコード不要プログラミング (自然言語の使用) があり、その対応のための設計がなされています。
ネイティブ C や C++ よりも Ring を使用する利点は?¶
Ring では、問題解決において、多種多様なプログラミングパラダイムを併用するための最良方法を提供しています。
Ring 言語では、多種多様なプログラミングパラダイムをまとめて扱うことができます。
言語構成要素では、類似の概念に関して類似のシンタックスを使用するため、あるプログラミングパラダイムから別のプログラミングパラダイムへの移行は容易です。
- パラダイムは相互作用のために提供されており、ソフトウェアでは異なる階層で併用されます。
例えば、ゲームエンジンの作成ではオブジェクト指向プログラミングを使用してますが、 ゲームのコードでは、宣言型プログラミングまたは自然言語プログラミングを使用して記述を行い、 そして、シーンの背後では宣言型または自然言語のコードをオブジェクト指向クラスを使用できます。
Ring は C/C++ よりも生産性が高く、自然です。
Ring は、動的プログラミング言語です。実行中にコードの生成と実行ができます。 Ring は動的型付け言語であり、柔軟性のために弱い型付けを採用しています。
ガベージコレクターは、世代間 (エスケープ解析) および参照カウントを使用しており、非常に高速で、いつでもメモリを削除できるようにするために、プログラマの制御権を提供しています。
C/C++ ライブラリを使用できます。 Ring には C 関数または C++ クラスからラッパーを作成するために、コード生成器が付属しています。さらなる処理能力を求めている、またはもっとライブラリを使用する必要がある場合は、簡単に実現できます。
Ring と Python との違いは? Ring はオープンソースなの?¶
もちろん。 Ring はオープンソースです (MIT ライセンス)。
全般的に筆者は Python と Ruby が好きですが、筆者には目的となる単純明快な変更があります。
- 英数大小文字の区別はしません。
- リストのインデックスは 1 から開始します。
- 関数の定義前に呼び出すことができます。
- Python 風のシンタックスを使用しない (インデント、self の使用、pass & _)
- 弱い型付け (コンテキストに基づいた型の間での自動変換)
- プログラムは、単純明快な一定の構造に従います (ステートメントの後に関数、続いてパッケージとクラス)。
- 代入と値のテストで ‘=’ 演算子の使用。
重要な変更は、
- 数日で習得できる単純明快な小規模プログラミング言語: Ring コンパイラ + 仮想計算機 = 約 20,000 行の ANSI C コード (すべてのプラットフォームでコンパイル可能)。ほかにライブラリ関連と C/C++ プログラムで使用するオプションで 500,000 行。
- ガベージコレクター: エスケープ解析・参照カウントの使用、および代入演算子の使用によりメモリの削除を行う機会をプログラマが決定する権限を与えています。
- 簡潔なシンタックス: Ring では、行は重要ではありません。 ; の記述または ENTER を押してステートメントを区切る必要はありません。
- 直接、オブジェクトの属性とメソッドを使用した後は { } で、オブジェクトへアクセスします。
- 自然言語プログラミング: オブジェクト指向プログラミングに基づき Ring を使用すると自然なインタフェースの作成が非常に簡単になります。
- 入れ子構造を使用した宣言型プログラミング
さらに、 Ring の目的を達成するために、画期的な機能が追加されています (参照: 言語設計 - 明確な目標のための設計)。
Perl, PHP, Python や Ruby よりも Ring を使用する利点は?¶
- Ring は画期的で新規性があります。 Ring はプログラミングに関する様々なことを考えさせられます。
- Ring は小規模言語として設計されています (Lua 言語からの教訓)。
- Ring は単純明快です(BASIC と Clipper/Harbour 言語からの教訓)。
- Ring はより自然言語的です (Supernova 言語からの教訓)。
- Ring はより宣言的です (REBOL と QML 言語からの教訓)。
- Ring の実装は透過性があり、視覚的であり、さらに豪華な機能があります。
Tcl や Lua よりも Ring を使用する利点は?¶
- うつくしいコード (より自然に)。
- 多機能 (豊富で実用的なプログラミングパラダイム)
C# や Java よりも Ring を使用する利点は?¶
- 簡潔なコード (きれいで自然)、さらなる生産性と柔軟性。
- 宣言型プログラミング、および自然言語プログラミングに関する対応の改善。
関数型プログラミングへの対応が言及されていますが、これは他になにが起きますか?¶
このコードに関する質問です:
f = func {
a = 42
return func { return a }
}
innerF = call f()
call innerF()
実行結果:
Using uninitialized variable : a In function _ring_anonymous_func_16601()
回答:
- これは無名関数です。つまり、クロージャー (関数閉包) ではありません。
- この世界の開発者たちがクロージャーへの対応を要望しましたが、 Ring 言語の開発で新しい機能を追加することは Ring 言語の目的と精神に反することです。
- 明瞭な解決方法を提供するために、関数とステートを統合したいときはクラスとオブジェクトを使用できます。
- リストを使用してリストの内側に無名関数を記述すると、ステートと関数のあるリストを返すことができます。なお、使用するときは関数へリストを渡します。
- eval() および substr() を使用すると、無名関数を返す前に変数の値を直接追加できます。
- 関数の定義時に、ほかのスコープを保護します。Ring では最大で三種類のスコープに属する各場所で、三種類のスコープ規則を提供しています (グローバル、オブジェクトのスコープ、およびローカルスコープ)。
- ほかのプログラミング言語を、全て真似をする必要もありませんし、真似しても全て得られるわけではありません! そのように考えているならば、非常に複雑怪奇なプログラミング言語を作成するか、時間を節約するために他のプログラミング言語を使うと思います。
- 新しいプログラミング言語の学習、または勉強に専念して (Ring の新しいところや優れたところ)、 いつから使い始めるかについて考えることがあります。数ヶ月前に、公開されたプログラミング言語と数年前に開発が始まったプログラミング言語を比較すること、および現在の世界で使用されているプログラミング言語をすべて理解したと錯覚しないでください。
- そのほかのプログラミング言語でも、各々のプログラミング言語で誤解されている機能があります。これは機能ではなくアイディアです (すべての機能の背景とともにある精神と才能です)。
シンタックスの処理ではなく自作言語の定義機能があり、コードなどで構文解析の使用を可能にしている理由は?¶
つまり、画期的です - 構文解析関連の学習をせずに、自然言語ステートメントを作成できます。 聡明な判断により、クラスを使用します (後でコンテキストに基づき 様々なステートメントへ対応するクラスを併用できるようにするためです - ステートメントの変更と変換など様々なことができます)。 また、すべての Ring 命令からでも使用可能にするためにステートメントを Ring の世界へ追加します。
ループの中断時に数値の指定ができる理由は?¶
Ring は小規模プログラミングと大規模プログラミングに対応しています。 目的と手段に基づいて使用する機能を選択します。 お望みとあれば、プログラマはプログラミング言語で粗悪なコードを記述できます。 このアイディアは、柔軟性の破壊など他の問題を起こさずにエラーを防ぐためにプログラミング言語の設計側で行わなくてはなりません。
例えば、 Linux カーネルと Ruby の実装としてコードの一部を読むと、普段は使用しない一般的規則による実用的な GOTO の用法と用例を理解するでしょう。また、優れたプログラマは、いつ規則を破るべきかを知っています。 Ring において GOTO は使用不能であり、実装予定については一切言及しません。 しかし、一階層以上のループを中断する機能や下位関数からループを中断する機能は、小規模プログラムでは実用的です。
とにかく、これらは言語により追加された小さな新機能の一部です (巨大なアイディアではありません)。
Ring で ‘See’, ‘Give’, ‘But’ および ‘Ok’ キーワードを採用する理由は?¶
See と Give は “反対の動作” ではありませんが、プログラマがしたいことを表すために選択されています。
画面から処理の過程や結果を確認したいときは ‘See’ です。
キーボードからの標準入力をプログラムへ与えたいときは ‘Give’ です。
“but” や “ok” を選んだ根拠は簡単に書けるキーワードだからです。
また “but” の使用は elseif/elif/elsif に対してプログラミング言語ごとに異なるキーワードを選択するよりも、覚えやすいです。
これらは Ring 1.1 以降ではオプション扱いです。
‘See’ と ‘Give’ の代わりに ‘Put’ と ‘Get’ を使用できます。
‘But’ と‘Ok’ の代わりに‘elseif’ または ‘end’ を使用できます。
それは読者の選択にゆだねられています。 Ring には複数の記法とシンタックスの柔軟性があります。
また、自然言語の新規定義、および言語のキーワードと演算子を変更可能です。
Ring においてデータ型の背景にある哲学とは?¶
Ring は開発で求められる基本概念を提供しています! 可能な限り、基本概念は単純明快・小規模を維持するのが目標の一つです。
Ring におけるリストの用法で可能なこと
- 配列の作成 (単体データ型)
- リストの作成 (混成データ型)
- ツリーの作成 (入れ子による配列)
- インデックスに文字列を使用 (ディクショナリー・ハッシュテーブル風の記法)
同じ原則は、数値に対して下記を使用するときにも適用されます。
- int 値
- double 値
- Boolean 値 (True/False)
この事例の原則は、文字列に対して下記を格納するときにも適用されます。
- 文字
- テキスト (一行以上)
- バイナリデータ
- 日付
- 日時
- NULL 値 (空の文字列)
プログラマが新しいデータ型を定義することで、言語の定義済みデフォルト型として 使用できるオブジェクト指向への対応。つまり、 + 演算子のオーバーロードがあります。
よって、このようになりました。
- 高速であり、 Ring 言語では基本型 (文字列、数値、リスト、オブジェクト) を提供しています。
- オブジェクト指向プログラミングを使用してアプリケーションの問題領域に従い、新しい型を追加することで拡張できる柔軟なプログラミング言語です。
Ring でのブール値とは?¶
コードでブール式の結果を判定するときに
true (真) では 1 を、および false (偽) では 0 を使用できます。
see 命令を使用して、値を表示するときに 1 は (true) であり、 0 は (false) を表示します。
理由は?
Ring には四種類の型があるからです。
- 数値
- 文字列
- リスト
- オブジェクト
最初の型 (数値) は、 int (整数)、倍精度数、ブール値を表すために使用されます。
二番目の型 (文字列) は、 char (文字) 型、文字の配列、日付と時刻を表すために使用されます。
三番目の型 (リスト) は配列型であり、一つ以上の型から構成される配列として、ハッシュ (ディクショナリ)、ツリーなどを表すために使用されます。
オブジェクトは、 Ring のクラス (全てのクラス) または C/C++ 関数、メソッドを呼び出すことで得られる C ポインタから作成されたオブジェクトです。
なぜですか?
Ring はプログラマ、開発者が様々な作業で使えるように 最も単純明快な概念で設計されています。問題領域の定義に関心があるならば、 プログラマ、開発者は様々な型を取得するために、新しいクラス (および演算子のオーバーロード)を作成することで言語をカスタマイズします。
どうしてですか?
単純なことは良いことであり、習得と記憶が簡単だからです! さらに、これは基本型を使用して表現できる高水準型の間で変換の柔軟性を提供します。
Ring に “Main” 関数を実装した理由は?¶
Main 関数は非常に重要であり、グローバルスコープの代わりにローカル変数を使用する ステートメントを記述したいときに必要です。
用例:
x = 10
myfunc()
See "X value = " + X # ここでは x の値は (10) と想定します。
# しかし myfunc() で x を使用しているため別の値 (6) になります!
Func myfunc
for x = 1 to 5
See x + nl
next
実行結果:
1
2
3
4
5
X value = 6
Main 関数の使用
Func Main
x = 10
myfunc()
See "X value = " + X
Func myfunc
for x = 1 to 5
See x + nl
next
実行結果:
1
2
3
4
5
X value = 10
Ring のインデックスが 1 から始まる理由は?¶
実生活では、三個のリンゴを手に持って数えるとき、
1 2 3 と数えます。
0 から数えることはしません。
質問: ほかのプログラミング言語において、インデックスが必ず 0 から開始されるのか?
回答: これは、計算機における値とメモリアドレスの取り扱い方法について関係があります。
用例:
myarray[5] 配列があります。
メモリには: myarray のアドレスがあります。
最初の項目は、アドレスへ格納されます。
二番目の項目は、アドレスの後などにあります。
myarray のアドレスで必要となる最初のアドレスを指し示す必要がある場合は
myarray + 0 の結果は、最初にある項目を指し示すため、そのまま myarray[0] と入力します。
myarray + 1 の結果は、二番目などにある項目を指し示すため、 myarray[1] と入力します。
このような仕組みは、低水準言語またはハードウェア寄りの言語では良いことです。
しかし、アプリケーション開発用に設計された高級言語では、自然な仕組みのほうが優れています。
用例:
mylist = [1,2,3,4,5]
for x = 1 to len(mylist)
see x + nl
next
前述の用例では、配列の長さは 1 から開始します。 0 から開始するインデックスを記述する場合は、
for x = 0 to len(mylist)-1
また、 ほかのプログラミング言語の for ループのようにする方法を覚えておいてください。
for(x=0 ; x<nMax ; x++ )
< 演算子を使用してください!
Ring が英数大小文字を区別しない理由は?¶
- もっとひとにやさしくするため。
- Ada, SQL, Pascal, Delphi, Visual Basic, Visual FoxPro などのようにするため。
- 自然言語プログラミングの対応において効果的であるため。
- プログラミング言語のキーワードを記述するとき、好みの記法を選択できるようにするため。
see "lower case!"
SEE "UPPER case!"
See "First Letter is UPPER case!"
- 手軽なテストを書くために、 “Variable” ではなく “variable” を入力してしまった後にエラーメッセージになるのを防ぐため。
- “dosomething()” ではなく、 “Dosomething()” を入力してしまった後にエラーメッセージになるのを防ぐため。
- Ring では、変数、メソッド名、およびクラス名の間で名前衝突を起こさないため。
変数名として、 person および クラス名として Person を記述できます。
person = new Person
class Person
name address phone
大小英数を区別したい場合は、キーワードと演算子の再定義 (またはプリプロセッサを自作)、および全角英数を使用してください。
代入演算子で深いコピーを使用する理由は?¶
- “つまり、実行性能の利得に関しては疑問と劣悪な等価交換があります。
- 第三者による証明が行われるまで、深いvs浅いコピーの良い手引きとしては深いコピーのほうが好ましいです。” ― スティーブ・マコーネル、コンプリートコードより
代入演算子を使用するとき、深いコピーを要求することは、より自然なことです。
深いコピーが不要ならば、使用しないだけで良いです!
Ring は、できる限り参照の使用を減らすように設計されます。
Ring は、これが意味がある特別な場合において、参照を単純かつ可能にするために設計されています。
- 関数へのリスト、およびオブジェクト渡すとき、 C/C++ ライブラリからオブジェクトを
作成するとき (GUI オブジェクトなど)、リストの内側に格納されている オブジェクトを返すときなど、これが自然な場合は参照となります。
- これは機能であり、純粋関数を作成するために使用できます。これが必要なとき、
stdlib の Value() 関数は、この機能を使用して値によるリストとオブジェクトを渡します。
参照が必要なときは、リストを共有管理するためのクラスとオブジェクトの作成を推奨します。
様々なロジックエラーを回避することは、アプリケーションの水準ではより安全なことです。
- Ring では、つまらない、細かいことに関して考えずに開発を開始してアプリケーションに専念するため、型を記述しなくても良いです (動的型付け)。
また、数値、および文字列の間で明示的変換を記述しなくても良いです (弱い型付け)。 さらに、値または参照、および使用の間で選択しなくても良いです。 そして、スコープを記述しなくても良いです (レキシカルスコープ)。
- Ring には、スマートガベージコレクター (単純で高速) があります。代入演算子を使用すれば、いつでも好きなときにメモリを直接削除できます。
これは参照の削減方法、または管理プログラムから使用することは、当目的を達成するのに大いに有効です。 これによる完全な制御があります。
- 参照の作成、および管理の作成を回避したい場合は
Object2Pointer() と Pointer2Object() 関数を使用します。 しかし、これは Ring の “精神” に反しています。
Ring にコンストラクタメソッドはありますか?¶
例えば新しいオブジェクトを作成するとき、
new point
1 - Ring で認識されていないときは Ring は新しいオブジェクトの属性で用いる動的メモリ空間を割り当てます。
2 - Ring は手順①で作成されたオブジェクトのステートを使用することで現在のオブジェクトのスコープとローカルスコープを変更します。
3 - Ring は実行中に、クラスの範囲を移動します (クラス名の後、そしてメソッドの前)。
4 - クラスの範囲内にあるすべての命令やコードは、 Ring のコードとして実行されます。
5 - クラスの範囲が終端に到達、または Return 命令を使用すると、制御はクラスの範囲から (新しい場所) へ移動します
オブジェクトが追加された全属性は動的属性であるため、これは実行時に追加する属性を制御できます。
用例:
$3D = False
see new point
$3D = True
see new point
class point
x y
if not $3D return ok
z
実行結果:
x: NULL
y: NULL
x: NULL
y: NULL
z: NULL
新しいオブジェクトを作成するときに、 init() メソッドを直接呼び出すオプションがあります。
このメソッドはオブジェクトの作成後に、クラスの範囲にあるコードの実行すると呼び出されるためオブジェクトの属性を使用して処理を行うことができます。
p1 = new point3d(100,200,300)
see p1
class point3d
x y z
func init p1,p2,p3
x=p1 y=p2 z=p3
オブジェクトの新規作成時に起きていることは?¶
1 - オブジェクトの作成時に、クラスの範囲にあるコードは実行されます。そして、この範囲にあるコードに基づいたオブジェクトの属性があります。
2 - Ring は、メソッドの呼び出しを開始するまでオブジェクトに関して気にしません。
3 - メソッドの呼び出し時に、 Ring はオブジェクトのクラスと親クラスの確認を行い (継承を使用しているならば)、同一クラスに所属する全てのオブジェクトから現在または今後使用するためにメソッドを収集します。
4 - メソッドは動的であり、各オブジェクトはクラスのメソッドから取得するため、オブジェクトの作成後に、メソッドの追加、オブジェクトまたは作成されたオブジェクトの使用、または同一クラスから作成できます。
用例:
o1 = new point {x=10 y=20 z=30}
o2 = new point {x=100 y=200 z =300}
addmethod(o1,"print", func { see x + nl + y + nl + z + nl } )
o1.print()
o2.print()
class point x y z
実行結果:
10
20
30
100
200
300
Getter と Setter メソッドでのアクセスにより属性を使用できますか?¶
もちろんです。クラスの外側から属性の使用を開始するときに、 Setter/Getter メソッドは自動的に呼び出されます。 また、属性を使用する代わりに、メソッドを呼び出せます。読者の選択しだいです。
用例:
o1 = new Developer
o1.name = "Mahmoud" see o1.name + nl
o1 { name = "Gal" see name }
o1 { name = "Bert" see name }
o1.setname("Marino")
see o1.getname()
Class Developer
name language = "Ring Programming Language"
func setname value
see "Message from SetName() Function!" + nl
name = value + " - " + language
func getname
see "Message from GetName() Function!" + nl + nl
return "Mr. " + name + nl
実行結果:
Message from SetName() Function!
Message from GetName() Function!
Mr. Mahmoud - Ring Programming Language
Message from SetName() Function!
Message from GetName() Function!
Mr. Gal - Ring Programming Language
Message from SetName() Function!
Message from GetName() Function!
Mr. Bert - Ring Programming Language
Message from SetName() Function!
Message from GetName() Function!
Mr. Marino - Ring Programming Language
クラスを定義している間にグローバルな名前の検索を行う理由は?¶
質問は、なぜクラス属性の定義時に グローバル変数との名前衝突を回避しないのですか?
先頭にオプションの $ 記号を使用することで、グローバル変数名の問題解決になることを覚えておいてください。 Main 関数は、グローバル変数を避けるために効果があります。
回答:
Ring は動的プログラミング言語です。
実行時に、クラスの属性を決定できます (追加・削除)。
クラスの属性を定義している間は、実行 (指定のコード) できます。
用例①
oPerson = new Person
Class Person
See "Welcome to the Ring language"
用例②
グローバル変数に基づき、属性をカスタマイズします。
$debug = true
oPerson = new Person
see oPerson
Class Person
if $debug date=date() time=time() ok
前述の用例では、 $debug フラグに true が設定されているとき、 オブジェクトのステートへ Date と Time 属性を追加します。
用例③
グローバル変数に基づき、オブジェクトのインデックスを格納します。
$ObjectsCount = 0
oPerson = new Person
see oPerson
oPerson2 = new Person
see oPerson2
Class Person
$ObjectsCount++
nIndex = $ObjectsCount
実行結果:
nindex: 1.000000
nindex: 2.000000
一般的な用例:
- データベースの接続後に、デーブルのカラムを取得します (グローバル変数やオブジェクトを使用)。
- カラム名に基づき、クラスの属性を作成します。
- 後でデータベースを修正します - 不要ならば、コードを修正しないでください。
柔軟性はありますが、すばらしい応答性による強力さがあることを覚えておいてください。
Ring でグローバル変数とクラスの属性名間の名前衝突を回避しない理由は?¶
このような場合に、使用するためです。
1 - $ などの特殊記号を使用せずに、グローバル変数を定義するためです。
2 - クラスには、特別なシンタックスを使用して定義された属性があります (クラスの後に属性名を直接入力します)。
3 - 属性は、コードの記述とグローバル変数の使用が許されているクラスの範囲で定義されます。
クラスの範囲内で、 Ring の変数検出方法の変更について提案を受け入れる場合は、この問題よりも更に重要な問題を多発する前に三つの機能のうち一つを破る必要があります。
Ring のコードをもっと綺麗なものにしておきたいし、 $ を使用する・しないときをプログラマに決定させたいため機能番号①の変更は好みではありません。
この機能は気に入っており、プログラマに Self.属性 の入力を強制するのは好みではないであるため機能番号②の変更は好みではありません。
ほとんどのアプリケーションでは、クラスの範囲内でグローバル変数へのアクセスは非常に重要であるため機能番号③の変更は好みではありません。
どのような判断ですか?
筆者は、この特例を回避するのにプログラマが決定するために、この事例を記載することに決定しました。
1 - グローバル変数の使用を回避でき (最良)、 Main 関数 (オプション扱い) を使用できます。
2 - プログラマは変数名の前に $
あるいは global_
または g_
などの記号を使用できます。
3 - プログラマは属性を定義するために、クラス名の後に Self.属性 を使用できます。
一般に、小規模プログラムではグローバル変数と関数を使用できます。 大規模プログラムでは、クラスとオブジェクトを使用してグローバル変数は数本にするか、または使用を避けてください。
ftell() と fseek() でファイルの大きさを取得するには?¶
この関数はファイルの読み込みを行わずに、ファイルの大きさを取得します!
func getFileSize fp
C_FILESTART = 0
C_FILEEND = 2
fseek(fp,0,C_FILEEND)
nFileSize = ftell(fp)
fseek(fp,0,C_FILESTART)
return nFileSize
注釈
前述の関数では仮引数として、 fp (ファイルポインタ) を扱います。 fopen() 関数で開いているファイルから fp を取得できます。
fp = fopen("filename","r")
see "File Size : " + getFileSize(fp) + nl
別の解決方法 (ファイルの読み取り):
see len(read("filename"))
現在のソースファイルのパスを取得するには?¶
この関数を使用することで、現在のソースファイルのパスを取得できます。 そして、パスを扱うための変数へファイル名を追加できます。
cPath = CurrentPath()
func currentpath
cFileName = filename()
for x = len(cFileName) to 1 step -1
if cFileName[x] = "/"
return left(cFileName,x-1)
ok
next
return cFileName
関数の定義済み仮引数またはオプションの仮引数とは?¶
定義済み仮引数、またはオプションの仮引数を使用したい場合は、ハッシュ、ディクショナリなどのリストを受け入れてください。
用例:
sum([ :a = 1, :b = 2])
sum([ :a = 1 ])
sum([ :b = 2 ])
func sum pList
if plist[:a] = NULL pList[:a] = 4 ok
if plist[:b] = NULL pList[:b] = 5 ok
see pList[:a] + pList[:b] + nl
実行結果:
3
6
6
リストやディクショナリでキーまたは値のみを表示するには?¶
キーまたは値のみを表示したい場合は、項目のインデックスを選択します (1 または 2)。
用例
C_COUNTRY = 1
C_CITY = 2
mylist = [
:KSA = "Riyadh" ,
:Egypt = "Cairo"
]
for x in mylist
see x[C_COUNTRY] + nl
next
for x in mylist
see x[C_CITY] + nl
next
実行結果:
ksa
egypt
Riyadh
Cairo
リストで nl を表示するときに変な結果になる理由は?¶
このコードでは、
list = 1:5 # list = [1,2,3,4,5]
see list + nl
リストへ改行を追加後にリストを表示します。つまり、通常のリスト表示では、リストの末尾にある改行も表示します。 新しい改行文字を追加したので、改行は二行表示となります。
See <式>
see 命令は式の最終結果を表示するため、このように式が評価されます。
nl = char(13) + char(10) # 変更可能な変数!
+ は演算子です。
文字列 + 文字列 ---> 新しい文字列
文字列 + 数値 ---> 新しい文字列
数値 + 数値 ---> 新しい数値
数値 + 文字列 ---> 新しい数値
リスト + 項目 —> なにも新規作成されませんが、同じリストへ項目が追加されます。
例外:
数値 + nl —> 新しい文字列
この例外は数値の表示後に、改行を簡単にできるよう追加されています。
最後の項目を表示した後には、改行が既にあるため、これはリストを表示するためには不要です。
StrCmp() の実行結果について解説していただけますか?¶
最初に ‘=’ 演算子を使用して、直接的に文字列を検査できることを覚えておいてください。
see strcmp("hello","hello") + nl +
strcmp("abc","bcd") + nl +
strcmp("bcd","abc") + nl
両方とも、同じ文字列の場合は 0 を返します。
abc と bcd は違います。二行目は -1 を返しており三行目は 1 を返します。
二行目では “abc” と “bcd” の比較を行っています。
“abc” = “a” の一文字目と “bcd” = “b” の一文字は等しくはないからです。 よって “a” != “b” と “a” < “b” の結果となります。
よって “a” != “b” と “a” < “b” の
実行結果は -1 となります。
三行目には “bcd” と “abc” があります。
“bcd” の一文字目は “b” であり “abc” の一文字は= “a” です。
結果は “b” != “a” と “b” > “a” です。
従って、実行結果は 1 となります。
注釈
ASCII(“a”) は 97 であり ASCII(“b”) は 98 です。よって 97 < 98 であるため “a” は “b” 以下となります。
プロジェクトで複数のソースコードを使用するには?¶
用例:
このようなフォルダがあります。
C:\LRing
このようなファイルがフォルダにあります。
C:\LRing\t1.ring
C:\LRing\mylib.ring
C:\LRing\libs\mylib2.ring
このようなコードが t1.ring ファイルにあります。
load "mylib.ring"
load "libs\mylib2.ring"
myfunc()
test()
このようなコードが mylib.ring ファイルにあります。
func myfunc
see "message from myfunc"+nl
このようなコードが libsmylib2.ring ファイルにあります。
func test
see "message from test" + nl
C:\LRing フォルダから。
Ring のパスを追加していない場合は、このコマンドで追加できます。
set path=%path%;c:\ring\bin;
Ring フォルダ C:\Ring のある場所で
実行します。
Ring t1.ring
実行結果:
message from myfunc
message from test
この用例で GetChar() を二度使用する理由は?¶
GetChar() 関数は、キーボードバッファから一文字受け取ります。
この用例では、
While True
See "
Main Menu
(1) Say Hello
(2) Exit
"
Option = GetChar()
GetChar() GetChar() # 行の終わり
# この行で前述の二行を置換できます。
# Give Option
if Option = 1
see "Enter your name : " give cName
see "Hello " + cName
else
bye
ok
End
GetChar() を三回使用しています。
最初はユーザの選択肢を取得するときに、
Option = GetChar()
しかし、二回目と三回目があります (バッファから改行文字を受け取ります)。
GetChar() GetChar() # 行の終わり
用例: ユーザが選択肢から 1 を選んだ後に ENTER を押します。
ここでは、三文字あります。
- 一文字目は : 数字の 1 です。
- 二文字目は : CHAR(13) です。
- 三文字目は : CHAR(10) です。
Windows において、 CHAR(13) および CHAR(10) は、それぞれ改行となります (すなわち CR+LF)。
NULL と isNULL() 関数の用法は?¶
Ring では、未初期化変数を使用すると、明示的なランタイムエラーメッセージが表示されます。
用例:
See x
実行結果:
Line 1 Error (R24) : Using uninitialized variable : x
in file tests\seeuninit.ring
未初期化の属性へアクセスすると、同じことが起こります。
用例:
o1 = new point
see o1
see o1.x
class point x y z
実行結果
x: NULL
y: NULL
z: NULL
Line 3 Error (R24) : Using uninitialized variable : x
in file tests\seeuninit2.ring
エラーを検査したい場合は、 Try/Catch/End を使用してください。
Try
see x
Catch
See "Sorry, We can't use x!" + nl
Done
実行結果:
Sorry, We can't use x!
さて、 NULL と isNULL() についてお話します。
未初期化の変数を扱おうとしたとき、エラーメッセージが出ます。
これらのエラーは Try/Catch/Done を使用することで検査できます。文字列で扱うためには NULL と isNULL() を使用します。
NULL には、空文字列の変数があります。
isNULL() は関数であり、入力が空の文字列、または文字列の内容が “NULL” ならば true (1) を返します。
これらの値 (空の文字列) をテストする必要があり、 DBMS などの外部リソースから “NULL” を有する文字列が入力されることがあるからです。
用例:
See isNULL(5) + nl + # 0 の表示
isNULL("hello") + nl + # 0 の表示
isNULL([1,3,5]) + nl + # 0 の表示
isNULL("") + nl + # 1 の表示
isNULL("NULL") # 1 の表示
オブジェクトのあるリストを表示するには?¶
この用例では、オブジェクトのあるリストの表示方法を確認します。
aList = [[1,2,3] , new point(1,2,3), new point(1,2,3)]
see "print the list" + nl
see alist
see "print the item (object)" + nl
see alist[2]
class point x y z
func init p1,p2,p3 x=p1 y=p2 z=p3
実行結果:
print the list
1
2
3
x: 1.000000
y: 2.000000
z: 3.000000
x: 1.000000
y: 2.000000
z: 3.000000
print the item (object)
x: 1.000000
y: 2.000000
z: 3.000000
改行と文字を表示するには?¶
nl 変数で改行します。
See "Hello" + nl
複数行リテラルでも改行できます。
See "Hello
"
char(nASCII) 関数で他の文字を表示します。
See char(109) + nl + # m の表示
char(77) # M の表示
qApp クラス名の後に () を使用しない理由は?¶
GUI 作成のために、 RingQt を使用する場合は、 新しいオブジェクトの作成時にクラス名の後に () を使用します。例えば、
new qWidget() { setWindowTitle("Hello World") resize(400,400) show() }
この処理の前に、 qApp クラスからオブジェクトを作成しますが、名前の後ろには () を使用しません。
Load "guilib.ring"
app = new qApp
{
win=new qWidget()
{
setwindowtitle(:test)
show()
}
exec()
}
クラス名の後に () を使用すると、クラス内にある init() メソッドの呼び出し、およびこのメソッドへの仮引数を渡す意味になります。
クラス内に init() がないメソッドで () を使用すると、例外エラーメッセージになります。
そのほかのクラスには、 init() メソッドはありますが qApp クラスにはありません。 関数を使用したオブジェクトのポインタを返すオブジェクトの作成に必要であり、 このポインタは pObject 属性に格納されるのが理由です。 詳細情報は ring_qt.ring ファイルに収録されているクラスを参照してください。
ウィンドウのタイトルバーが画面外に移動してしまう原因は?¶
このコードを記述した場合、
Load "guilib.ring"
app = new qApp
{
win=new qWidget()
{
setwindowtitle(:test)
setGeometry(0,0,200,200)
show()
}
exec()
}
ウィンドウが (200,200) の寸法で (0,0) の地点へ移動すると思うでしょう。 実際は、ウィンドウのタイトルバーが画面外に移動してしまいます。
これは Qt フレームワークの挙動と関連があります。
このコードは、問題を回避するためのものです。
load "guilib.ring"
new qApp {
new qWidget() {
move(0,0)
resize(200,200)
show()
}
exec()
}
GUI アプリケーションでボタンの配列を作成するには?¶
この用例をご確認ください:
Load "guilib.ring"
App1 = new qApp {
win1 = new qWidget() {
move(0,0)
resize(500,500)
new qPushButton(win1)
{
settext("OK")
setclickevent("click()")
}
btn1 = new qPushButton(win1)
{
setgeometry(100,100,100,30)
settext("Button1")
}
btn2 = new qPushButton(win1)
{
setgeometry(200,100,100,30)
settext("Button2")
}
button = [btn1, btn2]
show()
}
exec()
}
func click
button[1] { settext ("Button3") }
button[2] { settext ("Button4") }
ウィンドウを閉じた後に別のウィンドウを表示するには?¶
この用例は、ウィンドウを閉じる方法と別のウィンドウを表示する方法です。
Load "guilib.ring"
app=new qApp
{
frmBefore=new Qwidget()
{
setWindowTitle("before!")
resize(300,320)
move(200,200)
button=new qPushButton(frmBefore)
{
setText("Close")
setClickEvent("frmBefore.close() frmMain.show()")
}
show()
}
frmMain=new Qwidget()
{
setWindowTitle("After!")
resize(300,320)
move(200,200)
}
exec()
}
モーダルウィンドウの作成方法は?¶
この用例は、モーダルウィンドウの作成方法です。
load "guilib.ring"
app=new qApp
{
frmStart=new Qwidget()
{
setWindowTitle("The First Window")
resize(300,320)
move(200,200)
button=new qPushButton(frmStart)
{
setText("Show Modal Window")
resize(200,30)
setClickEvent("frmModal.show()")
}
new qPushButton(frmStart)
{
setText("Close Window")
move(0,50)
resize(200,30)
setClickEvent("frmStart.Close()")
}
show()
}
frmModal =new Qwidget()
{
setWindowTitle("Modal Window")
resize(300,320)
move(200,200)
setparent(frmStart)
setwindowmodality(true)
setwindowflags(Qt_Dialog)
}
exec()
}
関連資料:
最大化ボタンの無効化およびウィンドウのサイズを変更するには?¶
setWindowFlags() メソッドを使用します。
Load "guilib.ring"
app1 = new qapp {
win1 = new qwidget() {
setwindowtitle("First")
setgeometry(100,100,500,500)
new qpushbutton(win1) {
setgeometry(100,100,100,30)
settext("close")
setclickevent("app1.quit()")
}
new qpushbutton(win1) {
setgeometry(250,100,100,30)
settext("Second")
setclickevent("second()")
}
showmaximized()
}
exec()
}
func second
win2 = new qwidget() {
setwindowtitle("Second")
setgeometry(100,100,500,500)
setwindowflags(Qt_dialog)
show()
}
ODBC から SQLite を使用するには?¶
Ring 1.1 以降のバージョンでは、 SQLite に標準対応しているため、 ODBC から使用する必要はありません。
また、 RingQt から SQLite へアクセスできます。
質問への回答
pODBC = odbc_init()
odbc_connect(pODBC,"DRIVER=SQLite3 ODBC Driver;Database=mydb.db;LongNames=0;"+
"Timeout=1000;NoTXN=0;SyncPragma=NORMAL;StepAPI=0;")
odbc_execute(pODBC,"create table 'tel' ('ID','NAME','PHONE');")
odbc_execute(pODBC,"insert into 'tel' values ('1','Mahmoud','123456');")
odbc_execute(pODBC,"insert into 'tel' values ('2','Ahmed','123456');")
odbc_execute(pODBC,"insert into 'tel' values ('3','Ibrahim','123456');")
odbc_execute(pODBC,"select * from tel") + nl
nMax = odbc_colcount(pODBC)
See "Columns Count : " + nMax + nl
while odbc_fetch(pODBC)
See nl
for x = 1 to nMax
see odbc_getdata(pODBC,x)
if x != nMax see " - " ok
next
end
odbc_disconnect(pODBC)
odbc_close(pODBC)
実行結果:
Columns Count : 3
1 - Mahmoud - 123456
2 - Ahmed - 123456
3 - Ibrahim - 123456
このプログラムは、ファイルを作成します : mydb.db
注意 : ODBC ドライバを表示したとき、そこにある長いリストを確認できます。
SQLite3 ODBC Driver - UsageCount=1
SQLite ODBC Driver - UsageCount=1
SQLite ODBC (UTF-8) Driver - UsageCount=1
そして “SQLite3 ODBC Driver” を使用しています。
dBase/Harbour データベースへ接続できますか?¶
多種多様なデータベースを ODBC で接続できます。
xBase ファイル (*.DBF) へ接続するには、
See "Using DBF Files using ODBC" + nl
pODBC = odbc_init()
See "Connect to database" + nl
odbc_connect(pODBC,"Driver={Microsoft dBase Driver (*.dbf)};"+
"datasource=dBase Files;DriverID=277")
See "Select data" + nl
odbc_execute(pODBC,"select * from tel.dbf")
nMax = odbc_colcount(pODBC)
See "Columns Count : " + nMax + nl
while odbc_fetch(pODBC)
See "Row data:" + nl
for x = 1 to nMax
see odbc_getdata(pODBC,x) + " - "
next
end
See "Close database..." + nl
odbc_disconnect(pODBC)
odbc_close(pODBC)
実行結果
Using DBF Files using ODBC
Connect to database
Select data
Columns Count : 3
Row data:
Ahmad - Egypt - 234567 - Row data:
Fady - Egypt - 345678 - Row data:
Shady - Egypt - 456789 - Row data:
Mahmoud - Egypt - 123456 - Close database...
また Visual FoxPro データベースにも接続できます (Visual FoxPro ドライバのインストールが必要です)。
See "ODBC test 6" + nl
pODBC = odbc_init()
See "Connect to database" + nl
odbc_connect(pODBC,"Driver={Microsoft Visual FoxPro Driver};"+
"SourceType=DBC;SourceDB=C:\PWCT19\ssbuild\PWCTDATA\CH1\Data\mydata.dbc;")
See "Select data" + nl
see odbc_execute(pODBC,"select * from t38") + nl
nMax = odbc_colcount(pODBC)
See "Columns Count : " + nMax + nl
while odbc_fetch(pODBC)
See "Row data:" + nl
for x = 1 to nMax
see odbc_getdata(pODBC,x) + " - "
next
end
See "Close database..." + nl
odbc_disconnect(pODBC)
odbc_close(pODBC)
setClickEvent() はオブジェクトのメソッドを直接参照しない理由は?¶
setClickEvent(cCode) は、コードを有する文字列を受け入れます。 イベントの発生時にコードは実行されます。
Ring は 手続き型、オブジェクト指向、関数型など様々なプログラミングパラダイムに対応しています。
プログラミング言語の水準で様々なパラダイムに対応するときは、二つの選択肢のうち、どちらのパラダイムが使用されるのか検出することはできません。
- 様々なプログラミングパラダイムで動作する一般的な解決方法を提供します。
- 特定のパラダイムのうち一つのものと合致する様々な解決方法を提供します。
setClickEvent() および、そのほかは (様々なプログラミングパラダイムで動作する一般的な解決方法) に所属しています。
クラスとオブジェクトの取り扱いに関する注意を一切しなくても、文字列のコードを渡すことで実行されます。
このコードは関数の呼び出し、メソッドの呼び出しと変数の値の設定などができました。
そのほかのプログラミング言語では、イベントでオブジェクト指向プログラミングとメソッドの呼び出しの使用を強制します。 また、そのほかのプログラミング言語では、現在のオブジェクトなどの仮引数を取得するために無名関数を使用します。
現在、一般的な解決方法は方法はありますが、将来は、特定のパラダイムと合致する 明確な解決方法を追加する場合があります (オブジェクト指向、宣言型プログラミング、および自然言語プログラミング)。
定義エラーを起こさずに関数を呼び出せる理由は?¶
各プログラムは次の順序に従います。
- ファイルの読み込み
- グローバル変数とステートメント
- 関数
- パッケージ、クラスとメソッド
どのような意味がありますか?
- **** 関数がない場合は、その後はクラスとなります。 ****
- **** 関数、メソッド、クラス、パッケージを終わらせるための命令は不要です。 ****
この用例をご確認ください。
See "Hello"
test()
func test
see "message from the test function!" + nl
class test
前述の用例では、 test() 関数があるため test() を直接使用して呼び出すことができます。
この用例では、 test() がメソッドになります。
See "Hello"
test() # ランタイムエラーメッセージ
class test
func test # Test() はメソッドです (関数ではない)
see "message from the test method!" + nl
メソッドの定義後に、関数を直接呼び出そうとしたときはエラーになります。
前述のプログラムは必ずこの通りにしてください。
See "Hello"
new test { test() } # メソッドの呼び出し
class test
func test # Test() はメソッドです (関数ではない)
see "message from the test method!" + nl
Ring は Windows XP で動作しますか?¶
Ring は Windows XP で動作します。そして、拡張機能も問題なく読み込むことができます。 また、 USB ストレージに導入して外出先で Ring プログラミングが楽しめます。
注釈
環境によっては RingAllegro は正常に動作しません。 RingLibSDL をお使いください。
注釈
Microsoft Visual C++ 2010 では RingAllegro のビルドはできません。
注釈
Ring 1.10 は Windows XP ではインストーラーの不具合により、正常にインストールできません。 Windows 10 以降でインストール後に ring フォルダを再圧縮して手動インストールしてください。
拡張機能の動作可否は Windows XP とコンパイラのバージョンの対応をご確認ください (最新のコンパイラでは Windows XP への対応にはオプションの指定が必要です)。
- この記事をご確認ください:
- https://blogs.msdn.microsoft.com/vcblog/2012/10/08/windows-xp-targeting-with-c-in-visual-studio-2012/
例えば、下記を追加します。
/link /SUBSYSTEM:CONSOLE,"5.01"
- Windows XP 対応のためのバッチファイル
- 参照 : https://github.com/ring-lang/ring/blob/master/src/buildvccomplete.bat
Microsoft Visual C++ 2010 で ringconsolecolors のビルドに失敗します。対策方法は?¶
Ring 1.10 でも、修正されていないバグですが、下記の通りにすれば、ビルドできます。
console-colors.c - 修正前 (154 ~ 156行):
#ifdef _WIN32
HANDLE console;
#endif /* _WIN32 */
// C2275: 175行目の CONSOLE_SCREEN_BUFFER_INFO csbi; の定義位置の誤り。
console-colors.c - 修正後 (154 ~ 156行):
#ifdef _WIN32
HANDLE console;
CONSOLE_SCREEN_BUFFER_INFO csbi; // Avoids of C2275 error (in Visual C++ 2010) - Patched by. isVowel
#endif /* _WIN32 */
// 175行目の CONSOLE_SCREEN_BUFFER_INFO csbi; は削除してください。
RingQt の拡張機能とクラスの追加方法は?¶
一般に C または C++ のコードを使用して Ring を拡張できます。
Ring のコードから C 関数の呼び出し、または C++ クラスとメソッドを使用できます。
詳細情報は、本取扱説明書の「C/C++ による拡張機能の開発方法」をお読みください。
このコードの用例では Ring ライブラリ (*.lib) を使用して *.c ファイルを DLL ファイルへコンパイルします。
#include "ring.h"
RING_FUNC(ring_ringlib_dlfunc)
{
printf("Message from dlfunc");
}
RING_API void ringlib_init(RingState *pRingState)
{
ring_vm_funcregister("dlfunc",ring_ringlib_dlfunc);
}
Ring は、 LoadLib() 関数で DLL ファイルを読み込んだ後に Ring 関数から dlfunc() 関数が呼び出されます。その後に C 関数を呼び出します。
See "Dynamic DLL" + NL
LoadLib("ringlib.dll")
dlfunc()
実行結果:
Dynamic DLL
Message from dlfunc
取扱説明書を読むと、仮引数 (文字列、数値、リストとオブジェクト) などの取得方法について知ることができます。
また、関数から値 (任意型) を返す方法も知ることができます。
実体験ですが、 C ライブラリまたは C++ ライブラリへ対応作業をしているとき、
ほとんどの関数で、ほとんどのコードを共有していることを発見しました。
時間の節約、および手軽に Ring で使用する C/C++ ライブラリのラッパーを生成するために、
こちらにコード生成器があります。
https://github.com/ring-lang/ring/blob/master/extensions/codegen/parsec.ring
コード生成器は 1200 行以下の Ring プログラムです。
コード生成器で入力した設定ファイルには C/C++ ライブラリの情報があります。
関数プロトタイプ、クラスとメソッド、定数、列挙体、構造体とメンバ、など。
そして、コード生成器で生成します。
- C ライブラリに関する *.C ファイル (ライブラリ関数を使用可能)
- C++ ライブラリに関する *.CPP ファイル (C++ クラスとメソッドを使用可能)
- *.Ring ファイル (C++ のクラスを Ring のクラスとして使用可能)
- *.RH ファイル (定数)
コード生成器の動作を理解するには、この Allegro ゲームプログラミング・ライブラリ用の拡張機能をご確認ください。
https://github.com/ring-lang/ring/tree/master/extensions/ringallegro
ひとつ目の設定ファイルは、
https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/allegro.cf
このファイルを記述するために、 Allegro の取扱説明書と Ring コード生成器の規則を使用しました。
このバッチファイルを使用して、コード生成器を実行します。
https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/gencode.bat
または、このスクリプトを使用します。
https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/gencode.sh
生成されたソースコードファイルを取得します。
https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/ring_allegro.c
生成されたソースコードファイル (ring_allegro.c) は約 1,2000 行です。
ですが、設定ファイルは 1000 行以下です。
ライブラリをビルドするには (DLL ファイルの作成)
https://github.com/ring-lang/ring/blob/master/extensions/ringallegro/buildvc.bat
また、この拡張機能は LibSDL ライブラリに関して確認できます。
https://github.com/ring-lang/ring/tree/master/extensions/ringsdl
まとめとして、知っておく必要のある関連事項は
1 - 設定ファイルの記述
2 - コード生成器の使用
3 - ライブラリや拡張機能の作成
4 - Ring コードからライブラリや拡張機能を使用
さて Qt についての質問へ移りましょう。
RingQt は Ringの拡張機能です (ringqt.dll)。
Ring の改修や変更は不要です。
- RingQt の変更が必要です。
- または、別の Qt ベースの拡張機能により、 Ring の機能を拡張します (だだし、同じ Qt バージョンです)。
最初の選択肢に関しては RingQt を参照してください。
https://github.com/ring-lang/ring/tree/master/extensions/ringqt
設定ファイル
https://github.com/ring-lang/ring/blob/master/extensions/ringqt/qt.cf
ソースコードを生成するには
https://github.com/ring-lang/ring/blob/master/extensions/ringqt/gencode.bat
https://github.com/ring-lang/ring/blob/master/extensions/ringqt/gencode.sh
https://github.com/ring-lang/ring/blob/master/extensions/ringqt/gencodeandroid.bat
DLL/so/Dylib ファイルをビルドするには
https://github.com/ring-lang/ring/blob/master/extensions/ringqt/buildmingw32.bat
https://github.com/ring-lang/ring/blob/master/extensions/ringqt/buildgcc.sh
https://github.com/ring-lang/ring/blob/master/extensions/ringqt/buildclang.sh
RingQt の学習をしてください。
利用できる選択肢について学んでください。
- 直接 Qt のクラスを接続します。
- 自作の新しいクラスを接続するために新しいクラスを作成します。
第二の選択肢は (前述の二つの要点、またはそれ以前にある2つの要点)、
C++ コードによる新しいクラスを作成します。
そして、作成したクラスを RingQt へ統合、または特別な DLL を用意します (判断に応じて)。
一般的な動作ならば、 RingQt に記述してください (他の人の手助けになります)。
特別な動作ならば、別の拡張機能に記述してください (特定のアプリケーション)。
Combobox および QTableWidget のセルへ他の要素を追加するには?¶
このコードをご確認ください。
Load "guilib.ring"
New qApp
{
win1 = new qMainWindow() {
setGeometry(100,100,1100,370)
setwindowtitle("Using QTableWidget")
Table1 = new qTableWidget(win1) {
setrowcount(10) setcolumncount(10)
setGeometry(0,0,800,400)
setselectionbehavior(QAbstractItemView_SelectRows)
for x = 1 to 10
for y = 1 to 10
item1 = new qtablewidgetitem("R"+X+"C"+Y)
setitem(x-1,y-1, item1)
next
next
cmb = new QComboBox(Table1) {
alist = ["one","two","three","four","five"]
for x in aList additem(x,0) next
}
setCellWidget(5, 5, cmb)
}
setcentralwidget(table1)
show()
}
exec()
}
QTableWidget で選択されたセルの内容に処理を行うには?¶
このサンプルをご確認ください。
Load "guilib.ring"
New qApp {
win1 = new qMainWindow() {
setGeometry(100,100,800,600)
setwindowtitle("Using QTableWidget")
Table1 = new qTableWidget(win1) {
setrowcount(10) setcolumncount(10)
setGeometry(10,10,400,400)
for x = 1 to 10
for y = 1 to 10
item1 = new qtablewidgetitem("10")
setitem(x-1,y-1,item1)
next
next
}
btn1 = new qPushButton(win1) {
setText("Increase")
setGeometry(510,10,100,30)
setClickEvent("pClick()")
}
show()
}
exec()
}
func pClick
for nRow = 0 to Table1.rowcount() - 1
for nCol = 0 to Table1.columncount() - 1
Table1.item(nRow,nCol) {
if isSelected()
setText( "" + ( 10 + text()) )
ok
}
next
next
三種類の記法のうち一般に使用されている、またはコミュニティで推薦されているものは?¶
- 記法を選択するだけですが、同じプロジェクトで異なる記法の併用、
または最低でも、同じコンテキストを併用しないでください (実装、テスト、スクリプトなど)。
注釈
各プロジェクトの開始時に規則の明示、およびその規則に従ってください。
- 記法の自作ができます (キーワードの変更により) - この考えはカスタマイズと自由のためのものです。
注釈
自然言語を使用する場合など、明確な理由がある場合に限り、新しい記法の作成とキーワードの変更を行うほうが良いです (日本語、アラビア語、フランス語など)。
- 第一形式は質問、チュートリアル、および小規模アプリケーション・プログラム (5,000行以下のコード) には最適です (筆者個人の意見です)。
用例 : Ring 取扱説明書、 Ring のサンプル、およびアプリケーションの大部分
第三形式は大規模アプリケーション、および現役プログラマには最適です (筆者個人の意見です)。