Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

There are certainly times when operators seem to be overused (I'm thinking of Lens in particular). But I think this criticism is overstated. One of the things that makes it more desirable to use operators rather than named functions is that due to type classes, the meaning of the operators will change with what context they're being used in. Another is that sometimes there really isn't a great name to be found; an example is the `<* >` operator in the Applicative class (space put in for formatting). Once one becomes familiar with the operators, it's much easier to read something like `doThing1 >> doThing2 >> doThing3` than `sequence doThing1 (sequence doThing2 doThing3)`.

I'm not sure why you chose the two examples you did. The Haskell version of the Ada program you wrote is as simple as can be:

    hello = putStrLn "Hello, world!"
While I'm sure an Ada program that did what the code you pasted does would be of comparable complexity to the Haskell version. And being familiar with how monadic functions work lets me guess pretty well what the code does, despite having very little knowledge of the libraries involved.

    main = do -- atomically create a new transactional variable init'd to 0
              shared <- atomically $ newTVar 0
              -- atomically read the variable and print it
              before <- atomRead shared
              putStrLn $ "Before: " ++ show before
              -- Fork a thread where we show the variable and sleep 25 times
              forkIO $ 25 `timesDo` (dispVar shared >> milliSleep 20)
              -- Fork a thread where we add 2 to the variable and sleep 10 times
              forkIO $ 10 `timesDo` (appV ((+) 2) shared >> milliSleep 50)
              -- Fork a thread where we subtract 1 from the variable and sleep 20 times
              forkIO $ 20 `timesDo` (appV pred shared >> milliSleep 25)
              -- sleep 800 ms in the main thread
              milliSleep 800
              -- read the variable and print it
              after <- atomRead shared
              putStrLn $ "After: " ++ show after
     where -- define some convenience functions
           timesDo = replicateM_
           milliSleep = threadDelay . (*) 1000
   
    atomRead = atomically . readTVar -- perform an atomic read
    dispVar x = atomRead x >>= print -- read then print what was read
    appV fn x = atomically $ readTVar x >>= writeTVar x . fn -- read, apply a function and then write


"One of the things that makes it more desirable to use operators rather than named functions is that due to type classes, the meaning of the operators will change with what context they're being used in."

I don't understand what distinction you're making here. Named functions can also be members of typeclasses (and frequently are - return, mempty...)




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: