Public Read Only + Private Read Write Var? Language Change?

753 views
Skip to first unread message

kraythe

unread,
Feb 20, 2015, 12:12:44 PM2/20/15
to scala...@googlegroups.com
Currently the user can do a read/write var in a class like so 

class Customer(var username: String)

And a set once and read only after that like the following: 

class Customer(username: String)

But this doesnt really encompass the essence of good encapsulation. There are plenty of circumstances where the attribute should be read only to the public and privately the var should be read/write. Once conspicuous example is in ORM mapping of entities where you want some process to be able to validate a name before it gets saved to the database but that internal process should be able to set the value. So we currently have to do something like this: 

class Customer(username: String) {
  _username
= username
 
private var _username: String = null
 
def username = _username
 
def changeUserName(requested: String) = {
     
// check for uniqueness and throw exception if not, otherwise set it
     _username
= requested
 
}
}


This is incredibly verbose and very boilerplate. Instead we should be able to do something like this 

class Customer(readonly var username: String) {
 
def changeUserName(requested: String) = {
     
// check for uniqueness and throw exception if not, otherwise set it
     username
= requested
 
}
}
 
or if using an ORM like hibernate. 

class A() {
 
@Column(name = "user_name")
 
readonly var username: String

 
def changeUserName(requested: String) = {
     
// check for uniqueness and throw exception if not, otherwise set it
     username
= requested
 
}
}

In this example the name is readonly from the point of view of anyone outside the class but readwrite to the class and its companion object. You could add writeonly as well though I am not sure how useful that would be compared to readonly.

Is there currently a way to do this that I have missed or is there a way we can get this on the next version's wish list? 

Oliver Ruebenacker

unread,
Feb 20, 2015, 12:20:46 PM2/20/15
to kraythe, scala-user

     Hello,

  Like these?

     Best, Oliver

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Solutions Architect at Altisource Labs
Be always grateful, but never satisfied.

kraythe

unread,
Feb 20, 2015, 1:26:55 PM2/20/15
to scala...@googlegroups.com
Your response indicates you might have only read the subject line. Try reading the rest.

Som Snytt

unread,
Feb 20, 2015, 2:14:49 PM2/20/15
to kraythe, scala-user
Maybe Oliver was referring to that OP's comment:

"Those solutions are all pretty clunky looking."

Scala does prefer to make something clunky in order to persuade you not to do it.

But it looks like a poster-child use case for a macro annotation.


On Fri, Feb 20, 2015 at 10:26 AM, kraythe <kra...@gmail.com> wrote:
Your response indicates you might have only read the subject line. Try reading the rest.

Rex Kerr

unread,
Feb 20, 2015, 2:33:51 PM2/20/15
to kraythe, scala-user
Yes, it's pretty clunky, though not quite as clunky as you suggest:

class Customer(username: String) {
  private var myUsername = username
  def username = myUsername
}

vs.

class Customer(readonly var username: String) {}

I don't really like the verbosity, but I also don't like extra keywords.  There are other possibilities like "val with private var" or "val[private var]", but these are rather clunky.  One could use an annotation (e.g. @readonly) I suppose, though these tend to feel awkwardly tacked-on when they significantly change the semantics of the code (as this does).

Anyway, I share the concern and annoyance, but I'm not sure at _this_ point there is a good solution.  When creating a new language one has a unique chance to pick a good set of reserved words, but Scala is not that new any more.

  --Rex




kraythe

unread,
Feb 21, 2015, 12:52:13 PM2/21/15
to scala...@googlegroups.com
I disagree entirely. A macro is an interesting idea but is incompatible with things like hibernate and other forms of Java interoperability. My entire world in scala has to interoperate with our Java code or I will be forbidden to use scala on the project. Sure people can disagree with that directive, pan it for being shortsighted or voice objections but that is the way it is in the real world and there is no point arguing it.

I don't understand personally a couple of things.

First why this wasn't in the language to start with. It's arguable that many concepts in scala are macros for Java code generation including class properties and the concept of a public ally read only property is not original or unique. In a language that embraces so many computer science concepts this one would seem elementary.

Second of all I don't understand why adding a keyword is that big of a deal. One of the benefits of scala over Java is that it doesn't have a long tradition of support of legacy code. Java as a language evolved painfully slowly and not at all in some areas because of language inertia and scala is billed as being free of all of that. Or is it? The pure technical fact is that the lexical and syntactic structure could easily adopt a context sensitive keyword without much stress.

So to me the idea of adding it to the language is a bit of a no brainer. There are several proposals for what the words and struccture would be in just this thread and the exact word and structure is pretty unimportant to me whereas the concept is important.

Eugene Burmako

unread,
Feb 21, 2015, 12:56:19 PM2/21/15
to kraythe, scala-user
If you use a macro annotation in your Scala code, that doesn't prevent the results of compiling that code to interoperate with Java. After compilation, all macros (macro defs and macro annotations alike) disappear, leaving vanilla JVM classfiles behind.

kraythe

unread,
Feb 21, 2015, 10:55:31 PM2/21/15
to scala...@googlegroups.com
Would you like to point out how a macro can be made to allow hibernate mapping in an entity on my field?

And even if it is possible it does not diminish the point that it should be a language feature.

Roland Kuhn

unread,
Feb 22, 2015, 1:19:24 AM2/22/15
to kraythe, scala-user
Hi Robert,

22 feb 2015 kl. 04:55 skrev kraythe <kra...@gmail.com>:

Would you like to point out how a macro can be made to allow hibernate mapping in an entity on my field?

A macro is almost like a text expansion for your source files on their way into the compiler, only smarter. Everything you can write your own (as you did in the original post) can be generated by a macro in exactly the same fashion, indistinguishable to the rest of the compiler (in particular a macro cannot generate something that you could not write yourself).

And even if it is possible it does not diminish the point that it should be a language feature. 

Please consider that you are speaking to the group of Scala users, some of them very knowledgeable, including the inventor and the current developers of the language itself. Whether or not something is a language feature is a matter of philosophy and deliberation, that is what makes a language different from all others. Given this, no feature can be universally demanded as you currently do.

To your concrete point: mutable objects are not the focus of Scala, this language prefers immutability and persistent data structures to make it easier to understand which things can go wrong in your programs. The pattern you are proposing to support therefore is a lot less interesting to Scala than it is to you. The idiomatic way to express what you are after is to have a method that takes the new inputs, validates them and then creates a new object with the changes. This is natively supported very well in the whole package that comes with the case class keywords.

In summary, adding the two extra lines that Rex has shown is the price of going against the spirit of the language.

While trying to reconcile the above statements with the existence of relational databases I suggest that you take a look at Slick and in particular the direction it is being taken. This should make it clear in which ways the term ORM has been filled with the wrong contents by the likes of Hibernate.

Regards,

Dr. Roland Kuhn
Akka Tech Lead
Typesafe – Reactive apps on the JVM.
twitter: @rolandkuhn


kraythe

unread,
Feb 22, 2015, 10:51:20 AM2/22/15
to scala...@googlegroups.com
I am not discounting anyone's knowledge or expertise or disrespecting anyone. This is a pure technical debate. I am sure lots of smart people are out there. And disagreement with someone is not equatable to disrespect. Furthermore although respect is accorded to the inventors of the language and so on, I am libertarian and don't simply back off because of someone's status or title but rather only when my technical points are defeated which I don't believe thy have been here.

As for the spirit of the language I have two points to make. The first is that the technological world is littered with the corpses of ideologically pure languages that are relegated now to history, niche applications and academia. The point being that when ideological purity clashes with real world utility the real world will take a pass at scala. Using scala in the business world already takes convincing of the managers and powers that be. If I were to say, "sorry we need to ditch this rdbms crap and go object database, actor constructed system, spend five months redeveloping what already works" my managers would rightly ask where the ROI is and decline. Alternatively if I say, well I can't use scala with hibernate or ebeans In a safe manner like a Java class can, then my managers will say, "then do it in java". I already strongly push scala adoption in the business world and there is only so far that one can push.

Unless you are going to count on businesses abandoning ROI and capital investment to conform to the scala community's ideological purity you have to meet them half way. In fact this is the reason scala runs on the JVM and interoperates with java. In the battle between Scala vs Business Interests, scala will always lose. It has to be compelling for businesses to go there.

Back to the technical debate so far the only counters to the idea of having some read only construct are:

1) rebuild everything in case classes (not possible, No ROI)
2) if your persistence framework doesn't support it, change frameworks or persistence techniques (not possible, no ROI)
3) addition of a keyword might require changing the compiler.

Did I miss any reasons? I for one am not convinced they counter the point in the OP.

Haoyi Li

unread,
Feb 22, 2015, 11:23:26 AM2/22/15
to kraythe, scala-user
> My entire world in scala has to interoperate with our Java code or I will be forbidden to use scala on the project. Sure people can disagree with that directive, pan it for being shortsighted or voice objections but that is the way it is in the real world and there is no point arguing it.

Everything you say is correct, but based on this flawed premise. That is your world. My world is different, and involves running Scala to interact with Javascript (not paid), or using Scala to statically parse and manipulate Javascript and Python sources trees ($$$). Other people on this list of course have different worlds: writing compilers, researching type-theory, mangling tweets, selling groceries, and other things. I heard we even have an alpaca farmer.

Just because your world seems all-encompassing for you doesn't mean that it is the same world the rest of us live in =) 

To distill down your question to the bone, it basically is "How is it possible that other people in this community have other priorities than I do, and value things differently? Why doesn't everyone all think exactly the way I do? Why aren't my specific problems not everyone else's top priorities in life?". I could say what I think, but I'm sure you could come up with good answers yourself too!


I could argue the rest of your points but they're really all correct, given the premise. It's just that your premise is flawed.

Jon Pretty

unread,
Feb 22, 2015, 11:28:51 AM2/22/15
to kraythe, scala...@googlegroups.com
Hi Kraythe,

Sorry, I don't understand the point you're making about ROI. Where is the ROI on Scala implementing a `readonly` keyword? All I can see is that it would break existing code (I just did a search through my code and found a couple of uses of `readonly` as an identifier that would break), so that's a negative for me. And it would complicate the language. People would ask why `readonly` exists in addition to all the various other proposed ways of achieving what you requested, and the only answer I can see is "because Hibernate doesn't work with them".

I really don't understand the logic in modifying an entire language just to accommodate one library. That's first of all a net cost to everyone else who isn't interested in Hibernate, but furthermore a much bigger net cost if the same criteria are applied to other potential new features. Given it's 2015, and in the ten years that Scala has existed it has grown to tens (if not hundreds) of thousands of users without this issue previously being raised, I think that's a strong indication that it's not required.

I'm sorry to sound so abrupt, but Roland and others have been very generous in giving well-reasoned answers, and as far as I can tell, you've been quite dismissive of all of their points.

Cheers,
Jon

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.

Dale Wijnand

unread,
Feb 22, 2015, 11:55:55 AM2/22/15
to Jon Pretty, kraythe, scala...@googlegroups.com
I would recommend trying to fix your use-case with a macro, it'll give you exactly what you're after and you won't have to argue your reasons or wait for it to be available for you to use.

If you do it in the open then it would also be a contribution to the community of people that also need to try and make Hibernate work with Scala's classes.

Dale

To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

kraythe

unread,
Feb 22, 2015, 12:07:40 PM2/22/15
to scala...@googlegroups.com
Abrupt? I haven't dismissed anyone nor have I implied that the world should adapt to me. Nor have I demanded the patience of anyone in educating my "poor misguided" self. I have been arguing a technical point and that is all. I don't care who the person is disagreeing I just care about the technical points, nothing less nothing more. If the way the community goes, to rip people for disagreeing, is this I might as well dump scala now as it will be the next Haskell, an interesting but useless language in anything but niche applications. Let's just look at the meager penetration of scala in the business world and pair that with its complexity and a hostile community and it's no wonder many great developers take a pass.

Back to the technical matter at hand, do you really assert that a public read only and private read write var is only useful to Hibernate? I can't believe you could think that. To me this equates to "just make all attributes public" or "encapsulation is a bad idea" or "object oriented engineering is silly". All of those I can't imagine would be put forth by such talented people. Scala fuses OO with functional programming, immutability with mutability, it's a brilliant cross between the ruby and Java worlds, trying to force it one direction seems to be counter to the principles of its invention.

As for breaking legacy code the history of scala is replete with such breakages and as I recall that is the reason that warnings that major versions of scala are incompatible. So I wouldn't ask for it to be retroactively changed but rather changed in next version. Or are we past that whole "this language won't be stuck in the legacy trap of Java mantra?" If the new mantra is "backward compatibility at all cost" then scala is doomed to suffer many of the problems Java does and with 1/100,000th of the market penetration.

Andreas Joseph Krogh

unread,
Feb 22, 2015, 12:14:45 PM2/22/15
to scala...@googlegroups.com
I've been using Scala with Hibernate/EclipseLink since 2009 (when 2.8 started supporting nested annotations). I have fields in entities being primitives, option of primitives, relations, optional relations (entities wrapped in Option to avoid exposing null). Using appropriate converters (JPA-2.1) combined with getter/setter encapsulation where needed (typically when having Option @MayToOne relations) I don't have any problems using Scala. What exactly isn't working for you wrt. Hibernate?
 
--
Andreas Joseph Krogh
CTO / Partner - Visena AS
Mobile: +47 909 56 963
 

Jon Pretty

unread,
Feb 22, 2015, 1:10:56 PM2/22/15
to kraythe, scala...@googlegroups.com
Hi Kraythe,

I was calling *myself* "abrupt" - I just felt like the email I had just written might be considered unfair, so I gave my reasons for the tone. And since then, Dale has offered a very sensible suggestion. And Andreas has asked a very constructive question. The Scala community is trying very hard to be helpful here, and for little reward. If I or Haoyi or Roland have appeared irked, it's been a consequence of a perception that you think Scala is somehow to blame for not having this feature, which we all disagree with.

But I do take particular issue with your assertion that you've been "arguing a technical point" only. You've introduced topics like ROI, the "meager penetration of Scala in the business world" and the supposed hostility of the community. These are not technical points, but you pointed them out anyway. Neither I nor anyone else in the Scala community would normally bother to raise a point like this, but it is really wearying to be trying to help and to be criticized for it.

Please, try to be constructive and considerate. Other people are trying to find an answer for you, but they are nonetheless human and I think there's a limit on the number of times we can propose macros as a possible solution without any indication that you'll consider it viable. I notice that Eugene hasn't replied to your question about macros yet, though I wouldn't be surprised if he didn't have time to write or find the code example for you; often he does, and he frequently goes beyond the call of duty to help.

One last thing: you're completely correct about breaking legacy code. We should be willing to do it where there's a clear benefit, so the question is usually "is it worth it"? I'm generally in favor of more breaking changes, but that's because I'm not a corporation.

Cheers,
Jon





kraythe

unread,
Feb 22, 2015, 2:04:56 PM2/22/15
to scala...@googlegroups.com, kra...@gmail.com
Jon, 

Replies inline.


On Sunday, February 22, 2015 at 12:10:56 PM UTC-6, Jon Pretty wrote:
But I do take particular issue with your assertion that you've been "arguing a technical point" only. You've introduced topics like ROI, the "meager penetration of Scala in the business world" and the supposed hostility of the community. These are not technical points, but you pointed them out anyway. Neither I nor anyone else in the Scala community would normally bother to raise a point like this, but it is really wearying to be trying to help and to be criticized for it.

Actually I feel as if I have been jumped on for making a suggestion and have only reacted to attacks on myself but lets just chock it up to an imperfect communication medium and assume no one is attacking anyone and move on from that. 


On Sunday, February 22, 2015 at 12:10:56 PM UTC-6, Jon Pretty wrote:
Please, try to be constructive and considerate. Other people are trying to find an answer for you, but they are nonetheless human and I think there's a limit on the number of times we can propose macros as a possible solution without any indication that you'll consider it viable. I notice that Eugene hasn't replied to your question about macros yet, though I wouldn't be surprised if he didn't have time to write or find the code example for you; often he does, and he frequently goes beyond the call of duty to help.

Actually I am not trying to solve a particular problem but make a suggestion for the future. For the moment I have to either work around it or drop scala. If I can declare a private setter and that works I will be happier than I am now leaving members open to change like a gutted fish. I am more trying to look into what could be better in the future.

On Sunday, February 22, 2015 at 12:10:56 PM UTC-6, Jon Pretty wrote:
One last thing: you're completely correct about breaking legacy code. We should be willing to do it where there's a clear benefit, so the question is usually "is it worth it"? I'm generally in favor of more breaking changes, but that's because I'm not a corporation.

Good good! Im glad that is still part of the mantra. My personal opinion for the benefit is: 

1) readonly members from the point of view of the user of a class are common constructs in Object oriented design with mutable data. In fact they are much more common than set once and read a lot constructs (val) when dealing with mutable objects.
2) mutable data is unaviodable in many circumstances such as ORM tools. 
3) current techniques to make a member are boilerplate and thus a source of extraneous verbosity and potential errors. 
4) there is often little variance in the setters of these vals so a macro is not always called for. If the setter is private it is likely that complex logic to change the value, verify new values and so on happen or could happen elsewhere. 
4) the compiler could easily do this work for the user.

To me this adds up to a case for a new protection class in scala, namely "readonly var" in the next version of scala. 
 
Cheers,
Jon





On Sun Feb 22 2015 at 18:07:51 kraythe <kra...@gmail.com> wrote:
Abrupt? I haven't dismissed anyone nor have I implied that the world should adapt to me. Nor have I demanded the patience of anyone in educating my "poor misguided" self. I have been arguing a technical point and that is all. I don't care who the person is disagreeing I just care about the technical points, nothing less nothing more. If the way the community goes, to rip people for disagreeing, is this I might as well dump scala now as it will be the next Haskell, an interesting but useless language in anything but niche applications. Let's just look at the meager penetration of scala in the business world and pair that with its complexity and a hostile community and it's no wonder many great developers take a pass.

Back to the technical matter at hand, do you really assert that a public read only and private read write var is only useful to Hibernate? I can't believe you could think that. To me this equates to "just make all attributes public" or "encapsulation is a bad idea" or "object oriented engineering is silly". All of those I can't imagine would be put forth by such talented people. Scala fuses OO with functional programming, immutability with mutability, it's a brilliant cross between the ruby and Java worlds, trying to force it one direction seems to be counter to the principles of its invention.

As for breaking legacy code the history of scala is replete with such breakages and as I recall that is the reason that warnings that major versions of scala are incompatible. So I wouldn't ask for it to be retroactively changed but rather changed in next version. Or are we past that whole "this language won't be stuck in the legacy trap of Java mantra?" If the new mantra is "backward compatibility at all cost" then scala is doomed to suffer many of the problems Java does and with 1/100,000th of the market penetration.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.

kraythe

unread,
Feb 22, 2015, 2:08:11 PM2/22/15
to scala...@googlegroups.com, kra...@gmail.com
and thinking about it something like public[val] might be better than readonly. A lot less chance for name clashing: 

class Customer {
  public[val] private var name;
}

its a bit more verbose than "readonly" but a heck of a lot less verbose than current alternatives. 

-- Robert

Som Snytt

unread,
Feb 22, 2015, 4:17:46 PM2/22/15
to kraythe, scala-user
I also thought Rex's suggestion was kind of neat if syntax could be found.

Maybe in conjunction with re-inventing access. Would it be possible to make the setter package-private, for instance?

Also wanted to note that "And even if it is possible it does not diminish the point that it should be a language feature." does not itself assert that "it must be a language feature."  Also worth pointing out that macros are not even a language feature, but a language.experimental feature.

On keywords, it's worth pointing out the pain that appropriating "then" can cause.

We could have parser macros so that "import language.scala" enables the macros that accept core scala, "import language.scalaz" would accept that variant, with higher kinds and so on also enabled, and I could also tweak my language so that I could use // as an operator symbol.  Is it time to cc scala-debate?


Roland Kuhn

unread,
Feb 22, 2015, 4:28:20 PM2/22/15
to kraythe, scala-user
Hi Robert,

while most of the other angles have been thoroughly addressed already, there is the point remaining about adding keywords to the language grammar, in particular the quote «The pure technical fact is that the lexical and syntactic structure could easily adopt a context sensitive keyword without much stress.» This is not true, for two main reasons:

  • The grammar of Scala is deliberately context-free in order to keep tooling support sane (take C++ as an example of how much a context-sensitive grammar hurts); this is a stated design goal of the language, which means that your assertion may come across as presumptuous (not saying that you are, I’m just explaining what I meant earlier).
  • Adding a keyword means making all use of that token illegal otherwise, it is a reserved word. It is extremely unlikely to find a common english word that could still be reserved at this point without breaking a significant amount of code—Scala is widely used in the industry since years.

Coming back to the Hibernate and Scala vs. Java case, in Java the setup of a publicly readable and privately writable field involves at least the following (plus annotations):

private int myField;

public int getMyField() {
  return myField;
}

private void setMyField(int value) {
  // validate here
  myField = value;
}

The direct translation to Scala is

private[this] var _myField: Int

def myField: Int = _myField

private def myField_=(value: Int) = {
  // validate here
  _myField = value
}

Since Java is the benchmark, does this really look so bad? It expresses exactly what you want as far as I understand—which is the other point I was wondering about: you seemed to imply that Scala cannot accommodate Hibernate, but I have trouble seeing why that is.

Regards,

Roland

Haoyi Li

unread,
Feb 22, 2015, 9:26:58 PM2/22/15
to Roland Kuhn, kraythe, scala-user
@Som if we want to start mucking with the Scala parser, it's actually pretty easy with SBT:


Adding a new keyword is pretty straightforward, and could be added to your own SBT project with maybe a day's worth of work. 

If we wanted to go with an annotation rather than a keyword, it would be even easier, perhaps 4 hours to implement, tops.

It's really not that hard: solutions exist and a @readonly macro annotation could easily have been implemented in the time between @xeno_by left his first suggestion and the time of this post.

Som Snytt

unread,
Feb 22, 2015, 9:38:23 PM2/22/15
to Haoyi Li, kraythe, scala-user
To be fair, there are many low-bar items that could be adopted given enough github reviewers and consensus.

Maybe the problem is that there is no mechanism for sharing solutions such as sbaz, or as it would be called today, sbz.

As a footnote, Scalite could be known as ScaLi. Apologies in advance if you already considered that.

Vincent Marquez

unread,
Feb 22, 2015, 9:44:38 PM2/22/15
to Som Snytt, Haoyi Li, kraythe, scala-user
>
2) mutable data is unaviodable in many circumstances such as ORM tools.

No, only some ORM tools. 

--Vincent

Nils Kilden-Pedersen

unread,
Feb 23, 2015, 9:30:40 AM2/23/15
to kraythe, scala-user

On Fri, Feb 20, 2015 at 11:12 AM, kraythe <kra...@gmail.com> wrote:


This is incredibly verbose and very boilerplate. Instead we should be able to do something like this 

class Customer(readonly var username: String) {
 
def changeUserName(requested: String) = {
     
// check for uniqueness and throw exception if not, otherwise set it
     username
= requested
 
}
}
 

The closest would be this:

class Customer(private var _username: String) {
  def username = _username
  def username_=(requested: String): Unit = {
    
// check for uniqueness and throw exception if not, otherwise set it

    _username = username
  }
}

Or alternatively:

class Customer(private var _username: String) {
  def username = _username
  def changeUserName(requested: String): Unit = {
    
// check for uniqueness and throw exception if not, otherwise set it

    _username = username
  }
}

The first allows you to do customer.username = "New username", the other is customer.changeUserName("New username"), i.e. purely syntactic difference.

Adriaan Moors

unread,
Apr 16, 2015, 1:29:28 PM4/16/15
to kraythe, scala-user
On Fri, Feb 20, 2015 at 10:26 AM, kraythe <kra...@gmail.com> wrote:
Your response indicates you might have only read the subject line. Try reading the rest.
Please be kind. I would like to ask everyone to refrain from snarky replies, such as this one -- what purpose do they serve?
Instead, take a moment to appreciate (and marvel at!) how many people are eager to offer some of their time (no matter how little) to help out.

Thank you to all who offered their help! I'm grateful for your kindness, which is essential to make our community thrive.
Reply all
Reply to author
Forward
0 new messages