How should I manage objects that are passed by reference in the context of functional programming?

Lately, I have been experimenting with some code in an attempt to delve deeper into functional programming. However, I seem to have hit a snag. I am struggling with handling an object. My goal is to add key-value pairs to an object without reassigning it, as is common in functional programming. I was considering placing the object in a 'Box' container.

const Box = x =>
({
  map: f => Box(f(x)),
  fold: f => f(x),
})

I thought about using this 'Box' method to add all my key-value pairs:

const formData = obj =>
  Box(obj)
  .map(s => s.key1 = document.getElementById("value1").value)
  .map(s => s.key2 = document.getElementById("value2").value)
  .fold(s => s)

var emptyObj = {};
const test = formData(emptyObj);

However, I realized that while 'emptyObj' contains both key-value pairs, 'test' does not. Clearly, I am missing something crucial here. Despite watching tutorials like

and reading through the ebook, there seems to be a piece of the puzzle that eludes me. Any guidance or assistance on this matter would be immensely appreciated.

Answer №1

This solution involves incorporating the following approach:

const updateData = object =>
  Box(object)
   .then(data => ({ ...data, key: document.getElementById("value1").value }) )
   .then(data => ({ ...data, key2: document.getElementById("value2").value } )) 
   .bind(data => data)

It is worth considering using the monadic names then and bind instead of map and fold.

Answer №2

One issue is that the callback functions in your map do not return the object they are modifying, but instead return the string result of the assignment operation. To fix this, you should adjust your code like so:

Box(obj)
.map(s => (s.key1 = document.getElementById("value1").value, s))
.map(s => (s.key2 = document.getElementById("value2").value, s))
.fold(s => s)

This will ensure that test === emptyObject and both properties are successfully added.


However, it seems unclear why you are using this "Box" structure. A simpler approach would be to directly create an object like this:

const formData = () => ({
  key1: document.getElementById("value1").value,
  key2: document.getElementById("value2").value,
});

Answer №3

When it comes to functional programming, the practice is to create a new object with added key-value pairs instead of reassigning values.

It's important to note that immutability isn't solely tied to functional programming. However, based on your statement, I assume you want 'emptyObj' to remain unchanged while creating a separate object 'test' with specific properties like 'key1' and 'key2'.

The issue here is not about object usage conflicting with functional programming principles, but rather about the limitations of objects as dictionaries. In such cases, using Maps would be more appropriate. Maps function as true dictionaries and offer handy tools for manipulation with less cognitive strain.

const Box=(x)=>({
    map: (key,value)=>Box((new Map(x).set(key,value))),
    clear: (key,value)=>Box((copy=>(copy.delete(key),copy))(new Map(x))
    ),
    fold: f=>f(new Map(x)), // EDITED to prevent leaking the original map
})

const formData=obj=>(
    Box(obj)
    .map('key1',document.getElementById("value1").value)
    .map('key2',document.getElementById("value2").value)
    .fold(s=>s)
)
const clearData=obj=>(
    Box(obj)
    .clear('key1')
    .clear('key2')
    .fold(s=>s)
)

const emptyObj=new Map()
const test1=formData(emptyObj)
const test2=clearData(test1)

console.log(emptyObj) // empty
console.log(test1) // both keys
console.log(test2) // empty again

Incorporating additional features like the capability to immutably 'clear' data alongside 'map' operations exemplifies how straightforward this process can be. A particular syntax was utilized in the 'clear' method due to the behavior of Map.prototype.delete.

If delving into immutability without strictly adhering to functional programming, various immutable class libraries are accessible in JavaScript that offer immutable Maps or the option to subclass one easily.

EDIT

An update from the original post mentions the necessity of working with objects for JSON communication purposes. One easy workaround involves utilizing a helper function to convert Maps to JSON:

let map=new Map([['key1','value1'],['key2','value2']])

const mapToJson=map=>(
    '{'+
    [...map].map(([key,value])=>(
        '"'+key+'":'+(value===undefined ? 'null' : JSON.stringify(value)))
    ).join(',')+
    '}'
)

console.log(mapToJson(map)) // {"key1":"value1","key2":"value2"}

A special precaution had to be taken for checking 'undefined' since the JSON format recognizes only 'null' for undefined values, not the string representation 'undefined'.

This solution assumes the use of string keys in Maps, hence error checks can be implemented for scenarios involving other types of keys.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to utilize two different versions of a JavaScript library on a single page without causing function conflicts?

My current project involves using multiple versions of the Nvd3 library for different charts on a single page within an Angular application. Each chart is loaded through its own template and requires a specific version of Nvd3 (e.g., v1.8 for partial_1.htm ...

Using JQuery to target the input value based on its ID

When trying to extract the value of the input with id "registration_type," I entered the following command in the console: $('#registration_type') The output displayed was: <input id=​"registration_type" name=​"contact_registration[ty ...

Attempting to insert items into a storage array and subsequently outputting them using a loop

I am attempting to add "contacts" to local storage, and every time I add a new contact I want to refresh it in a jQuery list. I have successfully achieved this without using local storage. However, now I am facing a problem that I can't seem to solve. ...

jQuery is optimized to work specifically with select id tags

Here is the HTML code snippet I've put together, along with my script. While I admit it might look a bit messy, please bear with me as I'm still in the learning phase. If anyone could offer some assistance on this matter, I would be extremely gra ...

insert the "tr" element directly following the button

I am looking for a way to allow the user to add another input file right next to the button, so they can select and send multiple files at once. https://i.sstatic.net/TI4eJ.png I have tried using various solutions I found during my search but none of the ...

I am able to input data into other fields in mongoDB, however, I am unable to input the

I am facing an issue with the password while everything else seems to be working fine. I am using a schema and getting an error, but it could be a problem in my functions because I hashed the password. I am unable to identify what's causing the issue. ...

How can I update a specific element within an array of objects in JavaScript based on its reference rather than its index position?

I am dealing with multiple arrays of objects x=[ {a:1}, {b:2}, {c:3}, {d:4} ] y=[ {e:5}, {f:6}, {g:7}, {h:8} ] (etc) and I have a list of references pointing to the objects I need to replace. Instead of having an index into the array, I hold reference ...

Creating GeoJson using JavaScript

Currently, I am retrieving a latitude/longitude array using Ajax $.ajax({ type: "POST", url: '../m/m_share.php', data: 'zone=' + zone, dataType: 'json', success: function(tab) { var i = 0; ...

Display a toolbar underneath text that has been selected using jQuery

I am attempting to display a toolbar underneath selected text once the user has made a selection. After exploring various Stack Overflow responses, I have devised the following code. My goal is for the toolbar to activate when a user selects text not only ...

Transforming a string into an array containing objects

Can you help me understand how to transform a string into an array of objects? let str = `<%-found%>`; let result = []; JSON.parse(`["${str}"]`.replace(/},{/g, `}","{`)).forEach((e) => ...

Troubleshooting problems with integrating Jquery Plugin in Angular for creating dynamic dropdown menus

Currently, I am utilizing the selectric jQuery plugin in conjunction with my Angular dropdown. When I have the dropdown options hardcoded in the HTML, everything functions correctly with just the following code: $('select, .select').selectric() ...

Streaming data from BigQuery to the front-end using Express

Trying to extract a query from BigQuery and stream it to the frontend has been quite a challenge. In the Node.js environment with Express, one would assume it should look something like this: app.get('/endpoint', (req, res) => { bigQuery.cr ...

A guide on extracting the text content from an anchor tag by using xPath() with a combination of selenium and Mocha

I have successfully chosen an <a> tag. My goal is to display the text of the anchor tag, but I am facing difficulties. The technologies being used are selenium, mocha, javascript, and phantomJS This is the detailed script: var assert = require(&ap ...

Is JSON required to transmit an object using socket.io?

I have an object on the frontend that I want to broadcast to all connected clients. Can I send it as is, in its original form? Or do I always have to convert it into a JSON string before sending? Here is my object: var myBox = { x: 400, ...

Create a variety of unique objects on the canvas without any repetition or unwanted overlapping

Is there a way to generate objects on a map in a HTML5 Canvas without them overlapping or occupying the same space? I tried checking inside an array to see if the next 20 values are already taken to prevent overlapping, but it didn't work as expected ...

Using Local Storage to store arrays in JavaScript/jQuery

Currently, I am implementing a set of multiple buttons each containing data-id and data-name Below is my concept along with some sample code for reference: $(".clickCompare").click(function ({ var id = $(this).attr('data-id'); var ...

Increasing values in Mongoose using $inc can be done by following these steps

I've been struggling to increment a field value using $inc in my code. My schema looks like this: var postSchema = mongoose.Schema({ title : { type: String, required: true }, body : { type: String, default: '' }, coun ...

Having difficulty locating the login button on the webpage

I am attempting to log into a banking account using selenuim. After opening the webpage and locating the login element, I initially struggled to access it by its "name" or "id." Fortunately, I was able to successfully access it using driver.find_element_by ...

Guide on how to retrieve additional data from the API by pressing the "Load More" button

Hello, I am working on a project where I aim to display user data from an API called https://reqres.in/api/users?page=(the page number can be 1,2 or more) and present it in an HTML table using JavaScript with promises. Currently, I have successfully popula ...

"Utilize the style attribute to modify the appearance based on the

I was the original asker of this question, but I failed to provide a clear description which led to not getting an answer. However, I will now explain everything here. Essentially, I am looking for a JavaScript function that can identify a class with a spe ...