DEV Community

Keff
Keff

Posted on

[Challenge] log("this") or log("this").withData({})

This challenge is intended for JavaScript, but you can complete it with any language you like and can.


Fun little challenge. Hope you enjoy it 😄

Challenge Description

You need to create a function called log that receives a string and prints the string prepended with "log:". Easy.

Wait, log also returns an object with one method withData, which receives any data. If withData is called, it should print the message passed to log, prepended with "withData:" and appended with the data.

Check the following scenarios to understand the challenge better.

Scenario 1

If we call just log("test"); a message should be logged containing the message "log: test".

log("test"); // > log: test
Enter fullscreen mode Exit fullscreen mode

Scenario 2

But if we call the method withData as follows log("test").withData({ user: 'keff' });; It should log only the message "withData: test { user: 'keff' }".

See how the message from just log("test") is not printed. This is because the logic from log() is ignored when we call .withData().

log("test").withData(2); // > withData: test 2
Enter fullscreen mode Exit fullscreen mode

Can you accomplish this behavior?

💪 Best of luck! 💪


Top comments (6)

Collapse
 
nombrekeff profile image
Keff

Yup nice point, I could only figure this one out with setTimeout myself. This was intended as a fun experiment for people. Maybe to understand setTimeout or perhaps finding some quirks in the language, hopefully, if not, just a weird little behavior nonetheless.

Collapse
 
idanarye profile image
Idan Arye

This is possible in Python by utilizing the destructor and relying on the fact that Python uses reference counting as its first GC tier:

class log:  # yes this is a class but you can just use it like a function
    def __init__(self, text):
        self.text = text
        self.print_on_dtor = True

    def __del__(self):
        if self.print_on_dtor:
            self.print_on_dtor = False
            print('log:', self.text)

    def with_data(self, data):
        self.print_on_dtor = False
        print('withData:', self.text, data)

JS doesn't have destructors so you can't use that trick there. I'm also not sure if the GC is as predictable as Python's (and with all the various implementations I won't be surprised if it has different rules on different engines...)

Collapse
 
jessesolomon profile image
Jesse Solomon

Thanks for another fun challenge!

This took quite a bit of thinking, but I ended up working with the fact that setTimeout isn't actual asynchronous.
So here's what my log function looks like:

function log(text) {
    let logger = {
        label: "Log:",
        message: [ text ],
        withData(...data) {
            this.label = "withData:";
            this.message.push(...data);
        }
    };

    setTimeout(() => console.log(logger.label, ...logger.message), 0);

    return logger;
}
Enter fullscreen mode Exit fullscreen mode

And it passes the tests, of course!

log("test"); // > log: test
log("test").withData(2); // > withData: test 2
Enter fullscreen mode Exit fullscreen mode

It can even handle more complicated synchronous behavior!

let logger = log("Here's a");

if (Math.random() > 0.5) {
    logger.withData("number", Math.random());
}
else {
    logger.withData("boolean", Math.random() > 0.5);
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
nombrekeff profile image
Keff

I'm glad you enjoyed it :) cool solution. More extensible than mine for sure.

Collapse
 
nombrekeff profile image
Keff

I guess. The only way I figured it out was making use of setTimeout, but, as you explained in another comment, it's not 100% guaranteed it will always work and can behave in unexpected ways.

Hopefully, somebody comes up with some weird solutions :)

Collapse
 
pyrsmk profile image
Aurélien Delogu

That is something I did in a technical test for a job interview. Why couldn't we use the event loop mechanism to trigger something as soon as we exit the function ?

Nevertheless, that was not they were expecting ahah.