문제

As far as I know recursion is very elegant but unefficient in OOP and procedural programming (see the wonderful "High Order perl", Mark Jason Dominus). I had some informations that in functional programming recursion is fast - keeping its elegance and simplicity. Could someone confirm and possibly amplify this? I am thinking in terms of XSLT and Haskell (high on my next-language-to-learn list)

Thanks

Daniel

도움이 되었습니까?

해결책

Tail recursion is iteration in any decent functional language implementation. Here's an example using GHC Haskell. A simple program to add a sequence of numbers. It begins as the composition of several recursive functions:

import qualified Data.Vector as U

main = print (U.sum (U.enumFromTo 1 (10000000 :: Int)))

Which the compiler optimizes into a single tail recursive function (in a source-to-source transformation):

loop x y = case y <= y 10000000 of
      False -> x
      True  -> loop (x + y) (y + 1)

This recursive function is then compiled into a straight forward loop:

loop:
    .Lc216:
            cmpq $10000000,%rsi
            jle .Lc219
            movq %r14,%rbx
            movq (%rbp),%rax
            jmp *(%rax)
    .Lc219:
            addq %rsi,%r14
            incq %rsi
            jmp loop

Or with the GHC LLVM backend, additional optimizations are applied to the imperative representation of the program:

    loop:
        leaq    1(%rsi), %rax
        addq    %rsi, %r14
        cmpq    $10000001, %rax
        jge     .LBB1_5
        addq    $2, %rsi
        addq    %rax, %r14
    test:                                # %tailrecurse
        cmpq    $10000001, %rsi
        jl      loop

Note how the tail recursive label is tagged.

So we had a pipeline of recursive functions, which were compiled to a single tail recursive function, which was compiled to a single imperative loop using no stack. And 8 instructions in the end.

And that is why both function composition, and recursion, are extremely efficient in good, optimizing function languages.

다른 팁

OOP/Procedural languages tend to place data on the stack each time a recursive call is made - thus recursion is not as efficient as iteration in these languages.

By contrast, compilers/interpreters for functional languages are typically designed to optimize tail recursion to be as efficient as iteration:

Recursion may require maintaining a stack, but tail recursion can be recognized and optimized by a compiler into the same code used to implement iteration in imperative languages. The Scheme programming language standard requires implementations to recognize and optimize tail recursion. Tail recursion optimization can be implemented by transforming the program into continuation passing style during compilation, among other approaches.

what-is-tail-call-optimization and which-languages-support-tail-recursion-optimization have more detailed information.

If the compiler in use supports the tail call optimization and you structure your code to take advantage of it, recursion isn't inefficient.

Due to the prevelance of recursion in functional programming, compilers for functional languages are more likely to implement the tail call optimization that procedural ones.

Efficient recursion in XSLT

There are two main ways to achieve efficient recursion in XSLT:

  1. Tail-recursion optimization
  2. Divide and Conquer (DVC)

There are a lot of answers covering tail recursion, so here's just a simple example:

  <xsl:function name="my:sum">
   <xsl:param name="pAccum" as="xs:double*"/>
   <xsl:param name="pNums" as="xs:double*"/>

   <xsl:sequence select=
     "if(empty($pNums))
        then $pAccum
        else
           my:sum($pAccum + $pNums[1], $pNums[position() >1])
     "
   />
 </xsl:function>

One can check that my:sum(0, 1 to 100) is evaluated to: 5050.

Here is how one would implement the sum() function in a DVC way:

  <xsl:function name="my:sum2">
      <xsl:param name="pNums" as="xs:double*"/>

      <xsl:sequence select=
        "if(empty($pNums))
          then 0
          else
            if(count($pNums) eq 1)
              then $pNums[1]
              else
                for $half in count($pNums) idiv 2
                  return
                    my:sum2($pNums[not(position() gt $half)]) 
                   + 
                    my:sum2($pNums[position() gt $half])

        "
      />
  </xsl:function>

The main idea behind DVC is to subdivide the input sequence into two (usually) or more parts and to process them independently from one another, then to combine the results in order to produce the result for the total input sequence.

Note that for a sequence of N items, the maximum depth of the call stack at any point od time would not exceed log2(N), which is more than enough for most practical purposes. For example, the maximum depth of the call stack when processing a sequence of 1000000 (1M) items, would be only 19.

While there are some XSLT processors that are not smart enough to recognize and optimize tail-recursion, a DVC-recursive template works on any XSLT processor.

나는 다음을 사용하고 태그의 수를 얻었습니다

var tags = xdoc.Descendants(z + "row")
                                        .Select(r => (string)r.Attribute("ows_Article_x0020_Tags"));
                        // Join all the tags to form a string
                         string result = String.Join("", tags);
                        //Remove id's of the tags from the string
                         result = Regex.Replace(result, @"\d", "");   
                        //remove special characters from the string to get a list of tags               
                        var  tagTokens = result.Split(new string[]{";#"},StringSplitOptions.RemoveEmptyEntries).ToList();
                        //Get the count of each tag being used in the list
                        var tokenGroups = tagTokens.GroupBy(token => token).ToDictionary(token=> token.Key, tokenval=>tokenval.Count());
.

If the language isn't optimized by the compiler, recursion is very likely to be slower than iteration, because on top of descending down given lane, which is pretty much equivalent to iteration, you have to backtrace your steps back to top upon finishing the job.

Otherwise, it is pretty much equivalent, except it may be much more elegant, as you let the compiler and system handle the loop behind the scenes. And of course there are tasks (like processing tree-like structures) where recursion is the only way (or at least the only that isn't hopelessly convoluted).

다음 오류가 나타납니다.

라인 2에서는 $customcss에 자원을 넣습니다 ( 설명서 ).그런 다음 비위임 인 문자열 (3 행)을 추가하려고했습니다.따라서 2 번에서 var를 변경하십시오.

코드를 통해 할 수 있습니다 :

예 :

SPList list = web.Lists["My List"];
list.EnableVersioning = true;
.

목록을 만드는 경우 위의 코드에 간단히 추가 할 수 있습니다.

somthing lines :

//get web object from context
SPWeb web = SPContext.Current.Web;
//get list collection
SPListCollection lists = Web.Lists;
//add list to list collection
lists.Add("My List", "My list for user input form", SPListTemplateType.GenericList);
//call list that we just made
SPList newMyList = Web.Lists["My List"];
//enable versioning on that list
newMyList.EnableVersioning = true;
.

http://msdn.microsoft.com/en-us/library. /microsoft.sharepoint.splist.enableVersioning.aspx

편집

나는 당신을 얻습니다! VS2012를 사용하여 목록을 추가 할 때 목록의 XML (element.xml) :

<ListInstance 
  CustomSchema = string
  Description = "Text"
  DocumentTemplate = integer
  FeatureId = "Text"
  Hidden = "TRUE" | "FALSE"
  HyperlinkBaseUrl = string
  Id = Text
  OnQuickLaunch = "TRUE" | "FALSE"
  QuickLaunchUrl = "Text"
  RootWebOnly = "TRUE" | "FALSE"
  TemplateType = Integer
  Title = "Text"
  Url = "Text"
  VersioningEnabled = "TRUE" | "FALSE"
</ListInstance>
.

목록 elements.xml 목록에 추가됩니다. ListInstance에서 VersionInstance를 볼 수 있으므로 다음과 같이 추가합니다. versioningEnabled= true 및 버전 관리가 해당 사용자 정의 목록에 사용됩니다.

주요 개념과 동일한 개념 인 주요 버전의 경우 :

http://msdn.microsoft.com/en-us/library/office/ms415091. .aspx

<List
  BaseType = "Integer" | "Text"
  Default = "TRUE" | "FALSE"
  DefaultItemOpen = "Integer"
  Description = "Text"
  Direction = "Text"
  DisableAttachments = "TRUE" | "FALSE"
  DraftVersionVisibility = "Integer"
  EnableContentTypes = "TRUE" | "FALSE"  EnableMinorVersions = "TRUE" | "FALSE"  EnableThumbnails = "TRUE" | "FALSE"
  EventSinkAssembly = "Text"
  EventSinkClass = "Text"
  EventSinkData = "Text"
  FolderCreation = "TRUE" | "FALSE"
  Id = "GUID"
  ModeratedList = "TRUE" | "FALSE"
  ModerationType = "TRUE" | "FALSE"
  Name = "Text"
  OrderedList = "TRUE" | "FALSE"
  PrivateList = "TRUE" | "FALSE"
  QuickLaunchUrl = "URL"
  RootWebOnly = "TRUE" | "FALSE"
  ThumbnailSize = "Integer"
  Title = "Text"
  Type = "Integer"
  Url = "URL"
  URLEncode = "TRUE" | "FALSE"
  VersioningEnabled = "TRUE" | "FALSE" 
  WebImageHeight = "Integer"
  WebImageWidth = "Integer">
</List>
.

elements.xml 목록에 속한 schema.xml에 위의 사항을 추가합니다.

http://msdn.microsoft.com/en-us/library/office/ms459356. .aspx

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top