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

Reply via email to