0

I'm not really sure how to explain so I will start with the output. I need to return this:

{
   replies:
   [
      { type: 'text', content: 'one' }
      { type: 'text', content: 'two' }
      { type: 'text', content: 'three' }
   ],
   conversation: {
      memory
   }
}

And I wanted to return that through in-line statement. So I would like to call something like:

reply.addText('one').addText('two').addText('three').addConversation(memory)

Note that addText can be called infinite times while addConversation can be called only one time. Also conversation is optional, in that case, if conversation is absent the conversation object should not appear in the output.

C. Leo
  • 53
  • 1
  • 1
  • 8
  • 1
    This looks like a job for the builder pattern. https://www.dofactory.com/javascript/builder-design-pattern or the answer to this question https://stackoverflow.com/questions/33963800/javascript-builder-pattern-using-private-variables – vader Oct 16 '18 at 18:41

3 Answers3

1

To create a custom structured object use a constructor, say Reply.

To call instance methods on the return value of method calls, return the instance object from the method.

Choices to prevent multiple additions of conversation objects include throwing an error (as below) or perhaps logging a warning and simply not add additional objects after a first call to addConversation.

Write the code to implement the requirements.

For example using vanilla javascript:

function Reply() {
    this.replies = [];
}
Reply.prototype.addText = function( content) {
    this.replies.push( {type: "text", content: content});
    return this;
}
Reply.prototype.addConversation = function( value) {
    if( this.conversation) {
        //throw new Error("Only one conversation allowed");
    }
    this.conversation = {conversation: value};
    return this;
};
Reply.prototype.conversation = null;

// demo
var reply = new Reply();
reply.addText( "one").addText("two").addConversation("memory?");
console.log( JSON.stringify( reply, undefined," "));

(The console.log uses JSON stringify to avoid listing inherited methods)

traktor
  • 17,588
  • 4
  • 32
  • 53
0

A possible implementation is to create a builder as follows:

function create() {
  const replies = []; // store all replies in this array
  let conversation; // store the memory here
  let hasAddConversationBeenCalled = false; // a state to check if addConversation was ever called

  this.addText = function(content) {
    // add a new reply to the array
    replies.push({
      type: 'text',
      content
    });

    return this;  // return the builder
  };

  this.addConversation = function(memory) {
    if (!hasAddConversationBeenCalled) {  // check if this was called before
      // if not set the memory
      conversation = {
        memory
      };
      hasAddConversationBeenCalled = true;  // set that the memory has been set
    }
    return this;  // return the builder
  }

  this.build = function() {
    const reply = {
      replies
    };

    if (conversation) { // only if converstation was set
      reply.conversation = conversation;  // add it to the final reply object
    }

    return reply; // finally return the built respnse
  }

  return this; // return the new builder
}

You can then use it as follows:

const builder = create();

const reply = builder.addText('one').addText('two').addText('three').addConversation({}).build();

Here is a link to a codepen to play around with.

vader
  • 889
  • 8
  • 22
0

If you specifically want to add assemble this via multiple function calls, then the builder pattern is your best bet, as vader said in their comment.

However, if the goal is to simply create shorthand for concisely building these objects, it can be done using a function that takes the list of text as an array.

const buildObject = (textArray, memory) => {
  return Object.assign(
    {},
    {
      replies: textArray.map(x => {
        return {
           type: 'text',
           value: x
          }
        })
    },
    memory ? {conversation: memory} : null
  )
}
var memory = { };

//with memory
console.log(buildObject(['one', 'two', 'three'], memory ))

//without memory
console.log(buildObject(['one', 'two', 'three']));

Fiddle example: http://jsfiddle.net/ucxkd4g3/

Will
  • 482
  • 5
  • 8