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.