- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Re: Summary(2) - things to drop
Thu, 2009-01-08, 17:07
Ricky Clarkson wrote:
> My own thoughts are to follow what Scheme, Python and C# do - without any
> parentheses, a method/procedure/function name is just a reference to that
> method/procedure/function; it should only be invocable with parentheses.
> And then the trailing _ syntax can be dropped, and HOFs will live happily
> ever after. Ahem.
Public fields are safe to use in Scala because you can switch between
val/var and def without breaking client code. For example:
//Old version
class Person {
val fullName: String = . . .
}
//New version
class Person {
val firstName: String = . . .
val lastName: String = . . .
def fullName = firstName + " " + lastName
}
By convention, parentheses are only used when no-argument functions have
side effects, and thus can't be replaced with a field anyway.
Thu, 2009-01-08, 20:57
#2
Re: Summary(2) - things to drop
O/H GatesDA έγραψε:
> Public fields are safe to use in Scala because you can switch between
> val/var and def without breaking client code.
>
>
I guess such a change would at least require recompilation of client
code? Or even that is not necessary?
Thu, 2009-01-08, 21:47
#3
Re: Summary(2) - things to drop
David MacIver wrote:
>
> On Thu, Jan 8, 2009 at 4:06 PM, GatesDA wrote:
>> Public fields are safe to use in Scala because you can switch between
>> val/var and def without breaking client code. For example:
>
> This isn't true. You can switch between val and def while allowing some
> client code compiled against the old version to continue to run but be
> subtly broken, and the same code will fail to compile if you try to
> recompile the source. vals have a special place in Scala's type system as
> stable identifiers. Replacing a val with a def affects client code.
Thanks for pointing that out; I had assumed that an implicitly generated def
would behave the same as an explicit one. Compiling with -print indeed
shows automatically generated accessor defs as . Could
we get a code sample showing the distinction and where this changes client
behavior?
Thu, 2009-01-08, 22:07
#4
Re: Summary(2) - things to drop
Changing it from a val to a def can cause assumptions to break.
scala> class X { val x = 5 }
defined class X
scala> assert new X().x == new X().x
<console>:1: error: ';' expected but 'new' found.
assert new X().x == new X().x
^
scala> assert(new X().x == new X().x)
scala> class X { def x = (Math.random*100).toInt }
defined class X
scala> assert(new X().x == new X().x)
java.lang.AssertionError: assertion failed
at scala.Predef$.assert(Predef.scala:87)
at .<init>(<console>:6)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:3)
at RequestResult$.<clinit>(<console>)
at RequestResult$result(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.j..
2009/1/8 GatesDA <GatesDA [at] gmail [dot] com>
scala> class X { val x = 5 }
defined class X
scala> assert new X().x == new X().x
<console>:1: error: ';' expected but 'new' found.
assert new X().x == new X().x
^
scala> assert(new X().x == new X().x)
scala> class X { def x = (Math.random*100).toInt }
defined class X
scala> assert(new X().x == new X().x)
java.lang.AssertionError: assertion failed
at scala.Predef$.assert(Predef.scala:87)
at .<init>(<console>:6)
at .<clinit>(<console>)
at RequestResult$.<init>(<console>:3)
at RequestResult$.<clinit>(<console>)
at RequestResult$result(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.j..
2009/1/8 GatesDA <GatesDA [at] gmail [dot] com>
David MacIver wrote:
>
> On Thu, Jan 8, 2009 at 4:06 PM, GatesDA <GatesDA [at] gmail [dot] com> wrote:
>> Public fields are safe to use in Scala because you can switch between
>> val/var and def without breaking client code. For example:
>
> This isn't true. You can switch between val and def while allowing some
> client code compiled against the old version to continue to run but be
> subtly broken, and the same code will fail to compile if you try to
> recompile the source. vals have a special place in Scala's type system as
> stable identifiers. Replacing a val with a def affects client code.
Thanks for pointing that out; I had assumed that an implicitly generated def
would behave the same as an explicit one. Compiling with -print indeed
shows automatically generated accessor defs as <stable> <accessor>. Could
we get a code sample showing the distinction and where this changes client
behavior?
--
View this message in context: http://www.nabble.com/Summary%282%29---things-to-drop-tp20665104p21360434.html
Sent from the Scala - Debate mailing list archive at Nabble.com.
Thu, 2009-01-08, 22:47
#5
Re: Summary(2) - things to drop
Ricky Clarkson wrote:
>
> Changing it from a val to a def can cause assumptions to break.
>
> scala> class X { val x = 5 }
> defined class X
>
> scala> assert new X().x == new X().x
> :1: error: ';' expected but 'new' found.
> assert new X().x == new X().x
> ^
>
> scala> assert(new X().x == new X().x)
>
> scala> class X { def x = (Math.random*100).toInt }
> defined class X
>
> scala> assert(new X().x == new X().x)
> java.lang.AssertionError: assertion failed
> at scala.Predef$.assert(Predef.scala:87)
> at .(:6)
> at .()
> at RequestResult$.(:3)
> at RequestResult$.()
> at RequestResult$result()
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.j..
The assumptions are broken here not by the change from val to def, but by
the change in behavior. A behavioral change like this ought to break
assumptions and require changing client code, but nothing in this example
would change if the original class X had been "class X { def x = 5 }". I
was looking for an example to show the importance of vals being stable
identifiers.
Fri, 2009-01-09, 02:27
#6
Re: Summary(2) - things to drop
GatesDA wrote:
> I was looking for an example to show the importance of vals being stable identifiers.
Only stable identifiers can occur in types.
scala> class A { class B }
defined class A
scala> class C { val a : A = new A }
defined class C
scala> class Client(val c : C) { val x : c.a.B = new c.a.B }
defined class Client
scala> class C { def a : A = new A }
defined class C
scala> class Client(val c : C) { val x : c.a.B = new c.a.B }
:6: error: stable identifier required, but Client.this.c.a
found.
class Client(val c : C) { val x : c.a.B = new c.a.B }
^
:6: error: stable identifier required, but Client.this.c.a
found.
class Client(val c : C) { val x : c.a.B = new c.a.B }
^
Note that the path-dependent type "c.a.B" in Client contains the stable
identifiers c and a, so making c unstable is a bad idea.
Tillmann
Fri, 2009-01-09, 08:37
#7
Re: Summary(2) - things to drop
On Thu, Jan 8, 2009 at 8:36 PM, GatesDA <GatesDA [at] gmail [dot] com> wrote:
The primary example is with type members. Suppose we have something like this:
trait Foo{
type T;
var t : T;
}
Now we have val foo : Foo = new Foo { type T = String; var t = "foo"; }
it is valid to do
val bar = foo.t
foo.t = bar;
But if we change foo to a var it is not, because we could insert the following:
val bar = foo.t
foo = new Foo { type T = Int; var t = 42; }
foo.t = bar;
So in the third line we'd be assigning a String to something that requires an Int.
This is a bit of a contrived example obviously, but there are plenty of cases where it actually matters.
David MacIver wrote:
>
> On Thu, Jan 8, 2009 at 4:06 PM, GatesDA <GatesDA [at] gmail [dot] com> wrote:
>> Public fields are safe to use in Scala because you can switch between
>> val/var and def without breaking client code. For example:
>
> This isn't true. You can switch between val and def while allowing some
> client code compiled against the old version to continue to run but be
> subtly broken, and the same code will fail to compile if you try to
> recompile the source. vals have a special place in Scala's type system as
> stable identifiers. Replacing a val with a def affects client code.
Thanks for pointing that out; I had assumed that an implicitly generated def
would behave the same as an explicit one. Compiling with -print indeed
shows automatically generated accessor defs as <stable> <accessor>. Could
we get a code sample showing the distinction and where this changes client
behavior?
The primary example is with type members. Suppose we have something like this:
trait Foo{
type T;
var t : T;
}
Now we have val foo : Foo = new Foo { type T = String; var t = "foo"; }
it is valid to do
val bar = foo.t
foo.t = bar;
But if we change foo to a var it is not, because we could insert the following:
val bar = foo.t
foo = new Foo { type T = Int; var t = 42; }
foo.t = bar;
So in the third line we'd be assigning a String to something that requires an Int.
This is a bit of a contrived example obviously, but there are plenty of cases where it actually matters.









This isn't true. You can switch between val and def while allowing some client code compiled against the old version to continue to run but be subtly broken, and the same code will fail to compile if you try to recompile the source. vals have a special place in Scala's type system as stable identifiers. Replacing a val with a def affects client code.