4 ms·
I think best practice among languages that support dynamic scoping is to only make use of it for global variables. As I understand it, one should only read or s
by jolmg 6y ago
I think best practice among languages that support dynamic scoping is to only make use of it for global variables. As I understand it, one should only read or shadow, not modify, these variables. Since that's the case, besides the thread issue you mentioned, I'm not sure this solution is lacking. I don't know much C++, though, so I might be missing something.
- catern 6y agoIf you have multiple threads which try to bind the dynamically scoped variable to a new value, that should work fine and result in different values for the variable in each thread. In this implementation, the threads will corrupt the data structure and result in undefined behavior.
- jolmg 6y agoYes, that's why: > besides the thread issue you mentioned
- masklinn 6y ago> If you have multiple threads which try to bind the dynamically scoped variable to a new value, that should work fine and result in different values for the variable in each thread. That would work with proper threadlocals. However with dynamic variables you'd also get this for different sub-thread stacks. Not all languages can expose that but languages with generators do e.g. in Python if you `yield` then the stack is suspended, this means a threadlocal you've changed would not be rolled back, but a dynamic variable (which Python does not have) would.
- AnimalMuppet 6y agoOK, help me out here: If I'm only using it for global variables, what does the dynamic scoping do for me? Why not just use a normal global variable?
- jolmg 6y agoThe problem with local variables is that you can then not call a function that uses them unless you define such variables. One shouldn't be forced to know of such variables before calling such a function, since then they'd hardly be different from regular arguments. The difference with statically-scoped global variables is that you can't set them to different things in different threads, and you have to be careful to set it back to it's original value after you called the code you wanted. In other words, it's the same difference as using environment variables vs configuration files for executables.
- AnimalMuppet 6y agoIf I ever saw anyone I worked with trying to do something like "setting a global variable to different things in different threads", I would have very strong words for them. If they didn't listen, I'd have even stronger words for their manager: "Fire this bozo immediately". In what sane world is that considered a good idea? Is there any way in which doing so via "dynamic scoping" makes it any less of a horrible idea? I'm having trouble making sense of your first paragraph. Part of the point of local variables is that they're local. It doesn't matter whether the function you're calling uses them or not. If it uses something with the same name, it's their own copy, and you don't care whether they do or don't. If they want yours, you pass it in. What am I missing?
- jolmg 6y ago> If I ever saw anyone I worked with trying to do something like "setting a global variable to different things in different threads", I would have very strong words for them. Because global variables aren't used the same between the two types of languages. In lexically-scoped languages, it's bad practice overall to use global variables for anything except constants. In dynamically-scoped languages, they're used as an environment just like how environment variables are used among processes. You asked why not use "normal" (statically-scoped) global variables, and I replied on the difference. That doesn't mean that I support using them like that in such languages. Imagine environment variables didn't exist. A `su` command that modified the home directory in /etc/passwd for the duration of its subprocess to change it back when it dies would also seem pretty ugly for me. Indeed, if a language lacks dynamic scoping or environment variables didn't exist, the proper practice would be to pass the whole environment explicitly as arguments. That's what's typically done in statically-scoped languages, but it has the caveats I mentioned in this other comment: https://news.ycombinator.com/item?id=24545180 https://news.ycombinator.com/item?id=24545180 > I'm having trouble making sense of your first paragraph. Here's an example using Elisp: ; Turning off static-scoping (setq lexical-binding nil) ;; Bad practice (defun foo () bar) (foo) ;=> Debugger entered--Lisp error: (void-variable bar) (let ((bar 3)) (foo)) ;=> 3 ;; Good practice (defvar bar 2) (foo) ;=> 2 (let ((bar 3)) (foo)) ;=> 3