The lack of lexical scoping is giving me a very hard time and I feel stuck at the moment. So here’s the problem:
I want to make a function that mutates the dictionary that it is passed in as an argument. If I do it with call by value, instead of modifying in-place it just modifies a copy. If I use call-by-name, I have to do something like:
f:{[sym]
dict:get sym;
dict[`key]:42;
sym set dict;
}
The problem with this is that now the data is being copied and the data in the dictionary is large enough that I don’t believe it to be acceptable.
Is there a better solution? I don’t care about using call-by-naming, I just want a function to be able to access a dictionary or list in the surrounding scope and modify it in place. What is the best way to do this?
Thanks a bunch! Hopefully this isn’t a stupid question. I just started using Q and I’m loving it so far… except for the lack of lexical scoping, which honestly strikes me as a totally crazy design decision. As a second question, does anyone know why Q does not have lexical scoping? It would make so many things much easier and much more elegant.
There’s likely an elegant solution for the problem you’re solving which doesn’t require lexical scoping.
What’s your use case?
The only scenario where I found I miss lexical scoping is when doing exception handling (try-catch-finally and logging) which ends up looking dense as you need project context into the exception handler:
/ cleanupArg could e.g. be a handle that needs closing
@[{do something that may throw};arg;{[arg;cleanupArg;err]log arg, log err, handle}[arg;cleanupArg;]]
>> which honestly strikes me as a totally crazy design decision.
Ah, the five stages of learning Q - anger, denial..
Lets say I want a function that modifies a dictionary and then passes it to a different function that modifies it, etc etc. Are you saying its more efficient to use call-by-value instead of call-by-name? The only way I could imagine this to be true is if Q is using structural sharing to not copy the entire dictionary. If not, all the values will need to be copied regardless of whether its necessary or not.
What is the idiomatic and performant way to do it? Pass a handle and return the handle or pass the value and return the new copied value? In a functional language these two approaches would look the same, as pass-by-reference is the norm.