рд╕рд░рд▓рддрд╛ рдХреА рдЬрдЯрд┐рд▓рддрд╛


рдЬреИрд╕рд╛ рдХрд┐ рдореИрдВрдиреЗ рдкрд┐рдЫрд▓реЗ рд▓реЗрдЦ рдХреА рдкреНрд░рд╕реНрддрд╛рд╡рдирд╛ рдореЗрдВ рд▓рд┐рдЦрд╛ рд╣реИ, рдореИрдВ рдПрдХ рдРрд╕реА рднрд╛рд╖рд╛ рдХреА рддрд▓рд╛рд╢ рдореЗрдВ рд╣реВрдВ, рдЬрд┐рд╕рдореЗрдВ рдореИрдВ рдХрдо рд▓рд┐рдЦ рд╕рдХреВрдВ рдФрд░ рдЕрдзрд┐рдХ рд╕реБрд░рдХреНрд╖рд╛ рд╣реЛред рдореЗрд░реА рдореБрдЦреНрдп рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рд╣рдореЗрд╢рд╛ рд╕реА # рд░рд╣реА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рджреЛ рднрд╛рд╖рд╛рдУрдВ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рдЬреЛ рдЬрдЯрд┐рд▓рддрд╛ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╕рдордорд┐рдд рд░реВрдк рд╕реЗ рдЕрд▓рдЧ рд╣реИрдВ, рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдХреЗрд╡рд▓ рдкрд╣рд▓реЗ рд╣реА рд╕реБрдирд╛ рдерд╛, рд▓реЗрдХрд┐рди рдореИрдВ рдирд╣реАрдВ рд▓рд┐рдЦ рд╕рдХрд╛: рд╣рд╛рд╕реНрдХреЗрд▓ рдФрд░ рдЧреЛред рдПрдХ рднрд╛рд╖рд╛ рдпрд╣ рдХрд╣рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╕рд┐рджреНрдз рд╣реЛ рдЧрдИ рдХрд┐ "рд╣рд░ рдХреАрдордд рдкрд░ рд╕рдлрд▓рддрд╛ рд╕реЗ рдмрдЪреЗрдВ" *, рдЬрдмрдХрд┐ рджреВрд╕рд░рд╛, рдореЗрд░реА рд╡рд┐рдирдореНрд░ рд░рд╛рдп рдореЗрдВ, рдЗрд╕рдХрд╛ рдкреВрд░реНрдг рд╡рд┐рдкрд░реАрдд рд╣реИред рдЕрдВрдд рдореЗрдВ, рдореИрдВ рдпрд╣ рд╕рдордЭрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рдХреНрдпрд╛ рдмреЗрд╣рддрд░ рд╣реЛрдЧрд╛: рдЬрд╛рдирдмреВрдЭрдХрд░ рд╕рд╛рджрдЧреА рдпрд╛ рдЬрд╛рдирдмреВрдЭрдХрд░ рдХрдареЛрд░рддрд╛?


рдореИрдВрдиреЗ рдПрдХ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рдорд╛рдзрд╛рди рд▓рд┐рдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рдФрд░ рдпрд╣ рджреЗрдЦрд╛ рдХрд┐ рджреЛрдиреЛрдВ рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рдпрд╣ рдХрд┐рддрдирд╛ рдЖрд╕рд╛рди рд╣реИ, рдЕрдиреБрднрд╡ рдХреЗ рд╕рд╛рде рдПрдХ рдбреЗрд╡рд▓рдкрд░ рдХреЗ рд▓рд┐рдП рдЙрдирдХреА рд╕реАрдЦрдиреЗ рдХреА рдЕрд╡рд╕реНрдерд╛ рдХреНрдпрд╛ рд╣реИ, рдЗрд╕рдХреЗ рд▓рд┐рдП рдХрд┐рддрдирд╛ рдЕрдзреНрдпрдпрди рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдПрдХ рдФрд░ рджреВрд╕рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ "рдиреМрд╕рд┐рдЦрд┐рдпрд╛" рдХреЛрдб рдХрд┐рддрдирд╛ рдореБрд╣рд╛рд╡рд░рд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдореИрдВ рдпрд╣ рд╕рдордЭрдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдХрд┐ рд╣рд╛рд╕реНрдХреЗрд▓ рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдЦрд┐рд░рдХрд╛рд░ рдореБрдЭреЗ рдХрд┐рддрдирд╛ рднреБрдЧрддрд╛рди рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдФрд░ рдХрд┐рддрдирд╛ рд╕рдордп рдЧреЛрд░реЛрдирд╛рдЗрдЯреНрд╕ рдХреА рдкреНрд░рд╕рд┐рджреНрдз рд╕реБрд╡рд┐рдзрд╛ рдХреЛ рдмрдЪрд╛рдПрдЧрд╛ред рдореИрдВрдиреЗ рдпрдерд╛рд╕рдВрднрд╡ рдирд┐рд╖реНрдкрдХреНрд╖ рд░рд╣рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА, рдФрд░ рдореИрдВ рд▓реЗрдЦ рдХреЗ рдЕрдВрдд рдореЗрдВ рдПрдХ рд╡реНрдпрдХреНрддрд┐рдкрд░рдХ рд░рд╛рдп рджреВрдВрдЧрд╛ред рдЕрдВрддрд┐рдо рдкрд░рд┐рдгрд╛рдореЛрдВ рдиреЗ рдореБрдЭреЗ рдмрд╣реБрдд рдЖрд╢реНрдЪрд░реНрдпрдЪрдХрд┐рдд рдХрд┐рдпрд╛, рдЗрд╕рд▓рд┐рдП рдореИрдВрдиреЗ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рдХрд┐ рдЦрд╛рдмрд░реЛрд╡рд╕реНрдХ рдирд╛рдЧрд░рд┐рдХреЛрдВ рдХреЗ рд▓рд┐рдП рдЗрд╕ рддрд░рд╣ рдХреА рддреБрд▓рдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрдврд╝рдирд╛ рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛрдЧрд╛ред




рдФрд░ рддреБрд░рдВрдд рдПрдХ рдЫреЛрдЯреА рд╕реА рдЯрд┐рдкреНрдкрдгреАред рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ (*) рдЕрдХреНрд╕рд░ рд╡рд┐рдбрдВрдмрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдХреЗрд╡рд▓ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рд▓реЛрдЧ рдЗрд╕реЗ рдЧрд▓рдд рддрд░реАрдХреЗ рд╕реЗ рдкрд╛рд░реНрд╕ рдХрд░рддреЗ рд╣реИрдВред рд╡реЗ рдЗрд╕реЗ "рдмрдЪрдиреЗ (рд╕рдлрд▓рддрд╛) (рд╣рд░ рдХреАрдордд рдкрд░)" рдХреЗ рд░реВрдк рдореЗрдВ рдкрдврд╝рддреЗ рд╣реИрдВ, "," рдХреЛрдИ рдлрд░реНрдХ рдирд╣реАрдВ рдкрдбрд╝рддрд╛ рдХрд┐ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ, рдЕрдЧрд░ рдпрд╣ рд╕рдлрд▓рддрд╛ рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рдЗрд╕рд╕реЗ рдмрдЪрдирд╛ рдЪрд╛рд╣рд┐рдП, "рдЬрдмрдХрд┐ рдЕрд╕рд▓реА рд╡рд╛рдХреНрдпрд╛рдВрд╢" рд╕реЗ рдмрдЪреЗрдВ (рд╕рдлрд▓рддрд╛ рдмрд┐рд▓реНрдХреБрд▓) рд▓рд╛рдЧрдд) ", рдЕрд░реНрдерд╛рдд," рдпрджрд┐ рд╕рдлрд▓рддрд╛ рдХреА рдХреАрдордд рдмрд╣реБрдд рдЕрдзрд┐рдХ рд╣реИ, рддреЛ рд╣рдореЗрдВ рд╡рд╛рдкрд╕ рдХрджрдо рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рд╕рдм рдХреБрдЫ рдкреБрдирд░реНрд╡рд┐рдЪрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдПред " рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЗрд╕ рд╕реНрдкрд╖реНрдЯреАрдХрд░рдг рдХреЗ рдмрд╛рдж рдпрд╣ рд╣рд╛рд╕реНрдпрд╛рд╕реНрдкрдж рд╣реЛ рдЧрдпрд╛ рдФрд░ рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЕрд░реНрде рдорд┐рд▓рд╛: рднрд╛рд╖рд╛ рдХреА рд╡рд┐рдЪрд╛рд░рдзрд╛рд░рд╛ рдХреЛ рдЖрдкрдХреЗ рдЖрд╡реЗрджрди рдХреА рдЙрдЪрд┐рдд рдпреЛрдЬрдирд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдФрд░ рдПрдбрд╣реЙрдХ рдмреИрд╕рд╛рдЦреА рди рдбрд╛рд▓реЗрдВ рдЬрд╣рд╛рдВ рдЙрдирдХреА рдмрд╣реБрдд рдЕрдзрд┐рдХ рд▓рд╛рдЧрдд рд╣реИред рдЧреЛ рдХреА рд╡рд┐рдЪрд╛рд░рдзрд╛рд░рд╛, рдмрджрд▓реЗ рдореЗрдВ, "рдХреЛрдб рдкрд░реНрдпрд╛рдкреНрдд рд╕рд░рд▓ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рддрд╛рдХрд┐ рдмрджрд▓рддреА рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЗрд╕реЗ рдлреЗрдВрдХрдирд╛ рдФрд░ рдПрдХ рдирдпрд╛ рд▓рд┐рдЦрдирд╛ рдЖрд╕рд╛рди рд╣реЛ рд╕рдХреЗ"ред


рддреБрд▓рдирд╛ рддрдХрдиреАрдХ


рдЖрдЧреЗ рдХреА рд╣рд▓рдЪрд▓ рдХреЗ рдмрд┐рдирд╛, рдореИрдВрдиреЗ рдХреЙрдорд░реЗрдб 0xd34df00d рджреНрд╡рд╛рд░рд╛ рдЖрд╡рд┐рд╖реНрдХрд╛рд░ рдХреА рдЧрдИ рдкрд╣реЗрд▓реА рдХреЛ рд▓рд┐рдпрд╛ рдФрд░ рдпрд╣ рдЗрд╕ рддрд░рд╣ рд▓рдЧрддрд╛ рд╣реИ:


рдорд╛рди рд▓реАрдЬрд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреБрдЫ рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ рдХрд╛ рдПрдХ рдкреЗрдбрд╝ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдВ (рд╕реНрдореГрддрд┐ рдореЗрдВ, рдХрд┐рд╕реА рднреА рд░реВрдк рдореЗрдВ)ред рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


|- 1
   |- 2
   |- 3
      |- 4
      |- 5

API /api/{id} JSON- .


, , API, . , , IO .


API, , . , , , ..


:


|- 1
   |- 2
   |- 3
      |- 4
      |- 5

|- 1: 
   |- 2:   1
   |- 3:   2
      |- 4:   1
      |- 5:   2

https://jsonplaceholder.typicode.com/todos/


, , , .


Haskell



, -, - do-, . , . C#



- .


Disclaimer: , Haskell


, ML . , , Lingua Franca - * . , , , . . , , .


* /++/..., тАФ C++/C#/Java/Kotlin/Swift/...


, Haskell. Scala/F#/Idris/Elm/Elixir/тАж , тАФ , . , , Haskell . Rust/C#, , . Option/Maybe, Result/Either Task/Promise/Future/IO .


,


data Maybe a = Just a | Nothing  --  


//   
enum Maybe<T> {
   Just(T),
   Nothing
}

, . Rust: - - T. - . . ,


data Either a b = Left a | Right b

,


enum Either<A,B> {
   Left(A),
   Right(B)
}

. , ( - ).


- -, , :


data Comment = Comment {
      title :: String
    , id  :: Int
    } deriving (Show) --     
              --    (  ToString()  C#/Java)

:


#[derive(Debug)]
struct Comment {
    title: String,
    id: i32
}

, .



sqr :: Int -> Int
sqr x = x*x

main :: IO () -- IO   ,     ,     
main = print (sqr 3)


fn sqr(x: i32) -> i32 { x*x }
fn main() {
   println!("{}", sqr(3));
}

, тАФ , тАФ main.


, : - , ML- тАФ . - - . (sqr 3) , , . print sqr , sqr Fn(i32) -> i32 (Func<int, int> C#), show ( ToString()).


: : () тАФ , тАФ . - ( ) ->, . , foo :: Int -> Double -> String -> Bool, foo : , , .


, bar :: (Int -> Double) -> Int -> (String -> Bool)?


bar : Int -> Double Int, String -> bool.


Rust-: fn bar(f: impl Fn(i32) -> f64, v: i32) -> impl Fn(String) -> bool


C#-: Func<string, bool> Bar(Func<int, double> f, int v)


, ( ), . , , , .


,


sqr x = x*x     --     ,   
add x y = x + y -- : FOR EXAMPLE PURPOSES ONLY!
add5_long x = add 5 x
add5 = add 5    --    ,       , 
                --  add5     add5_long. 
                --    Method Groups  C#
                --     - 

main :: IO ()
main = putStrLn (show (add 10 (add5 (sqr 3)))) 


fn sqr(x: i32) -> i32 { x*x }
fn add(x: i32, y: i32) -> i32 { x + y }
fn add5(x: i32) -> i32 { add(5, x) }

fn main() {
   println!("{}", ToString::to_string(add(10, add(5, sqr(3)))));                
}

, . $ . a $ b a (b). :


main = putStrLn $ show $ add 10 $ add5 $ sqr 3 -- !  

, - . . тАФ , f (g x) = (f . g) x. print (sqr 3) (print . sqr) 3. "" " " " ", 3. :


main = putStrLn . show . add 10 . add5 $ sqr 3

, ? , тАФ , , - :


--     5,   10,    ,    
putStrLnShowAdd10Add5 = putStrLn . show . add 10 . add5
--   putStrLnShowAdd10Add5 x = putStrLn . show . add 10 . add5 x
--      (, ,    )

main :: IO ()
main = putStrLnShowAdd10Add5 $ sqr 3

"24". тАФ , , тАФ тАФ .


ML , Haskell ,



main :: IO ()
main = 
  let maybe15 = do
      let just5 = Just 5    --    Maybe   Just (.  )   5
      let just10 = Just 10  --     10
      a <- just5            --     ,   ,     `a`.           !
      b <- just10           --     `b`
      return $ a + b        --      ,      (    Just)      a  b.
  in 
    print maybe15

, do- <- , do-, , ( , ). Maybe - ( "Null condition operator"), null- , null, - . do- - , .


, ? , "" , ( Maybe, , Result<T,Error>, тАФ Either), , ? , <- , .


, async/await ( C# .. Rust async-await ):


async ValueTask<int> Maybe15() {
    var just5 = Task.FromResult(5);
    var just10 = Task.FromResult(10);
    int a = await just5; //         !
    int b = await just10;
    return a + b;
}

Console.WriteLine(Maybe15().ToString()) //   15

Task Maybe, , .
, do- async/await ( Task) , do тАФ " async-", <- тАФ "" ( ). Future/Option/Result/ List, .


C#

C# do-, async/await Task. , , LINQ-. , , - , . Nullable, Haskell ( Task). , ( ):


main :: IO ()
main = 
  let maybe15 = do
      a <- Just 5
      b <- Just 10
      return $ a + b 
  in 
    print maybe15

C#


int? maybe15 = from a in new int?(5)
               from b in new int?(10)
               select a + b;

Console.WriteLine(maybe15?.ToString() ?? "Nothing");

? тАФ , haskell Nothing , C# .


repl ( ). Result Task. , . , (, , ?).


Haskell: https://repl.it/@Pzixel/ChiefLumpyDebugging


, ,


Haskell



? , IDE


: GHC (), Stack ( , cargo dotnet), IntelliJ-Haskell, . , IDE .


, , , , , :


main :: IO ()
main = putStrLn "Hello, World!"

, ! , . Data.Tree drawTree. , , :


import Data.Tree

main :: IO ()
main = do
    let tree = Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]
    putStrLn . drawTree $ tree --      ,     .
                               --        

:


    тАв No instance for (Num String) arising from the literal тАШ1тАЩ
    тАв In the first argument of тАШNodeтАЩ, namely тАШ1тАЩ
      In the expression:
        Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]

- 30 , " ?.. тАж , ", "haskell map convert to string", map show. : putStrLn . drawTree . fmap show $ tree, ,


, , ?
, , . , , - - . .. - Rust , Option тАФ , - Maybe ( Option), , HTTP , . , .


-:


import Data.Tree

data Comment = Comment {
      title :: String
    , id  :: Int
    } deriving (Show)

getCommentById :: Int -> Maybe Comment
getCommentById i = Just $ Comment (show i) i

main :: IO ()
main = do
    let tree = Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]
    putStrLn . drawTree . fmap show $ tree

, - . "haskell map maybe list" ( , , ), " mapM". :


import Data.Tree
import Data.Maybe

data Comment = Comment {
      title :: String
    , id  :: Int
    } deriving (Show)

getCommentById :: Int -> Maybe Comment
getCommentById i = Just $ Comment (show i) i

main :: IO ()
main = do
    let tree = Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]
    putStrLn . drawTree . fmap show $ tree
    let commentsTree = mapM getCommentById tree
    putStrLn . drawTree . fmap show $ fromJust commentsTree

:


1
|
+- 2
|
`- 3
   |
   +- 4
   |
   `- 5
Comment {title = "1", id = 1}
|
+- Comment {title = "2", id = 2}
|
`- Comment {title = "3", id = 3}
   |
   +- Comment {title = "4", id = 4}
   |
   `- Comment {title = "5", id = 5}

, . fromJust ( unwrap() Nullable.Value C#, , , ), , .


, , JSON'.
, wreq . 15 :


{-# LANGUAGE DeriveGeneric #-}

import Data.Tree
import Data.Maybe
import Network.Wreq
import GHC.Generics
import Data.Aeson
import Control.Lens

data Comment = Comment {
      title :: String
    , id  :: Int
    } deriving (Generic, Show)

instance FromJSON Comment -- `impl FromJson for Comment {}`   Rust

getCommentById :: Int -> IO Comment
getCommentById i = do
  response <- get $ "https://jsonplaceholder.typicode.com/todos/" ++ show i
  let comment = decode (response ^. responseBody) :: Maybe Comment
  return $ fromJust comment

main :: IO ()
main = do
    let tree = Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]
    Prelude.putStrLn . drawTree . fmap show $ tree
    let commentsTree = mapM getCommentById tree
    Prelude.putStrLn . drawTree . fmap show $ fromJust commentsTree

тАж 20 , (, reqwest Rust), :


    * Couldn't match expected type `Maybe (Tree a0)'
                  with actual type `IO (Tree Comment)'
    * In the first argument of `fromJust', namely `commentsTree'
      In the second argument of `($)', namely `fromJust commentsTree'
      In a stmt of a 'do' block:
        putStrLn . drawTree . fmap show $ fromJust commentsTree
   |
28 |     Prelude.putStrLn . drawTree . fmap show $ fromJust commentsTree
   |                                                        ^^^^^^^^^^^^^

, fromJust Maybe Tree -> Tree, IO , IO Tree Maybe Tree. ? , " <-" . :


main :: IO ()
main = do
    let tree = Node 1 [Node 2 [], Node 3 [Node 4 [], Node 5 []]]
    Prelude.putStrLn . drawTree . fmap show $ tree
    commentsTree <- mapM getCommentById tree
    Prelude.putStrLn . drawTree . fmap show $ commentsTree

, . . , .


20 , . Concurrent-, - , -. , async. , - :


commentsTree <- mapConcurrently getCommentById tree

. , , . , тАФ .


: .. , HTTP , repl.it .


. C# Rust . 67 -. , reqwest 100 , . , .


. , , . , :


main = do
    let tree = [1,2,3,4,5]
    print tree
    commentsTree <- mapConcurrently getCommentById tree
    print commentsTree


[1,2,3,4,5]
[Comment {title = "delectus aut autem", id = 1},Comment {title = "quis ut nam facilis et officia qui", id = 2},Comment {title = "fugiat veniam minus", id = 3},Comment {title = "et porro tempora", id = 4},Comment {title = "laboriosam mollitia et enim quasi adipisci quia provident illum", id = 5}]

, . , , . , , ( , ), , , , . , , .


, , , go. , ( , go ) . , (, ), тАФ !


Go



,


, , https://play.golang.org/ .


, . , . go :


package main

type intTree struct {
    id int
    children []intTree
}

func main() {
    tree := intTree{ //    gofmt 
        id: 1,
        children: []intTree {
            {
                id: 2,
                children: []intTree{

                },
            },
            {
                id: 3,
                children: []intTree{
                    {
                        id: 4,
                    },
                    {
                        id: 5,
                    },
                },
            },
        },
    }
}

тАФ , tree declared and not used. , , , tree _. , no new variables on left side of :=. , , . , , foreach :


func showIntTree(tree intTree) {
    showIntTreeInternal(tree, "")
}

func showIntTreeInternal(tree intTree, indent string) {
    fmt.Printf("%v%v\n", indent, tree.id)
    for _, child := range tree.children {
        showIntTreeInternal(child, indent + "  ")
    }
}

, , , . Haskell , .


, . ,


type comment struct {
    id int
    title string
}

type commentTree struct {
    value comment
    children []commentTree
}

func loadComments(node intTree) commentTree {
    result := commentTree{}
    for _, c := range node.children {
        result.children = append(result.children, loadComments(c))
    }
    result.value = getCommentById(node.id)
    return result
}

func getCommentById(id int) comment { 
    return comment{id:id, title:"Hello"} //     go
}

:


func showCommentsTree(tree commentTree) {
    showCommentsTreeInternal(tree, "")
}

func showCommentsTreeInternal(tree commentTree, indent string) {
    fmt.Printf("%v%v - %v\n", indent, tree.value.id, tree.value.title)
    for _, child := range tree.children {
        showCommentsTreeInternal(child, indent + "  ")
    }
}

, -, . , http , , JSON, 5 :


func getCommentById(i int) comment {
    result := &comment{}
    err := getJson("https://jsonplaceholder.typicode.com/todos/"+strconv.Itoa(i), result)
    if err != nil {
        panic(err) //    
    }
    return *result
}

func getJson(url string, target interface{}) error {
    var myClient = &http.Client{Timeout: 10 * time.Second}
    r, err := myClient.Get(url)
    if err != nil {
        return err
    }
    defer r.Body.Close()

    return json.NewDecoder(r.Body).Decode(target)
}

,


1
  2
  3
    4
    5
0 - 
  0 - 
  0 - 
    0 - 
    0 - 

. , , . .


5 , , : {Title = "delectus aut autem", Id = 1} c id, title . , , тАФ . , : тАФ , тАФ , .


DTO, , , .


10 , ! тАФ . , , , , , .


5, go-.


func loadComments(root intTree) commentTree {
    var wg sync.WaitGroup
    result := loadCommentsInner(&wg, root)
    wg.Wait()
    return result
}

func loadCommentsInner(wg *sync.WaitGroup, node intTree) commentTree {
    result := commentTree{}
    wg.Add(1)
    for _, c := range node.children {
        result.children = append(result.children, loadCommentsInner(wg, c))
    }
    go func() {
        result.value = getCommentById(node.id)
        wg.Done()
    }()
    return result
}


0 - 
  0 - 
  0 - 
    0 - 
    0 - 

, - ? , , . , , wg.Wait() , , .


, - , . , , , 10 :


func loadComments(root intTree) commentTree {
    ch := make(chan commentTree, 1)   //  
    var wg sync.WaitGroup             //   
    wg.Add(1)                         //     
    loadCommentsInner(&wg, ch, root)  //  
    wg.Wait()                         //  
    result := <- ch                   //    
    return result
}

func loadCommentsInner(wg *sync.WaitGroup, channel chan commentTree, node intTree) {
    ch := make(chan commentTree, len(node.children))  //     
    var childWg sync.WaitGroup                        //     
    childWg.Add(len(node.children))
    for _, c := range node.children {
        go loadCommentsInner(&childWg, ch, c)         //      ()
    }
    result := commentTree{
        value: getCommentById(node.id),               //   
    }
    if len(node.children) > 0 {                       //     ,   ,   
        childWg.Wait()
        for value := range ch {                       //      ,    
            result.children = append(result.children, value)
        }
    }
    channel <- result                                 //     
    wg.Done()                                         //     
}

тАж . . , . , , , . - . ?


15 , , / , тАж HTTP :


func getCommentById(id int) comment {
    return comment{Id: id, Title: "Hello"}
}

:


1
  2
  3
    4
    5
fatal error: all Goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc00006e228)
    C:/go/src/runtime/sema.go:56 +0x49
sync.(*WaitGroup).Wait(0xc00006e220)
    C:/go/src/sync/waitgroup.go:130 +0x6b
main.loadCommentsInner(0xc00006e210, 0xc0000ce120, 0x1, 0xc000095f10, 0x2, 0x2)
    C:/Users/pzixe/go/src/hello/hello.go:47 +0x187
main.loadComments(0x1, 0xc000095f10, 0x2, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    C:/Users/pzixe/go/src/hello/hello.go:30 +0xec
main.main()
    C:/Users/pzixe/go/src/hello/hello.go:94 +0x14d

, - . , - ? HTTP , ...


@gogolang , . , :


  1. . , , comment JSON
  2. . , Task Task WhenAny/WhenAll . , , , . , , . тАФ - -
    for httpRequest := range webserer.listen() {
        go handle(httpRequest)
    } 
  3. go-way printTree:


    func printTree(tree interface{}) string {
        b, err := json.MarshalIndent(tree, "", "  ")
        if err != nil {
            panic(err)
        }
        return string(b)
    }

    interface {} тАФ dynamic any, . , .


    JSON , .



, : , , ? . :


func loadComments(root intTree) commentTree {
    result := commentTree{}
    var wg sync.WaitGroup
    loadCommentsInner(&result, root, &wg)
    wg.Wait()
    return result
}

func loadCommentsInner(resNode *commentTree, node intTree, wg *sync.WaitGroup) {
    wg.Add(1)
    for _, res := range node.children {
        resNode.children = append(resNode.children, &commentTree{})
        loadCommentsInner(resNode.children[len(resNode.children)-1], res, wg)
    }
    resNode.value = getCommentById(node.id)
    wg.Done()
}

? , "go-way": , . , , , .


, . , , ,


, , .


, , - :


func loadComments(root intTree) commentTree {
    result := commentTree{}
    var wg sync.WaitGroup
    loadCommentsInner(&result, root, &wg)
    wg.Wait()
    return result
}

func loadCommentsInner(resNode *commentTree, node intTree, wg *sync.WaitGroup) {
    wg.Add(len(node.children))
    for _, res := range node.children {
        child := &commentTree{}
        resNode.children = append(resNode.children, child)
        res := res
        go func() {
            defer wg.Done()
            loadCommentsInner(child, res, wg)
        }()
    }
    resNode.value = getCommentById(node.id)
}

, , . , , . , (, 4 , ), , .


, , . :


1
  2
  3
    4
    5
START 1
START 3
START 5
DONE 5
START 2
DONE 2
START 4
DONE 4

, 4 5 , 3 . , , , . , Rust , , , .


, , , :


if len(node.children) > 0 {
    childWg.Wait()
    for i := 0; i < len(node.children); i++ { //      
        result.children = append(result.children, <-ch)
    }
}
channel <- result
wg.Done()

, ? , , , , . , :


  1. func (n *IdTree) LoadComments(ctx context.Context) (*CommentTree, error) тАФ tree
  2. g, ctx := errgroup.WithContext(ctx) тАФ
  3. i, c := i, c // correct capturing by closure тАФ , , .
  4. g.Go(func() error тАФ ,

, , .


, ? , . ( ), , (- ), . , , .


, ? , , , . getCommentById.


.


CтЩп


C# , 6 , . , , , 8 :


class Program
{
    class Comment
    {
        public int Id { get; set; }
        public string Title { get; set; }

        public override string ToString() => $"{Id} - {Title}";
    }

    private static readonly HttpClient HttpClient = new HttpClient();

    private static Task<Comment> GetCommentById(int id) =>
        HttpClient.GetStringAsync($"https://jsonplaceholder.typicode.com/todos/{id}")
            .ContinueWith(n => JsonConvert.DeserializeObject<Comment>(n.Result));

    private static async Task<Tree<Comment>> GetCommentsTree(Tree<int> tree)
    {
        var children = Task.WhenAll(tree.Children.Select(GetCommentsTree));
        var value = await GetCommentById(tree.Value);
        var childrenResults = await children;
        return new Tree<Comment> { Value = value, Children = childrenResults };
    }

    private static async Task Main()
    {
        var tree = Tr(1, new[] { Tr(2), Tr(3, new[] { Tr(4), Tr(5) }) });
        PrintTree(tree);
        var comment_tree = await GetCommentsTree(tree);
        PrintTree(comment_tree);
    }

    class Tree<T>
    {
        public T Value { get; set; }
        public Tree<T>[] Children { get; set; }
    }

    private static void PrintTree<T>(Tree<T> tree, string intendantion = "")
    {
        Console.WriteLine(intendantion + tree.Value);
        foreach (var child in tree.Children)
        {
            PrintTree(child, intendantion + "  ");
        }
    }

    static Tree<T> Tr<T>(T value, Tree<T>[] children = null) => new Tree<T> { Value = value, Children = children ?? Array.Empty<Tree<T>>() };
}

, ? , , Task.WhenAll foreach . .
? , . GetCommentById. , AsyncEnumerable , , .




, . , , , , . . , .


HaskellgoC#
*177628
24-
3010-
1550-
тЬУтЬЧтЬЧ
тЬУтЬЧтЬУ
**тЬУтЬЧтЬУтЬУ
~3011
5c1.9c***1.6c

* , . , , Haskell showTree


** , 42. , , :


async Task<Tree<Comment>> GetCommentsTree(Tree<int> tree)
{
    if (tree.Children.Sum(c => c.Value) == 42)
    {
        return new Tree<Comment> { Value = await GetCommentById(tree.Value), Children = Array.Empty<Tree<int>> };
    }
    ...         

.


, , mapParallel. , , go C#.


*** , 7 , 1.9 , 200. , .




, :


""

Haskell: , . , , , , . , , 17 , , .


Go: - , - , , .


Haskell: , , . , " ", " Rust", . , . , . : . , , .


Go: . 10 . . , , . , , , , тАФ . , . - , , , . , , , . , . , , .


C

. , , , , , Maybe IO , .


C

, - , . Task.Run(() => DoStuffAsyncInAnotherThread()) , - . , go DoAsyncStuff(), , ( - ), Task.WhenAny/Task.WhenAll ( ), .


. , , . . , , .


- , , , .



, .


, . : , , , . , , , , " ?", Maybe IO " fromJust Maybe, IO?".


, .. , . , , , - . . , " ", . , . , , . , , .




, , , - , . ? . JSON? . . , (, ^.), , (- HTTP ), .


, - , . , , тАФ . . : , .




, .


IDE//etc, / .


.


- , - , тАФ . , , //тАж , ...


- , go 3 , . - , 8 , 5, - . , , , . .


- , ( ) . :


тАФ go , ,

тАФ *sarcasm*

тАФ Sorry, this group is no longer accessible

, ( ), , .




, ? , - . , - , , , , тАж , .


Upd. , , . , . , .



? , . . , , obj/bin . , . , Go , , - . , , . - gorm, EF/Linq2Db/Hibernate/Dapper API.


, , , . "" , , , , . SQL , . , . , . , , , , "" , - . , , , ( , ). go Map, : , тАФ .


, :



тАФ , ?..

Source: https://habr.com/ru/post/hi469441/


All Articles