Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

RawToast
RawToast

Posted on • Edited on • Originally published atitazura.io

     

Immutable Updates of Objects in Reason

I've recently been playing around with objects in ReasonML and reading about using them in OCaml to get a better understanding, as there is a lack of good documentation on their use in Reason. So I thought I'd try and writing something about one of the interesting and lesser-known features of objects in ReasonML.

I am sure none of this will come as a surprise to a seasoned OCaml developer, but like many developers, I have no experience with Ocaml and keep finding out new features that can also used in our projects.

In ReasonML the spread operator is a great piece of syntactic sugar that makes immutable updates quick to implement, similar to the copy method of case classes in Scala. I was happy to find out that this was also possible with objects, allowing the creation of immutable, but updatable, objects. In OCaml, these are known as functional objects.

Most ReasonML developers have come across the syntax below to update immutable records:

typecat={name:string,age:int};letkitten={name:"Charles",age:1};letoldCat={...kitten,age:4};
Enter fullscreen modeExit fullscreen mode

A similar technique exists for objects; however, it's not so well known amongst Reason developers, as I believe it is not included in the documentation. So at first, you might attempt something like the example below, which works but quickly becomes verbose as your records grow in size:

classimmutableDog(name,age)={as_;pubgetAge:int=age;pubgetName:string=name;pubsetName:string=>immutableDog=newName=>newimmutableDog(newName,age);pubsetAge:int=>immutableDog=newAge=>newimmutableDog(name,newAge);};
Enter fullscreen modeExit fullscreen mode

Instead, you can override values to make a new instance with only the specified updates, similar to records. The syntax is not so obvious:

classimmutableCat(name,age)={as_;valname=name;valage=age;pubgetAge:int=age;pubgetName:string=name;pubsetName=newName=>{<name:newName>};// Creates a new instance.pubsetAge=newAge=>{<age:newAge>};};
Enter fullscreen modeExit fullscreen mode

I believe this syntax is known as the override construct{< ... >}, which returns a copy of the current object and allows you to override the value of instance variables or methods.

Let's see what it looks like in action:

letmyImmutableCat:immutableCat=newimmutableCat("Cool Cat",5);letmyNewCat:immutableCat=myImmutableCat#setName("Dave");// does not change myImmutableCat
Enter fullscreen modeExit fullscreen mode

It is also possible to update values in the same way:

classimmutable=(number)=>{as_;valcounter=number*number;pubmakeNegative={<counter:-counter>};pubgetCounter=counter;};letmyImmutable=newimmutable(4);letnegative=myImmutable#makeNegative;myImmutable#getCounter// 4negative#getCounter// -16
Enter fullscreen modeExit fullscreen mode

Thanks for reading, I hope you found this post useful and legible!

Based on a post in a series onusing objects in Reason atitazura.io

Top comments(2)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
idkjs profile image
Alain
  • Joined

Awesome series! Really. Thanks.

I can't seem to logmyImmutableCat ormyNewCat. Is there a trick to that?

Thank again.

CollapseExpand
 
rawtoast profile image
RawToast
I write silly things in various languages
  • Location
    横浜
  • Education
    MSc Computer Science
  • Work
    Software Engineer at Coursebase
  • Joined

I presume because objects don't print as nicely as records. As reason will try to print the methods alongside the values.

Js.log2("Does this work", myNewCat);"Does this work" [[4,15,null,-278822339,null,243512077,null,461513217,null,588852681],16,"Cool Cat",5,"Dave",5]

One way would be to add ashow method to all your objects, where you manually make a string.

class immutableCat(name, age) = {  as _;  val name = name;  val age = age;  pub show = "Cat {name: " ++ name ++ ", age: " ++ string_of_int(age) ++ "}";};let myImmutableCat: immutableCat = new immutableCat("Cool Cat", 5);let show = obj => obj#show;  // put this in a Utility module somewhereJs.log2("Does this work", show(myImmutableCat));

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

I write silly things in various languages
  • Location
    横浜
  • Education
    MSc Computer Science
  • Work
    Software Engineer at Coursebase
  • Joined

More fromRawToast

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp