A Solidity Linearization Puzzle

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
2
down vote

favorite












I was playing in remix just to concretize my understanding of Solidity linearization, and got a result I didn't expect and can't rationalize. Why does AC_BA.go() return 3?



(Please scroll to the bottom of the code below.)



pragma solidity ^0.4.24;

contract A
function go() public pure returns (uint out)
out = 1;


contract B
function go() public pure returns (uint out)
out = 2;


contract C
function go() public pure returns (uint out)
out = 3;



// returns 2 as expected
contract AB is A, B
function go() public pure returns (uint out)
out = super.go();



// returns 1 as expected
contract BA is B, A
function go() public pure returns (uint out)
out = super.go();



// returns 3 as expected
contract AC is A, C
function go() public pure returns (uint out)
out = super.go();



// refuses to compile, can't linearize, ok
//
// contact AC_A is AC, A
// function go() public pure returns (uint out)
// out = super.go();
//
//

// compiles, returns 2, from AB
contract AC_AB is AC, AB
function go() public pure returns (uint out)
out = super.go();



// compiles, returns 3, why???
contract AC_BA is AC, BA
function go() public pure returns (uint out)
out = super.go();








share|improve this question
























    up vote
    2
    down vote

    favorite












    I was playing in remix just to concretize my understanding of Solidity linearization, and got a result I didn't expect and can't rationalize. Why does AC_BA.go() return 3?



    (Please scroll to the bottom of the code below.)



    pragma solidity ^0.4.24;

    contract A
    function go() public pure returns (uint out)
    out = 1;


    contract B
    function go() public pure returns (uint out)
    out = 2;


    contract C
    function go() public pure returns (uint out)
    out = 3;



    // returns 2 as expected
    contract AB is A, B
    function go() public pure returns (uint out)
    out = super.go();



    // returns 1 as expected
    contract BA is B, A
    function go() public pure returns (uint out)
    out = super.go();



    // returns 3 as expected
    contract AC is A, C
    function go() public pure returns (uint out)
    out = super.go();



    // refuses to compile, can't linearize, ok
    //
    // contact AC_A is AC, A
    // function go() public pure returns (uint out)
    // out = super.go();
    //
    //

    // compiles, returns 2, from AB
    contract AC_AB is AC, AB
    function go() public pure returns (uint out)
    out = super.go();



    // compiles, returns 3, why???
    contract AC_BA is AC, BA
    function go() public pure returns (uint out)
    out = super.go();








    share|improve this question






















      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      I was playing in remix just to concretize my understanding of Solidity linearization, and got a result I didn't expect and can't rationalize. Why does AC_BA.go() return 3?



      (Please scroll to the bottom of the code below.)



      pragma solidity ^0.4.24;

      contract A
      function go() public pure returns (uint out)
      out = 1;


      contract B
      function go() public pure returns (uint out)
      out = 2;


      contract C
      function go() public pure returns (uint out)
      out = 3;



      // returns 2 as expected
      contract AB is A, B
      function go() public pure returns (uint out)
      out = super.go();



      // returns 1 as expected
      contract BA is B, A
      function go() public pure returns (uint out)
      out = super.go();



      // returns 3 as expected
      contract AC is A, C
      function go() public pure returns (uint out)
      out = super.go();



      // refuses to compile, can't linearize, ok
      //
      // contact AC_A is AC, A
      // function go() public pure returns (uint out)
      // out = super.go();
      //
      //

      // compiles, returns 2, from AB
      contract AC_AB is AC, AB
      function go() public pure returns (uint out)
      out = super.go();



      // compiles, returns 3, why???
      contract AC_BA is AC, BA
      function go() public pure returns (uint out)
      out = super.go();








      share|improve this question












      I was playing in remix just to concretize my understanding of Solidity linearization, and got a result I didn't expect and can't rationalize. Why does AC_BA.go() return 3?



      (Please scroll to the bottom of the code below.)



      pragma solidity ^0.4.24;

      contract A
      function go() public pure returns (uint out)
      out = 1;


      contract B
      function go() public pure returns (uint out)
      out = 2;


      contract C
      function go() public pure returns (uint out)
      out = 3;



      // returns 2 as expected
      contract AB is A, B
      function go() public pure returns (uint out)
      out = super.go();



      // returns 1 as expected
      contract BA is B, A
      function go() public pure returns (uint out)
      out = super.go();



      // returns 3 as expected
      contract AC is A, C
      function go() public pure returns (uint out)
      out = super.go();



      // refuses to compile, can't linearize, ok
      //
      // contact AC_A is AC, A
      // function go() public pure returns (uint out)
      // out = super.go();
      //
      //

      // compiles, returns 2, from AB
      contract AC_AB is AC, AB
      function go() public pure returns (uint out)
      out = super.go();



      // compiles, returns 3, why???
      contract AC_BA is AC, BA
      function go() public pure returns (uint out)
      out = super.go();










      share|improve this question











      share|improve this question




      share|improve this question










      asked Aug 18 at 5:54









      Steve Waldman

      1926




      1926




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          2
          down vote



          accepted










          Borrowing the notation from C3 linearization on Wikipedia, and keeping in mind that Solidity reverses the typical ordering ("You have to list the direct base contracts in the order from 'most base-like' to 'most derived'. Note that this order is different from the one used in Python."):



          L(AC) := [AC] + merge(L(C), L(A), [C, A])
          = [AC] + merge([C], [A], [C, A])
          = [AC, C] + merge([A], [A])
          = [AC, C, A]

          L(BA) := [BA] + merge(L(A), L(B), [A, B])
          = [BA] + merge([A], [B], [A, B])
          = [BA, A] + merge([B], [B])
          = [BA, A, B]

          L(AC_BA) := [AC_BA] + merge(L(BA), L(AC), [BA, AC])
          = [AC_BA] + merge([BA, A, B], [AC, C, A], [BA, AC])
          = [AC_BA, BA] + merge([A, B], [AC, C, A], [AC])
          = [AC_BA, BA, AC] + merge([A, B], [C, A])
          = [AC_BA, BA, AC, C] + merge([A, B], [A])
          = [AC_BA, BA, AC, C, A] + merge([B])
          = [AC_BA, BA, AC, C, A, B]


          So calling AC_BA.go() ends up calling C.go(), which returns 3. I don't have an intuitive explanation for you; this is just the behavior of the C3 linearization algorithm, which Solidity follows.



          EDIT



          The Solidity compiler can export an AST which includes the linearization of base contracts. A little Python can convert it into a readable form:



          import json
          import sys

          symbol_map =

          for source in json.load(sys.stdin)['sources'].values():
          for symbol, ids in source['AST']['attributes']['exportedSymbols'].items():
          for id in ids:
          symbol_map[id] = symbol

          for child in source['AST']['children']:
          attributes = child['attributes']
          if attributes.get('contractKind', None) == 'contract':
          print(': '.format(attributes['name'], ' -> '.join(symbol_map[id] for id in attributes['linearizedBaseContracts'])))


          How to run it:



          solc --combined-json ast test.sol | python3 linearization.py


          Output:



          A: A
          B: B
          C: C
          AB: AB -> B -> A
          BA: BA -> A -> B
          AC: AC -> C -> A
          AC_AB: AC_AB -> AB -> B -> AC -> C -> A
          AC_BA: AC_BA -> BA -> AC -> C -> A -> B


          When you call AC_BA.go(), that calls BA.go(), which in turn calls AC.go() and finally C.go() (returning 3).



          EDIT 2



          Surya is a handy tool that will show contract inheritance in linearized order.



          $ surya dependencies AC_BA test.sol
          AC_BA
          ↖ BA
          ↖ AC
          ↖ C
          ↖ A
          ↖ B





          share|improve this answer






















          • Given the potential costs of misunderstanding the linearization of ones contracts, and the not-so-intuitive outcomes, it'd be nice if solc emitted the linearization it settles upon. Is there any way to get that?
            – Steve Waldman
            Aug 19 at 20:33










          • Edited my answer. The first part was actually wrong (forgot that Solidity reverses the typical order of base classes), and I added the second part which shows how to get the Solidity compiler to tell you the linearization.
            – smarx
            Aug 19 at 21:15










          • Thanks! (That makes a lot more sense, I was a bit confused about the prior ordering, but thought it was on me to puzzle that out.) I'll try Surya.
            – Steve Waldman
            Aug 19 at 21:25











          Your Answer







          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "642"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fethereum.stackexchange.com%2fquestions%2f56802%2fa-solidity-linearization-puzzle%23new-answer', 'question_page');

          );

          Post as a guest






























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          2
          down vote



          accepted










          Borrowing the notation from C3 linearization on Wikipedia, and keeping in mind that Solidity reverses the typical ordering ("You have to list the direct base contracts in the order from 'most base-like' to 'most derived'. Note that this order is different from the one used in Python."):



          L(AC) := [AC] + merge(L(C), L(A), [C, A])
          = [AC] + merge([C], [A], [C, A])
          = [AC, C] + merge([A], [A])
          = [AC, C, A]

          L(BA) := [BA] + merge(L(A), L(B), [A, B])
          = [BA] + merge([A], [B], [A, B])
          = [BA, A] + merge([B], [B])
          = [BA, A, B]

          L(AC_BA) := [AC_BA] + merge(L(BA), L(AC), [BA, AC])
          = [AC_BA] + merge([BA, A, B], [AC, C, A], [BA, AC])
          = [AC_BA, BA] + merge([A, B], [AC, C, A], [AC])
          = [AC_BA, BA, AC] + merge([A, B], [C, A])
          = [AC_BA, BA, AC, C] + merge([A, B], [A])
          = [AC_BA, BA, AC, C, A] + merge([B])
          = [AC_BA, BA, AC, C, A, B]


          So calling AC_BA.go() ends up calling C.go(), which returns 3. I don't have an intuitive explanation for you; this is just the behavior of the C3 linearization algorithm, which Solidity follows.



          EDIT



          The Solidity compiler can export an AST which includes the linearization of base contracts. A little Python can convert it into a readable form:



          import json
          import sys

          symbol_map =

          for source in json.load(sys.stdin)['sources'].values():
          for symbol, ids in source['AST']['attributes']['exportedSymbols'].items():
          for id in ids:
          symbol_map[id] = symbol

          for child in source['AST']['children']:
          attributes = child['attributes']
          if attributes.get('contractKind', None) == 'contract':
          print(': '.format(attributes['name'], ' -> '.join(symbol_map[id] for id in attributes['linearizedBaseContracts'])))


          How to run it:



          solc --combined-json ast test.sol | python3 linearization.py


          Output:



          A: A
          B: B
          C: C
          AB: AB -> B -> A
          BA: BA -> A -> B
          AC: AC -> C -> A
          AC_AB: AC_AB -> AB -> B -> AC -> C -> A
          AC_BA: AC_BA -> BA -> AC -> C -> A -> B


          When you call AC_BA.go(), that calls BA.go(), which in turn calls AC.go() and finally C.go() (returning 3).



          EDIT 2



          Surya is a handy tool that will show contract inheritance in linearized order.



          $ surya dependencies AC_BA test.sol
          AC_BA
          ↖ BA
          ↖ AC
          ↖ C
          ↖ A
          ↖ B





          share|improve this answer






















          • Given the potential costs of misunderstanding the linearization of ones contracts, and the not-so-intuitive outcomes, it'd be nice if solc emitted the linearization it settles upon. Is there any way to get that?
            – Steve Waldman
            Aug 19 at 20:33










          • Edited my answer. The first part was actually wrong (forgot that Solidity reverses the typical order of base classes), and I added the second part which shows how to get the Solidity compiler to tell you the linearization.
            – smarx
            Aug 19 at 21:15










          • Thanks! (That makes a lot more sense, I was a bit confused about the prior ordering, but thought it was on me to puzzle that out.) I'll try Surya.
            – Steve Waldman
            Aug 19 at 21:25















          up vote
          2
          down vote



          accepted










          Borrowing the notation from C3 linearization on Wikipedia, and keeping in mind that Solidity reverses the typical ordering ("You have to list the direct base contracts in the order from 'most base-like' to 'most derived'. Note that this order is different from the one used in Python."):



          L(AC) := [AC] + merge(L(C), L(A), [C, A])
          = [AC] + merge([C], [A], [C, A])
          = [AC, C] + merge([A], [A])
          = [AC, C, A]

          L(BA) := [BA] + merge(L(A), L(B), [A, B])
          = [BA] + merge([A], [B], [A, B])
          = [BA, A] + merge([B], [B])
          = [BA, A, B]

          L(AC_BA) := [AC_BA] + merge(L(BA), L(AC), [BA, AC])
          = [AC_BA] + merge([BA, A, B], [AC, C, A], [BA, AC])
          = [AC_BA, BA] + merge([A, B], [AC, C, A], [AC])
          = [AC_BA, BA, AC] + merge([A, B], [C, A])
          = [AC_BA, BA, AC, C] + merge([A, B], [A])
          = [AC_BA, BA, AC, C, A] + merge([B])
          = [AC_BA, BA, AC, C, A, B]


          So calling AC_BA.go() ends up calling C.go(), which returns 3. I don't have an intuitive explanation for you; this is just the behavior of the C3 linearization algorithm, which Solidity follows.



          EDIT



          The Solidity compiler can export an AST which includes the linearization of base contracts. A little Python can convert it into a readable form:



          import json
          import sys

          symbol_map =

          for source in json.load(sys.stdin)['sources'].values():
          for symbol, ids in source['AST']['attributes']['exportedSymbols'].items():
          for id in ids:
          symbol_map[id] = symbol

          for child in source['AST']['children']:
          attributes = child['attributes']
          if attributes.get('contractKind', None) == 'contract':
          print(': '.format(attributes['name'], ' -> '.join(symbol_map[id] for id in attributes['linearizedBaseContracts'])))


          How to run it:



          solc --combined-json ast test.sol | python3 linearization.py


          Output:



          A: A
          B: B
          C: C
          AB: AB -> B -> A
          BA: BA -> A -> B
          AC: AC -> C -> A
          AC_AB: AC_AB -> AB -> B -> AC -> C -> A
          AC_BA: AC_BA -> BA -> AC -> C -> A -> B


          When you call AC_BA.go(), that calls BA.go(), which in turn calls AC.go() and finally C.go() (returning 3).



          EDIT 2



          Surya is a handy tool that will show contract inheritance in linearized order.



          $ surya dependencies AC_BA test.sol
          AC_BA
          ↖ BA
          ↖ AC
          ↖ C
          ↖ A
          ↖ B





          share|improve this answer






















          • Given the potential costs of misunderstanding the linearization of ones contracts, and the not-so-intuitive outcomes, it'd be nice if solc emitted the linearization it settles upon. Is there any way to get that?
            – Steve Waldman
            Aug 19 at 20:33










          • Edited my answer. The first part was actually wrong (forgot that Solidity reverses the typical order of base classes), and I added the second part which shows how to get the Solidity compiler to tell you the linearization.
            – smarx
            Aug 19 at 21:15










          • Thanks! (That makes a lot more sense, I was a bit confused about the prior ordering, but thought it was on me to puzzle that out.) I'll try Surya.
            – Steve Waldman
            Aug 19 at 21:25













          up vote
          2
          down vote



          accepted







          up vote
          2
          down vote



          accepted






          Borrowing the notation from C3 linearization on Wikipedia, and keeping in mind that Solidity reverses the typical ordering ("You have to list the direct base contracts in the order from 'most base-like' to 'most derived'. Note that this order is different from the one used in Python."):



          L(AC) := [AC] + merge(L(C), L(A), [C, A])
          = [AC] + merge([C], [A], [C, A])
          = [AC, C] + merge([A], [A])
          = [AC, C, A]

          L(BA) := [BA] + merge(L(A), L(B), [A, B])
          = [BA] + merge([A], [B], [A, B])
          = [BA, A] + merge([B], [B])
          = [BA, A, B]

          L(AC_BA) := [AC_BA] + merge(L(BA), L(AC), [BA, AC])
          = [AC_BA] + merge([BA, A, B], [AC, C, A], [BA, AC])
          = [AC_BA, BA] + merge([A, B], [AC, C, A], [AC])
          = [AC_BA, BA, AC] + merge([A, B], [C, A])
          = [AC_BA, BA, AC, C] + merge([A, B], [A])
          = [AC_BA, BA, AC, C, A] + merge([B])
          = [AC_BA, BA, AC, C, A, B]


          So calling AC_BA.go() ends up calling C.go(), which returns 3. I don't have an intuitive explanation for you; this is just the behavior of the C3 linearization algorithm, which Solidity follows.



          EDIT



          The Solidity compiler can export an AST which includes the linearization of base contracts. A little Python can convert it into a readable form:



          import json
          import sys

          symbol_map =

          for source in json.load(sys.stdin)['sources'].values():
          for symbol, ids in source['AST']['attributes']['exportedSymbols'].items():
          for id in ids:
          symbol_map[id] = symbol

          for child in source['AST']['children']:
          attributes = child['attributes']
          if attributes.get('contractKind', None) == 'contract':
          print(': '.format(attributes['name'], ' -> '.join(symbol_map[id] for id in attributes['linearizedBaseContracts'])))


          How to run it:



          solc --combined-json ast test.sol | python3 linearization.py


          Output:



          A: A
          B: B
          C: C
          AB: AB -> B -> A
          BA: BA -> A -> B
          AC: AC -> C -> A
          AC_AB: AC_AB -> AB -> B -> AC -> C -> A
          AC_BA: AC_BA -> BA -> AC -> C -> A -> B


          When you call AC_BA.go(), that calls BA.go(), which in turn calls AC.go() and finally C.go() (returning 3).



          EDIT 2



          Surya is a handy tool that will show contract inheritance in linearized order.



          $ surya dependencies AC_BA test.sol
          AC_BA
          ↖ BA
          ↖ AC
          ↖ C
          ↖ A
          ↖ B





          share|improve this answer














          Borrowing the notation from C3 linearization on Wikipedia, and keeping in mind that Solidity reverses the typical ordering ("You have to list the direct base contracts in the order from 'most base-like' to 'most derived'. Note that this order is different from the one used in Python."):



          L(AC) := [AC] + merge(L(C), L(A), [C, A])
          = [AC] + merge([C], [A], [C, A])
          = [AC, C] + merge([A], [A])
          = [AC, C, A]

          L(BA) := [BA] + merge(L(A), L(B), [A, B])
          = [BA] + merge([A], [B], [A, B])
          = [BA, A] + merge([B], [B])
          = [BA, A, B]

          L(AC_BA) := [AC_BA] + merge(L(BA), L(AC), [BA, AC])
          = [AC_BA] + merge([BA, A, B], [AC, C, A], [BA, AC])
          = [AC_BA, BA] + merge([A, B], [AC, C, A], [AC])
          = [AC_BA, BA, AC] + merge([A, B], [C, A])
          = [AC_BA, BA, AC, C] + merge([A, B], [A])
          = [AC_BA, BA, AC, C, A] + merge([B])
          = [AC_BA, BA, AC, C, A, B]


          So calling AC_BA.go() ends up calling C.go(), which returns 3. I don't have an intuitive explanation for you; this is just the behavior of the C3 linearization algorithm, which Solidity follows.



          EDIT



          The Solidity compiler can export an AST which includes the linearization of base contracts. A little Python can convert it into a readable form:



          import json
          import sys

          symbol_map =

          for source in json.load(sys.stdin)['sources'].values():
          for symbol, ids in source['AST']['attributes']['exportedSymbols'].items():
          for id in ids:
          symbol_map[id] = symbol

          for child in source['AST']['children']:
          attributes = child['attributes']
          if attributes.get('contractKind', None) == 'contract':
          print(': '.format(attributes['name'], ' -> '.join(symbol_map[id] for id in attributes['linearizedBaseContracts'])))


          How to run it:



          solc --combined-json ast test.sol | python3 linearization.py


          Output:



          A: A
          B: B
          C: C
          AB: AB -> B -> A
          BA: BA -> A -> B
          AC: AC -> C -> A
          AC_AB: AC_AB -> AB -> B -> AC -> C -> A
          AC_BA: AC_BA -> BA -> AC -> C -> A -> B


          When you call AC_BA.go(), that calls BA.go(), which in turn calls AC.go() and finally C.go() (returning 3).



          EDIT 2



          Surya is a handy tool that will show contract inheritance in linearized order.



          $ surya dependencies AC_BA test.sol
          AC_BA
          ↖ BA
          ↖ AC
          ↖ C
          ↖ A
          ↖ B






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Aug 19 at 21:28

























          answered Aug 18 at 6:29









          smarx

          15.8k1515




          15.8k1515











          • Given the potential costs of misunderstanding the linearization of ones contracts, and the not-so-intuitive outcomes, it'd be nice if solc emitted the linearization it settles upon. Is there any way to get that?
            – Steve Waldman
            Aug 19 at 20:33










          • Edited my answer. The first part was actually wrong (forgot that Solidity reverses the typical order of base classes), and I added the second part which shows how to get the Solidity compiler to tell you the linearization.
            – smarx
            Aug 19 at 21:15










          • Thanks! (That makes a lot more sense, I was a bit confused about the prior ordering, but thought it was on me to puzzle that out.) I'll try Surya.
            – Steve Waldman
            Aug 19 at 21:25

















          • Given the potential costs of misunderstanding the linearization of ones contracts, and the not-so-intuitive outcomes, it'd be nice if solc emitted the linearization it settles upon. Is there any way to get that?
            – Steve Waldman
            Aug 19 at 20:33










          • Edited my answer. The first part was actually wrong (forgot that Solidity reverses the typical order of base classes), and I added the second part which shows how to get the Solidity compiler to tell you the linearization.
            – smarx
            Aug 19 at 21:15










          • Thanks! (That makes a lot more sense, I was a bit confused about the prior ordering, but thought it was on me to puzzle that out.) I'll try Surya.
            – Steve Waldman
            Aug 19 at 21:25
















          Given the potential costs of misunderstanding the linearization of ones contracts, and the not-so-intuitive outcomes, it'd be nice if solc emitted the linearization it settles upon. Is there any way to get that?
          – Steve Waldman
          Aug 19 at 20:33




          Given the potential costs of misunderstanding the linearization of ones contracts, and the not-so-intuitive outcomes, it'd be nice if solc emitted the linearization it settles upon. Is there any way to get that?
          – Steve Waldman
          Aug 19 at 20:33












          Edited my answer. The first part was actually wrong (forgot that Solidity reverses the typical order of base classes), and I added the second part which shows how to get the Solidity compiler to tell you the linearization.
          – smarx
          Aug 19 at 21:15




          Edited my answer. The first part was actually wrong (forgot that Solidity reverses the typical order of base classes), and I added the second part which shows how to get the Solidity compiler to tell you the linearization.
          – smarx
          Aug 19 at 21:15












          Thanks! (That makes a lot more sense, I was a bit confused about the prior ordering, but thought it was on me to puzzle that out.) I'll try Surya.
          – Steve Waldman
          Aug 19 at 21:25





          Thanks! (That makes a lot more sense, I was a bit confused about the prior ordering, but thought it was on me to puzzle that out.) I'll try Surya.
          – Steve Waldman
          Aug 19 at 21:25













           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fethereum.stackexchange.com%2fquestions%2f56802%2fa-solidity-linearization-puzzle%23new-answer', 'question_page');

          );

          Post as a guest













































































          這個網誌中的熱門文章

          How to combine Bézier curves to a surface?

          Mutual Information Always Non-negative

          Why am i infinitely getting the same tweet with the Twitter Search API?