I'm wondering what are the main differences between the REPL and scalac.
What I'm aware of, but I can't find if that's due to my imagination, or
if I read that somewhere (and so, where ?)
- I believe the REPL defines an object for the session, and that all the
session is a big compilation unit. Is that true ?
- each command in REPL is compiled with the REPL session past compiled
commands as environment, and the result is added to the environment. Is
that true, too ?
- scopes in REPL have to be dealt with care (but I can't find back any
good example of that);
- Does the REPL load some special environment over scalac that may
influence compilation or evaluation ? (I don't think so).
- I also know that in the past, REPL "print" part was a little to
agressive for lazy vals and structures, and that it was considered as a
bug. Is there any other difference of that kind which are expected (not
bugs, but genuine difference between REPL and scalac) ?
- finally, does the Scala "script" mode is exactly the same as REPL, or
does it have some other specificities ?
Thanks !
--
Francois ARMAND
http://fanf42.blogspot.com
http://www.normation.com
Nope.
> - each command in REPL is compiled with the REPL session past compiled
> commands as environment, and the result is added to the environment. Is
> that true, too ?
Sort of. To compile any given "line" of code (in quotes because a
"line" is arbitrarily long) all the identifiers are imported from the
previous lines. These used to be in objects with pretty ungodly names
but now I have every line in its own package to pave the way for future
improvements.
scala> [paulp@stem ~]$ scala29 -Dscala.repl.power
Welcome to Scala version 2.9.0.r24393-b20110306225200 (Java HotSpot(TM)
64-Bit Server VM, Java 1.6.0_22).
Type in expressions to have them evaluated.
Type :help for more information.
Starting in power mode, one moment...
** Power User mode enabled - BEEP BOOP WHIR **
** scala.tools.nsc._ has been imported **
** global._ and definitions._ also imported **
** New vals! Try repl, intp, global, power **
** New cmds! :help to discover them **
** New defs! Type power.<tab> to reveal **
scala> def bippy = 55
bippy: Int
scala> RootClass.tpe.members
res0: List[global.Symbol] = List(package $line22, package $line21,
package $line17, package $line18, package $line19, package $line20,
package $line16, package $line15, ...
scala> getModule("$line21").tpe.members
res1: List[global.Symbol] = List(object $eval, object $read)
scala> getModule("$line21").tpe.member("$eval").tpe.member("$result")
res3: global.Symbol = lazy value $result
scala> getModule("$line21").tpe.member("$eval").tpe.member("$result").tpe
res4: global.Type = ()Int
scala> $line21.$eval.$result
res6: Int = 55
> - Does the REPL load some special environment over scalac that may
> influence compilation or evaluation ? (I don't think so).
I wouldn't put it that way, but there's enough stuff going on that I
wouldn't ever be too surprised at differences poking out.
> - I also know that in the past, REPL "print" part was a little to
> agressive for lazy vals and structures, and that it was considered as a
> bug. Is there any other difference of that kind which are expected (not
> bugs, but genuine difference between REPL and scalac) ?
Expected differences should mostly be in the category of the scalac way
being impractical to mimic in an interactive session. That means things
like hitting enter meaning "I'm done" even if when compiling the next
line would have been considered.
> - finally, does the Scala "script" mode is exactly the same as REPL, or
> does it have some other specificities ?
It is not exactly the same, but close enough for the purposes of the
amount of time I have for this answer.
Wow, I'm happy to have asked :)
>[...]
>
> It is not exactly the same, but close enough for the purposes of the
> amount of time I have for this answer.
Thanks a lot for the insightful answer.
--
Francois Armand
http://fanf42.blogspot.com
Something I don't understand here. OK for the one object (or package) by
line (and it's really clever).
But if a REPL session is not a compilation unit and considered as one
source file, why can I extends a sealed class defined on one line on an
other one ? Is sealed even more magic than I thought ?
8<--------------------------------------------------------------------
Welcome to Scala version 2.8.1.final (Java HotSpot(TM) Server VM, Java
1.6.0_23).
Type in expressions to have them evaluated.
Type :help for more information.
scala> sealed class A
defined class A
scala> class B extends A
defined class B
scala>
8<--------------------------------------------------------------------
I said it's not one big compilation unit, but I didn't say anything
about source files. Sealed only requires they have the same source, and
they do (they are both null.)
Ah, clever, too :)
Thanks again,
A general question... is sealed the only Scala feature that is specific to
source file "scoping?"
My understanding has been that for the most part the source file layout is,
in theory anyway, indpendent of the logical constructs of the language...
except for sealed. Perhaps my understanding is flawed.
Peter
There is at least one much more important one: companions.
Ah yes, of course. Thanks for reminding me.
So then here is a follow up question. If it is possible to extend a sealed
class in the REPL, why isn't it possible to define a class and it's
companion in the REPL? For example:
Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM,
Java 1.6.0_23).
Type in expressions to have them evaluated.
Type :help for more information.
scala> object X {
| private val a = 1
| }
defined module X
scala> class X {
| def a_value = X.a
| }
<console>:7: error: value a cannot be accessed in object X
def a_value = X.a
^
Peter
> So then here is a follow up question. If it is possible to extend a sealed
> class in the REPL, why isn't it possible to define a class and it's
> companion in the REPL? For example:
>
> Welcome to Scala version 2.8.1.final (Java HotSpot(TM) 64-Bit Server VM,
> Java 1.6.0_23).
> Type in expressions to have them evaluated.
> Type :help for more information.
>
> scala> object X {
> | private val a = 1
> | }
> defined module X
>
> scala> class X {
> | def a_value = X.a
> | }
> <console>:7: error: value a cannot be accessed in object X
> def a_value = X.a
> ^
Never mind, I answered my own question. If each REPL line is its own package
than clearly the object X and the class X above can't be companions. On the
other hand the following file does compile quite happily with scalac
package p1 {
sealed class A;
}
package p2 {
import p1.A
class B extends A;
}
Peter
This is a common question and the common answer is to put them
together in an object:
object GroupTheseInREPL { object X { ... } class X { ... } }
-- Jim
Although I see you answered your question, the answer did not really
capture the meaningful difference. The same-file restriction on sealed
is a way of limiting the universe of possible subclasses for
exhaustiveness checking: without such a limitation it is impossible to
say a match is exhaustive. That it works in the repl is purely an
artifact of the implementation (the check is as simple as "are these
source files the same" and since they're both null the answer is "yes".)
It is not a design choice that it works in the repl.
The same-file restriction on companions is a technical limitation
because it would make the implementation way harder if we never knew
whether a companion was lurking in the wings. In a magical world where
the implementations fall from the sky fully debugged, cycles do not
exist, and you can always backtrack if your initial impression was
wrong, there's no reason I can see to require companions in the same file.