Let me preface by saying you generally want to avoid `execute` and `call`, except when implementing combinators (http://docs.factorcode.org/content/article-combinators.html). As you've already seen, they might have some finicky behavior. It's not quite the same level of antipattern as "eval is evil", but it's always felt similar to me. Perhaps the following is a bit better:
``` USING: arrays combinators formatting fry kernel sequences unicode.normalize ; : normalizations ( str -- norms ) { [ nfc ] [ nfd ] [ nfkc ] [ nfkd ] } cleave 4array [ [ "U+%04X" sprintf ] { } map-as ] map ; ``` That said... The reason this issue was tripped was because of `nfc`---and probably the others, too, but `nfc` is the first one done in the `map`. `nfc` is defined like this: ``` USING: unicode.normalize.private ; IN: unicode.normalize : nfc ( string -- nfc ) [ (nfd) combine ] with-string ; ``` The `with-string` combinator that it uses is defined like this: ``` USING: accessors kernel ; IN: unicode.normalize.private : with-string ( str quot -- str ) over aux>> [ call ] [ drop ] if ; inline ``` Because the above word is inlined, `nfc` is "really" behaving like this: ``` : nfc ( string -- nfc ) [ (nfd) combine ] over aux>> [ call ] [ drop ] if ; ``` Thus, if the input string doesn't have an `aux` slot set, we don't do any computation because the `[ (nfd) combine ]` quotation just gets `drop`ped. It's as though we defined it as just a no-op, like this: ``` : nfc ( string -- nfc ) ; ``` So, just take a look: ``` IN: scratchpad "Factor" aux>> . f IN: scratchpad "\xF1" aux>> . B{ 0 0 } ``` Because of the above, the call to `"Factor" nfc` becomes a no-op, and it *looks* to the Factor VM like `nfc` had the stack-effect `( -- )`. So, the `execute( -- )` doesn't raise an error in this example. To get really technical, I think the reason the VM thinks the stack-effect looks OK is because of how this primitive is implemented: https://github.com/slavapestov/factor/blob/master/vm/contexts.cpp#L274 Basically, the datastack before & after the call to `nfc` is exactly the same, so it thinks the stack effect was `( -- )`. But with "\xF1", this isn't the case, and the error is thus caught. Hope that helps, --Alex Vondrak On Wed, Oct 30, 2013 at 3:24 PM, OwnWaterloo <ownwater...@gmail.com> wrote: > I'm new to Factor and don't know how to minimize the code while get > the similar behaviour. Sorry for that. > But thanks to the expressiveness and good libraries of Factor the code > won't be too long, I hope... > > Firstly, the primary goal is to normalize some unicode string. > Formating the result will make it more clear. And I also want to learn > the "Fried quotations". > So I use the three vocabularies: > > IN: scratchpad USING: unicode.normalize formatting fry ; > Loading resource:basis/formatting/formatting.factor > Loading resource:basis/formatting/formatting-docs.factor > > Then the implement it with correct stack effect declaration in "execute(" : > > IN: scratchpad : normalizations ( str -- norm ) > '[ _ swap execute( x -- x ) ] ! correct stack effect declaration > { nfc nfd nfkc nfkd } swap map ! normalize str with four methods > [ >array [ "U+%04X" sprintf ] map ] map ; ! make it more clear > > It gives me the expected results except the last two(but it maybe not > important to this question): > > IN: scratchpad "Factor" normalizations . > { > { "U+0046" "U+0061" "U+0063" "U+0074" "U+006F" "U+0072" } > { "U+0046" "U+0061" "U+0063" "U+0074" "U+006F" "U+0072" } > { "U+0046" "U+0061" "U+0063" "U+0074" "U+006F" "U+0072" } > { "U+0046" "U+0061" "U+0063" "U+0074" "U+006F" "U+0072" } > } > IN: scratchpad "\xF1" normalizations . > { > { "U+00F1" } > { "U+006E" "U+0303" } > { "U+00F1" } > { "U+006E" "U+0303" } > } > IN: scratchpad "\x6E\u000303" normalizations . > { > { "U+00F1" } > { "U+006E" "U+0303" } > { "U+00F1" } > { "U+006E" "U+0303" } > } > IN: scratchpad "\u01D160" normalizations . > { > { "U+1D158" "U+1D165" "U+1D16E" } > { "U+1D158" "U+1D165" "U+1D16E" } > { "U+1D158" "U+1D165" "U+1D16E" } > { "U+1D158" "U+1D165" "U+1D16E" } > } > IN: scratchpad "\u01D158\u01D165\u01D16E" normalizations . > { > { "U+1D158" "U+1D165" "U+1D16E" } > { "U+1D158" "U+1D165" "U+1D16E" } > { "U+1D158" "U+1D165" "U+1D16E" } > { "U+1D158" "U+1D165" "U+1D16E" } > } > > But with the wrong stack effect declaration(actually I use the wrong > declaration first and the correct one latter during the study): > > IN: scratchpad : normalizations ( str -- norm ) > '[ _ swap execute( -- ) ] ! wrong stack effect declaration > { nfc nfd nfkc nfkd } swap map > [ >array [ "U+%04X" sprintf ] map ] map ; > > The first case will pass: > > IN: scratchpad "Factor" normalizations . > { > { "U+0046" "U+0061" "U+0063" "U+0074" "U+006F" "U+0072" } > { "U+0046" "U+0061" "U+0063" "U+0074" "U+006F" "U+0072" } > { "U+0046" "U+0061" "U+0063" "U+0074" "U+006F" "U+0072" } > { "U+0046" "U+0061" "U+0063" "U+0074" "U+006F" "U+0072" } > } > > And the rest will get an error: > > IN: scratchpad "\xF1" normalizations . > Quotation's stack effect does not match call site > quot [ \ nfc execute ] > call-site ( -- ) > > Type :help for debugging help. > > The same thing will happen in "\x6E\u000303" "\u01D160" > "\u01D158\u01D165\u01D16E". > > I promise that I will not depend on this behaviour and will use the > correct stack effect declaration in real code. > I'm just curious that why "execute(" will check it in some cases but > won't in others? > > Thanks! > > ------------------------------------------------------------------------------ > Android is increasing in popularity, but the open development platform that > developers love is also attractive to malware creators. Download this white > paper to learn more about secure code signing practices that can help keep > Android apps secure. > http://pubads.g.doubleclick.net/gampad/clk?id=65839951&iu=/4140/ostg.clktrk > _______________________________________________ > Factor-talk mailing list > Factor-talk@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/factor-talk ------------------------------------------------------------------------------ Android is increasing in popularity, but the open development platform that developers love is also attractive to malware creators. Download this white paper to learn more about secure code signing practices that can help keep Android apps secure. http://pubads.g.doubleclick.net/gampad/clk?id=65839951&iu=/4140/ostg.clktrk _______________________________________________ Factor-talk mailing list Factor-talk@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/factor-talk