Skip to content

Commit 010aa52

Browse files
Add DebuggingLog (#161)
* Add DebuggingLog * Fix typo * Add example of using spy as a 'drop-in' for seeing function args * Add more examples of `spy` in `traceM` examples * Add note about compiler warning * Fix whitespace issues * Remove duplicate example in `Aff` as its not necessary * Fix duplicate ST import * Remove `useTraceMInAff` * Merge Effect/ST version of useTraceM; note color difference in output * Remove paralell usage of traceM in Aff * Clarify usage of traceM in ST monadic context * Compare spy and traceM in same block * Remove unused dependency and imports * Regenerate readme
1 parent 9fb85ee commit 010aa52

File tree

8 files changed

+135
-0
lines changed

8 files changed

+135
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ Running a web-compatible recipe:
9393
| | :heavy_check_mark: | [CardsReactHooks](recipes/CardsReactHooks) | A React port of the ["Random - Cards" Elm Example](https://elm-lang.org/examples/cards). |
9494
| | :heavy_check_mark: | [CatGifsHalogenHooks](recipes/CatGifsHalogenHooks) | A Halogen port of the ["HTTP - Cat GIFs" Elm Example](https://elm-lang.org/examples). |
9595
| | :heavy_check_mark: | [CatGifsReactHooks](recipes/CatGifsReactHooks) | A React port of the ["HTTP - Cat GIFs" Elm Example](https://elm-lang.org/examples/cat-gifs). |
96+
| :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. |
9697
| :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. |
9798
| :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. |
9899
| | :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). |

recipes/DebuggingLog/.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/bower_components/
2+
/node_modules/
3+
/.pulp-cache/
4+
/output/
5+
/generated-docs/
6+
/.psc-package/
7+
/.psc*
8+
/.purs*
9+
/.psa*
10+
/.spago
11+
/web-dist/
12+
/prod-dist/
13+
/prod/

recipes/DebuggingLog/README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# DebuggingLog
2+
3+
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.
4+
5+
## Expected Behavior:
6+
7+
Does console-printing-based debugging in various contexts to show the pros/cons of each approach and how reliable/unpredictable they can be.
8+
9+
For the browser, make sure to open the console with dev tools first, then reload/refresh the page.

recipes/DebuggingLog/nodeSupported.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
This file just indicates that the node backend is supported.
2+
It is used for CI and autogeneration purposes.

recipes/DebuggingLog/spago.dhall

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{ name = "DebuggingLog"
2+
, dependencies =
3+
[ "aff", "console", "debug", "effect", "psci-support", "st" ]
4+
, packages = ../../packages.dhall
5+
, sources = [ "recipes/DebuggingLog/src/**/*.purs" ]
6+
}

recipes/DebuggingLog/src/Main.purs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
module DebuggingLog.Main where
2+
3+
import Prelude
4+
5+
import Control.Monad.ST.Internal as ST
6+
import Data.Tuple (Tuple(..))
7+
import Debug.Trace (spy, traceM)
8+
import Effect (Effect)
9+
import Effect.Aff (launchAff_)
10+
import Effect.Class (liftEffect)
11+
import Effect.Console (log)
12+
13+
data MyADT = MyADT Int (Tuple Int (Array String)) { foo :: String }
14+
15+
main :: Effect Unit
16+
main = do
17+
log "When we are in the 'Effect' monad, we can print content to the console."
18+
launchAff_ do
19+
liftEffect $ log $ "We can still print values to the console as long as \
20+
\the monad in question implements the MonadEffect \
21+
\type class. Since `Aff` implements MonadEffect, we \
22+
\can lift that effect into `Aff`."
23+
24+
log "However, there are times when we want to debug some code and wish \
25+
\to use print-based debugging. Since PureScript is pure, how do we \
26+
\do that?"
27+
28+
usingSpy
29+
30+
usingTraceM
31+
32+
compareSpyAndTraceM
33+
34+
usingSpy :: Effect Unit
35+
usingSpy = do
36+
log "usingSpy"
37+
-- `spy` returns the value it receives. However, it prints that value
38+
-- to the console before it "returns."
39+
-- spy :: forall a. DebugWarning => String -> a -> a
40+
-- You can use this in a `let` clause pretty reliably
41+
let
42+
x = 5
43+
y = spy "y" 8
44+
adt = spy "adt" $ MyADT 1 (Tuple 4 ["a", "b"]) { foo: "foo value" }
45+
function = spy "function" $ \intValue -> show $ 4 + intValue
46+
47+
-- quick way of debugging something without showing it or using a
48+
-- variable name
49+
_ = spy "debug for me what x + y is" $ x + y
50+
arrayOfStrings = spy "debug some array" $ map show [1, 2, 3, 4, 5]
51+
52+
-- quickly drop-in `spy` to see every step of a recursive function
53+
fact :: Int -> Int -> Int
54+
fact 0 acc = acc
55+
fact n acc = fact (spy "n" (n - 1)) (spy "acc" (acc * n))
56+
57+
_ = fact 5 1
58+
59+
log $ "Thus, spying is an effective way of quickly adding debugging where \
60+
\you need it without affecting any other part of your code. \
61+
\Note: you should not use `spy` to do logging in production code. \
62+
\Use a proper logger in production code."
63+
64+
usingTraceM :: Effect Unit
65+
usingTraceM = do
66+
log "usingTraceM"
67+
traceM "Notice how this text's color is different than what is outputted \
68+
\via `log`."
69+
70+
let
71+
localMutationComputation
72+
:: forall ensureMutationStaysLocal. ST.ST ensureMutationStaysLocal Int
73+
localMutationComputation = do
74+
-- the ST monad does not implement `MonadEffect`,
75+
-- so `traceM` is the only way to log output to the console in a
76+
-- `log`-like fashion.
77+
localReference <- ST.new 0
78+
traceM localReference
79+
four <- ST.modify (_ + 4) localReference
80+
traceM four
81+
ST.write (four + 2) localReference
82+
83+
log $ "Local reference value is: " <> show (ST.run localMutationComputation)
84+
85+
compareSpyAndTraceM :: Effect Unit
86+
compareSpyAndTraceM = do
87+
let x = 5
88+
_ = spy "x" x
89+
traceM x

recipes/DebuggingLog/web/index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html>
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<title>DebuggingLog</title>
7+
</head>
8+
9+
<body>
10+
<script src="./index.js"></script>
11+
</body>
12+
13+
</html>

recipes/DebuggingLog/web/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"use strict";
2+
require("../../../output/DebuggingLog.Main/index.js").main();

0 commit comments

Comments
 (0)