diff --git a/README.md b/README.md index 92524b56..d0e4a25a 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ Running a web-compatible recipe: | | :heavy_check_mark: | [CardsReactHooks](recipes/CardsReactHooks) | A React port of the ["Random - Cards" Elm Example](https://elm-lang.org/examples/cards). | | | :heavy_check_mark: | [CatGifsHalogenHooks](recipes/CatGifsHalogenHooks) | A Halogen port of the ["HTTP - Cat GIFs" Elm Example](https://elm-lang.org/examples). | | | :heavy_check_mark: | [CatGifsReactHooks](recipes/CatGifsReactHooks) | A React port of the ["HTTP - Cat GIFs" Elm Example](https://elm-lang.org/examples/cat-gifs). | +| :heavy_check_mark: | :heavy_check_mark: | [DebuggingLog](recipes/DebuggingLog) | This recipe shows how to do print-debugging using the `Debug` module's `spy` and `traceM` functions. The compiler will emit warnings to remind you to remove these debug functions before you ship production code. | | :heavy_check_mark: | | [DiceCLI](recipes/DiceCLI) | This recipe shows how to create an interactive command line prompt that repeatedly generates a random number between 1 and 6. | | :heavy_check_mark: | :heavy_check_mark: | [DiceLog](recipes/DiceLog) | This recipe shows how to log a random integer between 1 and 6 (representing a roll of a die) in either the node.js or web browser console. | | | :heavy_check_mark: | [DragAndDropHalogenHooks](recipes/DragAndDropHalogenHooks) | A Halogen port of the ["Files - Drag-and-Drop" Elm Example](https://elm-lang.org/examples/drag-and-drop). | diff --git a/recipes/DebuggingLog/.gitignore b/recipes/DebuggingLog/.gitignore new file mode 100644 index 00000000..fcea5928 --- /dev/null +++ b/recipes/DebuggingLog/.gitignore @@ -0,0 +1,13 @@ +/bower_components/ +/node_modules/ +/.pulp-cache/ +/output/ +/generated-docs/ +/.psc-package/ +/.psc* +/.purs* +/.psa* +/.spago +/web-dist/ +/prod-dist/ +/prod/ diff --git a/recipes/DebuggingLog/README.md b/recipes/DebuggingLog/README.md new file mode 100644 index 00000000..e873530f --- /dev/null +++ b/recipes/DebuggingLog/README.md @@ -0,0 +1,9 @@ +# DebuggingLog + +This recipe shows how to do print-debugging using the `Debug` module's `spy` and `traceM` functions. The compiler will emit warnings to remind you to remove these debug functions before you ship production code. + +## Expected Behavior: + +Does console-printing-based debugging in various contexts to show the pros/cons of each approach and how reliable/unpredictable they can be. + +For the browser, make sure to open the console with dev tools first, then reload/refresh the page. diff --git a/recipes/DebuggingLog/nodeSupported.md b/recipes/DebuggingLog/nodeSupported.md new file mode 100644 index 00000000..7bd63dd1 --- /dev/null +++ b/recipes/DebuggingLog/nodeSupported.md @@ -0,0 +1,2 @@ +This file just indicates that the node backend is supported. +It is used for CI and autogeneration purposes. diff --git a/recipes/DebuggingLog/spago.dhall b/recipes/DebuggingLog/spago.dhall new file mode 100644 index 00000000..440392df --- /dev/null +++ b/recipes/DebuggingLog/spago.dhall @@ -0,0 +1,6 @@ +{ name = "DebuggingLog" +, dependencies = + [ "aff", "console", "debug", "effect", "psci-support", "st" ] +, packages = ../../packages.dhall +, sources = [ "recipes/DebuggingLog/src/**/*.purs" ] +} diff --git a/recipes/DebuggingLog/src/Main.purs b/recipes/DebuggingLog/src/Main.purs new file mode 100644 index 00000000..fde77124 --- /dev/null +++ b/recipes/DebuggingLog/src/Main.purs @@ -0,0 +1,89 @@ +module DebuggingLog.Main where + +import Prelude + +import Control.Monad.ST.Internal as ST +import Data.Tuple (Tuple(..)) +import Debug.Trace (spy, traceM) +import Effect (Effect) +import Effect.Aff (launchAff_) +import Effect.Class (liftEffect) +import Effect.Console (log) + +data MyADT = MyADT Int (Tuple Int (Array String)) { foo :: String } + +main :: Effect Unit +main = do + log "When we are in the 'Effect' monad, we can print content to the console." + launchAff_ do + liftEffect $ log $ "We can still print values to the console as long as \ + \the monad in question implements the MonadEffect \ + \type class. Since `Aff` implements MonadEffect, we \ + \can lift that effect into `Aff`." + + log "However, there are times when we want to debug some code and wish \ + \to use print-based debugging. Since PureScript is pure, how do we \ + \do that?" + + usingSpy + + usingTraceM + + compareSpyAndTraceM + +usingSpy :: Effect Unit +usingSpy = do + log "usingSpy" + -- `spy` returns the value it receives. However, it prints that value + -- to the console before it "returns." + -- spy :: forall a. DebugWarning => String -> a -> a + -- You can use this in a `let` clause pretty reliably + let + x = 5 + y = spy "y" 8 + adt = spy "adt" $ MyADT 1 (Tuple 4 ["a", "b"]) { foo: "foo value" } + function = spy "function" $ \intValue -> show $ 4 + intValue + + -- quick way of debugging something without showing it or using a + -- variable name + _ = spy "debug for me what x + y is" $ x + y + arrayOfStrings = spy "debug some array" $ map show [1, 2, 3, 4, 5] + + -- quickly drop-in `spy` to see every step of a recursive function + fact :: Int -> Int -> Int + fact 0 acc = acc + fact n acc = fact (spy "n" (n - 1)) (spy "acc" (acc * n)) + + _ = fact 5 1 + + log $ "Thus, spying is an effective way of quickly adding debugging where \ + \you need it without affecting any other part of your code. \ + \Note: you should not use `spy` to do logging in production code. \ + \Use a proper logger in production code." + +usingTraceM :: Effect Unit +usingTraceM = do + log "usingTraceM" + traceM "Notice how this text's color is different than what is outputted \ + \via `log`." + + let + localMutationComputation + :: forall ensureMutationStaysLocal. ST.ST ensureMutationStaysLocal Int + localMutationComputation = do + -- the ST monad does not implement `MonadEffect`, + -- so `traceM` is the only way to log output to the console in a + -- `log`-like fashion. + localReference <- ST.new 0 + traceM localReference + four <- ST.modify (_ + 4) localReference + traceM four + ST.write (four + 2) localReference + + log $ "Local reference value is: " <> show (ST.run localMutationComputation) + +compareSpyAndTraceM :: Effect Unit +compareSpyAndTraceM = do + let x = 5 + _ = spy "x" x + traceM x diff --git a/recipes/DebuggingLog/web/index.html b/recipes/DebuggingLog/web/index.html new file mode 100644 index 00000000..09473267 --- /dev/null +++ b/recipes/DebuggingLog/web/index.html @@ -0,0 +1,13 @@ + + + + + + DebuggingLog + + + + + + + diff --git a/recipes/DebuggingLog/web/index.js b/recipes/DebuggingLog/web/index.js new file mode 100644 index 00000000..846e5980 --- /dev/null +++ b/recipes/DebuggingLog/web/index.js @@ -0,0 +1,2 @@ +"use strict"; +require("../../../output/DebuggingLog.Main/index.js").main();