问题
I have an array:
{ 1 2 3 4 }
I want to push its contents to the stack.
I tried:
(sc) { 1 2 3 4 } dup length firstn
1
2
3
4
Great!
Inside a word, though:
: explode ( a -- * ) dup length firstn ; inline
Throws an error Cannot apply “firstn” to a run-time computed value
, because firstn
calls call
and
Words which call an input parameter must be declared inline so that a caller which passes in a literal quotation can have a static stack effect.
... and because of call
's semantics it's hard to compute quotations at runtime.
There must be a way to accomplish this. What is it?
回答1:
As Björn Lindqvist said, Factor won't let you do that1, but there are some workarounds.
The most direct way is perhaps using a vector as a stack:
: explode ( v s -- v ) dupd [ swap push ] with each ;
V{ } "somestring" explode
==> V{ 115 111 109 101 115 116 114 105 110 103 }
Of course, this means redesigning all related functions to work with this.
Maybe better than vectors, there are also string buffers, that can behave like a stack too.
"somestring" >sbuf
==> SBUF" somestring"
"-abcd" [ over push ] each
==> "somestring-abcd"
(Alternatively SBUF" somesbuf"
)
If you need to keep working with the content as if it were the input to some other words passed on the stack, you can use with-datastack
:
"somestring-abcd" [ 5 ndrop 3dup ] with-datastack >string
==> "somestringing"
But think of this as if it where a regular non-stack-based language. Each word takes a fixed number of parameters and outputs a fixed number of results.
[1]. There must be some metaprogramming ways to do this. I don't imagine there's an easy practical way, though.
回答2:
No. There is no way to write such a word. If you think you need a word like that, you must rethink how you approach the problem.
来源:https://stackoverflow.com/questions/36047593/unpack-an-array-to-the-stack-at-runtime