Lexfeathers

I make music!

🏳️‍⚧️ Musician | Sound Designer

Find me elsewhere:
My website
Bsky
Instagram
Masto

 

img


It occurred to me that sometimes it might be useful to be able to output the name of a variable I'm using.

Here's my test code:

let liar = false;
let soothsayer = true;

function tester(input) {
  let varName = input => Object.keys(input)[0];
  return input ? varName + ' was true' : varName + ' was not true';
}

console.log(tester(liar));
console.log(tester(soothsayer));
syntax highlighting by codehost

At the moment, varName just gets output as the code it contains, in string form. Am I missing something, fucking up, or just silly?

Thank u cohost!


You must log in to comment.

in reply to @Lexfeathers's post:

I think you need to do varName(input) in the return input ? line. Right now varName is a function (because of the varName = input => )
You could also remove the input => and then it would work also

Right now inside tester what's being passed is only the bare boolean value true or false. The variable that value came from has been obliterated and there's no way to recover it.

You could restructure your code so that liar and soothsayer are objects with a value field and a name field. And then retrieve those fields when printing.

so what you're trying to do is essentially impossible.

first of all, the reason why this prints input => Object.keys(input)[0] was not true is because you forgot to call your function! varName is a function here, and you concatenate it to a string in varName + ' was not true', and concatenating a string to a function returns the function source code.

here's the problem though: functions do not know what the parameter name is. in its current form you're trying to squeeze info out of a function that javascript doesn't know.

but you can (ab)use objects for this! you were already on the right track with Object.keys. for example, this works as intended:

function kv(obj) { return [Object.keys(obj)[0], Object.values(obj)[0]] }

let liar = false;
let soothsayer = true;

function tester(_input) {
  let [varName, input] = kv(_input)
  return input ? varName + ' was true' : varName + ' was not true';
}

console.log(tester({liar})); //> liar was not true
console.log(tester({soothsayer})); //> soothsayer was true

note that i called the tester function with tester({...}) instead of tester(...), because we need objects here. and {varname} is a shorthand for {varname: varname}, so this works!

also, fun fact, object keys have an order in JS, so while it wouldn't be considered to be "clean code" you can do this:

function kv(obj) { return Object.keys(obj).flatMap((k, i) => [k, Object.values(obj)[i]]) }

let liar = false;
let soothsayer = true;

function tester(args) {
  let [firstK, firstV, secondK, secondV] = kv(args)
  return `${firstK} is ${firstV}` + 
    (secondV != undefined ? ` and ${secondK} is ${secondV}` : "") 
}

console.log(tester({liar})); //> 'liar is false'
console.log(tester({soothsayer, liar})); //> 'soothsayer is true and liar is false'
console.log(tester({liar, soothsayer})); //> 'liar is false and soothsayer is true'

you need to call tester with an object, like this:

tester({ liar });
tester({ soothsayer });

because the tester function takes an object and gets its first key. { liar } is equivalent to { liar: liar }, an object with 1 key "liar"

also, thanks for using codehost :)

mint's point is also correct. here's a full working version. let me know what questions you have

let liar = false;
let soothsayer = true;

function tester(obj) {
  let varName = Object.keys(obj)[0];
  let value = obj[varName];
  return value ? varName + " was true" : varName + " was not true";
}

console.log(tester({ liar }));
console.log(tester({ soothsayer }));