Throwing exceptions from records

Ty Young youngty1997 at gmail.com
Mon Mar 9 20:18:56 UTC 2020


On 3/9/20 2:41 PM, Brian Goetz wrote:
> Ty;
>
> I think this discussion has largely run its course, and is threatening 
> to stray outside of the bounds of what this list is for.


I was told that amber-dev was for discussion of records. I guess there 
was a miscommunication?


>
> As a reminder, this list is for those involved in the _development_ of 
> the Amber features.  We consider "experience reports" to be a valid 
> (and often, highly valuable) contribution from that perspective, to 
> the extent they are grounded in the concrete: "I tried X, and Y 
> worked, but Z didn't."


I've converted several classes to records(although there isn't much of a 
different between them). Here is [1] converted to record:


https://pastebin.com/V1eHehc0


As said before, all meaningful logic is now gone from the class. At this 
point individual files no longer need to exist since all NativeFunction 
implementations require the same fields and records are too limiting 
as-is. You might as well have a "NativeFunctionRecord" record that takes 
care of everything, with static methods that do the required object 
creation to pass to the canonical constructor.


>
> I'd summarize the useful part of your feedback as follows:
>
>  - It might be reasonable to allow record constructors to throw 
> checked exceptions, since they already can throw unchecked exceptions 
> (though, you don't really provide much in the way of concrete 
> examples, just that you are worried about calling exception-throwing 
> code from the ctor (though, as Kasper said, this is a sign you might 
> be using the wrong tool in the first place))


And the ability to have a no-args constructor that sets everything(see 
above link as to why this would be nice). This is possible technically 
but the issue is that the canonical constructor has to be called first.


>
> Which is fine as far as it goes, and we'll take a note to discuss this 
> in the EG.  The rest is, let's just say, "out of scope" for this list.
>
> You also received some excellent advice from more experienced 
> developers such as Remi and Kasper, which you seem more interested in 
> arguing with than being educated by.  Which is fine, but don't do it 
> here, that's not what this list is for.


Surely education requires giving explanations, not simply saying "no"? I 
asked why it wasn't a good fit for records and you say it's 
"out-of-scope" of this list.


Again, AFAIK, the only two requirements for a class to be a record are:


1. All fields must be final


and


2. You must be able to recreate a record using the same inputs(or lack 
thereof).


No one has said otherwise nor has anyone layed down or linked to any 
other design documents that say my use case is wrong or invalid. I 
actually tried looking for some online article showing a more advanced 
usage of records and 75% of the articles just copy/pasted the Point 
example from the JEP. There wasn't much information on what does and 
doesn't make for a record other than those two things, which my classes 
do seem to fall under.


Is the Point example really it? It feels so simple to the point(pun not 
intended) of feeling being wrong. Yes, records are not classes and 
that's perfectly fine and totally not the issue. The issue is the 
implementation details like forcing a call to the canonical constructor 
first or not being able to throw exceptions.


>
>
>
>
>
> On 3/9/2020 3:27 PM, Ty Young wrote:
>>
>> On 3/8/20 4:10 AM, Kasper Nielsen wrote:
>>>> Right, because any and all meaningful logic is just thrown in other
>>>> places making them more complicated.
>>>>
>>> I took a look at one of the classes you are trying to convert to a 
>>> record [1].
>>> And it really looks like a really poor fit for record conversion.
>>
>>
>> Why?
>>
>>
>>>   What exactly
>>> are you trying to accomplish? Avoid writing a single getter?
>>
>>
>> No. The point is to signify that the classes merely contain data.
>>
>>
>>>   Because something
>>> like equals() and toString() doesn't really make sense.
>>
>>
>> Again, why? You claim things but provide zero reasons as to why.
>>
>>
>>>   Also, by converting to
>>> records you would end up exposing the VarHandle which I assume is 
>>> something
>>> you would actually want to encapsulate?
>>
>>
>> It's exposed anyway?
>>
>>
>>>   On top of that, you have a set method,
>>> which I find really weird given that records signal pure data carriers.
>>
>>
>> There is no "set" method, only an action, "call".
>>
>>
>> And what is a "pure data carrier" exactly? I don't see any concrete 
>> definition by anyone. No one said you couldn't have actions or 
>> setters which modify a records field's fields.
>>
>>
>> Also, why would a "pure" data carrier then need to have the ability 
>> to implement interfaces? It introduces problems where an interface 
>> method "getX()" could be different than just "x()".
>>
>>
>>> /Kasper
>


More information about the amber-dev mailing list