Comments (12)
Additional thought: at least in the current implementation, juggling values on the stack is somewhat more efficient in terms of allocations required. Values moving around stack aren't allocated, just referenced. Words are based on code injection which requires some allocation
from pumpkindb.
An important downside of this feature: one won't be able to retrieve a bunch of definitions from the storage and EVAL them to define a number of words
from pumpkindb.
PR has been updated to reduce the scope and implement a new word called EVAL/SCOPED
from pumpkindb.
Gated feature merged
from pumpkindb.
While playing further with it, I discovered one more edge case that's not great about it. Let me think about it a bit more.
Basically, there's a situation when we pass closures between scopes. This is sneaky:
CURSOR/DOWHILE : ['iterator SET 'closure SET 'c SET
[c closure EVAL [c iterator EVAL] [0] IFELSE] DOWHILE] EVAL/SCOPED.
?CURSOR/DOWHILE : ['iterator SET 'closure SET 'c SET
c [?CURSOR/CUR closure EVAL] iterator CURSOR/DOWHILE] EVAL/SCOPED.
will fail on this:
PumpkinDB> [CURSOR 'c SET c "testkey" CURSOR/SEEK? DROP c [UNWRAP 1] 'CURSOR/NEXT? ?CURSOR/DOWHILE] READ
Error: "Invalid value" 0x1a17746573746b65790000000014a454200eded6f0000000000101 0x03
However, if I change the closure
name like this:
?CURSOR/DOWHILE : ['iterator SET 'closure_ SET 'c SET
c [?CURSOR/CUR closure_ EVAL] iterator CURSOR/DOWHILE] EVAL/SCOPED.
then everything is fine:
PumpkinDB> [CURSOR 'c SET c "testkey" CURSOR/SEEK? DROP c [UNWRAP 1] 'CURSOR/NEXT? ?CURSOR/DOWHILE] READ
0x746573746b65790000000014a454200eded6f000000000 0x01 0x746573746b65790000000014a454200f336b4800000000 0x02 0x746573746b65790000000014a454200f79af9000000000 0x03 0x746573746b65790000000014a454200fb5513000000000 "Hello"
It basically comes down to one very interesting question: how do we pass scoped words inside of closures... because once we pased from ?CURSOR/DOWHILE to CURSOR/DOWHILE, CURSOR/DOWHILE overrode 'closure
from pumpkindb.
What can we do about this?
- Keep at as is, but if you know you're passing a closure into a word that has its own scope, check if you are not going to clash.
- Implement a word that would replace dictionary-based words with their values ("expand")
- ?
from pumpkindb.
I think have a decent solution for this. Just like we have EVAL that evaluates in the curren scope, EVAL/SCOPED evaluated in a new scope, we should have EVAL/UNSCOPED that evaluates in the parent scope. It's not perfect though, as (I think) if an interim scope just passes the closure through, then it might not work. Need to check
from pumpkindb.
I am still not 100% happy with EVAL/UNSCOPED as this would require a ceremony to pass closure by names. I am leaning towards stating that the only safe way to pass a named closure is to get its value first, so it can be passed by value.
from pumpkindb.
Current idea: enable unwrapping syntax
for the text form:
[1 `closure] => [1] closure CONCAT [] CONCAT
from pumpkindb.
#108 would resolve this issue
from pumpkindb.
Graduated the feature in #103. Still tracking as the feature gate hasn't been dropped, simply moved to default
.
from pumpkindb.
I suggest keeping this feature-gated until we see what the future compilation technique will bring in in terms of scoping. Thoughts?
from pumpkindb.
Related Issues (20)
- Problem: nom dependency outdated
- Problem: numerous mio deprecation notices HOT 1
- Problem: non-trivial to detect if JSON's value is an integer or a float
- Problem: overflowing integer literals are parsed as instructions
- Problem: Documentation of master is out of sync with code too often
- Problem: is overwriting key/value with the same value a duplicate? HOT 2
- Problem: zero terminated by period doesn't get parsed right
- Problem: integer constants in builtins get interpreted as instructions
- Problem: switching storage backends is nearly impossible HOT 2
- Problem: different users would use different naming conventions
- Problem: "builtins" files don't allow for computed constants HOT 2
- Problem: PumpkinDB is too low-level HOT 8
- Problem: lazy builtins! macro defers syntax checking until run time
- Problem: sharing stack with closures prevents typing
- Problem: use of return stack to accumulate values reverses them
- Problem: return stack nomenclature differs from Forth
- Problem: Rust nightly after 2017-06-20 affects benchmarks negatively HOT 2
- Problem: Missing input / output elements from queue operations
- Is this project abandoned? HOT 3
- `Read` on uninitialized buffer may cause UB ( `PacketReader::read()` )
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pumpkindb.