scalaで無限に続く関数を返す方法

このQ&Aのポイント
  • Scalaで無限に続く関数を返す方法について教えてください。
  • 現在、Scalaを学んでいる初心者です。無限に続く関数を返す方法を知りたいです。
  • Schemeでは、無限に続く関数を返すことができますが、同じようにScalaでも可能でしょうか?
回答を見る
  • ベストアンサー

scalaで無限に続く関数を返したい

scalaで無限に続く関数を返したい scalaという物を知って現在弄り始めた初心者です。 例えばschemeでなら (define f (lambda () (define n (lambda (x) (display x) (display "\n") (lambda () (n (+ x 1))))) (n 0))) (((f))) こんな感じの事がしてみたいですが、これをそのまま下の様に書き換えたところ、コンパイルに失敗しました。 def f()={ def n(x:Int) = { println(x) () => n(x+1) } n(0) } def main(arg:Array[String])={ f()()() } これだと、コンパイラにnが何返すか分からんと怒られてしまいます。単純に返す物が分かっているときは :(()=>Int)= などと書いたら出来たのですが、今回は永遠に終わらないので書き方が分かりません。 どの様に返値を指定すればいいのでしょうか?

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

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

まず、結論から言うと、それと全く同じものをScalaで実装するのは無理です。 というのは、Scalaでは、型A = () => Aみたいな循環した定義を直接的に実現する方法が 無いからです。ただし、それに近いことを次のようなコードで行うことはできます。 object F { class Link(f: () => Link) extends (() => Link) { def apply(): Link = f() } def f(): Link = { def n(x: Int): Link = { println(x) new Link(() => n(x + 1)) } n(0) } } ここで、Linkというクラスのコンストラクタに、() => Linkという自分自身の型を 返す関数を持たせることで、呼び出すと自分と同じ型が返ってくる関数のようなものを 疑似的に実現できるわけです。また、Linkクラスは() => Link型の関数を継承する ようにしているため、Linkクラスは() => Link型の関数として扱うことができます。 なお、このコードは、 import F._ f()()()()()()()()... のようにして利用することができます。

参考URL:
http://gist.github.com/393363
Vitaminles
質問者

お礼

ご回答、そしてご丁寧に例まで示して頂き、ありがとうございます。(返事が遅れてすみません。) なるほど、同じ物は作れないのですね。 関数から複雑な関数を返すときはクラスを利用する、といった感じですかね。 特にお考え無しにプログラムするとき、直感的に関数から関数を返すと言う私は、scalaでは関数言語の思考を変えなくてはならないですね。

関連するQ&A

  • rubyでScalaのようにコールバックを変数として定義するには?

    rubyでScalaのようにコールバックを変数として定義するには? 最近Scalaの勉強を始めました。自分の一番好きな言語はrubyなので、比較しながら勉強してます。 参考書によると、関数をオブジェクトとして扱えるのがScalaの特徴との説明がありました。例えば、以下のような例なのですが、(行頭スペースは全角) class Kuku(a:Int,b:Int){  def calc(func:(Int,Int)=>String):String={   return func(a,b)+a*b  } } val f1=(a:Int,b:Int)=>a+"*"+b+"=" println(new Kuku(3,5).calc(f1)) これをrubyで書くと、(行頭スペースは全角) class Kuku  def initialize(x,y)   @x=x   @y=y  end  def calc   yield(@x,@y)+(@x*@y).to_s  end end puts Kuku.new(3,5).calc{|a,b| a.to_s+'*'+b.to_s+'='} とまでは書けたのですが、コールバック(ブロックパラメータの部分)、上記例だと |a,b| a.to_s+'*'+b.to_s+'=' の部分 を変数として定義(Scalaの例のf1として定義するところ)する方法を知りません。 このように関数を変数として定義する事ってrubyではできないと考えるのですが、そういった認識で間違いないでしょうか? ご指導の程、よろしくお願いいたします。

    • ベストアンサー
    • Ruby
  • Scalaのmatch式について

    Scala初心者です. 以下のサンプルプログラムを作ってみました. import scala.xml.XML import scala.xml.Node import scala.xml.NodeSeq import scala.xml.Elem import scala.xml.Text import scala.xml object Main { val xmlDoc = <section> <title>Section title</title> <p id="id_001">Paragraph 1</p> <p id="id_002">Paragraph <ph fo="font-weight:bold;">2</ph></p> <p id="id_003">Paragraph <ph fo="font-style:italic;">3</ph></p> </section> def main(args: Array[String]): Unit = { println("Program started") // Select element val secondP = ( (xmlDoc \\ "section") \ "p" filter (_ \ "@id" contains Text("id_002")) ) println(secondP.toString) // Check the result //<p id="id_002">Paragraph <ph fo="font-weight:bold;">2</ph></p> match{ secondP match { case e @ <p>{ ns @ _* }</p> => println("Match!=" + e.toString) case n => println("Not match") } println("Program ended") } } 結果は Program started <p id="id_002">Paragraph <ph fo="font-weight:bold;">2</ph></p> Not match Program ended となります. しかし、 <p id="id_002">Paragraph <ph fo="font-weight:bold;">2</ph></p> match{ case e @ <p>{ ns @ _* }</p> => println("Match!=" + e.toString) case n => println("Not match") } とすると、ちゃんと Match!=<p id="id_002">Paragraph <ph fo="font-weight:bold;">2</ph></p> と表示されます. secondP match { case e @ <p>{ ns @ _* }</p> => println("Match!=" + e.toString) case n => println("Not match") } で"Not match"と表示されてしまうのは何故でしょうか? 以上 よろしくお願いいたします.

  • 関数式マクロでエラーです。

    原因と解決方法を教えてください。 御願いします。 ・現象  Solarisでは問題なくコンパイル出来ますが、Linux(以下のバージョン参照)上ではエラーになります。  他の人によるとgcc 2.xでは問題なけれど、gcc 3.x以上ではエラーになると聞きましたが… ・質問  1.コンパイラのバージョン問題ですか?  2.解決するにはパッチが必要ですか?  3.必要だったら、何のパッチが必要ですか?  (ソースの修正なしで解決したいです。) ・エラーメッセージ: define_test.c:38:1: pasting "_test" and "(" does not give a valid preprocessing token Kernel:Red Hat Enterprise Linux AS release 4 (Nahant) Compiler:g++ (GCC) 3.4.3 20041212 (Red Hat 3.4.3-9.EL4) -- 以下 ソース -- #include <stdio.h> #include <stdlib.h> #define SEND4(o, m, l, on_off) o->send_extr_indir(o->_##m##l, on_off) class Define { public: int send_extr_indir(int data1, int data2); int _test(int arg1, int arg2); int test(void); }; int Define::send_extr_indir(int data1, int data2) { printf("data1=%d\n", data1); printf("data2=%d\n", data2); return data1+data2; } int Define::_test(int arg1, int arg2) { return arg1 + arg2; } int Define::test(void) { return SEND4(this, test, (1,2), 5 ); } int main(void) { int result = 0; Define object; result = object.test(); printf("result=%d\n", result); return 0; }

  • 関数のプロトタイプ宣言

    #include <stdio.h> #define N 3 #define M 4 int sum(int [][M]); (関数のプロトタイプ宣言) int main(){   ・   ・   ・ return(0); } int sum(int x[][M]){    ・    ・ } 以上のプログラムより、関数のプロトタイプ宣言や、関数内の 行列の定義でint sum(int [][M]);や int sum(x[][M]){}となっていますが なぜ、列にMだけを代入することだけでよいのでしょうか? また、教科書に関数のプロトタイプ宣言ではint sum(int [][]);だけでもよいと書かれていたのですが 実際、コンパイルしてみたところ 'int[]' 型のサイズは未知あるいはゼロとエラーがでました。 これは、コンパイラによってできるものとできないものがあるのでしょうか?? よろしくお願いします。

  • Shemeで掛け算の関数

    Shemeで掛け算の関数 関数muliを定義しなさい。ただしzero,inc,dec,add,mulはすでに定義されて、 muliはmulの中から(mulli x y (zero))と呼ばれる。 なんとなくわかるかもしれませんが、 (define (dec n) (cdr n)) (define (zero) (quote())) (define (add x y) (if (null? y) x (add (inc x) (dec y)))) となっています。 この問題で (define muli (lambda (x y n) ((if (null? y) n (muli x (dec y) (add n x)))))) と考えたのですがうまくいきません。 ご教授よろしくお願いします。

  • Scalaのmainが見つからないエラー

    すみません.またScala初心者の質問ですが教えてください. 以下のようなmainだと何の問題もなく動きます.(あたりまえです) object Main { def main(args: Array[String]): Unit = { def title ="AAA" println("The title='" + title + "'") } } ところがこれを以下のように書き換えて、Eclipseから実行してみたのですが、 import scales.utils._ import ScalesUtils._ import scales.xml._ import ScalesXml._ import java.io._ import parser.strategies._ import scalaz._ import Scalaz._ import scales.xml.jaxen._ object Main { def main(args: Array[String]): Unit = { val doc = loadXml(new java.io.FileReader("MusicLibrary.xml"),defaultPathOptimisation) val root = top(doc) val xpath = ScalesXPath("musicLibrary/cd[string(year) = '1994']/title") val titles = xpath.evaluate(root) titles.foreach(title => println("The title='" + title.toString() + "'")) } } Cannot locate main type 'Main' in project 'ScaleXmlTest'. Check your Run Configuration and make sure that the value of "Main class" is in sync with the package and the type name declared in class 'Main'. のエラーになってしまいます.つまりimportしているライブラリを参照するとおかしくなるように見えます. これはインポートしているライブラリの作り方に問題があるのでしょうか? ちなみに、 Scale XMLは https://github.com/chris-twiner/scalesXml から、 Scalazは https://github.com/scalaz/scalaz からそれぞれ落として、自分でsbtでビルドして.jarを作り、上記のプロジェクトで参照しています. 以上 よろしくお願いします.

  • 関数に配列を渡すときの質問です

    関数に配列を渡したいんですがこのソースが問題ないか見てください。 #include<stdio.h> #define N 10 #define M 20 int sig(int X[],int x); main() { int a[N],b[M],i,x,y; for(i=0 ; i<N ; i++){ a[i]=i; } for(i=0 ; i<M ; i++){ b[i]=i; } x=sig(a,N); y=sig(b,M); } int sig(int Z[],int x){ int i,k; k=0; for(i=0 ; i<x ; i++){ k=k+Z[i]; } return k; } ソースは以上です。 1つのソースの中でa[N]とb[M]のように違う数の 配列があるんですが、その配列全部(0~N-1、0~M-1)とかを足してくれる(シグマ)関数を作りたいんですが、Z[]と配列の数を指定しなくてもちゃんと動いてくれるんでしょうか?関数のほうの int x で配列の数を指定するようにしています。 自分でテストした限りではちゃんと動いているようなんですが、間違ってるようなら指摘お願いします。

  • StringクラスのcompareToメソッド

    ArrayListに登録した文字列を五十音順にソートしようと思いComparator を使用して 以下のようなサンプルプログラムを作ってみました。 ところが想定していたような {赤ちゃん、富士山、山口県}とはならず {富士山、山口県、赤ちゃん} というような結果になりました。 compare() の戻り値の部分を return ((String)arg1).compareTo((String)arg0); に変更しても{赤ちゃん、山口県、富士山} となり辞書の並びとは異なる結果になりました。 辞書順に並べるにはなにかよい方法はありますでしょうか。 public class compareTest { public static void main(String[] args) { ArrayList<String> array = new ArrayList<String>(); String a = "赤ちゃん"; String b = "山口県"; String c = "富士山"; array.add(a); array.add(b); array.add(c); for(int i=0;i<array.size();i++) { System.out.println("ソート前=" + array.get(i)); } Collections.sort(array, new testComp()); for(int i=0;i<array.size();i++) { System.out.println("ソート後=" + array.get(i)); } } } public class testComp implements Comparator { public int compare(Object arg0, Object arg1) { return ((String)arg0).compareTo((String)arg1); } }

    • ベストアンサー
    • Java
  • schemeのことです

    schemeのことです expression datatypeを作りました 一番最後のexp->string部分で困っています consとかifとか使うべきですか? -------------------------------- (define-datatype expression expression? (const-exp (num number?)) (var-exp (var symbol?)) (zero?-exp (exp1 expression?)) (diff-exp (exp1 expression?) (exp2 expression?))) ;; Predicates. (define const-exp? (lambda (exp) (cases expression exp (const-exp (num) #t) (else #f)))) (define var-exp? (lambda (exp) (cases expression exp (var-exp (var) #t) (else #f)))) (define zero?-exp? (lambda (exp) (cases expression exp (zero?-exp (exp1) #t) (else #f)))) (define diff-exp? (lambda (exp) (cases expression exp (diff-exp (exp1 exp2) #t) (else #f)))) ;; ====================================================================== ;; Extractors. (define exp->const (lambda (exp) (cases expression exp (const-exp (num) num) (else #f)))) (define exp->var (lambda (exp) (cases expression exp (var-exp (var) var) (else #f)))) (define exp->exp1 (lambda (exp) (cases expression exp (zero?-exp (exp1) exp1) (else #f)))) (define exp->exp2 (lambda (exp) (cases expression exp (diff-exp (exp1 exp2) exp2) ;; ====================================================================== ;; exp->string: exp -> string ;; Abstract syntax to concrete syntax. (define exp->string (lambda (exp) (cond ((const-exp? exp) (format "~a" (exp->const exp))) ((var-exp? exp) (format "~a" (exp->var exp))) ((zero?-exp? exp) (format "zero?(~a)" (exp->exp1 exp))) ((diff-exp? exp) (format "-(~a,~a)" (exp->exp2 exp)(exp->exp2 exp))) (else #f

  • Lisp

    Lisp 今リリカルLispをやっているのですが、 詰まってしまって答えがないので困っています。 問題は (s n)を評価すると1+2+・・・+nが返るように関数をsiを定義する(ただしsは次のように定義されている define (s n) (si n 0) ) という問題です。 一応自分なりに考えたのが (define si (lambda (n x) (if (= n 1) (x) (si (- n 1) (+ n x))))) なんですが無限ループのようになるのかこれを実行すると固まって落ちてしまいます。 ご指摘よろしくお願いします。

専門家に質問してみよう