Schemeのコンストラクタの引数について

このQ&Aのポイント
  • Schemeのコンストラクタの引数は変数を取ることができない
  • コンストラクタの引数には値を直接指定する必要がある
  • 指定されたフィールドの値を取り出して返す関数を定義する必要がある
回答を見る
  • ベストアンサー

Schemeのコンストラクタの引数は?

Schemeのコンストラクタの引数は? 以前、Schemeについて質問させて頂いた者です。 まず、4つのフィールドx,y,delta-x,delta-yから成るBALL構造体と、2つのフィールドx,yから成るPOSN構造体を定義しました。 (define-struct BALL (x y delta-x delta-y)) (define-struct POSN (x y)) そして、そこから課せられた内容が 「BALL構造体データ a-ball から座標位置を取り出し、POSN構造体データとして返す関数 get-ball-posn を定義せよ。(make-posnを利用せよ)」 というものです。 私はまず、以下のように書いてみました。 (define a-ball (make-BALL x y delta-x delta-y)) ・・・(☆) (define (get-ball-posn a-ball) (make-POSN (BALL-x a-ball) (BALL-y a-ball))) そして (get-ball-posn (make-BALL 10 20 30 40)) のように実行してみると、 (☆)の部分の、x,y,delta-x,delta-yは定義されてない、という内容のエラーが返って来ました。 仕方ないので、その部分を'x 'y 'delta-x 'delta-yにそれぞれ直して再び実行してみると、 (make-POSN 10 20) と正しい答えが返ってきました。 色々試した結果、“コンストラクタの引数は、変数を取ることが出来ない”という結論に至りました。 これは正しいのですか? また、上記の'x 'y 'delta-x 'delta-yのままでは、正しい答えは返ってくるものの、どうも納得いきません。模範解答はどうすれば良いのでしょうか。 何とぞご教授の程、宜しくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

ええとですね。まず。 「Schemeには構造体はありません。」 少なくともR5RSでは存在しませんね。最新の仕様、R6RSでは定義されているらしいんですが、今のトコ、R6RS準拠のScheme処理系と言うのは、PLTくらいしか知りません(しかもビミョー)。 つまり、ここで言う「define-structure」ってのは実装依存です。どの実装か、と言うと「PLT Scheme」って言う処理系の実装です。このIDE(統合開発環境)の名前が「DrScheme」と言います。 何人か、教えてgoo!/O.K.Waveで見かけてるんですが、「How to Design Programs」って本使って実習行ってる大学があるみたいですね。HTDP自体がPLTベッタリなんで(と言うか、PLTの実装者達が書いてる教科書の模様です)、そこの問題質問するんでしたら、PLT Schemeと明示しておいた方がいいです。じゃないと、冒頭のように、 「Schemeの構造体?define-structure?ないよ。そんなの。」 って言われかねません。 と言うわけで、以下はPLT依存の話を絡んで。 ちょっと質問の意味が分からない部分があるんですけど、まず、一般に「構造体」と言うのは「ユーザーがデータ型を定義出来る手段」の事です。 と言う事は。 manaka3161さんは、次の式で何をしたいのでしょうか? (define a-ball (make-BALL x y delta-x delta-y)) ・・・(☆) これは「データを定義」しようとしてるんですか、それとも「手続きを定義」しようとしてるんでしょうか? 仮に、構造体から離れて、リストa-listを次のように定義しようとします。 (define a-list (list x y)) これもエラーが出ますね。当然です。構造体/リストに関わらず、defineでデータを定義したい筈なのに、実体がこれらには存在しないから、です。 つまり、「任意のデータを生成する手続き」にしたいのなら、次のように書かなければならないのは自明ですよね。 (define (a-ball x y delta-x delta-y) ; 構造体の場合   (make-BALL x y delta-x delta-y)) (define (a-list x y)         ; リストの場合   (list x y)) 実体を与えたいのなら、次の通りでしょう。 (define a-ball (make-BALL 10 20 30 40)) ; 構造体の場合 (define a-list (list 1 2))       ; リストの場合 同じですね。後者の「データを定義した」形であれば、manaka3161さんが定義したget-ball-posnを用いれば、 > (get-ball-posn a-ball) #<POSN> > となって、「POSNと言う構造体が作成された」と返して来ます。つまり、問題文にある >POSN構造体データとして返す関数 としては満たされている、って事ですね。

参考URL:
http://docs.plt-scheme.org/guide/define-struct.html
manaka3161
質問者

お礼

申し訳ありませんでした。PLTでの話でした。 仰るとおり、「任意のデータを生成する手続き」を行いたかったのだと思います。 これでもう1度やってみようと思います。 詳しい説明、有り難うございました。

関連するQ&A

  • scheme でのスコープについて

    次のようなcar,consの定義をします. ;;consの定義 (define (cons x y)  (define (dispatch m)   (cond ((= m 0) x)      ((= m 1) y)      (else (error "Argument not 0 or 1 -- CONS" m)))) ;;carの定義 (define (car z) (z 0)) ここで、 (car (cons 1 2)) を評価したいのですが、次のような置き換えモデルで考えてみました。 (car (cons 1 2)) (car dispatch) ;まず引数を評価 (dispatch 0) ;car を評価して引数に作用させる 1 質問は、dispatchの有効範囲についてです。 dispatchはconsの内部定義なので(cons 1 2)を評価後、carに引数として渡すには,その時点でdispatchが有効でなくなりエラーになると考えたのですが、実際は動きました。 どこがおかしいのでしょうか。環境モデルでも考えてみたのですが分かりませんでした。よろしくお願いします。

  • C++テンプレートでの引数

     こんにちは。 今回は、C++ テンプレートで引数に構造体を使えないか悩んでいます。 例えば #include <stdio.h> typedef struct _rect{ int x; int y; }RECT; typedef struct _rect{ double x; double y; }DATA; template <calss T> T Function(T abc) { // 構造体の要素にも対応している。 cout << abc//の要素x << endl; cout << abc//の要素y << endl; return T; } int main() { RECT t; DATA r; t.x = 80; t.y = 90; t = Function(t); // こういった事をしたい r = Function(r); return 0; } というふうにしたいんです。 テンプレート関数に引数として構造体にしてそれぞれの要素を参照する場合はどうすれば よろしいのか教えてください。 よろしくお願いします。

  • 関数内で引数の別名称を定義したい

    関数への引数として構造体のポインタを指定しているのですが、 その構造体のある要素については関数内で別名称を使用したいと思っています。 単純化した例をあげますと //child --------------------- typedef struct{ char bookTitle[100]; int pageNum; } Book; //parent --------------------- typedef struct{ Book book[1000]; int bookNum; } Library; void bookSet(Library *lib); という構造体と関数に関してbookSet関数内ではlib->pageNumをpNumという名称で使いたいです。 普通はbookSet(int pNum)と定義して引数に構造体の要素を渡すと思うのですが、その場合プログラムを書き換える(構造体の他のメンバにもアクセスする)時にいちいち引数を指定しなおさなければならず、また引数に何が入っているのかをすべて確認しなければいけないので他の方法を模索しています。 今のところdefineとifdefを使うしかないかなと考えているのですが… 同じような経験をお持ちで、よいアイディアありましたらお待ちしてます。

  • コンストラクタ

    恐れ入ります。 たとえばSample classを定義するとして class Sample{ int a=0; int b=0; Sample(){ //まあ、この場合は通常省略ですが。 } } とコンストラクタの前に処理を書く場合と、 class Sample{    Sample(){ int a=0; int b=0; } とコンストラクタに書く場合とでは何か違いがあるのでしょうか?本を見ると「コンストラクタはインスタンスが生成されたときに呼び出される処理」とありますが、上のような記述でも「生成されたときに処理」されますよね・・・? インスタンスを生成するときに引数を使う場合には違いはわかるのですが・・・? 引数がない場合には「コンストラクタには意味はない」であっていますか?

    • ベストアンサー
    • Java
  • C++、コンストラクタの引数の数を可変にしたい

    次のようなプログラムを作ろうとしています。 あるクラスComponentは DIM(整数)次元(要素数)のdouble型配列と ここで DIM は別のところでconstで宣言されています。 (他にもいくつか変数を持っているのですが話に関係ないので割愛します) とりあえずこんな感じにしたいです。 class Component{ public: double x[DIM]; Component(double x,double y,double z, ,,,,,); //コンストラクタ } ここでコンストラクタComponentは引数にDIM個の実数をとり、たとえば DIM = 3のとき Component obj(1.0,2.0,3.0); と宣言したら obj.x[0]=1.0 obj.x[1]=2.0 obj.x[2]=3.0 となるようにしたいのです。 むろん代入すること自体は代入すればよいのですが 外で宣言されているDIMによってコンストラクタの引数の数が変わってしまいます。 こういう時はどのような解決策があるでしょうか。 今書いたのと全然違うやり方でもかまいません。 (ただ何個も何個もコンストラクタをオーバーロードするのは避けたいです。 いろんなDIM次元で実験がしたく、きりがありません)。 よろしくお願いいたします!

  • 引数をつけたマクロ定義とは

    引数つきマクロ宣言って、どういった場面で使うのでしょうか? 例えば #define abc(a) a*a と定義している場合 x=abc(a) のabc(a)がa*aに変わる。 でも、こんなことしたら abc(a)関数を呼び出せなくなるのでは? 要するに、「引数つきのマクロ定義が ある理由などを、説明していただければと思います。

  • 構造体の代入と比較

    構造体のコピーは以下のようで正しいと思いますが、 struct A { int a; }; struct x, y; x.a=1; y = x; 構造体の比較は if (x != y)ではいけないのでしょうか? 構造体に限らずクラスも同じ考えでしょうか?

  • コンストラクターの引数が多い

    Javaにオブジェクトとかインスタンスってあるじゃん。これを作るときの文法は決まっていて、 new コンストラクター(型 引数,型 引数,・・・); です。 ただ、モノには色々な属性(メタデータ、フィールド)があります。多いと数百数千のメタデータがあるでしょうし、今はビッグデータの時代ですから、数万数億の属性があるのかもしれません。この属性はコンストラクターの引数に相当すると思いますが、オブジェクト生成時にコンストラクター書いて引数を代入していくのでしょうか? ///// class T図書 { String タイトル,出版社,著者,用紙サイズ; int ページ数,販売額,印刷費用,重量mg,総文字数,初回発行部数,表紙の厚さmm; java.util.Calendar 発行年月日,作成年月日,構想年月日,認可年月日; T図書( String タイトル, String 出版社, String 著者, String 用紙サイズ, int ページ数, int 販売額, int 印刷費用, int 重量mg, int 総文字数, int 初回発行部数, int 表紙の厚さmm, java.util.Calendar 発行年月日, java.util.Calendar 作成年月日, java.util.Calendar 構想年月日, java.util.Calendar 認可年月日){} } class H発行{public static void main(String[] args){ java.util.Calendar h1821_11_4=java.util.Calendar.getInstance(); h1821_11_4.set(1821,11,4);//(日付セット繰り返し中略) new T図書("白い巨塔","新潮出版社","山崎豊子","A5", 345,2000,60,716,34569,20000,7, h1821_11_4,h1823_11_4,h1820_1_4,h1821_10_4); }} ///// この例だと15個です。許容範囲といえばそれまでですが、どこか違和感を感じております。そして、薬がクラスで、具体的な薬品がオブジェクトで、成分含有量がフィールドだとすると、コンストラクターの引数が莫大になると思う。 薬 ai00kity=new 錠剤薬(リプナビックスX,0,0,0,12,776,98.45,54,・・・・・); こんな感じ?

  • 既定のコンストラクタがない?

    次のコードをビルドすると 「error C2512: 'Hoge' : クラス、構造体、共用体に既定のコンストラクタがありません。 」 とでるのですが、なぜそのようになるのかわかりません。 環境はVC8、XP sp2 になります。 struct Boo {int handle_;}; struct Hoge { Hoge(Boo&){} }; int main() { Boo boo; Hoge( boo ); } これは一体どういうことなのでしょうか? ご教授よろしくお願いします。

  • デフォルトコンストラクタについて

    クラスについて、デフォルトコンストラクタについて理解が乏しいのですが、クラスB側で何か細工をすると、クラスAのデフォルトコンストラクタ無しで、エラーなくコンパイルできるのでしょうか? 派生クラスの親のベースクラスのコンストラクタを呼ぶsuper?でOKなのでしょうか? #include "stdafx.h" class A { public: //A(){} // これをコメントアウトにすると // error C2512: 'B' : クラス、構造体、共用体にデフォルト コンストラクタがありません。 A(int x){} ~A(){}; }; class B : A { }; void main(void){ B b; }