I have a file called sumit.scala with the following contents
object sumit {
def main(args: Array[String]) = {
val start:Double = System.nanoTime
total_select_values(1 to 15000, {e => true})
val end:Double = System.nanoTime
println("time " + (end - start)/ 1000000000.0)
println("")
}
}
def total_select_values(list: Range, selector : Int => Boolean) = {
var sum = 0
list.foreach { e =>
if (selector(e)) sum += e
}
sum
}
i'm trying to compile it on the command line
scalac sumit.scala
which compiles without error but when i run it
scala sumit
i get a bunch of errors, i'm new to scala and i'm just trying to time this code once it's compiled to see the performance difference. I've tried putting my "total_select_values" in the object and out (as shown here) with no difference.
Thanks for any help!
Updated with Scala info and the actual error
Scala version 2.11.4 Java 1.7.0_40
java.lang.NoSuchMethodException: sumit.main([Ljava.lang.String;)
at java.lang.Class.getMethod(Unknown Source)
at scala.reflect.internal.util.ScalaClassLoader$class.run(ScalaClassLoader.scala:66)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:101)
at scala.tools.nsc.CommonRunner$class.run(ObjectRunner.scala:22)
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
at scala.tools.nsc.CommonRunner$class.runAndCatch(ObjectRunner.scala:29)
at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:65)
at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:87)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:98)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:103)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
The function
def total_select_values ...
Has to go inside an object or class. This appears to be a constraint of Scala based on the
JVM; can't have true free functions.
Try to run it like this
scala sumit.scala
i.e., add the extension of the file.
The code you have gives me the following error when I run scalac:
sumit.scala:11: error: expected class or object definition
def total_select_values(list: Range, selector : Int => Boolean) = {
^
one error found
But, if I change the code to put total_select_values inside the sumit object (as suggested in the comments):
object sumit {
def main(args: Array[String]) = {
val start:Double = System.nanoTime
total_select_values(1 to 15000, {e => true})
val end:Double = System.nanoTime
println("time " + (end - start)/ 1000000000.0)
println("")
}
def total_select_values(list: Range, selector : Int => Boolean) = {
var sum = 0
list.foreach { e =>
if (selector(e)) sum += e
}
sum
}
}
Then, when I run:
scalac sumit.scala
scala sumit
it produces:
time 0.003286401time 0.003286401
But, also, since scala can be run interactively. Just running:
scala sumit.scala
also works. (The scalac step can be left out.)
Related
I'm trying to get started with writing a compiler plugin for scala 3. At this stage, it's primarily based on https://github.com/liufengyun/scala3-plugin-example/blob/master/plugin/src/main/scala/Phases.scala (and the accompanying youtube video explaining how it works).
It's been an interesting process so far, and I'm getting a bit of a feel for some aspects of the compiler.
As a first step, I'm simply trying to wrap a method body into a block, print whatever the returned object was going to be, and then return the object.
This differs from the original plugin mainly in that there was a single side-effecting method call added to each method - this is also assigning a local variable, (which I think is probably the cause of the problem), and moving the method body into a block.
I've produced as minimal of a working example as I could in a fork here: https://github.com/robmwalsh/scala3-plugin-example
The plugin compiles fine, seems to run as part of compilation as expected, and then blows up at runtime. I'm not entirely sure if this is me doing something wrong (not unlikely) or a bug in the compiler (less likely, but a distinct possibility!).
Can anybody please shed some light on why this isn't working? I don't know what flags should be set when creating a new Symbol, so that's one possibility, but there's heaps of stuff that sorta seemed to work so I rolled with it.
Here's where I'm at (the interesting bits):
...
override def prepareForUnit(tree: Tree)(using ctx: Context): Context =
//find the printLn method
val predef = requiredModule("scala.Predef")
printlnSym = predef.requiredMethod("println", List(defn.AnyType))
ctx
override def transformDefDef(tree: DefDef)(using ctx: Context): Tree =
val sym = tree.symbol
// ignore abstract and synthetic methods
if tree.rhs.isEmpty|| sym.isOneOf(Synthetic | Deferred | Private | Accessor)
then return tree
try {
println("\n\n\n\n")
println("========================== tree ==========================")
println(tree.show)
// val body = {tree.rhs}
val body = ValDef(
newSymbol(
tree.symbol, termName("body"), tree.symbol.flags, tree.rhs.tpe),
Block(Nil, tree.rhs)
)
// println(body)
val bodyRef = ref(body.symbol)
val printRes = ref(printlnSym).appliedTo(bodyRef)
// shove it all together in a block
val rhs1 = tpd.Block(body :: printRes :: Nil, bodyRef)
//replace RHS with new
val newDefDef = cpy.DefDef(tree)(rhs = rhs1)
println("====================== transformed ======================")
println(newDefDef.show)
newDefDef
} catch {
case e =>
println("====================== error ===========================")
println(e)
println(e.printStackTrace)
tree
}
...
test program for compiler plugin
object Test extends App:
def foo: String = "forty two"
def bar(x: String): Int = x.length
def baz(x: String, y: Int): String = x + y
baz(foo, bar(foo))
output during compile using plugin (exactly what I wanted! I got very excited at this point)
========================== tree ==========================
def foo: String = "forty two"
====================== transformed ======================
def foo: String =
{
val body: ("forty two" : String) =
{
"forty two"
}
println(body)
body
}
========================== tree ==========================
def bar(x: String): Int = x.length()
====================== transformed ======================
def bar(x: String): Int =
{
val body: Int =
{
x.length()
}
println(body)
body
}
========================== tree ==========================
def baz(x: String, y: Int): String = x.+(y)
====================== transformed ======================
def baz(x: String, y: Int): String =
{
val body: String =
{
x.+(y)
}
println(body)
body
}
output during runtime :'( (this changes depending on the code it's running on, but always the same theme)
Exception in thread "main" java.lang.VerifyError: Bad local variable type
Exception Details:
Location:
testing/Test$.body$2()I #0: aload_1
Reason:
Type top (current frame, locals[1]) is not assignable to reference type
Current Frame:
bci: #0
flags: { }
locals: { 'testing/Test$' }
stack: { }
Bytecode:
0000000: 2bb6 007d ac
at testing.Test.main(Example.scala)
Edit: I'm using scala 3.1.2
I was using the existing flags when creating my new symbol. Instead, I needed to use the Local flag, which I suppose makes sense.
I am trying to run tutorialspoint example
trait Equal {
def isEqual(x: Any): Boolean
def isNotEqual(x: Any): Boolean = !isEqual(x)
}
class Point(xc: Int, yc: Int) extends Equal {
var x: Int = xc
var y: Int = yc
def isEqual(obj: Any) = obj.isInstanceOf[Point] && obj.asInstanceOf[Point].x == y
}
object Demo {
def main(args: Array[String]) {
val p1 = new Point(2, 3)
val p2 = new Point(2, 4)
val p3 = new Point(3, 3)
println(p1.isNotEqual(p2))
println(p1.isNotEqual(p3))
println(p2.isNotEqual(2))
}
}
I got no print on screen if I run from terminal
milenko#milenko-desktop:~$ scala d8.scala
If I run code from eclipse,then I have
Why do I have problem with this simple example?
I think you might be missing a few steps in the edit-compile-run loop, because it works fine for me.
prompt> vi demo.scala # input your code here
prompt> scalac demo.scala # compile the code, creates .class files
prompt> scala Demo # object Demo has a "main" method
true
false
true
prompt>
You need to compile first
scalac d8.scala
then
scala Demo
The scala command wont run source files if they have traits
My question is based on a search that I have made on the following pages (but I am still to new to scala to succeed in what I want to do):
reflection overview
The purpose of my code is to invoke a method from a generic type and not an instance of a known type.
The following demonstrate the idea:
class A {
def process = {
(1 to 1000).foreach(x => x + 10)
}
}
def getTypeTag[T: ru.TypeTag](obj: T) = ru.typeTag[T]
def perf[T: ru.TypeTag](t: T, sMethodName: String): Any = {
val m = ru.runtimeMirror(t.getClass.getClassLoader)
val myType = ru.typeTag[T].tpe
val mn = myType.declaration(ru.newTermName(sMethodName)).asMethod
val im = m.reflect(getTypeTag(t))
val toCall = im.reflectMethod(mn)
toCall()
}
val a = new A
perf(a, "process")
The code compile perfectly (on a worksheet) but give the following stack at execution:
scala.ScalaReflectionException: expected a member of class TypeTagImpl, you provided method A$A11.A$A11.A.process
at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$ErrorNotMember(test-log4j.sc:126)
at scala.reflect.runtime.JavaMirrors$JavaMirror$$anonfun$scala$reflect$runtime$JavaMirrors$JavaMirror$$checkMemberOf$1.apply(test-log4j.sc:221)
at scala.reflect.runtime.JavaMirrors$JavaMirror.ensuringNotFree(test-log4j.sc:210)
at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$checkMemberOf(test-log4j.sc:220)
at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaInstanceMirror.reflectMethod(test-log4j.sc:257)
at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaInstanceMirror.reflectMethod(test-log4j.sc:239)
at #worksheet#.perf(test-log4j.sc:20)
at #worksheet#.get$$instance$$res0(test-log4j.sc:28)
at #worksheet#.#worksheet#(test-log4j.sc:138)
Any idea about how to correct this ?
Many thanks to all
In order to reflect a particular object, you have to pass it to Mirror.reflect(obj: T), and you're passing its typeTag for some reason. To fix, you have to modify perf signature to generate a ClassTag along with a TypeTag, and pass t directly to reflect, like so:
class A {
def process = {
(1 to 1000).foreach(x => x + 10)
println("ok!")
}
}
def perf[T : ClassTag : ru.TypeTag](t: T, sMethodName: String): Any = {
// ^ modified here
val m = ru.runtimeMirror(t.getClass.getClassLoader)
val myType = ru.typeTag[T].tpe
val mn = myType.decl(ru.TermName(sMethodName)).asMethod
val im = m.reflect(t)
// ^ and here
val toCall = im.reflectMethod(mn)
toCall()
}
val a = new A
perf(a, "process")
// ok!
// res0: Any = ()
(Note: I also replaced deprecated declaration and newTermName with recommended alternatives)
$ scala -Xexperimental
Welcome to Scala version 2.9.0.1 (OpenJDK Server VM, Java 1.6.0_22).
Type in expressions to have them evaluated.
Type :help for more information.
scala> class D extends Dynamic {
| def invokeDynamic(s:String)(args:Any*) = println(s)
| def doo() = { this hello }
| }
dynatype: this.applyDynamic("hello")()
dynatype: this.applyDynamic("applyDynamic")
...
This repeats a few dozen times....
...
dynatype: this.applyDynamic("applyDynamic")
java.lang.StackOverflowError
at scala.tools.nsc.symtab.Types$TypeMap$$anonfun$mapOverArgs$1.apply(Types.scala:3107)
at scala.tools.nsc.symtab.Types$TypeMap$$anonfun$mapOverArgs$1.apply(Types.scala:3103)
at scala.tools.nsc.symtab.Types$class.map2Conserve(Types.scala:4867)
at scala.tools.nsc.symtab.SymbolTable.map2Conserve(SymbolTable.scala:13)
at scala.tools.nsc.symtab.Types$TypeMap.mapOverArgs(Types.scala:3103)
at scala.tools.nsc.symtab.Types$TypeMap.mapOver(Types.scala:3010)
at scala.tools.nsc.symtab.Types$ApproximateDependentMap$.apply(Types.scala:3594)
at scala.tools.nsc.symtab.Types$ApproximateDependentMap$.apply(Types.scala:3591)
at scala.tools.nsc.symtab.Types$TypeMap$$anonfun$16.apply(Types.scala:3125)
at scala.tools.nsc.symtab.Types$TypeMap$$anonfun$16.apply(Types.scala:3122)
at scala.collection.LinearSeqOptimized$class.exists(LinearSeqOptimized.scala:79)
at scala.collection.immutable.List.exists(List.scala:45)
at scala.tools.nsc.symtab.Types$TypeMap.mapOver(Types.scala:3122)
at scala.tools.nsc.symtab.Types$TypeMap.mapOver(Types.scala:3024)
at scala.tools.nsc.symtab.Types$ApproximateDependentMap$.apply(Types.scala:3594)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.scala$tools$nsc$typechecker$Implicits$ImplicitSearch$$depoly(Implicits.scala:261)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.survives(Implicits.scala:619)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation$$anonfun$6$$anonfun$7.apply(Implicits.scala:648)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation$$anonfun$6$$anonfun$7.apply(Implicits.scala:648)
at scala.collection.TraversableLike$$anonfun$filter$1.apply(TraversableLike.scala:213)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
at scala.collection.immutable.List.foreach(List.scala:45)
at scala.collection.TraversableLike$class.filter(TraversableLike.scala:212)
at scala.collection.immutable.List.filter(List.scala:45)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation$$anonfun$6.apply(Implicits.scala:648)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation$$anonfun$6.apply(Implicits.scala:647)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:200)
at scala.collection.TraversableLike$$anonfun$flatMap$1.apply(TraversableLike.scala:200)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
at scala.collection.immutable.List.foreach(List.scala:45)
at scala.collection.TraversableLike$class.flatMap(TraversableLike.scala:200)
at scala.collection.immutable.List.flatMap(List.scala:45)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch$ImplicitComputation.<init>(Implicits.scala:647)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.searchImplicit(Implicits.scala:753)
at scala.tools.nsc.typechecker.Implicits$ImplicitSearch.bestImplicit(Implicits.scala:1084)
at scala.tools.nsc.typechecker.Implicits$class.inferImplicit(Implicits.scala:57)
at scala.tools.nsc.Global$analyzer$.inferImplicit(Global.scala:347)
at scala.tools.nsc.typechecker.Typers$Typer.wrapImplicit$1(Typers.scala:167)
at scala.tools.nsc.typechecker.Typers$Typer.inferView(Typers.scala:171)
at scala.tools.nsc.typechecker.Typers$Typer.adaptToMember(Typers.scala:985)
at scala.tools.nsc.typechecker.Typers$Typer.adaptToMemberWithArgs(Typers.scala:1024)
at scala.tools.nsc.typechecker.Typers$Typer.typedSelect$1(Typers.scala:3534)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4123)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4217)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedApply$1$1.apply(Typers.scala:3326)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedApply$1$1.apply(Typers.scala:3326)
at scala.tools.nsc.typechecker.Typers$Typer.silent(Typers.scala:623)
at scala.tools.nsc.typechecker.Typers$Typer.typedApply$1(Typers.scala:3326)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4062)
at scala.tools.nsc.typechecker.Typers$Typer.typedSelect$1(Typers.scala:3554)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4123)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4217)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedApply$1$1.apply(Typers.scala:3326)
at scala.tools.nsc.typechecker.Typers$Typer$$anonfun$typedApply$1$1.apply(Typers.scala:3326)
at scala.tools.nsc.typechecker.Typers$Typer.silent(Typers.scala:623)
at scala.tools.nsc.typechecker.Typers$Typer.typedApply$1(Typers.scala:3326)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4062)
at scala.tools.nsc.typechecker.Typers$Typer.typedSelect$1(Typers.scala:3554)
at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:4123)
at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:4217)
at
And so on...until finally:
The repl compiler has crashed spectacularly. Shall I replay your
session? I can re-run all lines except the last one.
[y/n]
It crashes the compiler because it can't find the right method to handle your code.
I agree that it shouldn't crash the compiler, but should return an useful error message instead.
Note that it works correctly with the right method name applyDynamic:
scala> class D extends Dynamic {
def applyDynamic(s: String)(i: Int) {
println("Called "+ s +" with "+ i)
}
}
defined class D
scala> val d = new D
d: D = D#3b2601c
scala> d hello 42
dynatype: $line33.$read.$iw.$iw.d.applyDynamic("hello")
Called hello with 42
Very weird. I think it shouldn't compile, because you're supposed to implement applyDynamic and not invokeDynamic. This one works for me:
class D extends Dynamic {
def applyDynamic(s: String)(args: Any*) = println(s)
def doo() = { this.hello }
}
Probably invokeDynamic somehow messes with the synthetic stuff...?
trying to run the sample code in the Apress book called "Beginning Scala". I even downloaded the code from their website to make sure I didn't goof. Getting the following message:
/root/sum.scala:19: error: missing arguments for method collect in trait Iterator;
follow this method with `_' if you want to treat it as a partially applied function
val lines = input.getLines.collect
^
one error found
and here is the source code i used (running Scala version 2.8.1.final (Java HotSpot(TM) Server VM, Java 1.6.0_22 on Fedora 13)
import scala.io._
def toInt(in: String): Option[Int] =
try {
Some(Integer.parseInt(in.trim))
} catch {
case e: NumberFormatException => None
}
def sum(in: Seq[String]) = {
val ints = in.flatMap(s => toInt(s))
ints.foldLeft(0)((a, b) => a + b)
}
println("Enter some numbers and press ctrl-D (Unix/Mac) ctrl-C (Windows)")
val input = Source.fromInputStream(System.in)
val lines = input.getLines.collect
println("Sum "+sum(lines))
looks like this is the relevant change:
The Iterator.collect() method in 2.7.7 returns a Seq. In 2.8, it is used to perform a conditional map using a PartialFunction. You can use input.getLines.toSeq instead.
Ah, I remember this:
EDIT: replaced with more in depth answer
The code was written against Scala
2.7.3 and 2.8 introduces some breaking changes.
Here's an update to the code that
works under Scala 2.8.0:
import scala.io._
object Sum {
def main(args: Array[String]): Unit = {
println("Enter some numbers and press ctrl-D (Unix/Mac) ctrl-Z (Windows)")
val input = Source.fromInputStream(System.in)
val lines = input.getLines.toList
println("Sum " + sum(lines))
}
def toInt(s: String): Option[Int] = {
try {
Some(Integer.parseInt(s))
} catch {
case e: NumberFormatException => None
}
}
def sum(in: Seq[String]): Int = {
val ints = in.flatMap(toInt(_))
ints.foldLeft(0)((a, b) => a + b)
}
}
Source: http://scala-programming-language.1934581.n4.nabble.com/Beginning-Scala-book-problem-td2966867.html