Hi, Vondrak. My original goal is to have a try on "unicode.normalize" vocab. And after simply did `"factor" nfc .`, `"unicode" nfd .`, etc. I wanted to find some ways: * to make the output more clear, i.e. show the numerical value in hexadecimal format of each character in a string * to apply each function in a sequence to a value(no Factor term here, because I don't know it...) as opposite to apply a function to each value in a sequence.
I(as a novice) didn't know which one is good(idiomatic) or bad(verbose, complex, shouldn't be depended on, should be avoid expect in special case, etc.). I just try hard to find many possible ways to reach my goals. As a example which didn't appear in the original post, `{ nfc } [ ] each` was the only way for me to leave a word on the stack before I knew `\ nfc ` ... So pretty thanks for the following suggestions which are not so obvious to a beginner! `"clear it" [ "U+%04X" sprintf ] { } map-as .` is exactly what I looked for and `"clear it" >array [ "U+%04X" sprintf ] map .` was what I found at that time. For applying many functions to the same value(still, in applicative term), I found a way: `{ [ abs ] [ neg ] } [ 1 swap call ] map .` . And then I found a way to omit the quotation: `{ abs neg } [ 1 swap execute ] map .` And finally, I discovered the different behaviours about "execute(" and posted it to here to find some helps. Also, `"norm" { [ nfc ] [ nfd ] [ nfkc ] [ nfkd ] } cleave 4array .` is better because: * "call" and "execute" should be avoid in normal use * "Applies each quotation to the object in turn." is said in http://docs.factorcode.org/content/word-cleave,combinators.html However, how to do it when I don't know the exact length of the array? Is `"norm" { [ nfc ] [ nfd ] [ nfkc ] [ nfkd ] } [ cleave ] keep length narray .` idiomatic? For the deep investigation part, both in here and in the issue list on github(thanks for posting it Benediktsson!), it is informative and also helpful. I can't say that I understands it fully and I need more time to digest it. But I still have learned a lot from it: the slot, the meaning of stack-effect in the VM point of view, and especially the `infer` word in the smaller example posted in github. Thanks! On Thu, Oct 31, 2013 at 10:46 AM, Alex Vondrak <ajvond...@gmail.com> wrote: > 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 ------------------------------------------------------------------------------ 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